gRPC之gRPC,consul整合springboot

320 阅读3分钟

跟孙哥学java

孙哥主页

服务器的坑

在原始的gRPC与consul进行服务注册时,会产生一个Http2Connection异常

打开日志 image.png 会出现异常,但不会对我们的开发产生影响 这是因为 consul会一直发送健康检查给grpc-server image.png 站在 grpc-server角度:check-RegCheck请求
这个check-RegCheck请求 跟 grpc-client请求完全一样 基于HTPP2协议,而Consul不支持Http2协议,所以 报错异常: DEBUG i.g.n.s.i.n.h.codec.http2.Http2ConnectionHandler - [id: 0x9758112f, L:/127.0.0.1:6649 ! R:/127.0.0.1:59386] Sending GOAWAY failed: lastStreamId '2147483647', errorCode '2', debugData '你的主机中的软件中止了一个已建立的连接。'. Forcing shutdown of the connection. 但consul无法建立Http2协议的连接

:::info 注意:

  1. 这个异常不会影响到我们目前程序的运行。
  2. 不能为了取消这个异常,而不使用 .check(Registration.RegCheck.tcp(address + ":" + port, 10))。
  3. gRPC+consul+springboot ---> springcloud 健康检查 springboot actuator进行整合 而不采用.check(Registration.RegCheck.tcp(address + ":" + port, 10))。 这样也就不会出现这个异常了。 :::

拦截器

  1. 开发一个拦截器

image.png

  1. 添加拦截器

image.png springboot中添加拦截器

@Configuration
public class CustomBootInterceptorConfiguration {
   //@Bean 只能让spring认识这个Bean,但是Spring容器不会把他当成grpc的拦截器
   //@GrpcGlobalClientInterceptor 可以讲这个对象设置到 ManagedChannel中.intercept(new CustomClientInterceptor())
   @GrpcGlobalClientInterceptor
   public CustomBootInterceptor customBootInterceptor(){
      return new CustomBootInterceptor();
   }
}

或者直接在拦截器类上加注解@GrpcGlobalClientInterceptor

@GrpcGlobalClientInterceptor
public class CustomBootInterceptor implements ClientInterceptor {
   @Override
   public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor, CallOptions callOptions, Channel channel) {
      System.out.println("客户端拦截器.....");
      return channel.newCall(methodDescriptor,callOptions);
   }
}

image.png

consul注册中心

服务端开发

  1. 引入依赖

怎么引入依赖,与我们其他框架的依赖相融合

  1. 通过maven仓库

image.png spring-cloud-starter-consul-discovery 3.1.2 使用spring boot的版本最低 2.6.11 最高 3.1.5

1. 服务器端开发 【nacos,zookeeper】
   1. 依赖 
      <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            <version>3.1.2</version>
       </dependency>
       
       <!--健康检查  http协议 -->
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator</artifactId>
        </dependency>

main: web-application-type: none 取消这个配置 这是因为 我们引入consul做注册中心,要用到健康检查,健康检查和服务注册都是基于HTTP协议

application.yml

spring:
  application:
    name: boot-server
  cloud:
    consul:
      discovery:
        register: true
        hostname: 127.0.0.1
        port: 8500
        heartbeat:
          enabled: true

#  main:
#    web-application-type: none
grpc:
  server:
    port: 9000

image.png image.png

启动服务 image.png image.png

关闭服务: 这个服务就停了 image.png 如果没有启动tomcat,就不会进行健康检查,也不会注册到consul中

:::info 注意事项:

  1. 必须进行健康检查heartbeat:enabled: true
  2. 服务端做激情群
  3. 替换注册中心(consul zk nacos)

替换cloud 依赖jar application.yml ip+port ::: image.png 通过环境变量,启动多个实例 image.png

客户端开发

  1. 引入依赖
  <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        <version>3.1.2</version>
 </dependency>
  1. application.yml


spring:
  application:
    name: boot-client

#grpc:
#  client:
#    grpc-server:
#      address: 'static://127.0.0.1:9000'
#      negotiation-type: plaintext

server:
  port: 8888

# 'discovery:[//]/<service-name>'; but was 'discovery://boot-server'
grpc:
  client:
    cloud-grpc-server:
      address: 'discovery:///boot-server'
      negotiation-type: plaintext
#      TCP相关设置
      enable-keep-alive: true
      keep-alive-without-calls: true
  1. 通过@GrpcClient("cloud-grpc-server") 注入
@RestController
public class TestController {

   @GrpcClient("cloud-grpc-server")
   private HelloServerGrpc.HelloServerBlockingStub helloServerBlockingStub;

   @RequestMapping("/test1")
   public String test1(String name){
      System.out.println("name="+name);
      HelloProto.HelloResponse helloResponse = helloServerBlockingStub.hello(HelloProto.HelloRequest.newBuilder().setName(name).build());
      return helloResponse.getResult();
   }
}

访问 http://localhost:8888/test1?name=xiaohei2 image.png image.png image.png实现了负载均衡