赞
踩
在微服务开发中,服务间的调用一般有两种方式:Feign、RestTemplate,但在实际使用过程中,尤其是Feign,存在各种限制及局限性,如:HTTP请求方式、返回类型等限制,有时会让你觉得那那都别扭。在微服务项目中,服务间的调用,是非常普遍频繁的,其性能也不是很理想。
为了解决上述问题,进行反复对比,最终服务间的调用方式采取了gRPC方式,其显著特点就是性能之高(通信采用Netty),通过proto文件定义的接口也是非常清晰而又灵活。本文主要就gRPC在Spring Cloud项目中的使用进行说明实战。
关于gRPC相关基础知识可以参考上一篇文章gRPC的使用。
看过上一篇文章gRPC的使用的话,你就清楚如果直接使用gRPC,显得有些吃力,因此借助一些开源的框架变得尤为必要。gRPC在Spring Cloud中使用开源项目grpc-spring-boot-starter,便于在Spring Cloud项目中开发应用。
(grpc-spring-boot-starter虽然存在一些问题,但集成Sping Cloud项目已经相当高了,还是不错之选。如果你有时间,精力,还是又必要在源码基础上进行开发。)
下面以实际demo来说明grpc-spring-boot-starter的应用。
(看了上面这些特点,就知道为啥选择这个开源项目了)
基于protobuf来声明数据模型和RPC接口服务。
创建一个公共字模块项目spring-boot-grpc-common,用于定义存放gRPC接口(proto),便于gRPC服务端和客户端使用。以helloworld.proto(src\main\proto\helloworld.proto)为例:
- syntax = "proto3";
-
- option java_multiple_files = true;
- option java_package = "com.xcbeyond.springboot.grpc.lib";
- option java_outer_classname = "HelloWorldProto";
-
- // The greeting service definition.
- service Simple {
- // Sends a greeting
- rpc SayHello (HelloRequest) returns (HelloReply) {
- }
- }
-
- // The request message containing the user's name.
- message HelloRequest {
- string name = 1;
- }
-
- // The response message containing the greetings
- message HelloReply {
- string message = 1;
- }
根据proto的命令可以转换成对应的语言的代码,生成java代码,也可以借助maven插件,在编译时自动生成。这里通过mavent插件,可以在pom.xml中增加如下依赖:
<build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>${os.plugin.version}</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>${protobuf.plugin.version}</version> <configuration> <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
在maven中进行package编译打包,将会在target中看见根据proto自动生成的Java类。(编译过程中可能会报错,此时可以忽略)
maven依赖:
- <dependency>
- <groupId>net.devh</groupId>
- <artifactId>grpc-server-spring-boot-starter</artifactId>
- <version>2.2.1.RELEASE</version>
- </dependency>
实现 gRPC server 的业务逻辑,使用注解@GrpcService定义gRPC服务端,如下所示:
- package com.xcbeyond.springboot.grpc.server.service;
-
- import com.xcbeyond.springboot.grpc.lib.HelloReply;
- import com.xcbeyond.springboot.grpc.lib.HelloRequest;
- import com.xcbeyond.springboot.grpc.lib.SimpleGrpc;
- import io.grpc.stub.StreamObserver;
- import net.devh.boot.grpc.server.service.GrpcService;
-
- /**
- * @Auther: xcbeyond
- * @Date: 2019/3/6 18:15
- */
- @GrpcService
- public class GrpcServerService extends SimpleGrpc.SimpleImplBase {
- @Override
- public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
- System.out.println("GrpcServerService...");
- HelloReply reply = HelloReply.newBuilder().setMessage("Hello ==> " + request.getName()).build();
- responseObserver.onNext(reply);
- responseObserver.onCompleted();
- }
- }
application.yml配置:
gRPC 的 host 跟 port ,默认的监听的 host 是 0.0.0.0,默认的 port 是 9090,配置为0将会自动分配未使用的端口。
- grpc:
- server:
- port: 0
maven依赖:
- <dependency>
- <groupId>net.devh</groupId>
- <artifactId>grpc-client-spring-boot-starter</artifactId>
- <version>2.2.1.RELEASE</version>
- </dependency>
使用注解@GrpcClient来调用服务端接口,通过
HelloReply response = simpleBlockingStub.sayHello(HelloRequest.newBuilder().setName(name).build());
直接向服务端发起请求,和调用本地接口一样。
- package com.xcbeyond.springboot.grpc.client.service;
-
- import com.xcbeyond.springboot.grpc.lib.HelloReply;
- import com.xcbeyond.springboot.grpc.lib.HelloRequest;
- import com.xcbeyond.springboot.grpc.lib.SimpleGrpc.SimpleBlockingStub;
- import io.grpc.StatusRuntimeException;
- import net.devh.boot.grpc.client.inject.GrpcClient;
- import org.springframework.stereotype.Service;
-
- /**
- * @Auther: xcbeyond
- * @Date: 2019/3/7 09:10
- */
- @Service
- public class GrpcClientService {
-
- @GrpcClient("spring-boot-grpc-server")
- private SimpleBlockingStub simpleBlockingStub;
-
- public String sendMessage(String name) {
- try {
- HelloReply response = simpleBlockingStub.sayHello(HelloRequest.newBuilder().setName(name).build());
- return response.getMessage();
- } catch (final StatusRuntimeException e) {
- return "FAILED with " + e.getStatus().getCode();
- }
- }
- }
application.yml配置:
spring-boot-grpc-server,即:服务端应用名,结合spring cloud Eureka注册中心,通过服务名将会找到服务端的ip,进行通信,实际上是netty通信。
- grpc:
- client:
- spring-boot-grpc-server:
- enableKeepAlive: true
- keepAliveWithoutCalls: true
- negotiationType: plaintext
本demo完整代码请参考https://github.com/xcbeyond/spring-boot-grpc.git
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。