当前位置:网站首页>玩转gRPC—不同编程语言间通信
玩转gRPC—不同编程语言间通信
2022-07-01 13:37:00 【Barry Yan】
1 简介gRPC在不同语言间是如何连接的

2 安装Protoc buffer
下载链接:https://github.com/protocolbuffers/protobuf/releases
Windows下建议直接下载可执行文件:
下载完成后放到指定目录,配置环境变量:
验证:
如果出现如下异常:
解决方式:
把protoc.exe拷贝到C:\Windows\System32
3 Go使用gRPC进行Go程序之间的通信
项目结构:
下载依赖:
go get google.golang.org/protobuf/runtime/[email protected]
go get google.golang.org/grpc
go get google.golang.org/protobuf
go.mod文件:
module grpc_go
go 1.16
require (
google.golang.org/grpc v1.43.0 // indirect
google.golang.org/protobuf v1.26.0 // indirect
)
protoc文件:
syntax = "proto3"; //指定语法格式
package proto; //指定生成的包名字
option java_package = "org.ymx.proto";
option go_package = "/";
// 定义gRPC服务接口
service HelloService {
// 接口的具体方法
rpc SayHello(HelloRequest) returns (HelloReply) {}
}
// 接口的请求参数类型
message HelloRequest {
string name = 1;
}
// 接口的响应参数类型
message HelloReply {
string message = 1;
}
到proto目录下进行编译,编译完成后会出现指定的go文件:
C:\Users\17122\Desktop\grpc_demo\grpc_go\protoc> protoc -I . --go_out=plugins=grpc:. hello.proto
如果出现异常:
'protoc-gen-go' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
--go_out: protoc-gen-go: Plugin failed with status code 1.
解决方式:
下载这个项目,到protoc-gen-go目录下,go build -o protoc-gen-go.exe main.go ,生成protoc-gen-go.exe文件
再将protoc-gen-go.exe拷贝到C:\Windows\System32
grpc客户端,main.go
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
_ "grpc_go/proto"
__ "grpc_go/proto"
"log"
)
func main() {
//1 配置grpc服务端的端口作为客户端的监听
conn, err := grpc.Dial(":6666", grpc.WithInsecure())
if err != nil {
log.Fatalf("正在监听服务端 : %v\n", err)
}
defer conn.Close()
//2 实例化 UserInfoService 服务的客户端
client := __.NewHelloServiceClient(conn)
//3 调用grpc服务
req := new (__.HelloRequest)
req.Name = "YMX"
resp, err := client.SayHello(context.Background(), req)
if err != nil {
log.Fatalf("请求错误 : %v\n", err)
}
fmt.Printf("响应内容 : %v\n", resp)
}
grpc服务端,main.go
import (
"context"
"fmt"
"google.golang.org/grpc"
__ "grpc_go/proto"
"log"
"net"
)
//定义服务端 实现 约定的接口
type HelloServiceServer struct{
}
var u = HelloServiceServer{
}
//实现 interface
func (s *HelloServiceServer) SayHello(ctx context.Context, req *__.HelloRequest) (resp *__.HelloReply, err error) {
name := req.Name
if name == "YMX" {
resp = &__.HelloReply{
Message: "Hello YMX"}
} else {
resp = &__.HelloReply{
Message: "Hi NoYMX"}
}
err = nil
return resp, nil
}
//启动服务
func main() {
//1 添加监听的端口
port := ":6666"
l, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("端口监听错误 : %v\n", err)
}
fmt.Printf("正在监听: %s 端口\n", port)
//2 启动grpc服务
s := grpc.NewServer()
//3 将UserInfoService服务注册到gRPC中,注意第二个参数是接口类型的变量,需要取地址传参
__.RegisterHelloServiceServer(s, &u)
s.Serve(l)
}
启动服务端和客户端,进行测试:
4 Java使用gRPC进行Java程序之间的通信
项目结构:
pom依赖
<?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.ymx</groupId>
<artifactId>grpc_java</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>1.43.0</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.1.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.0.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
protoc文件内容:
syntax = "proto3"; //指定语法格式
package proto; //指定生成的包名字;
option java_multiple_files = true;
option java_package = "org.ymx.proto";
option go_package = "/";
option java_outer_classname = "Hello";
option objc_class_prefix = "YMX";
service HelloService {
rpc SayHello(HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
进行编译,首先利用protobuf进行编译:
然后再利用maven进行编译:
grpc服务端代码:
package org.ymx;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import org.ymx.proto.HelloReply;
import org.ymx.proto.HelloRequest;
import org.ymx.proto.HelloServiceGrpc;
import java.io.IOException;
/** * @desc: grpc服务端 * @author: YanMingXin * @create: 2021/12/18-14:52 **/
public class Server {
private final static int port = 5555;
private io.grpc.Server server;
private void start() throws IOException {
server = ServerBuilder.forPort(port)
.addService(new HelloServiceImpl())
.build()
.start();
System.out.println("service start...");
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.err.println("*** shutting down gRPC server since JVM is shutting down");
Server.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 Server server = new Server();
server.start();
server.blockUntilShutdown();
}
/** * 实现 定义一个实现服务接口的类 */
private class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
System.out.println("service:" + req.getName());
HelloReply reply = HelloReply.newBuilder().setMessage(("Hello: " + req.getName())).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
grpc客户端代码:
package org.ymx;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import org.ymx.proto.HelloReply;
import org.ymx.proto.HelloRequest;
import org.ymx.proto.HelloServiceGrpc;
import java.util.concurrent.TimeUnit;
/** * @desc: grpc客户端 * @author: YanMingXin * @create: 2021/12/18-14:52 **/
public class Client {
private final ManagedChannel channel;
private final HelloServiceGrpc.HelloServiceBlockingStub blockingStub;
public Client(String host, int port) {
channel = ManagedChannelBuilder.forAddress(host, port)
.usePlaintext()
.build();
blockingStub = HelloServiceGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
public void hello(String name) {
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
HelloReply response = blockingStub.sayHello(request);
System.out.println(response.getMessage());
}
public static void main(String[] args) {
Client client = new Client("127.0.0.1", 5555);
for (int i = 0; i < 5; i++) {
if (i < 3) {
client.hello("ZS");
} else {
client.hello("YMX");
}
}
}
}
启动测试:
5 使用gRPC进行Go和Java程序间的通信
5.1 使用Java作为服务端,Go作为客户端
修改客户端端口:
Java服务端代码,其他代码不变:
/** * @desc: grpc服务端 * @author: YanMingXin * @create: 2021/12/18-14:52 **/
public class Server {
private final static int port = 5555;
private io.grpc.Server server;
private void start() throws IOException {
server = ServerBuilder.forPort(port)
.addService(new HelloServiceImpl())
.build()
.start();
System.out.println("service start...");
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.err.println("*** shutting down gRPC server since JVM is shutting down");
Server.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 Server server = new Server();
server.start();
server.blockUntilShutdown();
}
/** * 实现 定义一个实现服务接口的类 */
private class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
System.out.println("service:" + req.getName());
HelloReply reply = HelloReply.newBuilder().setMessage(("Hello: " + req.getName())).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
Go客户端代码,其他代码不变:
import (
"context"
"fmt"
"google.golang.org/grpc"
_ "grpc_go/proto"
__ "grpc_go/proto"
"log"
)
func main() {
//1 配置grpc服务端的端口作为客户端的监听
conn, err := grpc.Dial(":5555", grpc.WithInsecure())
if err != nil {
log.Fatalf("正在监听服务端 : %v\n", err)
}
defer conn.Close()
//2 实例化 UserInfoService 服务的客户端
client := __.NewHelloServiceClient(conn)
//3 调用grpc服务
req := new (__.HelloRequest)
req.Name = "YMX"
resp, err := client.SayHello(context.Background(), req)
if err != nil {
log.Fatalf("请求错误 : %v\n", err)
}
fmt.Printf("响应内容 : %v\n", resp)
}
测试:
5.2 使用Go作为服务端,Java作为客户端
修改客户端端口:
Go服务端代码,其他代码不变:
import (
"context"
"fmt"
"google.golang.org/grpc"
__ "grpc_go/proto"
"log"
"net"
)
//定义服务端 实现 约定的接口
type HelloServiceServer struct{
}
var u = HelloServiceServer{
}
//实现 interface
func (s *HelloServiceServer) SayHello(ctx context.Context, req *__.HelloRequest) (resp *__.HelloReply, err error) {
name := req.Name
if name == "YMX" {
resp = &__.HelloReply{
Message: "Hello YMX"}
} else {
resp = &__.HelloReply{
Message: "Hi NoYMX"}
}
err = nil
return resp, nil
}
//启动服务
func main() {
//1 添加监听的端口
port := ":6666"
l, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("端口监听错误 : %v\n", err)
}
fmt.Printf("正在监听: %s 端口\n", port)
//2 启动grpc服务
s := grpc.NewServer()
//3 将UserInfoService服务注册到gRPC中,注意第二个参数是接口类型的变量,需要取地址传参
__.RegisterHelloServiceServer(s, &u)
s.Serve(l)
}
Java客户端代码,其他代码不变:
/** * @desc: grpc客户端 * @author: YanMingXin * @create: 2021/12/18-14:52 **/
public class Client {
private final ManagedChannel channel;
private final HelloServiceGrpc.HelloServiceBlockingStub blockingStub;
public Client(String host, int port) {
channel = ManagedChannelBuilder.forAddress(host, port)
.usePlaintext()
.build();
blockingStub = HelloServiceGrpc.newBlockingStub(channel);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
public void hello(String name) {
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
HelloReply response = blockingStub.sayHello(request);
System.out.println(response.getMessage());
}
public static void main(String[] args) {
Client client = new Client("127.0.0.1", 6666);
for (int i = 0; i < 5; i++) {
if (i < 3) {
client.hello("ZS");
} else {
client.hello("YMX");
}
}
}
}
测试:
6 总结
- 存放protoc的文件目录尽量用proto命名
源码获取方式:关注下方公众号,回复【0701】
边栏推荐
- 分布式事务简介(seata)
- Application of 5g industrial gateway in scientific and technological overload control; off-site joint law enforcement for over limit, overweight and overspeed
- C语言订餐管理系统
- Terminal identification technology and management technology
- 流量管理技术
- Analysis report on production and marketing demand and investment forecast of global and Chinese diamond powder industry Ⓤ 2022 ~ 2027
- 龙蜥社区开源 coolbpf,BPF 程序开发效率提升百倍
- [Jianzhi offer] 55 - ii balanced binary tree
- 20个实用的 TypeScript 单行代码汇总
- French Data Protection Agency: using Google Analytics or violating gdpr
猜你喜欢

Fiori 应用通过 Adaptation Project 的增强方式分享

Summary of interview questions (1) HTTPS man in the middle attack, the principle of concurrenthashmap, serialVersionUID constant, redis single thread,

1553B environment construction

Chen Yu (Aqua) - Safety - & gt; Cloud Security - & gt; Multicloud security

开源者的自我修养|为 ShardingSphere 贡献了千万行代码的程序员,后来当了 CEO

The stack size specified is too small, specify at least 328k

5G工业网关的科技治超应用 超限超重超速非现场联合执法

SAP intelligent robot process automation (IRPA) solution sharing

Liu Dui (fire line safety) - risk discovery in cloudy environment

2022 · 让我带你Jetpack架构组件从入门到精通 — Lifecycle
随机推荐
Dragon lizard community open source coolbpf, BPF program development efficiency increased 100 times
QT社团管理系统
Etcd 概要 机制 和使用场景
String input function
In the next stage of digital transformation, digital twin manufacturer Youyi technology announced that it had completed a financing of more than 300 million yuan
Introduction to topological sorting
Summary of interview questions (1) HTTPS man in the middle attack, the principle of concurrenthashmap, serialVersionUID constant, redis single thread,
当你真的学会DataBinding后,你会发现“这玩意真香”!
1. Sum of two numbers: given an integer array num and an integer target value, please find the two integers whose sum is the target value target in the array and return their array subscripts
1.8 new features list
2. Sensor size "recommended collection"
Applet - applet chart Library (F2 chart Library)
Declare an abstract class vehicle, which contains the private variable numofwheel and the public functions vehicle (int), horn (), setnumofwheel (int) and getnumofwheel (). Subclass mot
Yan Rong looks at how to formulate a multi cloud strategy in the era of hybrid cloud
Kongsong (Xintong Institute) - cloud security capacity building and trend in the digital era
ArrayList扩容机制以及线程安全性
Content Audit Technology
6年技术迭代,阿里全球化出海&合规的挑战和探索
Investment analysis and prospect prediction report of global and Chinese p-nitrotoluene industry Ⓙ 2022 ~ 2027
[安网杯 2021] REV WP