springcloud利用consul作为注册中心,并整合grpc完成远程服务调用。
首先创建一个公共父工程,工程直接用maven工程即可
父工程pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>springcloud_test01</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<!-- 子工程module,读者自行删除即可 -->
<modules>
<module>service1</module>
<module>service03</module>
<module>service2</module>
<module>grpc_common</module>
</modules>
<!-- 1 确定spring boot的版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<!--2 确定版本-->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<spring-cloud-release.version>Greenwich.RELEASE</spring-cloud-release.version>
</properties>
<!-- 3 锁定sprig cloud版本-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-release.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 4 确定spring cloud私有仓库-->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
创建子工程,工程建成maven项目,后面引入springboot、consul、grpc相关依赖等即可。
子工程1:grpc公共模块:grpc_common
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_test01</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>grpc_common</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<grpc.version>2.10.1.RELEASE</grpc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--grpc -->
<!-- <!– 客户端添加这个依赖 –>-->
<!-- <dependency>-->
<!-- <groupId>net.devh</groupId>-->
<!-- <artifactId>grpc-client-spring-boot-starter</artifactId>-->
<!-- <version>${grpc.version}</version>-->
<!-- </dependency>-->
<!-- <!– 服务端添加这个依赖 –>-->
<!-- <dependency>-->
<!-- <groupId>net.devh</groupId>-->
<!-- <artifactId>grpc-server-spring-boot-starter</artifactId>-->
<!-- <version>${grpc.version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.47.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.47.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--跳过test测试-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<!--添加protobuf-plugin插件-->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.9.1:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.23.0:exe:${os.detected.classifier}</pluginArtifact>
<!--默认值-->
<protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
<!--默认值-->
<!--<outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>-->
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<!--设置是否在生成java文件之前清空outputDirectory的文件,默认值为true,设置为false时也会覆盖同名文件-->
<clearOutputDirectory>false</clearOutputDirectory>
</configuration>
<executions>
<execution>
<!--在执行mvn compile的时候会执行以下操作-->
<phase>compile</phase>
<goals>
<!--生成OuterClass类-->
<goal>compile</goal>
<!--生成Grpc类-->
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<!--</pluginManagement>-->
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.0</version>
</extension>
</extensions>
</build>
</project>
编写proto文件
syntax = "proto3"; //#协议类型
package proto;
option java_multiple_files = true;
option java_package = "com.ccj.proto";
option java_outer_classname = "GrpcProto";
message GrpcRequest {
string parameter1 = 1;
string parameter2 = 2;
string parameter3 = 3;
}
message GrpcResponse {
string response1 = 1;
string response2 = 2;
}
service GrpcService {
rpc query(GrpcRequest) returns (GrpcResponse);
}
编译后会自动生成代码
新建子工程service1,此处微服务作为grpc service
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_test01</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-service1</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<grpc.version>2.10.1.RELEASE</grpc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- conslu -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- actuator 心跳检查 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 服务端添加这个依赖 -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
<version>${grpc.version}</version>
</dependency>
<!-- 引入grpc公共模块依赖 -->
<dependency>
<groupId>org.example</groupId>
<artifactId>grpc_common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
application.yaml
server:
port: 8080
spring:
application:
name: service1
cloud:
consul:
port: 8500
host: 127.0.0.1
discovery:
instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.ip-address}
prefer-ip-address: true
grpc:
server:
port: 9090
新建grpcTestService.class类,作为grpcService
package com.ccj.service1.grpcservice;
import com.ccj.proto.GrpcRequest;
import com.ccj.proto.GrpcResponse;
import com.ccj.proto.GrpcServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
@GrpcService
public class GrpcServiceTest extends GrpcServiceGrpc.GrpcServiceImplBase {
@Override
public void query(GrpcRequest grpcRequest, StreamObserver<GrpcResponse> observer) {
observer.onNext(GrpcResponse.newBuilder()
.setResponse1("response1 str")
.setResponse2("response2 str")
.build());
observer.onCompleted();
}
}
新建子工程service2,作为grpcClient微服务
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_test01</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service2</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<grpc.version>2.10.1.RELEASE</grpc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- conslu -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- actuator 心跳检查 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--grpc -->
<!-- 客户端添加这个依赖 -->
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>grpc_common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
</project>
application.yaml
server:
port: 8081
spring:
application:
name: service2
cloud:
consul:
port: 8500
host: 127.0.0.1
discovery:
instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.ip-address}
prefer-ip-address: true
grpc:
server:
port: 9093
client:
GLOBAL:
negotiation-type: plaintext
enable-keep-alive: true
keep-alive-without-calls: true
新建GrpcClient.class,作为grpc客户端
package com.ccj.grpcclient;
import com.ccj.proto.GrpcServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import lombok.Getter;
import org.springframework.cloud.client.ServiceInstance;
import java.io.Closeable;
import java.io.IOException;
public class GrpcClient implements Closeable {
private static final String GRPC_PORT = "gRPC.port";
static GrpcClient newInstance(ServiceInstance serviceInstance) {
String host = serviceInstance.getHost();
int port = Integer.parseInt(serviceInstance.getMetadata().get(GRPC_PORT));
return newInstance(host, port, serviceInstance.getInstanceId());
}
static GrpcClient newInstance(String host, int port, String instanceId) {
ManagedChannel managedChannel = ManagedChannelBuilder
.forTarget("static://" + host + ":" + port)
.usePlaintext()
.build();
return new GrpcClient(
instanceId,
host,
port,
managedChannel,
GrpcServiceGrpc.newBlockingStub(managedChannel));
}
@Getter
private final String instanceId;
@Getter
private final String host;
@Getter
private final int port;
private final ManagedChannel managedChannel;
private final GrpcServiceGrpc.GrpcServiceBlockingStub stub;
private GrpcClient(
String instanceId,
String host,
int port,
ManagedChannel managedChannel,
GrpcServiceGrpc.GrpcServiceBlockingStub stub) {
this.instanceId = instanceId;
this.host = host;
this.port = port;
this.managedChannel = managedChannel;
this.stub = stub;
}
public GrpcServiceGrpc.GrpcServiceBlockingStub stub() {
return stub;
}
@Override
public void close() throws IOException {
managedChannel.shutdown();
}
}
新建GrpcTest.class作为入口调用grpc客户端
package com.ccj.grpcclient;
import com.ccj.proto.GrpcRequest;
import com.ccj.proto.GrpcResponse;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.consul.serviceregistry.ConsulRegistration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Iterator;
import java.util.List;
@RestController
@RequestMapping("grpc")
public class GrpcTest {
private static final String SERVICE_NAME = "service1";
private final ConsulRegistration consulRegistration;
private final DiscoveryClient discoveryClient;
public GrpcTest(
ConsulRegistration consulRegistration,
DiscoveryClient discoveryClient) {
this.consulRegistration = consulRegistration;
this.discoveryClient = discoveryClient;
}
private List<ServiceInstance> discoveryInstance() {
List<ServiceInstance> instances = discoveryClient.getInstances(SERVICE_NAME);
String instanceId = consulRegistration.getInstanceId();
if(null != instances && instances.size()>0) {
for (Iterator<ServiceInstance> it = instances.iterator(); it.hasNext(); ) {
ServiceInstance serviceInstance = it.next();
if(serviceInstance.getInstanceId().equals(instanceId)) {
it.remove();
}
}
}
return instances;
}
@GetMapping
public void requestGrpc() {
List<ServiceInstance> serviceInstances = discoveryInstance();
if(null != serviceInstances && serviceInstances.size()>0) {
for(ServiceInstance instance : serviceInstances) {
GrpcClient grpcClient = GrpcClient.newInstance(instance);
GrpcResponse respone = grpcClient.stub().query(
GrpcRequest.newBuilder()
.setParameter1("param1")
.setParameter2("param2")
.setParameter3("param3")
.build());
System.out.println("respone1: " + respone.getResponse1() + "respone2: " + respone.getResponse2());
}
}
}
}
调用接口即可跨服务调用。