gRPC SkyLB
gRPC 作為一款高性能、通用的 RPC 框架,相比傳統(tǒng)的RPC框架有著自己天然的優(yōu)勢(shì):
- protobuf二進(jìn)制消息,性能好/效率高(空間和時(shí)間效率都很不錯(cuò));
- proto文件生成目標(biāo)代碼,簡(jiǎn)單易用;
- 序列化反序列化直接對(duì)應(yīng)程序中的數(shù)據(jù)類,不需要解析后在進(jìn)行映射(XML,JSON都是這種方式);
- 支持向前兼容(新加字段采用默認(rèn)值)和向后兼容(忽略新加字段),簡(jiǎn)化升級(jí);
- 支持多種語言(可以把proto文件看做IDL文件);
- Netty等一些框架集成;
服務(wù)注冊(cè)/發(fā)現(xiàn) 是RPC框架的核心組件,但是gRPC 作為企業(yè)級(jí)框架,他的開源組件官方并未直接提供服務(wù)注冊(cè)與發(fā)現(xiàn)的功能實(shí)現(xiàn)。而是在設(shè)計(jì)文檔(load-balancing.md)中提供了實(shí)現(xiàn)的思路,并在不同語言的gRPC代碼API中提供了命名解析和負(fù)載均衡接口供擴(kuò)展。
關(guān)于gRPC 服務(wù)發(fā)現(xiàn)&負(fù)載均衡的介紹,可以參見我之前寫的一篇文章 gRPC服務(wù)發(fā)現(xiàn)&負(fù)載均衡
Overview
gRPC SkyLB 采用獨(dú)立LB進(jìn)程(External Load Balancing Service)負(fù)載均衡方式,支持輪詢、一致性哈希兩種負(fù)載均衡策略,并支持服務(wù)端權(quán)重。采用etcd作為注冊(cè)中心。
項(xiàng)目地址:
https://github.com/binchencoder/grpc-skylb
Architecture of SkyLB

服務(wù)提供者起來后向注冊(cè)中心(SkyLB) 注冊(cè)自己的信息,ip、端口、權(quán)重等,并保持心跳??蛻舳吮O(jiān)聽注冊(cè)中心,獲取服務(wù)器列表,一旦服務(wù)器發(fā)生變化,客戶端馬上更新本地的服務(wù)器列表??蛻舳嗣總€(gè)請(qǐng)求都通過負(fù)載均衡策略選擇一個(gè)合適的服務(wù)器去訪問。
Usage
-
Dependency
Install skylb-client local repository
chenbindeMacBook-Pro:grpc-skylb chenbin$ mvn clean install<dependency> <groupId>com.binchencoder.skylb</groupId> <artifactId>skylb-client</artifactId> <version>1.0-SNAPSHOT</version> </dependency> -
Implements gRPC API
public class DemoGrpcImpl extends DemoGrpc.DemoImplBase { private final Logger LOGGER = LoggerFactory.getLogger(DemoGrpcImpl.class); private Random rand = new Random(System.currentTimeMillis()); private int port; public DemoGrpcImpl(int port_) { this.port = port_; } @Override public void greeting(GreetingProtos.GreetingRequest request, StreamObserver<GreetingProtos.GreetingResponse> responseObserver) { LOGGER.info("Got req: {}", request); // 隨機(jī)耗時(shí)350~550毫秒. int elapse = 350 + rand.nextInt(200); try { TimeUnit.MILLISECONDS.sleep(elapse); } catch (InterruptedException ie) { LOGGER.warn("sleep interrupted"); } GreetingResponse reply = GreetingResponse.newBuilder().setGreeting( "Hello " + request.getName() + ", from :" + port + ", elapse " + elapse + "ms").build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } @Override public void greetingForEver(GreetingProtos.GreetingRequest request, StreamObserver<GreetingProtos.GreetingResponse> responseObserver) { super.greetingForEver(request, responseObserver); } } -
Register gRPC Server to SkyLB Server
Server server = ServerTemplate.create( {port} 9090, {bindableService} new DemoGrpcImpl(), {serviceName} "shared-test-client-service") .build() .start(); SkyLBServiceReporter reporter = ServerTemplate.reportLoad( {skylbUri} "skylb://127.0.0.1:1900/", {serviceName} ServiceNameUtil.toString(ServiceId.CUSTOM_EASE_GATEWAY_TEST), {portName} "grpc", {port} 9090); -
Call gRPC Server
Create gRPC Stub
ManagedChannel channel = ClientTemplate.createChannel( {skylbAddr} "skylb://127.0.0.1:1900/", {calleeServiceName} ServiceNameUtil.toString(ServiceId.CUSTOM_EASE_GATEWAY_TEST), {calleePortName} "grpc", {calleeNamespace} null, {callerServiceName} ServiceNameUtil.toString(ServiceId.SERVICE_NONE)).getOriginChannel(); DemoGrpc.DemoBlockingStub blockingStub = DemoGrpc.newBlockingStub(channel);GreetingRequest request = GreetingRequest.newBuilder() .setName("GC " + Calendar.getInstance().get(Calendar.SECOND)) .build(); GreetingResponse response = blockingStub .withDeadlineAfter(2000, TimeUnit.MILLISECONDS) .greeting(request);
Run Demo
-
Build SkyLB Server
chenbindeMacBook-Pro:grpc-skylb chenbin$ cd skylb-server chenbindeMacBook-Pro:skylb-server chenbin$ mvn clean package最終skylb.jar 打包到 skylb-server/target 目錄下
-
Start SkyLB Server
Start ETCD3
yum install etcd -y systemctl enable etcd && systemctl start etcdNOTE
部署ETCD遇到問題可參考 https://www.cnblogs.com/shawhe/p/10640820.html
chenbindeMacBook-Pro:skylb-server chenbin$ cd target/skylblib chenbindeMacBook-Pro:skylblib chenbin$ java -jar skylb.jar -h Usage: java -jar skylb.jar [options] [command] [command options] Options: --auto-disconn-timeout, -auto-disconn-timeout The timeout to automatically disconnect the resolve RPC. e.g. 10s(10 Seconds), 10m(10 Minutes) Default: PT5M Commands: etcd Help for etcd options Usage: etcd [options] Options: --etcd-endpoints, -etcd-endpoints The comma separated ETCD endpoints. e.g., http://etcd1:2379,http://etcd2:2379 Default: [http://127.0.0.1:2379] --etcd-key-ttl, -etcd-key-ttl The etcd key time-to-live. e.g. 10s(10 Seconds), 10m(10 Minutes) Default: PT10S chenbindeMacBook-Pro:skylblib chenbin$ java -jar skylb.jar -etcd-endpoints=http://127.0.0.1:2379 -
Start gRPC Server
Run com/binchencoder/skylb/demo/grpc/server/GreetingServer#main
-
Start gRPC Client
Run com/binchencoder/skylb/demo/grpc/client/GreetingClient#main
More Examples
grpc-skylb/examples/echo
該示例采用SpringBoot腳手架,在spring-boot-grpc-common.jar中封裝好了注冊(cè)服務(wù)的邏輯,啟動(dòng)方式比較簡(jiǎn)單
@GrpcService(applyGlobalInterceptors = true) // Default use Global Interceptor
public class EchoGrpcService extends EchoServiceGrpc.EchoServiceImplBase {
}
使用
@GrpcService注解方式標(biāo)示gRPC Service在 spring-boot-grpc-common.jar 中默認(rèn)配置兩個(gè)Global Interceptor(ExceptionInterceptor, AuthenticationInterceptor)
-
使用者可通過注解不使用Global Interceptor,實(shí)現(xiàn)自己的Interceptor
@GrpcService(applyGlobalInterceptors = false, interceptors = ExceptionInterceptor.class)
Features
- @GrpcService Annotation
- 支持配置全局?jǐn)r截器
- 將來計(jì)劃支持skylb-client Golang版本
References
- gRPC服務(wù)發(fā)現(xiàn)&負(fù)載均衡
- https://github.com/binchencoder/grpc-skylb
- https://github.com/grpc/grpc/blob/master/doc/load-balancing.md
- 部署ETCD3集群
本人現(xiàn)在正在找工作,有合適的伯樂可隨時(shí)騷擾