码云地址:https://gitee.com/lpxs/lp-springcloud.git 有问题可以多沟通:136358344@qq.com。
GRPC简介
是谷歌开源的一个高性能的、通用的RPC框架。和其他RPC一样,客户端应用程序可以直接调用远程服务的方法,就好像调用本地方法一样。它隐藏了底层的实现细节,包括序列化(XML、JSON、二进制)、数据传输(TCP、HTTP、UDP)、反序列化等,开发人员只需要关自业务本身,而不需要关注RPC的技术细节。
与其他RPC框架一样,gRPC也遵循定义服务(类似于定义接口的思想)。gRPC客户端通过定义方法名、方法参数和返回类型来声明一个可以被远程调用的接口方法。由服务端实现客户端定义的接口方法,并运行一个gRPC服务来处理gPRC 客户端调用。注意,gRPC客户端和服务端共用一个接口方法。
springcloud与grpc
springcloud使用restful api进行内部通信,使用的是http1,而grpc使用http2来作为通信协议
至于http2的优势就不说了,对于很多电商服务内部调用链很复杂,使用grpc能有效的缩短通信时长。
springboot2集成net.devh.grpc
这里序列化框架使用protobuf
grpc-server
1、增加依赖
1<dependency> 2 <groupId>io.protostuff</groupId> 3 <artifactId>protostuff-core</artifactId> 4 <version>1.6.0</version> 5</dependency> 6 7<dependency> 8 <groupId>io.protostuff</groupId> 9 <artifactId>protostuff-runtime</artifactId> 10 <version>1.6.0</version> 11</dependency> 12<dependency> 13 <groupId>io.grpc</groupId> 14 <artifactId>grpc-all</artifactId> 15 <version>${grpc.version}</version> 16</dependency> 17<!-- Spring Boot 配置处理 --> 18<dependency> 19 <groupId>org.springframework.boot</groupId> 20 <artifactId>spring-boot-configuration-processor</artifactId> 21 <optional>true</optional> 22</dependency> 23 24<dependency> 25 <groupId>org.projectlombok</groupId> 26 <artifactId>lombok</artifactId> 27 <optional>true</optional> 28</dependency> 29<dependency> 30 <groupId>net.devh</groupId> 31 <artifactId>grpc-server-spring-boot-starter</artifactId> 32</dependency>
2、增加protobuf配置文件
在src/main/proto下增加配置文件hello.proto
1syntax = "proto3"; 2package com.demo; 3option java_package = "com.demo"; 4 5 6message HelloRequest { 7 string name = 1; 8} 9 10message HelloResponse { 11 string name = 1; 12 string status = 1; 13} 14 15// rpc 服务 16service HelloService { 17 rpc hello(HelloRequest) returns(HelloResponse) {} 18}
3、通过proto自动生成java代码并增加grpcservice
1@GrpcService 2public class HelloGrpcService extends HelloServiceGrpc.HelloServiceImplBase { 3 private static Logger logger = LoggerFactory.getLogger(UserProfileGrpcService.class); 4 5 @Override 6 public void hello(Hello.HelloRequest request, StreamObserver<Hello.HelloResponse> responseObserver) { 7 logger.info("hello start"); 8 final Hello.HelloResponse.Builder replyBuilder = Hello.HelloResponse.newBuilder().setName(request.getName()).setStatus("success"); 9 responseObserver.onNext(replyBuilder.build()); 10 responseObserver.onCompleted(); 11 } 12}
4、增加启动类
1@EnableDiscoveryClient 2public class GrpcServerApplication { 3 4 public static void main(String[] args) { 5 SpringApplication.run(GrpcServerApplication.class, args); 6 } 7 8}
5、增加yml配置
1server: 2 port: 8011 3grpc: 4 server: 5 port: 6000 6spring: 7 application: 8 name: hello-grpc-server
grpc-client
1、依赖包
1<dependency> 2 <groupId>io.protostuff</groupId> 3 <artifactId>protostuff-core</artifactId> 4 <version>1.6.0</version> 5</dependency> 6 7<dependency> 8 <groupId>io.protostuff</groupId> 9 <artifactId>protostuff-runtime</artifactId> 10 <version>1.6.0</version> 11</dependency> 12<dependency> 13 <groupId>io.grpc</groupId> 14 <artifactId>grpc-all</artifactId> 15 <version>${grpc.version}</version> 16</dependency> 17<!-- Spring Boot 配置处理 --> 18<dependency> 19 <groupId>org.springframework.boot</groupId> 20 <artifactId>spring-boot-configuration-processor</artifactId> 21 <optional>true</optional> 22</dependency> 23<dependency> 24 <groupId>org.springframework.boot</groupId> 25 <artifactId>spring-boot-starter-web</artifactId> 26 </dependency> 27<dependency> 28 <groupId>org.projectlombok</groupId> 29 <artifactId>lombok</artifactId> 30 <optional>true</optional> 31</dependency> 32<dependency> 33 <groupId>net.devh</groupId> 34 <artifactId>grpc-client-spring-boot-starter</artifactId> 35</dependency>
2、增加调用service
1@Service 2public class GrpcClientService { 3 4 @GrpcClient("hello-grpc-server") 5 private Channel serverChannel; 6 7 public String hello(String name) { 8 HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(serverChannel); 9 Hello.HelloRequest.Builder builder= Hello.HelloRequest.newBuilder(). 10 setName("xiaoli"); 11 Hello.HelloResponse response = stub.hello(builder.build()); 12 return "{'responseStatus':'"+response.getStatus()+"','result':[]}"; 13 14 } 15}
其中这里已经增加了负载均衡,grpc官网推荐的负载均衡方案就是在应用层管理http2长连接池。
增加controller
1@RestController 2@RequestMapping("/test") 3public class HelloController { 4 private static Logger logger = LoggerFactory.getLogger(HelloController.class); 5 @Autowired 6 private GrpcClientService grpcClientService; 7 8 @RequestMapping(value = "/hello", method = RequestMethod.GET) 9 public String hello() { 10 try { 11 String result = grpcClientService.hello(“aa”); 12 logger.debug(" respString : {}",result); 13 return result; 14 } catch (Throwable e) { 15 logger.error("hello error", e); 16 } 17 return null; 18 }
增加yml配置
1info: 2 version: 1.0 3 name: hello-grpc-client 4 5 6server: 7 port: 8012 8 9grpc: 10 client: 11 hello-grpc-server: 12 enableKeepAlive: true 13 keepAliveWithoutCalls: true 14 negotiationType: plaintext 15 16
启动服务可以访问http://localhost:8012/test/hello?进行测试
总结
这种方式集成每次都需要编写proto接口文件并自动生成代码,客户端和服务端都需要另外组装参数。
不过优势是,有详细的接口规范(protobuf),并且可以支持异构语言调用。
后面会介绍只有java语言调用,但是不用每次都编写proto文件的集成方式。