当前位置:网站首页>玩转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】
边栏推荐
- Anti fraud, refusing to gamble, safe payment | there are many online investment scams, so it's impossible to make money like this
- 5. Use of ly tab plug-in of header component
- 【 剑指 Offer】55 - I. 二叉树的深度
- LeetCode重建二叉树详解[通俗易懂]
- 啟動solr報錯The stack size specified is too small,Specify at least 328k
- Leetcode第一题:两数之和(3种语言)
- Build a vc2010 development environment and create a tutorial of "realizing Tetris game in C language"
- Content Audit Technology
- word2vec训练中文词向量
- MySQL 66 questions, 20000 words + 50 pictures in detail! Necessary for review
猜你喜欢

Spark source code (V) how does dagscheduler taskscheduler cooperate with submitting tasks, and what is the corresponding relationship between application, job, stage, taskset, and task?

The best landing practice of cave state in an Internet ⽹⾦ financial technology enterprise

啟動solr報錯The stack size specified is too small,Specify at least 328k

Understand the window query function of tdengine in one article

进入前六!博云在中国云管理软件市场销量排行持续上升

学历、长相、家境普通的人,未来的发展方向是什么?00后的职业规划都已经整得明明白白......

SAP intelligent robot process automation (IRPA) solution sharing

流量管理技术

MySQL 66 questions, 20000 words + 50 pictures in detail! Necessary for review

What is the future development direction of people with ordinary education, appearance and family background? The career planning after 00 has been made clear
随机推荐
MySQL 66 questions, 20000 words + 50 pictures in detail! Necessary for review
Use of shutter SQLite
SAP intelligent robot process automation (IRPA) solution sharing
AnimeSR:可学习的降质算子与新的真实世界动漫VSR数据集
Etcd 概要 机制 和使用场景
Investment analysis and prospect prediction report of global and Chinese dimethyl sulfoxide industry Ⓦ 2022 ~ 2028
一文读懂TDengine的窗口查询功能
China NdYAG crystal market research conclusion and development strategy proposal report Ⓥ 2022 ~ 2028
Dragon lizard community open source coolbpf, BPF program development efficiency increased 100 times
leetcode 322. Coin Change 零钱兑换(中等)
[anwangbei 2021] Rev WP
MySQL六十六问,两万字+五十图详解!复习必备
French Data Protection Agency: using Google Analytics or violating gdpr
6. Wiper part
20个实用的 TypeScript 单行代码汇总
Chen Yu (Aqua) - Safety - & gt; Cloud Security - & gt; Multicloud security
Global and Chinese silicone defoamer production and marketing demand and investment forecast analysis report Ⓨ 2022 ~ 2027
Benefiting from the Internet, the scientific and technological performance of overseas exchange volume has returned to high growth
word2vec训练中文词向量
Simplex, half duplex, full duplex, TDD and FDD