Java-gRPC-Consul整合
一、整合consul
工程搭建
- 使用springboot自带的consul-starter
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
- 在工程配置目录下创建bootstrap.yml
#这里是自定义的consul配置
consul:
cluster: dc1
index: 2
#spring的
spring:
application:
name: hall #项目名or服务名or应用名
profiles:
active: zwb #启用哪个配置文件
cloud:
consul:
host: 127.0.0.1 #consul地址
port: 2000
discovery:
tags: ${consul.cluster}, ${consul.index} #一些自定义的tag
metadata: #一些自定义的meta
cluster: ${consul.cluster}
index: ${consul.index}
service-name: ${spring.application.name} #服务名
prefer-ip-address: true #表示注册时使用ip而不是hostname
instance-id: ${consul.cluster}:${spring.application.name}:${consul.index} #实例id
register: true #配置服务注册
deregister: true #服务停止时取消注册
health-check-critical-timeout: 30s #健康检查失败多长时间取消注册
config:
enabled: true # 启用配置中心
prefix: config #读取consul配置中心的哪个文件夹
format: YAML # 表示consul上面文件的格式 有四种 YAML PROPERTIES KEY-VALUE FILES
data-key: zwb #表示consul上面的KEY值(或者说文件的名字) 默认是data
watch:
delay: 60000 #watch间隔
注意:
这里springcould-consul默认的watch配置文件的时间间隔是1s,我改成的60s
springcould-consul默认的拉取更新健康服务列表的间隔是30s,要改自行修改配置
- 启动类上添加@EnableDiscoveryClient注解
工程到这里就算搭建完毕了
consul上的配置文件路径
更正一下:应该是对应spring.application.name
二、整合grpc
这里打算使用grpc-spring-boot-starter , 虽然不是springboot官方的,但是使用还是比较方便
父工程依赖管理
<properties>
<protobuf.version>3.5.0</protobuf.version>
<grpc.version>1.23.0</grpc.version>
<guava.version>20.0</guava.version>
</properties>
<dependencyManagement>
<dependencies>
<!--grpc-spring相关-->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>
<!--grpc包-->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>${grpc.version}</version>
</dependency>
<!--proto包-->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<!--guava包-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
这里注意:在比较新的guava版本里面已经移除掉了com.google.guava这个包,但是不知道在哪个jar依赖了这个东西,就会报找不到这个jar包的问题。
解决办法:这里选择grpc 的版本为1.23.0,guava的版本为20.0是没有问题的
message工程
导入依赖
msg工程需要导入io.grpc:grpc-all包,build下需要加入编译proto文件的插件。
<dependencies>
<!--protobuf-->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
<!--grpc-->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</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.6.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.6.0:exe:${os.detected.classifier}</pluginArtifact>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<clearOutputDirectory>false</clearOutputDirectory>
</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>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
proto格式
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.demo.lib"; //包名
option java_outer_classname = "HelloWorld"; //输出类名
//接口请求入参
message HelloRequest{
string request = 1;
}
//接口返回出参
message HelloResponse{
string response = 1;
}
//定义接口
service HelloService{
//一个简单的rpc
rpc HelloWorld(HelloRequest) returns (HelloResponse){}
//一个服务器端流式rpc
rpc HelloWorldServerStream(HelloRequest) returns (stream HelloResponse){}
//一个客户端流式rpc
rpc HelloWorldClientStream(stream HelloRequest) returns (HelloResponse){}
//一个客户端和服务器端双向流式rpc
rpc HelloWorldClientAndServerStream(stream HelloRequest) returns (stream HelloResponse){}
}
请注意,这里的proto协议使用的是proto3
相比之前的文件增加了如下部分,这个service 块是用于定义接口
//定义接口
service HelloService{
//一个简单的rpc
rpc HelloWorld(HelloRequest) returns (HelloResponse){}
//一个服务器端流式rpc
rpc HelloWorldServerStream(HelloRequest) returns (stream HelloResponse){}
//一个客户端流式rpc
rpc HelloWorldClientStream(stream HelloRequest) returns (HelloResponse){}
//一个客户端和服务器端双向流式rpc
rpc HelloWorldClientAndServerStream(stream HelloRequest) returns (stream HelloResponse){}
}
生成java文件
因为我们已经使用了maven插件,所以不需要像之前那样手动使用命令生成
只需要点击install就可以自动生成代码
服务提供者工程
添加依赖
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
</dependency>
如果既是服务提供者,又是调用者,使用下面的依赖
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
</dependency>
配置yml
在yml里面添加配置
grpc:
server:
port: 9999 #rpc端口
编写service类
这个类就是对应proto的HelloService实现
package com.demo;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
import com.demo.lib.HelloServiceGrpc;
import com.demo.lib.HelloWorld;
@GrpcService //标记这是一个rpc服务
public class HelloWorldService extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void helloWorld(HelloWorld.HelloRequest request, StreamObserver<HelloWorld.HelloResponse> responseObserver) {
//构建一个返回消息并发送
HelloWorld.HelloResponse.Builder builder = HelloWorld.HelloResponse.newBuilder();
builder.setResponse("1");
responseObserver.onNext(builder.build());
responseObserver.onCompleted();
}
}
服务调用端工程
添加依赖
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
</dependency>
配置yml
grpc:
client:
hello-world-server: #对应的服务名称
enableKeepAlive: true #获取是否启用keepAlive。
keepAliveWithoutCalls: true #获取当连接上没有未完成的RPC时是否执行keepAlive。
negotiationType: plaintext #获取要在连接上使用的协仪类型。
注意:这里的negotiationType,如果服务器调用者双方都没有使用SL协议,这里就必须选择plaintext类型
编写service类
package com.demo.service;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service;
import proto.HelloServiceGrpc;
import proto.HelloWorld;
@Service
public class UserClientService {
@GrpcClient("hello-world-server") //微服务名称,就是yml里面的spring.application.name
private HelloServiceGrpc.HelloServiceBlockingStub stub; //对应HelloService
public String invokeHelloWorld() {
//构建请求消息
HelloWorld.HelloRequest build = HelloWorld.HelloRequest.newBuilder().setRequest("1").build();
//调用方法
HelloWorld.HelloResponse helloResponse = stub.helloWorld(build);
return helloResponse.getResponse();
}
}
以上就是java工程的整合
三、调用go工程
java工程和go工程都采用微服务方式注册到consul上
注意:服务提供方的tags里面需要带上gRPC.port=9999这个标记,用于表明tcp的端口,这里spring-grpc会帮我们自动生成,go工程就需要手动设置
然后go服务调用java服务也是需要通过gRPC.port来获取tpc端口进行调用