RPC初体验之 gRPC Java 简单实例
关于RPC远程过程调用,分布式架构下不同服务之间调用越来越紧密,对调用效率,可靠性,可用性要求越来越高。RPC就是在此环境下应运而生的。需要结合服务注册中心一起使用。Eureka,Zookeeper,Consul,Etcd等等。客户端,服务端,RPC之间的通讯:一个服务自己可以是客户端同时也是服务端。最好采用TCP连接,传输层的TCP链接比应用层的HTTP链接更高效快速,远程过程调用的所有...
关于RPC远程过程调用,分布式架构下不同服务之间调用越来越紧密,对调用效率,可靠性,可用性要求越来越高。RPC就是在此环境下应运而生的。需要结合服务注册中心一起使用。Eureka,Zookeeper,Consul,Etcd等等。
- 客户端,服务端,RPC之间的通讯: 一个服务自己可以是客户端同时也是服务端。最好采用TCP连接,传输层的TCP链接比应用层的HTTP链接更高效快速,远程过程调用的所有数据都在这个连接里传输。
- 数据传输: 请求参数和响应数据都需要序列化成二进制数据在网络上传输,接收数据时反序列化。
- 服务地址: 结合服务注册中心。请求某个服务我需要知道该服务的地址URL,端口号,方法名等等。Web服务协议栈的RPC,就要提供一个endpoint URI。
服务调用流程,借用别人一张图:
1)服务消费方(client)调用以本地调用方式调用服务;
2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
3)client stub找到服务地址,并将消息发送到服务端;
4)server stub收到消息后进行解码;
5)server stub根据解码结果调用本地的服务;
6)本地服务执行并将结果返回给server stub;
7)server stub将返回结果打包成消息并发送至消费方;
8)client stub接收到消息,并进行解码;
9)服务消费方得到最终结果。
RPC的目标就是要2~8这些步骤都封装起来。
参考文章:
https://blog.csdn.net/u013521220/article/details/70157956
https://blog.csdn.net/KingCat666/article/details/78577079
一、gRPC Java 实例
官方文档:http://doc.oschina.net/grpc?t=58008
本实例GitHub地址:https://github.com/MistraR/grpc-java-mistra
gRPC 一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。
本文写个gRPC的小栗子。
gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如 JSON)。正如你将在下方例子里所看到的,你用 proto files 创建 gRPC 服务,用 protocol buffers 消息类型来定义方法参数和返回类型。本文使用“proto3”版本。
新建一个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>com.grpc</groupId>
<artifactId>mistra</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.9.1</grpc.version>
</properties>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.6.0</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</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.11.0:exe:${os.detected.classifier}</pluginArtifact>
</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>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
新建proto文件,注意包结构
helloworld.proto
注意java_package的值最好跟你等会要拷贝这些生成类存放的目录一致。
syntax = "proto3";
option java_multiple_files = true;
//生成java代码的package
option java_package = "com.grpc.mistra.generate";
//创建的javaBean的文件名
option java_outer_classname = "MistraProto";
// 可以生成rpc接口
//option java_generic_services = true;
package mistra;
//声明一个服务名称
service MistraService {
//请求参数MistraRequest 响应参数MistraResponse
rpc SayHello (MistraRequest) returns (MistraResponse);
}
//请求
message MistraRequest {
string name = 1;
}
//响应
message MistraResponse {
string message = 1;
}
这个时候就可以根据proto文件生成基本类了,maven install,然后就在target文件夹下看见生成的类:
把看到的这6个类都拷贝到主目录下。然后新建一个client类,新建一个server类。最后目录结构如下:
编写Client
package com.grpc.mistra.client;
import com.grpc.mistra.generate.MistraRequest;
import com.grpc.mistra.generate.MistraResponse;
import com.grpc.mistra.generate.MistraServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import java.util.concurrent.TimeUnit;
/**
* @Author: WangRui
* @Date: 2018/11/27
* Time: 14:46
* Description:
*/
public class MistraClient {
private final ManagedChannel channel;
private final MistraServiceGrpc.MistraServiceBlockingStub blockingStub;
public MistraClient(String host, int port) {
channel = ManagedChannelBuilder.forAddress(host, port)
.usePlaintext(true)
.build();
blockingStub = MistraServiceGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
public void greet(String name) {
MistraRequest request = MistraRequest.newBuilder().setName(name).build();
MistraResponse response = blockingStub.sayHello(request);
System.out.println(response.getMessage());
}
public static void main(String[] args) throws InterruptedException {
MistraClient client = new MistraClient("127.0.0.1", 8001);
System.out.println("-------------------客户端开始访问请求-------------------");
for (int i = 0; i < 10; i++) {
client.greet("你若想生存,绝处也能缝生: " + i);
}
}
}
server
package com.grpc.mistra.server;
import com.grpc.mistra.generate.MistraRequest;
import com.grpc.mistra.generate.MistraResponse;
import com.grpc.mistra.generate.MistraServiceGrpc;
import io.grpc.BindableService;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
/**
* @Author: WangRui
* @Date: 2018/11/27
* Time: 14:46
* Description:
*/
public class MistraServer {
private int port = 8001;
private Server server;
private void start() throws IOException {
server = ServerBuilder.forPort(port)
.addService((BindableService) new MistraHelloWorldImpl())
.build()
.start();
System.out.println("------------------- 服务端服务已开启,等待客户端访问 -------------------");
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.err.println("*** shutting down gRPC server since JVM is shutting down");
MistraServer.this.stop();
System.err.println("*** server shut down");
}
});
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
final MistraServer server = new MistraServer();
//启动服务
server.start();
//服务一直在线,不关闭
server.blockUntilShutdown();
}
// 定义一个实现服务接口的类
private class MistraHelloWorldImpl extends MistraServiceGrpc.MistraServiceImplBase {
@Override
public void sayHello(MistraRequest mistraRequest, StreamObserver<MistraResponse> responseObserver) {
// 具体其他丰富的业务实现代码
System.err.println("server:" + mistraRequest.getName());
MistraResponse reply = MistraResponse.newBuilder().setMessage(("响应信息: " + mistraRequest.getName())).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
运行server的main方法,启动服务。
运行client端访问服务。
更多推荐
所有评论(0)