原創聲明:本文系作者原創,謝絕個人、媒體、公衆号或網站未經授權轉載,違者追究其法律責任。
SOFARPC 是近期螞蟻金服開源的一個高可擴充性、高性能、生産級的 Java RPC 架構。在螞蟻金服 SOFARPC 已經經曆了十多年及五代版本的發展。SOFARPC 緻力于簡化應用之間的 RPC 調用,為應用提供友善透明、穩定高效的點對點遠端服務調用方案。為了使用者和開發者友善的進行功能擴充,SOFARPC 提供了豐富的模型抽象和可擴充接口,包括過濾器、路由、負載均衡等等。
伴随 SOFARPC 的開源,我們也開源了 sofa-bolt-node 和 sofa-rpc-node 兩個 Nodejs RPC 基礎子產品。但細心的使用者可能注意了我們在文檔裡面寫到并不希望大家直接使用它們,并預告會在 Eggjs 裡提供 RPC 最佳實踐。
現在這個最佳實踐來了,它就是:
egg-sofa-rpc 插件:
https://github.com/eggjs/egg-sofa-rpc
egg-rpc-generator 工具:
https://github.com/eggjs/egg-rpc-generator
本文通過 Step by Step 的形式介紹了 Eggjs 和 SOFA(Java)是如何進行互聯互通的,涵蓋了 RPC 的服務發現、接口定義、本地代理生成、服務端實作等各方面,期望展現給你一個相對完整的 Nodejs RPC 解決方案。考慮到社群的接受度、多語言友好性等因素,接下來的示例采用 protobuf 作為 RPC 的序列化方式。
一、準備工作
注意: 本文以 macOS 為例,其他作業系統的安裝、使用方法請自行 google。
安裝 nodejs >= 8.0.0
下載下傳安裝包:
https://nodejs.org/en/download/執行安裝
安裝 zookeeper
`
$ brew install zookeeper
啟動 zookeeper 服務
$ zkServer start
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Starting zookeeper ... STARTED
克隆 SOFARPC Java 的示例倉庫
SOFARPC 的更多資訊可以參考官方文檔
git clone [email protected]:gxcsoccer/sofa-rpc-java-demo.git
安裝 egg-init
$ npm i egg-init -g
二、建立工程
通過 egg-init 初始化項目腳手架,選擇 simple 模闆,接下來根據實際情況填寫必要資訊
$ egg-init
? Please select a boilerplate type (Use arrow keys)
──────────────
simple - Simple egg app boilerplate
ts - Simple egg && typescript app boilerplate
empty - Empty egg app boilerplate
plugin - egg plugin boilerplate
framework - egg framework boilerplate
進入生成好的項目目錄,并安裝依賴
$ cd /rpc-demo
$ npm i
安裝 egg-sofa-rpc 插件和 egg-rpc-generator 工具
$ npm i egg-sofa-rpc --save
$ npm i egg-rpc-generator --save-dev
配置 package.json 的 scripts 節點,增加一個指令 rpc 如下
{
"scripts": {
"start": "egg-scripts start --daemon --title=egg-server-rpc-demo",
"stop": "egg-scripts stop --title=egg-server-rpc-demo",
"dev": "egg-bin dev",
"debug": "egg-bin debug",
"test": "npm run lint -- --fix && npm run test-local",
"test-local": "egg-bin test",
"cov": "egg-bin cov",
"lint": "eslint .",
"ci": "npm run lint && npm run cov",
"autod": "autod",
"rpc": "egg-rpc-generator"
}
}
配置 config/plugin.js 開啟 egg-sofa-rpc 插件
// config/plugin.js
exports.sofaRpc = {
enable: true,
package: 'egg-sofa-rpc'
};
三、定義接口
protobuf 有自己的接口定義語言,詳細可以參考官方文檔。
# ProtoService.proto
syntax = "proto3";
package com.alipay.sofa.rpc.protobuf;
option java_multiple_files = true; // 可選
option java_outer_classname = "ProtoServiceModels"; // 可選
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;
}
上面這個 ProtoService.proto 檔案定義了一個服務:com.alipay.sofa.rpc.protobuf.ProtoService,它有一個叫 echoObj 的方法,入口參數類型是 EchoRequest,傳回值類型是 EchoResponse。
四、調用 Java 暴露的 RPC 服務
1、啟動 Java 服務端
進入上面克隆的 Java 示例倉庫,運作 ProtobufServiceServerMain
2、配置服務發現參數
我們預設的服務發現依賴于 zookeeper,是以需要配置一個 zk 的位址。在 config/config.{env}.js 中配置如下:
// config/config.default.js
'use strict';
exports.sofaRpc = {
registry: {
address: '127.0.0.1:2181', // zk 位址指向本地 2181 端口
}
};
3、擷取接口定義
在 egg 項目根目錄下建立 proto 目錄,然後将上面定義的 ProtoService.proto 檔案放到裡
.
├── app
│ ├── controller
│ │ └── home.js
│ └── router.js
├── config
│ ├── config.default.js
│ └── plugin.js
├── package.json
└── proto
└── ProtoService.proto
4、配置要調用的接口
在 config/proxy.js 中配置要調用的服務資訊
'use strict';
module.exports = {
services: [{
appName: 'sofarpc',
api: {
ProtoService: 'com.alipay.sofa.rpc.protobuf.ProtoService',
}
}]
};
appName(必選): 服務提供方的應用名,如果沒有可以任意起一個
api(必選): 接口清單,是一個 key-value 鍵值對,key 是生成的 proxy 檔案名,value 是接口名(如果要跟精細的配置也可以是一個對象)
config/proxy.js 詳細的配置說明可以參考文檔
5、生成調用代理
在根目錄下運作 npm run rpc,生成調用的 proxy 檔案
$ 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"
運作成功以後,會發現生成了兩個檔案
app/proxy/ProtoService.js - 調用服務的代理檔案
run/proto.json - 從 .proto 檔案中導出的接口資訊,是一個 json 格式檔案
.
├── app
│ ├── controller
│ │ └── home.js
│ ├── proxy
│ │ └── ProtoService.js
│ └── router.js
├── config
│ ├── config.default.js
│ ├── plugin.js
│ └── proxy.js
├── package.json
├── proto
│ └── ProtoService.proto
└── run
└── proto.json
生成的 app/proxy/ProtoService.js 檔案内容如下(注意:不要手動去改這個檔案):
// 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 */
6、調用代理類,實作業務邏輯
上面定義的這個 ProtoService 這個類,會挂載在 app.proxyClasses 上。通過 ctx.proxy.protoService(注意這裡是小駝峰)可以通路它的執行個體,這樣我們就可以在業務中調用 RPC 的服務了,例如:下面我們在 home controller 調用 ProtoService 的 echoObj 方法
// 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;
7、啟動應用,調試
`
$ npm run dev
在浏覽器中通路
http://127.0.0.1:7001/,得到下面的結果,說明成功了
五、暴露 RPC 服務給 Java 調用
這回換做 Nodejs 來暴露同樣的服務,Java 端作為消費者
1、配置服務發現參數
和上面作為調用者的配置一樣
// config/config.default.js
'use strict';
exports.sofaRpc = {
registry: {
address: '127.0.0.1:2181', // zk 位址指向本地 2181 端口
}
};
2、定義接口
同樣需要先定義接口,然後将 .proto 檔案放到 proto 目錄下,然後運作 npm run rpc,這些和上面作為調用者時都一樣
3、配置 RPC 服務端的參數
通過 config/config.{env}.js 配置 RPC 服務端的參數
// config/config.default.js
'use strict';
exports.sofaRpc = {
server: {
namespace: 'com.alipay.sofa.rpc.protobuf'
}
};
其中最主要的配置就是 namespace,其他配置都可以預設:
namespace(必選): 接口的命名空間,所有的暴露的接口預設都在該命名空間下
selfPublish(可選): 是否每個 worker 程序獨立暴露服務。nodejs 多程序模式下,如果多個程序共享一個端口,在 RPC 這種場景可能造成負載不均,是以 selfPublish 預設為 true,代表每個程序獨立監聽端口和釋出服務
port(可選): 服務監聽的端口(注意:在 selfPublish=true 時,監聽的端口是基于這個配置生成的)
maxIdleTime(可選): 用戶端連接配接如果在該配置時長内沒有任何流量,則主動斷開連接配接
responseTimeout(可選): 服務端建議的逾時時長,具體的逾時還是以用戶端配置為準
codecType(可選): 推薦的序列化方式,預設為 protobuf
4、實作接口邏輯
在 app/rpc 目錄下建立 ProtoService.js 檔案,用于實作接口邏輯
'use strict';
exports.echoObj = async function(req) {
return {
code: 200,
message: 'hello ' + req.name + ', you are in ' + req.group,
};
};
5、啟動應用,釋出服務
$ npm run dev
6、Java 作為用戶端調用服務
進入上面克隆的 Java 示例倉庫,運作 ProtobufServiceClientMain
執行的結果如下:
Sofa-Middleware-Log SLF4J : Actual binding is of type [ com.alipay.sofa.rpc Log4j2 ]
2018-06-11 18:07:59,977 INFO [main] com.alipay.sofa.common.log:report:30 - Sofa-Middleware-Log SLF4J : Actual binding is of type [ com.alipay.sofa.rpc Log4j2 ]
2018-06-11 18:08:00,419 INFO [main] org.apache.curator.framework.imps.CuratorFrameworkImpl:start:234 - Starting
2018-06-11 18:08:00,432 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:zookeeper.version=3.4.6-1569965, built on 02/20/2014 09:09 GMT
2018-06-11 18:08:00,432 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:host.name=30.23.232.6
2018-06-11 18:08:00,432 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:java.version=1.8.0_171
2018-06-11 18:08:00,432 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:java.vendor=Oracle Corporation
2018-06-11 18:08:00,432 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre
2018-06-11 18:08:00,432 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:java.class.path=/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/lib/tools.jar:/Users/gaoxiaochen/projj/github.com/gxcsoccer/sofa-rpc-java-demo/target/classes:/Users/gaoxiaochen/.m2/repository/com/alipay/sofa/sofa-rpc-all/5.4.0/sofa-rpc-all-5.4.0.jar:/Users/gaoxiaochen/.m2/repository/com/alipay/sofa/bolt/1.4.1/bolt-1.4.1.jar:/Users/gaoxiaochen/.m2/repository/com/alipay/sofa/common/sofa-common-tools/1.0.12/sofa-common-tools-1.0.12.jar:/Users/gaoxiaochen/.m2/repository/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.jar:/Users/gaoxiaochen/.m2/repository/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA.jar:/Users/gaoxiaochen/.m2/repository/io/netty/netty-all/4.1.25.Final/netty-all-4.1.25.Final.jar:/Users/gaoxiaochen/.m2/repository/com/alipay/sofa/hessian/3.3.0/hessian-3.3.0.jar:/Users/gaoxiaochen/.m2/repository/com/alipay/sofa/tracer-core/2.1.1/tracer-core-2.1.1.jar:/Users/gaoxiaochen/.m2/repository/io/opentracing/opentracing-api/0.22.0/opentracing-api-0.22.0.jar:/Users/gaoxiaochen/.m2/repository/io/opentracing/opentracing-noop/0.22.0/opentracing-noop-0.22.0.jar:/Users/gaoxiaochen/.m2/repository/io/opentracing/opentracing-mock/0.22.0/opentracing-mock-0.22.0.jar:/Users/gaoxiaochen/.m2/repository/io/opentracing/opentracing-util/0.22.0/opentracing-util-0.22.0.jar:/Users/gaoxiaochen/.m2/repository/org/jboss/resteasy/resteasy-netty4/3.0.12.Final/resteasy-netty4-3.0.12.Final.jar:/Users/gaoxiaochen/.m2/repository/org/jboss/resteasy/resteasy-jaxrs/3.0.12.Final/resteasy-jaxrs-3.0.12.Final.jar:/Users/gaoxiaochen/.m2/repository/org/jboss/resteasy/jaxrs-api/3.0.12.Final/jaxrs-api-3.0.12.Final.jar:/Users/gaoxiaochen/.m2/repository/org/jboss/spec/javax/annotation/jboss-annotations-api_1.1_spec/1.0.1.Final/jboss-annotations-api_1.1_spec-1.0.1.Final.jar:/Users/gaoxiaochen/.m2/repository/javax/activation/activation/1.1.1/activation-1.1.1.jar:/Users/gaoxiaochen/.m2/repository/org/apache/httpcomponents/httpclient/4.3.6/httpclient-4.3.6.jar:/Users/gaoxiaochen/.m2/repository/org/apache/httpcomponents/httpcore/4.3.3/httpcore-4.3.3.jar:/Users/gaoxiaochen/.m2/repository/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:/Users/gaoxiaochen/.m2/repository/commons-codec/commons-codec/1.6/commons-codec-1.6.jar:/Users/gaoxiaochen/.m2/repository/commons-io/commons-io/2.1/commons-io-2.1.jar:/Users/gaoxiaochen/.m2/repository/net/jcip/jcip-annotations/1.0/jcip-annotations-1.0.jar:/Users/gaoxiaochen/.m2/repository/org/jboss/resteasy/resteasy-client/3.0.12.Final/resteasy-client-3.0.12.Final.jar:/Users/gaoxiaochen/.m2/repository/org/jboss/resteasy/resteasy-jackson-provider/3.0.12.Final/resteasy-jackson-provider-3.0.12.Final.jar:/Users/gaoxiaochen/.m2/repository/org/codehaus/jackson/jackson-core-asl/1.9.12/jackson-core-asl-1.9.12.jar:/Users/gaoxiaochen/.m2/repository/org/codehaus/jackson/jackson-mapper-asl/1.9.12/jackson-mapper-asl-1.9.12.jar:/Users/gaoxiaochen/.m2/repository/org/codehaus/jackson/jackson-jaxrs/1.9.12/jackson-jaxrs-1.9.12.jar:/Users/gaoxiaochen/.m2/repository/org/codehaus/jackson/jackson-xc/1.9.12/jackson-xc-1.9.12.jar:/Users/gaoxiaochen/.m2/repository/com/alipay/sofa/lookout/lookout-api/1.4.0/lookout-api-1.4.0.jar:/Users/gaoxiaochen/.m2/repository/org/apache/curator/curator-recipes/2.9.1/curator-recipes-2.9.1.jar:/Users/gaoxiaochen/.m2/repository/org/apache/curator/curator-framework/2.9.1/curator-framework-2.9.1.jar:/Users/gaoxiaochen/.m2/repository/org/apache/curator/curator-client/2.9.1/curator-client-2.9.1.jar:/Users/gaoxiaochen/.m2/repository/org/apache/zookeeper/zookeeper/3.4.6/zookeeper-3.4.6.jar:/Users/gaoxiaochen/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar:/Users/gaoxiaochen/.m2/repository/jline/jline/0.9.94/jline-0.9.94.jar:/Users/gaoxiaochen/.m2/repository/io/netty/netty/3.7.0.Final/netty-3.7.0.Final.jar:/Users/gaoxiaochen/.m2/repository/com/google/guava/guava/16.0.1/guava-16.0.1.jar:/Users/gaoxiaochen/.m2/repository/com/google/protobuf/protobuf-java/3.1.0/protobuf-java-3.1.0.jar:/Users/gaoxiaochen/.m2/repository/org/apache/logging/log4j/log4j-core/2.3/log4j-core-2.3.jar:/Users/gaoxiaochen/.m2/repository/org/apache/logging/log4j/log4j-api/2.3/log4j-api-2.3.jar:/Users/gaoxiaochen/.m2/repository/com/lmax/disruptor/3.3.7/disruptor-3.3.7.jar:/Users/gaoxiaochen/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.3/log4j-slf4j-impl-2.3.jar:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar
2018-06-11 18:08:00,432 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:java.library.path=/Users/gaoxiaochen/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
2018-06-11 18:08:00,433 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:java.io.tmpdir=/var/folders/q4/4nwl16wn32ndm69rzh1zyvhh0000gn/T/
2018-06-11 18:08:00,433 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:java.compiler=<NA>
2018-06-11 18:08:00,433 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:os.name=Mac OS X
2018-06-11 18:08:00,433 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:os.arch=x86_64
2018-06-11 18:08:00,433 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:os.version=10.13.4
2018-06-11 18:08:00,433 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:user.name=gaoxiaochen
2018-06-11 18:08:00,433 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:user.home=/Users/gaoxiaochen
2018-06-11 18:08:00,433 INFO [main] org.apache.zookeeper.ZooKeeper:logEnv:100 - Client environment:user.dir=/Users/gaoxiaochen/projj/github.com/gxcsoccer/sofa-rpc-java-demo
2018-06-11 18:08:00,434 INFO [main] org.apache.zookeeper.ZooKeeper:<init>:438 - Initiating client connection, connectString=127.0.0.1:2181 sessionTimeout=60000 watcher=org.apache.curator.ConnectionState@2e005c4b
2018-06-11 18:08:00,459 INFO [main-SendThread(127.0.0.1:2181)] org.apache.zookeeper.ClientCnxn:logStartConnect:975 - Opening socket connection to server 127.0.0.1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
2018-06-11 18:08:00,547 INFO [main-SendThread(127.0.0.1:2181)] org.apache.zookeeper.ClientCnxn:primeConnection:852 - Socket connection established to 127.0.0.1/127.0.0.1:2181, initiating session
2018-06-11 18:08:00,555 INFO [main-SendThread(127.0.0.1:2181)] org.apache.zookeeper.ClientCnxn:onConnected:1235 - Session establishment complete on server 127.0.0.1/127.0.0.1:2181, sessionid = 0x1000894bb75004f, negotiated timeout = 40000
2018-06-11 18:08:00,558 INFO [main-EventThread] org.apache.curator.framework.state.ConnectionStateManager:postState:228 - State change: CONNECTED
2018-06-11 18:08:00,594 WARN [main] org.apache.curator.utils.ZKPaths:<clinit>:76 - The version of ZooKeeper being used doesn't support Container nodes. CreateMode.PERSISTENT will be used instead.
Sofa-Middleware-Log SLF4J : Actual binding is of type [ com.alipay.remoting Log4j2 ]
2018-06-11 18:08:00,645 INFO [SOFA-CLI-CONN-com.alipay.sofa.rpc.protobuf.ProtoService-3-T1] com.alipay.sofa.common.log:report:30 - Sofa-Middleware-Log SLF4J : Actual binding is of type [ com.alipay.remoting Log4j2 ]
2018-06-11 18:08:00,703 WARN No Root logger was configured, creating default ERROR-level Root logger with Console appender
/Users/gaoxiaochen/logs/tracelog/rpc-client-digest.log -> /Users/gaoxiaochen/logs/tracelog/rpc-client-digest.log.2018-06-09
200: hello zhang, you are in 0
200: hello zhang, you are in 0
200: hello zhang, you are in 0
200: hello zhang, you are in 0
200: hello zhang, you are in 0
200: hello zhang, you are in 0
200: hello zhang, you are in 0
200: hello zhang, you are in 0
相關資源連結:
SOFA Java Demo :
https://github.com/gxcsoccer/sofa-rpc-java-demoEggjs RPC Example :
https://github.com/eggjs/examples/tree/master/sofa-rpcSOFARPC Node:
https://github.com/alipay/sofa-rpc-nodeSOFABolt Node:
https://github.com/alipay/sofa-bolt-nodeEggjs:
https://eggjs.orgSOFARPC:
https://github.com/alipay/sofa-rpc