One, foreword
SOFARPC is ant Financial open source a high scalability, high performance, production level Java RPC framework, provides a wealth of model abstraction and extensible interfaces, including filters, routing, load balancing and so on, is committed to simplify RPC calls between applications. It provides a convenient, transparent, stable and efficient point-to-point remote service invocation scheme for applications.
Egg. Js as a mature open source projects, clearly defined from the configuration, routing, middleware and extend to the controller, timing task each Web application such as research and development in the process of some of the most basic concepts, such a different team of developers using the framework written code style will be more consistent, take over old projects to fit the cost will be lower.
This article will briefly introduce the interaction between egg.js and SOFA (Java), using sofarPC’s open source, and present a preliminary Node.js RPC solution.
2. Introduction to RPC
Remote Procedure Call (RPC) is used to Call Remote functions as local functions. Simply put, this means that the logic of the local invocation is handled on a remote machine rather than by the local service proxy.
In fact, HTTP can also achieve the effect of remote calls, so what is the relationship between HTTP and RPC? What’s the difference?
Upon understanding, we find that RPC and HTTP are not at the same level.
(1) The difference between RPC and HTTP
RPC is generally referred to as a framework
In combination with the above figure, Ali’s interpretation of the advantages of SOFA, RPC open source RPC framework, we know that RPC can also be implemented based on HTTP. For example, GRPC in the above figure is Google based on HTTP2.0 protocol, and RPC can also be implemented based on TCP and Sockets.
gRPC is a modern open source high performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.
The HyperText Transfer Protocol (HTTP) is a TCP based HyperText Transfer Protocol, while HTTP is stateless. Originally used for communication between browsers and servers, it was later widely used for communication between services.
RPC is a remote procedure call. The communication process that RPC framework can use can be implemented using various communication protocols (such as HTTP, TCP and various custom protocols).
To put it simply, compared with HTTP container, mature RPC library encapsulates advanced service-oriented features such as “service discovery”, “load balancing” and “circuit breaker degradation”. RPC framework is a more advanced service-oriented packaging. If an HTTP servlet container encapsulates a layer of service discovery and function proxy calls, it can be used as an RPC framework. So why use RPC calls? Because good RPC calls are service-oriented encapsulation, they are optimized for service availability and efficiency. Using HTTP calls alone lacks these features.
Here you can follow Zhihu to learn more: why use RPC calls when there are HTTP requests?
What are the popular RPC frameworks for Nodejs?
- GRPC – grPC. IO, this is more popular abroad, with Google endorsement, support for multiple languages, heard that the use of the company is also more, looks like a more mature framework.
- Sofa — tech.antfin.com/sofa This is a domestic Ali open source, the current Ali open source Eggjs framework is also open source based on sofa best practices.
- DUBBO — Alibaba’s open source Java RPC framework
Four, the practice
Based on “Cross-language intermodulation of Eggjs and SOFA” we tried RPC calls under Eggjs.
(1) ZooKeeper introduction
Back to the original RPC principle, the Client does not initiate communication with the Server, but needs to bridge the Client Stub and Server Stub to complete communication between the Client and Server. Here’s the question:
- How to find the Server during the bridge between the Client Stub and Server Stub? (Service Address Storage)
- After the Server receives the request, how does the Client receive the processing result? (Service state awareness)
Zookeeper for use in the framework of this implementation is to solve the above two questions, details may refer to: ketao1989. Making. IO / 2016/12/10 /…
In contrast to HTTP services, we have a supporting infrastructure component called DNS, which finds several external IP addresses based on the domain name. The request then goes inside the site, usually to the Nginx group first. Nginx also finds a configured set of IP addresses based on url rules. In addition, Nginx checks the AVAILABILITY of HTTP services based on HealthCheck.
Zookeeper does what DNS and Nginx do with service address storage. Next try mainly from “Node service — > Java Service” and “Java service — > Node Service” (using sofa call)
1. The configuration
- through
egg-init
Initialize the project scaffolding, select the Simple template, and fill in the necessary information as required.
$ egg-init
? Please select a boilerplate type❯ simple-simple Egg App BoilerPlate TS-Simple Egg && typescript app BoilerPlate empty - Empty egg app boilerplate plugin - egg plugin boilerplate framework - egg framework boilerplateCopy the code
-
Go to the generated project directory and install the dependencies
-
$NPM I egg-SOFA – RPC –save $NPM I egg-rpc-generator –save-dev
-
Configure the package.json scripts node by adding the command “RPC “: “egg-rpc-generator”
{
"scripts": {
"dev": "egg-bin dev"."rpc": "egg-rpc-generator"}}Copy the code
One additional point not mentioned in ali’s documentation: it must be added to the outermost layer of package.json, which the egg-int tool does not help build.
"egg": {
"framework": "sofa-node"
}
Copy the code
- configuration
config/plugin.js
openegg-sofa-rpc
The plug-in
// config/plugin.js
exports.sofaRpc = {
enable: true,
package: 'egg-sofa-rpc'};Copy the code
- in
config/config.default.js
configurationzookeeper
// config/config.default.js
'use strict';
exports.sofaRpc = {
registry: {
address: '127.0.0.1:2181', // zk address to local port 2181},};Copy the code
2. Configure interfaces
ProtoService.proto
syntax = "proto3"; package com.alipay.sofa.rpc.protobuf; option java_multiple_files = true; // Optional option JAVA_outer_className = "ProtoServiceModels"; // Optional service ProtoService {RPC echoObj (EchoRequest) returns (EchoResponse) {}} message EchoRequest {string name = 1; Group group = 2; } message EchoResponse { int32 code = 1; string message = 2; } enum Group { A = 0; B = 1; }Copy the code
The above protoservice. proto file defines a service: Is actually need to invoke the Java project com. Alipay. Sofa. RPC. Protobuf. ProtoService, it has a method named echoObj type is EchoRequest entrance parameters, the return value type is EchoResponse.
The Java project is in this Eggjs RPC Example
(2) the protobuf
1. What is a protobuf?
Protocol Buffers is a language-neutral, platform-independent, extensible format for serializing data that can be used for communication protocols, data storage, and more. Protocol buffers are flexible and efficient in serializing data. Protocol Buffers are smaller, faster, and simpler than XML. Once the data structure of the data to be processed has been defined, the code generation tool for Protocol Buffers can be used to generate the relevant code. Data structures can even be updated without redeploying the program. Using Protobuf to describe the data structure once, you can easily read and write your structured data in different languages or from different data streams. It is ideal for data storage or RPC data exchange formats. A language-independent, platform-independent, extensible serialized structured data format for communication protocols, data storage, etc. Currently provides C++, Java, Python three language API.
Protobuf uses data serialization in the following ways:
- Configure the service information to be invoked in config/proxy.js:
'use strict';
module.exports = {
services: [{
appName: 'sofarpc',
api: {
ProtoService: 'com.alipay.sofa.rpc.protobuf.ProtoService',}}]};Copy the code
- Run NPM run RPC in the root directory to generate the proxy text for the call:
$NPM run RPC > [email protected] RPC /egg-rpc-demo > egg-rpc-generator [EggRpcGenerator] framework: /egg-rpc-demo/node_modules/egg, baseDir: /egg-rpc-demo [ProtoRPCPlugin] found"com.alipay.sofa.rpc.protobuf.ProtoService" in proto file
[ProtoRPCPlugin] save all proto info into "/egg-rpc-demo/run/proto.json"
Copy the code
2.Egg-sofa-generator
The SOFARPC plug-in, which provides egg with the ability to call and publish RPC services, provides the ability to call SOFARPC interfaces exposed by other systems. So how does this plug-in apply to a real project? Is actually generated app/proxy/ProtoService js – invokes the service proxy files.
// Don't modified this file, it's auto created by egg-rpc-generator
'use strict';
const path = require('path');
/* eslint-disable */
/* istanbul ignore next */
module.exports = app => {
const consumer = app.sofaRpcClient.createConsumer({
interfaceName: 'com.alipay.sofa.rpc.protobuf.ProtoService',
targetAppName: 'sofarpc',
version: '1.0',
group: 'SOFA',
proxyName: 'ProtoService',
responseTimeout: 3000,
});
if(! consumer) { // `app.config['sofarpc.rpc.service.enable'] = false` will disable this consumer
return;
}
app.beforeStart(async() => {
await consumer.ready();
});
class ProtoService extends app.Proxy {
constructor(ctx) {
super(ctx, consumer);
}
async echoObj(req) {
return await consumer.invoke('echoObj', [ req ], {
ctx: this.ctx,
codecType: 'protobuf'}); }}return ProtoService;
};
/* eslint-enable */
Copy the code
How do I call this method?
- Call ctx.proxy in the route
// app/controller/home.js
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx } = this;
const res = await ctx.proxy.protoService.echoObj({
name: 'gxcsoccer',
group: 'A'}); ctx.body = res; } } module.exports = HomeController;Copy the code
npm run dev
Copy the code
In terms of debugging results, the following figure is shown after the interface is called:
Five, the summary
With the open source of SOFARPC, sofa- Bolt – Node and SOFA – RPC-Node two Nodejs RPC basic modules are also gradually improved. This article attempts to provide some references to RPC in egg.js by connecting Eggjs to SOFA (Java). As the Node community continues to improve, more and more node.js will be used in RPC in the future.
Vi. References
- Intermodulation of Eggjs and SOFA across languages
- Simple RPC principle
- The core RPC principles of distributed architecture
- RPC Principle Analysis
- The Demo sample