资源
关键词
高性能
,开源
,双向流式
,多开发语言支持
,Apache 2.0
示例
ProtoBuffer定义
protobuf-maven-plugin编译的默认路径
syntax = "proto3";
option java_multiple_files = true;
package com.wjg.grpc.helloworld;
message Person {
string first_name = 1;
string last_name = 2;
}
message Greeting {
string message = 1;
}
service HelloWorldService {
rpc sayHello (Person) returns (Greeting);
}
使用protobuf-maven-plugin生成stub
源:https://github.com/xolstice/protobuf-maven-plugin
grpc-spring-boot-starter
: @GRpcService使应用内嵌一个gRPC server。
os-maven-plugin
:生成平台依赖的工程属性,ProtocolBuffer编译器依赖这些信息。即是说,protobuf-maven-plugin需要获取当前平台使用的正确的编译器。
sprint-boot-maven-plugin
:可以构建独立可运行的jar。
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>com.codenotfound</groupId>
<artifactId>grpc-java-hello-world</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>grpc-java-hello-world</name>
<description>gRPC Java Example</description>
<url>https://codenotfound.com/grpc-java-example.html</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<grpc-spring-boot-starter.version>3.0.0</grpc-spring-boot-starter.version>
<os-maven-plugin.version>1.6.1</os-maven-plugin.version>
<protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.github.lognet</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>${grpc-spring-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os-maven-plugin.version}</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${protobuf-maven-plugin.version}</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.16.1:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
mvn compile生成的类
server代码示例
GRpcService
:自动配置gRPC服务在端口6565
上发布。可以使用grpc.port=xxxx
进行修改发布端口。
package com.wjg.wjggrpcstart.service;
import com.wjg.grpc.helloworld.Greeting;
import com.wjg.grpc.helloworld.HelloWorldServiceGrpc;
import com.wjg.grpc.helloworld.Person;
import io.grpc.stub.StreamObserver;
import org.lognet.springboot.grpc.GRpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* created by jingang.wu on 2019/8/26
*/
@GRpcService
public class HelloWorldServiceImpl
extends HelloWorldServiceGrpc.HelloWorldServiceImplBase {
private static final Logger LOGGER =
LoggerFactory.getLogger(HelloWorldServiceImpl.class);
@Override
public void sayHello(Person request,
StreamObserver<Greeting> responseObserver) {
LOGGER.info("server received {}", request);
String message = "Hello " + request.getFirstName() + " "
+ request.getLastName() + "!";
Greeting greeting =
Greeting.newBuilder().setMessage(message).build();
LOGGER.info("server responded {}", greeting);
// 使用onNext返回greeting,调用onCompleted告诉gRPC响应写入完成
responseObserver.onNext(greeting);
responseObserver.onCompleted();
}
}
client示例代码
调用gRPC服务,首先需要创建一个stub。stub的类型有:
- 同步stub,阻塞等待server响应
- 异步stub,响应异步返回
gRPC使用http/2传输消息。
MessageChannel
管理连接,隐藏了复杂性。建立:
一个应用使用一个channel,并在
service stubs
中共享。
package com.wjg.wjggrpcstart.service;
import com.wjg.grpc.helloworld.Greeting;
import com.wjg.grpc.helloworld.HelloWorldServiceGrpc;
import com.wjg.grpc.helloworld.Person;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* created by jingang.wu on 2019/8/26
*/
@Component
public class HelloWorldClient {
private static final Logger LOGGER =
LoggerFactory.getLogger(HelloWorldClient.class);
private HelloWorldServiceGrpc.HelloWorldServiceBlockingStub helloWorldServiceBlockingStub;
@PostConstruct
private void init() {
//gRPC默认使用TLS安全连接,需要配置安全组件,这里示例不使用
ManagedChannel managedChannel = ManagedChannelBuilder
.forAddress("localhost", 6565).usePlaintext().build();
// 这里使用同步调用
helloWorldServiceBlockingStub =
HelloWorldServiceGrpc.newBlockingStub(managedChannel);
//异步调用HelloWorldServiceGrpc.newFutureStub(managedChannel);
}
public String sayHello(String firstName, String lastName) {
Person person = Person.newBuilder().setFirstName(firstName)
.setLastName(lastName).build();
LOGGER.info("client sending {}", person);
Greeting greeting =
helloWorldServiceBlockingStub.sayHello(person);
LOGGER.info("client received {}", greeting);
return greeting.getMessage();
}
}
unit test
@RunWith(SpringRunner.class)
@SpringBootTest
public class WjgGrpcStartApplicationTests {
@Test
public void contextLoads() {
}
@Autowired
private HelloWorldClient helloWorldClient;
@Test
public void testSayHello() {
assert(helloWorldClient.sayHello("John", "Doe").equals("Hello John Doe!"));
}
}