基于java的Grpc实例创建及基于Nginx的Grpc服务端负载均衡
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了基于java的Grpc实例创建及基于Nginx的Grpc服务端负载均衡,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7376字,纯文字阅读大概需要11分钟。
内容图文
Grpc是googe开发的,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。新公司的项目服务之间的调用使用的Grpc来实现服务间的调用,这边一开始接到的工作内容是基于Nginx实现Grpc服务端的负载均衡。Nginx的1.13及以上版本是支持grpc的反向代理和负载均衡的。但是公司的nginx服务器的版本是1.10的,所以没办法直接使用grpc的代理。只能使用更底层的tcp层的负载均衡。最终服务跑起来是感觉挺简单的,但是nginx的基础太差,所以过程有点曲折。还是记录下吧。
文章分两部分,一个是创建简单的Grpc客户端和服务端的例子(其实也是用的网上的demo,这边就贴一下源码,讲下更细的实现步骤),然后对比下Nginx的Grpc负载均衡和Tcp的负载均衡。
一、Java创建Grpc客户端和服务端的例子(创建的配置信息相关的代码基本网上博客的,忘记是哪篇文章了,所以暂时没法给出转载链接。)
1、在开发工具ide上创建一个maven project。打包方式选择jar。
2、在POM.xml上增加grpc相关的依赖及maven的打包插件
< dependencies > < dependency > < groupId >io.grpc</groupId><artifactId>grpc-netty</artifactId><version>1.17.1</version></dependency><dependency><groupId>io.grpc</groupId><artifactId>grpc-protobuf</artifactId><version>1.17.1</version></dependency><dependency><groupId>io.grpc</groupId><artifactId>grpc-stub</artifactId><version>1.17.1</version></dependency></dependencies><build><extensions><extension><groupId>kr.motd.maven</groupId><artifactId>os-maven-plugin</artifactId><version>1.4.1.Final</version></extension></extensions><plugins><plugin><groupId>org.xolstice.maven.plugins</groupId><artifactId>protobuf-maven-plugin</artifactId><version>0.5.0</version><configuration><protocArtifact>com.google.protobuf:protoc:3.0.0:exe:${os.detected.classifier}</protocArtifact><pluginId>grpc-java</pluginId><pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.0:exe:${os.detected.classifier}</pluginArtifact></configuration><executions><execution><goals><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build>
3、在项目下的路径src/main下面创建proto文件夹,并在里面创建一个hello.proto文件。具体如下截图。
4、在hello.proto文件上输入,相应的配置信息,用来映射生成java代码。里面的内容就是生成一个MyRPC的服务提供一个sayHi的接口,接口需要传递一个request类的实例,该request实例只有一个name的字段。然后进行相应的业务代码处理之后,返回一个response类的实例,也是只有一个name的字段。
如果进行到这边,看到第2步添加依赖上面的 <execution>标签可能报错,先暂时不要管他。直接进行第5步。
syntax = "proto3";
option java_package = "com.qidai.proto";
option java_outer_classname = "MyThing";
message Request {
string name = 1;
}
message Response {
string name = 2;
}
service MyRPC {
rpc sayHi(Request) returns(Response);
}
5、运行项目,右击项目Run as -->maven build....->protobuf:compile以及protobuf:compile-custom,这样就编译生成了相应的代码了。不过存放的路径不对,需要自己拷贝到相应的项目目录下。
6、grpc的客户端和服务端代码需要自己编写。不过这一块的demo已经很全了。c+v然后改成自己的自己需要的就行了。
服务端demo:
package server; import com.qidai.proto.MyRPCGrpc; import com.qidai.proto.MyThing; import io.grpc.ServerBuilder; import io.grpc.stub.StreamObserver; import service.RequestImpl; import java.io.IOException; public class Server { private static final int PORT = 2222; privatefinal io.grpc.Server server; public Server() throws IOException { //这个部分启动serverthis.server = ServerBuilder.forPort(PORT) .addService(new RequestImpl()) .build() .start(); System.out.println("Server1 Started ..."); } privatevoid stop() { if (server != null) { server.shutdown(); } } privatevoid blockUntilShutdown() throws InterruptedException { if (server != null) { server.awaitTermination(); } } publicstaticvoid main(String[] args) throws IOException, InterruptedException { Server server = new Server(); //block Server防止关闭 server.blockUntilShutdown(); } }
客户端demo
package client; import com.qidai.proto.MyRPCGrpc; import com.qidai.proto.MyRPCGrpc.MyRPCBlockingStub; import com.qidai.proto.MyThing; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.concurrent.TimeUnit; public class Client { private final ManagedChannelBuilder<?> managedChannelBuilder; privatefinal MyRPCBlockingStub blockingStub; privatefinal ManagedChannel channel; public Client(String name, int port) { managedChannelBuilder = ManagedChannelBuilder.forAddress(name, port); channel = managedChannelBuilder.usePlaintext().build(); blockingStub = MyRPCGrpc.newBlockingStub(channel); } publicvoid shutdown() throws InterruptedException { channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); } publicvoid sayHi(String name){ MyThing.Request request = MyThing.Request.newBuilder().setName(name).build(); MyThing.Response response = blockingStub.sayHi(request); System.out.println(response.getName()); } publicstaticvoid main(String[] args) throws Exception{ Client client = new Client("localhost", 5005); for (int i = 0; i < 10; i++) { Thread.sleep(1000); //进行rpc调用的真正逻辑 client.sayHi("Hello Server1111 ->5005 " + i); } client.shutdown(); Client client2 = new Client("localhost", 5005); for (int i = 0; i < 10; i++) { Thread.sleep(1000); //进行rpc调用的真正逻辑 client2.sayHi("Hello Server2222 ->5005 " + i); } client2.shutdown(); } }
7、接下来就是才是比较关键的一步,实现自己的grpc服务端的业务代码。主要的关键步骤就是继承grpc自动映射出来的抽象类。是不是很熟悉,没错就是proto文件里面配置的服务。然后重写服务里面配置的方法即可。最后放心大胆的去根据传递的request参数去做相关的业务逻辑的处理。并用response封装需要返回的接口。(此处的request与response均是grcp根据proto配置文件映射出来的相关实体类。)
package service; import com.qidai.proto.MyRPCGrpc.MyRPCImplBase; import com.qidai.proto.MyThing.Response; public class RequestImpl extends MyRPCImplBase { @Override publicvoid sayHi(com.qidai.proto.MyThing.Request request, io.grpc.stub.StreamObserver<com.qidai.proto.MyThing.Response> responseObserver) { //proto文件上定义的response返回信息 Response response; System.out.println("Request>>>say::" + request.getName()); //AccountQryResponse response = QryAccountProto.AccountQryResponse.newBuilder().setRc(1).setAmount(666).build(); response = Response.newBuilder().setName("Response11111>>>say:::hello_client"+request.getName()).build(); responseObserver.onNext(response); responseObserver.onCompleted(); } }
二、Grpc服务基于nginx(1.12.2)实现负载均衡。下面直接贴nginx相关的配置,服务端和客户端的代码改动都很小。只需调整ip和port的值即可。其他的不需要改动。
TCP层负载均衡配置
stream { log_format proxy ‘$remote_addr [$time_local] ‘ ‘$protocol $status $bytes_sent $bytes_received ‘ ‘$session_time "$upstream_addr" ‘ ‘"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"‘; include ./conf.d/*.tcpstream; upstream grpc { server 127.0.0.1:2223; server 127.0.0.1:2222; } server { error_log logs/device5001_error.log; access_log logs/device5001_access.log proxy; listen 5005; proxy_pass grpc; } }
grpc的负载均衡配置(grpc的支持在nginx1.13之后才有,所以这里是1.17.0)
http { include mime.types; default_type application/octet-stream; log_format main ‘$remote_addr - $remote_user [$time_local] "$request" ‘ ‘$status $body_bytes_sent "$http_referer" ‘ ‘"$http_user_agent" "$http_x_forwarded_for"‘; access_log logs/access.log main; sendfile on; keepalive_timeout 65; gzip on; upstream grpcservers { server 127.0.0.1:2222; server 127.0.0.1:2223; } server { listen 8080 http2; server_name localhost; location / { grpc_pass grpc://grpcservers; } } }
最后分别启动nginx1.12.2和nginx1.17.0,并在ide上启动服务端和客户端,更改相应的客户端端口。就可以看到控制台打印不同的信息了。tcp和grcp的负载均衡的效果是不一样的。这也是我客户端new 了一个client,然后又new 了一个client2的原因。比较懒,效果图就不贴了。
原文:https://www.cnblogs.com/8593l/p/11078061.html
内容总结
以上是互联网集市为您收集整理的基于java的Grpc实例创建及基于Nginx的Grpc服务端负载均衡全部内容,希望文章能够帮你解决基于java的Grpc实例创建及基于Nginx的Grpc服务端负载均衡所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。