当前位置:网站首页>玩转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】
边栏推荐
- Station B was scolded on the hot search..
- 终端识别技术和管理技术
- Analysis report on the development prospect and investment strategy of the global and Chinese laser chip industry Ⓑ 2022 ~ 2027
- word2vec训练中文词向量
- 10. Page layout, guess you like it
- 陈宇(Aqua)-安全-&gt;云安全-&gt;多云安全
- 详细讲解面试的 IO多路复用,select,poll,epoll
- 当你真的学会DataBinding后,你会发现“这玩意真香”!
- Sign APK with command line
- 20个实用的 TypeScript 单行代码汇总
猜你喜欢

Application of 5g industrial gateway in scientific and technological overload control; off-site joint law enforcement for over limit, overweight and overspeed

【机器学习】VAE变分自编码器学习笔记
![[241. Design priority for operation expression]](/img/72/29d27204d5213a8efdb2c5be925dec.png)
[241. Design priority for operation expression]

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

SAP intelligent robot process automation (IRPA) solution sharing

A Fletter version of Notepad

详细讲解面试的 IO多路复用,select,poll,epoll

面试题目总结(1) https中间人攻击,ConcurrentHashMap的原理 ,serialVersionUID常量,redis单线程,

Qtdeisgner, pyuic detailed use tutorial interface and function logic separation (nanny teaching)

Chen Yu (Aqua) - Safety - & gt; Cloud Security - & gt; Multicloud security
随机推荐
盲盒NFT数字藏品平台系统开发(搭建源码)
网络中的listen
Nexus builds NPM dependent private database
【剑指Offer】54. 二叉搜索树的第k大节点
The stack size specified is too small, specify at least 328k
【机器学习】VAE变分自编码器学习笔记
Uni app realizes advertisement scroll bar
leetcode 322. Coin change (medium)
刘对(火线安全)-多云环境的风险发现
Sharing with the best paper winner of CV Summit: how is a good paper refined?
C语言订餐管理系统
Simplex, half duplex, full duplex, TDD and FDD
Global and Chinese silicone defoamer production and marketing demand and investment forecast analysis report Ⓨ 2022 ~ 2027
Applet - applet chart Library (F2 chart Library)
ArrayList capacity expansion mechanism and thread safety
一款Flutter版的记事本
进入前六!博云在中国云管理软件市场销量排行持续上升
Global and Chinese n-butanol acetic acid market development trend and prospect forecast report Ⓧ 2022 ~ 2028
Grafana reports an error: error= "failed to send notification to email addresses: [email protected] : 535 Error:
1.8新特性-List