跟孙哥学java
服务器的坑
在原始的gRPC与consul进行服务注册时,会产生一个Http2Connection异常
打开日志
会出现异常,但不会对我们的开发产生影响
这是因为 consul会一直发送健康检查给grpc-server
站在 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 注意:
- 这个异常不会影响到我们目前程序的运行。
- 不能为了取消这个异常,而不使用 .check(Registration.RegCheck.tcp(address + ":" + port, 10))。
- gRPC+consul+springboot ---> springcloud 健康检查 springboot actuator进行整合 而不采用.check(Registration.RegCheck.tcp(address + ":" + port, 10))。 这样也就不会出现这个异常了。 :::
拦截器
- 开发一个拦截器
- 添加拦截器
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);
}
}
consul注册中心
服务端开发
- 引入依赖
怎么引入依赖,与我们其他框架的依赖相融合
- 通过maven仓库
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
启动服务
关闭服务:
这个服务就停了
如果没有启动tomcat,就不会进行健康检查,也不会注册到consul中
:::info 注意事项:
- 必须进行健康检查heartbeat:enabled: true
- 服务端做激情群
- 替换注册中心(consul zk nacos)
替换cloud 依赖jar
application.yml ip+port
:::
通过环境变量,启动多个实例
客户端开发
- 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>3.1.2</version>
</dependency>
- 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
- 通过@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
实现了负载均衡