您现在的位置是:首页 > 技术教程 正文

gRPC Java、Go、PHP使用例子

admin 阅读: 2024-03-18
后台-插件-广告管理-内容页头部广告(手机)

RPC选型入门测试系列文章
【1】GraphQL基础知识与Spring for GraphQL使用教程
【2】gRPC Java、Go、PHP使用例子
【3】Thrift RPC Java、Go、PHP使用例子

文章目录

    • 1、Protocol Buffers定义接口
      • 1.1、编写接口服务
      • 1.2、Protobuf基础数据类型
    • 2、服务器端实现
      • 2.1、生成gRPC服务类
      • 2.2、Java服务器端实现
    • 3、java、go、php客户端实现
      • 3.1、Java客户端实现
      • 3.2、Go客户端实现
      • 3.3、PHP客户端实现

本文例子是在Window平台测试,Java编写的gRPC服务器端,同时使用Java、Go、PHP编写客户端调用。

1、Protocol Buffers定义接口

1.1、编写接口服务

// 定义protocol buffers版本(proto3) syntax = "proto3"; // 定义包名,避免协议消息类型之间的命名冲突。 package helloworld; // 定义java格式 option java_multiple_files = true; option java_package = "com.penngo.grpc"; option java_outer_classname = "HelloWorldProto"; option objc_class_prefix = "HLW"; // 服务接口定义 service Greeter { // 方法1定义 rpc SayHello (HelloRequest) returns (HelloReply) {} // 方法2定义 rpc SayHelloAgain (HelloRequest) returns (HelloReply) {} } // HelloRequest消息类型格式定义, message HelloRequest { // name为定义字段名,1为消息传输中的字段编号,使用后,不应该改编号。 string name = 1; } // HelloReply消息类型格式定义, message HelloReply { // message为定义字段名,1为消息传输中的字段编号,使用后,不应该改编号。 string message = 1; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

1.2、Protobuf基础数据类型

.protoC++Java/KotlinPythonGoRubyC#PHPDart
doubledoubledoublefloatfloat64Floatdoublefloatdouble
floatfloatfloatfloatfloat32Floatfloatfloatdouble
int32int32intintint32Fixnum or Bignum
(as required)
intintegerint
int64int64longint/longint64Bignumlonginteger/stringInt64
uint32uint32intint/longuint32Fixnum or Bignum
(as required)
uintintegerint
uint64uint64longint/longuint64Bignumulonginteger/stringInt64
sint32int32intintint32Fixnum or Bignum
(as required)
intintegerint
sint64int64longint/longint64Bignumlonginteger/stringInt64
fixed32uint32int[2]int/long[4]uint32Fixnum or Bignum
(as required)
uintintegerint
fixed64uint64long[2]int/longuint64Bignumulonginteger/stringInt64
sfixed32int32intintint32Fixnum or Bignum
(as required)
intintegerint
sfixed64int64longint/longint64Bignumlonginteger/stringInt64
boolboolbooleanboolboolTrueClass/FalseClassboolbooleanbool
stringstringStringstr/unicodestringString (UTF-8)stringstringString
bytesstringByteStringstr (Python 2)
bytes (Python 3)
[]byteString (ASCII-8BIT)ByteStringstringList

参考自官方:https://protobuf.dev/programming-guides/proto3/

2、服务器端实现

服务器端实例使用java编写

2.1、生成gRPC服务类

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.0modelVersion> <groupId>com.penngogroupId> <artifactId>grpc-helloworldartifactId> <version>1.0version> <properties> <maven.compiler.source>11maven.compiler.source> <maven.compiler.target>11maven.compiler.target> <project.build.sourceEncoding>UTF-8project.build.sourceEncoding> properties> <dependencies> <dependency> <groupId>io.grpcgroupId> <artifactId>grpc-netty-shadedartifactId> <version>1.59.0version> <scope>runtimescope> dependency> <dependency> <groupId>io.grpcgroupId> <artifactId>grpc-protobufartifactId> <version>1.59.0version> dependency> <dependency> <groupId>io.grpcgroupId> <artifactId>grpc-stubartifactId> <version>1.59.0version> dependency> <dependency> <groupId>org.apache.tomcatgroupId> <artifactId>annotations-apiartifactId> <version>6.0.53version> <scope>providedscope> dependency> dependencies> <build> <extensions> <extension> <groupId>kr.motd.mavengroupId> <artifactId>os-maven-pluginartifactId> <version>1.7.1version> extension> extensions> <plugins> <plugin> <groupId>org.xolstice.maven.pluginsgroupId> <artifactId>protobuf-maven-pluginartifactId> <version>0.6.1version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.24.0:exe:${os.detected.classifier}protocArtifact> <pluginId>grpc-javapluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.59.0:exe:${os.detected.classifier}pluginArtifact> configuration> <executions> <execution> <goals> <goal>compilegoal> <goal>compile-customgoal> goals> execution> executions> plugin> plugins> build> <repositories> <repository> <id>alimavenid> <name>Maven Aliyun Mirrorname> <url>https://maven.aliyun.com/repository/centralurl> repository> repositories> <pluginRepositories> <pluginRepository> <id>publicid> <name>aliyun nexusname> <url>https://maven.aliyun.com/nexus/content/groups/public/url> <releases> <enabled>trueenabled> releases> <snapshots> <enabled>falseenabled> snapshots> pluginRepository> pluginRepositories> project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

命令行下执行gRPC的java代码

mvn compile
  • 1

自动扫描代码目中src/main/proto/helloworld.proto下的proto文件,自动生成gRPC相关代码到target/generated-sources/protobuf目录下。
在这里插入图片描述

2.2、Java服务器端实现

HelloServer.java

package com.penngo; import com.penngo.grpc.GreeterGrpc; import com.penngo.grpc.HelloReply; import com.penngo.grpc.HelloRequest; import io.grpc.Grpc; import io.grpc.InsecureServerCredentials; import io.grpc.Server; import io.grpc.stub.StreamObserver; import java.io.IOException; public class HelloServer { public static void main(String[] args) throws IOException, InterruptedException { int port = 50051; Server server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create()) .addService(new GreeterImpl()) .build() .start(); Runtime.getRuntime().addShutdownHook(new Thread(()->{ System.err.println("*** shutting down gRPC server since JVM is shutting down"); stopServer(server); System.err.println("*** server shut down"); })); server.awaitTermination(); } private static void stopServer(Server server) { if (server != null) { server.shutdown(); } } static class GreeterImpl extends GreeterGrpc.GreeterImplBase { @Override public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) { System.out.println("收到客户端消息:" + req.getName()); String msg = "我是Java Server"; System.out.println("回复客户端消息:" + msg); HelloReply reply = HelloReply.newBuilder().setMessage("你好!" + msg).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } @Override public void sayHelloAgain(HelloRequest req, StreamObserver<HelloReply> responseObserver) { System.out.println("再次收到客户端消息:" + req.getName()); String msg = "我是Java Server2"; System.out.println("再次回复客户端消息:" + msg); HelloReply reply = HelloReply.newBuilder().setMessage(msg).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

https://github.com/protocolbuffers/protobuf/releases

3、java、go、php客户端实现

3.1、Java客户端实现

HelloClient.java

package com.penngo; import com.penngo.grpc.GreeterGrpc; import com.penngo.grpc.HelloReply; import com.penngo.grpc.HelloRequest; import io.grpc.Grpc; import io.grpc.InsecureChannelCredentials; import io.grpc.ManagedChannel; import java.util.concurrent.TimeUnit; public class HelloClient { public static void main(String[] args) throws InterruptedException { String host = "localhost"; int port = 50051; ManagedChannel managedChannel = Grpc.newChannelBuilderForAddress(host, port, InsecureChannelCredentials.create()).build(); GreeterGrpc.GreeterBlockingStub blockingStub = GreeterGrpc.newBlockingStub(managedChannel); String msg1 = "我是java client"; System.out.println("向服务器端发送消息:" + msg1); HelloRequest helloRequest1 = HelloRequest.newBuilder().setName(msg1).build(); HelloReply reply1 = blockingStub.sayHello(helloRequest1); System.out.println("收到服务器端消息:" + reply1.getMessage()); String msg2 = "我是java client2"; System.out.println("再次向服务器端发送消息:" + msg2); HelloRequest helloRequest2 = HelloRequest.newBuilder().setName(msg2).build(); HelloReply reply2 = blockingStub.sayHelloAgain(helloRequest2); System.out.println("再次收到服务器端消息:" + reply2.getMessage()); managedChannel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

3.2、Go客户端实现

Go的代码生成需要使用protoc.exe来编译helloworld.proto服务文件,生成对应的服务调用代码
下载地址:https://github.com/protocolbuffers/protobuf/releases,当前最新版本为protoc-25.1-win64.zip
解压到目录D:\Program Files\protoc-25.1-win64\bin,需要把这个目录添加到环境变量PATH当中。

安装protocol编译器的Go插件

$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
  • 1
  • 2

执行下边命令生成Go的gRPC代码

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld/helloworld.proto
  • 1

在这里插入图片描述

编写客户端实现代码

package main import ( "context" "flag" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" pb "grpctest/helloworld" "log" "time" ) var ( addr = flag.String("addr", "localhost:50051", "the address to connect to") ) func main() { flag.Parse() // Set up a connection to the server. conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() c := pb.NewGreeterClient(conn) // Contact the server and print out its response. ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() msg1 := "我是go client" log.Printf("向服务器端发送消息: %s", msg1) r1, err1 := c.SayHello(ctx, &pb.HelloRequest{Name: msg1}) if err1 != nil { log.Fatalf("could not greet: %v", err1) } log.Printf("收到服务器端消息:%s", r1.GetMessage()) msg2 := "我是go client2" log.Printf("再次向服务器端发送消息: %s", msg1) r2, err2 := c.SayHelloAgain(ctx, &pb.HelloRequest{Name: msg2}) if err2 != nil { log.Fatalf("could not greet: %v", err2) } log.Printf("再次收到服务器端消息: %s", r2.GetMessage()) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

3.3、PHP客户端实现

安装gRPC的PHP扩展https://pecl.php.net/package/gRPC
当前测试php版本7.3,下载php_grpc-1.42.0-7.3-nts-vc15-x64.zip
php.ini这个文件加入

extension=php_grpc.dll
  • 1

新建composer.json

{ "name": "xxs/grpc", "require": { "grpc/grpc": "^v1.4.0", "google/protobuf": "^v3.3.0" }, "autoload":{ "psr-4":{ "GPBMetadata\\":"GPBMetadata/", "Helloworld\\":"Helloworld/" } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在composer.json相同目录下执行命令下载依赖库

composer install
  • 1

安装grpc的php插件,https://github.com/lifenglsf/grpc_for_windows
解压复制到项目下grpc_for_windows/x64/grpc_php_plugin.exe

执行命令生成gRPC代码

protoc --proto_path=. --php_out=. --grpc_out=. --plugin=protoc-gen-grpc=grpc_for_windows/x64/grpc_php_plugin.exe ./helloworld.proto
  • 1

在这里插入图片描述

client.php实现

<?php require dirname(__FILE__) . '/vendor/autoload.php'; //echo dirname(__FILE__) . '/vendor/autoload.php'; function greet($hostname) { $client = new Helloworld\GreeterClient($hostname, [ 'credentials' => Grpc\ChannelCredentials::createInsecure(), ]); $request = new Helloworld\HelloRequest(); $msg1 = "我是PHP client"; $request->setName($msg1); echo "向服务器端发送消息: $msg1". PHP_EOL; list($response, $status) = $client->SayHello($request)->wait(); if ($status->code !== Grpc\STATUS_OK) { echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL; exit(1); } echo "收到服务器端消息:".$response->getMessage() . PHP_EOL; $msg2 = "我是PHP client2"; $request->setName($msg2); echo "再次向服务器端发送消息: $msg2". PHP_EOL; list($response, $status) = $client->SayHelloAgain($request)->wait(); if ($status->code !== Grpc\STATUS_OK) { echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL; exit(1); } echo "再次收到服务器端发送消息:".$response->getMessage() . PHP_EOL; $client->close(); } $hostname = !empty($argv[2]) ? $argv[2] : 'localhost:50051'; greet($hostname);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

附件源码

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索
排行榜