gRPC 是由 Google 主导开发的 RPC 框架,使用 HTTP/2 协议并用 ProtoBuf 作为序列化工具。
gRPC官方对REST的声音是:
和REST一样遵循HTTP协议(明确的说是HTTP/2),但是gRPC提供了全双工流
和传统的REST不同的是gRPC使用了静态路径,从而提高性能
用一些格式化的错误码代替了HTTP的状态码更好的标示错误
背景
regist 是在微服务架构上再抽出的一层,用于服务注册,心跳机制,服务注销。
regist 和 微服务架构 之间使用的是 REST 协议进行通信,现需要改造成 gRPC
RPC 框架: gRPC
协议:HTTP/2
序列化工具: ProtoBuf
服务端: regist (golang)
客户端 :微服务架构(java)
一、服务端改造(golang)
1. protocal buffer安装
去官网下载 protoc 压缩包,解压后,将 protoc.exe放在 GOPATH\bin目录下面
2. 安装GoLang protoc 插件
gRPC-go可以通过golang 的get命令直接安装,非常方便。go get -a github.com/golang/protobuf/protoc-gen-go
3. 定义register.proto文件
syntax = "proto3";
package proto;
service Regist { rpc Register (ResponseService) returns (RegisterReply) {} rpc Deregister (ResponseService) returns (DeregisterReply) {}
}
message RegisterReply { string message = 1;
}
message DeregisterReply { string message = 1;
}
message ResponseService { string id = 1; string name = 2; string version = 3; string address = 4;
int32 port = 5; map<string, string> metadata = 6;
}syntax = "proto3",声明protobuf版本为3,默认为2。定义了一个服务 Regist,其中有两个API
Register和Register。定义3个message为接受和返回的参数。
4. 生成 register.pb.go 文件
在register.proto文件所在根目录下,执行:protoc --go_out=plugins=grpc:. register.proto
则会在同目录下生成对应的 register.pb.go 文件,相应的服务器端和客户端的GoLang代码。生成的代码中包含了客户端能够进行RPC的方法以及服务器端需要进行实现的接口。
5.服务端代码改造
register.pb.go文件中提供的服务接口
type RegistClient interface {
Register(ctx context.Context, in *ResponseService, opts ...grpc.CallOption) (*RegisterReply, error)
Deregister(ctx context.Context, in *ResponseService, opts ...grpc.CallOption) (*DeregisterReply, error)
}服务端代码实现上面的接口
func (s *server) Register(ctx context.Context, in *pb.ResponseService) (*pb.RegisterReply, error) { // 定义注册的服务,组装 gRPC 传过来的参数
service := &rp.Service{
Name: in.GetName(),
Version: in.GetVersion(),
Metadata: in.GetMetadata(),
NodeName: nodeName,
Nodes: []*rp.Node{
&rp.Node{
ID: in.GetId(),
Address: in.GetAddress(),
Port: int(in.GetPort()),
},
},
Endpoints: []*rp.Endpoint{
&rp.Endpoint{
Name: in.GetName(),
Request: &rp.Value{},
Response: &rp.Value{},
Metadata: in.GetMetadata(),
},
},
} // 调用 consul 注册接口
return &pb.RegisterReply{}, registry.Register(service, rp.RegisterTTL(time.Duration(ttl)*time.Second))
}二、客户端改造(java)
1. pom.xml文件中添加 maven 依赖
<dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> <version>1.7.0</version></dependency><dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <version>1.7.0</version></dependency><dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <version>1.7.0</version></dependency>
2. pom.xml文件中 配置protobuf maven插件
<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.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.4.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.7.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>3. 定义regist.proto文件
syntax = "proto3";
package proto;
option java_multiple_files = true;
option java_package = "com.fiberhome.smartms.grpc";
option java_outer_classname = "RegistProto";
service Regist { rpc Register (ResponseService) returns (RegisterReply) {} rpc Deregister (ResponseService) returns (DeregisterReply) {}
}
message RegisterReply { string message = 1;
}
message DeregisterReply { string message = 1;
}
message ResponseService { string id = 1; string name = 2; string version = 3; string address = 4;
int32 port = 5; map<string, string> metadata = 6;
}4. 自动生成java接口代码
在pom.xml文件根目录中,执行mvn compile(也可试下mvn install),根据.proto文件自动生成一系列的接口文件。
- 若生成不成功,多试几次
5.客户端代码改造
public class ServiceRegistryGrpc implements ServiceRegistry<Registration> { private static final Logger logger = Logger.getLogger(ServiceRegistryGrpc.class.getName()); private final ManagedChannel channel; private final RegistGrpc.RegistBlockingStub blockingStub;
public ServiceRegistryGrpc(String host, int port) {
channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true).build();
blockingStub = RegistGrpc.newBlockingStub(channel);
} public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
} @Override
public void register(Registration reg) {
Service service = reg.getService();
ServiceRegistryGrpc client = new ServiceRegistryGrpc("mos", 9999);
ResponseService request = ResponseService.newBuilder().setId(service.getId()).setName(service.getName())
.setVersion(service.getVersion()).setAddress(service.getAddress()).setPort(service.getPort()).build();
RegisterReply response; try {
response = blockingStub.register(request);
} catch (StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); return;
}
logger.info("Registering service success ");
}
}public ServiceRegistryGrpc(String host, int port) {},这个函数是构造客户端 连接 服务response = blockingStub.register(request);,调用服务接口
三、验证
启动服务端
服务端
启动客户端
客户端
数据通信成功
服务端获取客户端 传来的数据
consul注册成功
attachment服务
作者:angeChen
链接:https://www.jianshu.com/p/4e9935b3f721
共同学习,写下你的评论
评论加载中...
作者其他优质文章




