用grpc-gateway实现http和gRPC的服务转发
Posted 技术和生活小站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用grpc-gateway实现http和gRPC的服务转发相关的知识,希望对你有一定的参考价值。
pic by amir_asani13 from Instagram
在Spring Cloud体系里,负责RPC服务的是Feign组件,它是基于http的服务调用。在吞吐量很高,性能要求很高的场景下,需要用gRPC或thrift。因为它们是基于二进制的TCP协议,数据压缩更紧凑。
gRPC通常用于后台服务之间的模块调用,但对外发布服务,没有Restful API方便。grpc-gateway可以实现restful到gRPC的协议转换。前端用restful接口调用,经过grpc-gateway转换成gRPC协议,交给后台gRPC server服务。
gRPC对主流编程语言很友好,定义好proto规范文件后,自动生成对应的编程语言代码。编程语言不用再实现接口的参数封装和响应解析了,更专注于业务逻辑的实现。具体到Java语言,就是gRPC自动生成了Bean对象,而且IDE有自动代码提示,相对restful编程,在开发速度上的更有优势。
nginx从1.13.10版本开始,支持gRPC协议的转发。Nginx的gRPC转发和grpc-gateway的主要不同在于:nginx不用关心gRPC的具体内容,直接转发到目标端口。而grpc-gateway需要知道gRPC的具体内容,才能实现http和gRPC两种协议之间的转换。简单地说,就是nginx转发不需要proto文件,而grpc-gateway需要proto文件。
grpc-gateway原理
下面给的例子可以在grpc-gateway的官网上找到,本文再给出Java的例子,实现后台gRPC服务。
在实际应用中,如果想增加一个grpc服务,有两种做法:
1、在echo_service.proto中增加一个rpc调用:
rpc getDate(Empty) returns (StringMessage) { option (google.api.http) = { get: "/v1/example/getdate" }; }
则 /v1/example/echo 和 /v1/example/getdate 会共用java后台的9090端口服务。
重新生成go和java的gRPC类,修改EchoImpl.java,增加getDate()方法实现:
@Override public void getDate(EchoServiceOuterClass.StringMessage request, StreamObserver<EchoServiceOuterClass.StringMessage> responseObserver) { EchoServiceOuterClass.StringMessage reply = EchoServiceOuterClass.StringMessage.newBuilder() .setValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); }
这种做法是,所有的接口都在一个proto文件里。如果接口很多会导致proto文件越来越大,并难以维护。
2、重新创建proto描述文件,java后台新增一个服务端口,如9091。同样运行protoc生成go和java相关的程序类。
需要手工修改的是gateway.go,加上新增的endpoint:
var ( echoEndpoint = flag.String("echo_endpoint", "localhost:9090", "echo_endpoint") dateEndpoint = flag.String("date_endpoint", "localhost:9091", "date_endpoint") ) ...... err = gw.RegisterDateServiceHandlerFromEndpoint(ctx, mux, *dateEndpoint, opts) if err != nil { return err }
grpc-gateway至此就可以通过8080对外提供服务,对内转发到多个后台服务端口。
代码请查看“阅读原文”。
以上是关于用grpc-gateway实现http和gRPC的服务转发的主要内容,如果未能解决你的问题,请参考以下文章