本文介绍: gRPC Java、Go、PHP使用例

RPC入门系列文章
【1】GraphQL基础知识与Spring for GraphQL使用教程
【2】gRPC Java、Go、PHP使用例子
【3】Thrift RPC Java、Go、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、Protobuf基础数据类型

    <th&gt;C++</th&gt;
    <th&gt;Java/Kotlin</th&gt;
    <th&gt;Python</th>
    <th>Go</th>
    <th>Ruby</th>
    <th>C#</th>
    <th>PHP</th>
    <th>Dart</th>
</tr>
<tr>
    <td>double</td>
    
    <td>double</td>
    <td>double</td>
    <td>float</td>
    <td>float64</td>
    <td>Float</td>
    <td>double</td>
    <td>float</td>
    <td>double</td>
</tr>
<tr>
    <td>float</td>
   
    <td>float</td>
    <td>float</td>
    <td>float</td>
    <td>float32</td>
    <td>Float</td>
    <td>float</td>
    <td>float</td>
    <td>double</td>
</tr>
<tr>
    <td>int32</td>
  
    <td>int32</td>
    <td>int</td>
    <td>int</td>
    <td>int32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>int</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>int64</td>

    <td>int64</td>
    <td>long</td>
    <td>int/long<sup>[4]</sup></td>
    <td>int64</td>
    <td>Bignum</td>
    <td>long</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>uint32</td>
   
    <td>uint32</td>
    <td>int<sup>[2]</sup></td>
    <td>int/long<sup>[4]</sup></td>
    <td>uint32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>uint</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>uint64</td>
 
    <td>uint64</td>
    <td>long<sup>[2]</sup></td>
    <td>int/long<sup>[4]</sup></td>
    <td>uint64</td>
    <td>Bignum</td>
    <td>ulong</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>sint32</td>
   
    <td>int32</td>
    <td>int</td>
    <td>int</td>
    <td>int32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>int</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>sint64</td>
    
    <td>int64</td>
    <td>long</td>
    <td>int/long<sup>[4]</sup></td>
    <td>int64</td>
    <td>Bignum</td>
    <td>long</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>fixed32</td>
  
    <td>uint32</td>
    <td>int<sup>[2]</sup></td>
    <td>int/long<sup>[4]</sup></td>
    <td>uint32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>uint</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>fixed64</td>
  
    <td>uint64</td>
    <td>long<sup>[2]</sup></td>
    <td>int/long<sup>[4]</sup></td>
    <td>uint64</td>
    <td>Bignum</td>
    <td>ulong</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>sfixed32</td>
   
    <td>int32</td>
    <td>int</td>
    <td>int</td>
    <td>int32</td>
    <td>Fixnum or Bignum (as required)</td>
    <td>int</td>
    <td>integer</td>
    <td>int</td>
</tr>
<tr>
    <td>sfixed64</td>
   
    <td>int64</td>
    <td>long</td>
    <td>int/long<sup>[4]</sup></td>
    <td>int64</td>
    <td>Bignum</td>
    <td>long</td>
    <td>integer/string<sup>[6]</sup></td>
    <td>Int64</td>
</tr>
<tr>
    <td>bool</td>
   
    <td>bool</td>
    <td>boolean</td>
    <td>bool</td>
    <td>bool</td>
    <td>TrueClass/FalseClass</td>
    <td>bool</td>
    <td>boolean</td>
    <td>bool</td>
</tr>
<tr>
    <td>string</td>
    
    <td>string</td>
    <td>String</td>
    <td>str/unicode<sup>[5]</sup></td>
    <td>string</td>
    <td>String (UTF-8)</td>
    <td>string</td>
    <td>string</td>
    <td>String</td>
</tr>
<tr>
    <td>bytes</td>
    
    <td>string</td>
    <td>ByteString</td>
    <td>str (Python 2)<br>bytes (Python 3)</td>
    <td>[]byte</td>
    <td>String (ASCII-8BIT)</td>
    <td>ByteString</td>
    <td>string</td>
    <td>List
        <int></int>
    </td>
</tr>
</tbody>
.proto

https://protobuf.dev/programmingguides/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.0</modelVersion>

    <groupId>com.penngo</groupId>
    <artifactId>grpc-helloworld</artifactId>
    <version>1.0</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.59.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>1.59.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>1.59.0</version>
        </dependency>
        <dependency> <!-- necessary for Java 9+ -->
            <groupId>org.apache.tomcat</groupId>
            <artifactId>annotations-api</artifactId>
            <version>6.0.53</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.7.1</version>
            </extension>
        </extensions>
        <plugins>
            <!-- grpc代码生成插件 -->
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.24.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.59.0:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>alimaven</id>
            <name>Maven Aliyun Mirror</name>
            <url>https://maven.aliyun.com/repository/central</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>

命令行执行gRPC的java代码

mvn compile

自动扫描代码目中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();
        }
    }
}

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);
    }

}

3.2、Go客户端实现

Go的代码生成需要使用protoc.exe编译helloworld.proto服务文件生成对应的服务调用代码
下载地址https://github.com/protocolbuffers/protobuf/releases当前最新版本为protoc-25.1-win64.zip
解压目录D:Program Filesprotoc-25.1-win64bin需要这个目录添加环境变量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

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

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

在这里插入图片描述

编写客户端实现代码

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, &amp;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, &amp;pb.HelloRequest{Name: msg2})

	if err2 != nil {
		log.Fatalf("could not greet: %v", err2)
	}
	log.Printf("再次收到服务器端消息: %s", r2.GetMessage())
}

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

新建composer.json

{
  "name": "xxs/grpc",
  "require": {
    "grpc/grpc": "^v1.4.0",
    "google/protobuf": "^v3.3.0"
  },
  "autoload":{
    "psr-4":{
      "GPBMetadata\":"GPBMetadata/",
      "Helloworld\":"Helloworld/"
    }
  }
}

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

composer install

安装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

在这里插入图片描述

client.php实现

<?php
require dirname(__FILE__) . '/vendor/autoload.php';
//echo dirname(__FILE__) . '/vendor/autoload.php';
function greet($hostname)
{

    $client = new HelloworldGreeterClient($hostname, [
        'credentials' => GrpcChannelCredentials::createInsecure(),
    ]);
    $request = new HelloworldHelloRequest();

    $msg1 = "我是PHP client";
    $request->setName($msg1);
    echo "向服务器端发送消息: $msg1". PHP_EOL;
    list($response, $status) = $client->SayHello($request)->wait();
    if ($status->code !== GrpcSTATUS_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 !== GrpcSTATUS_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);

附件源码

原文地址:https://blog.csdn.net/penngo/article/details/134680135

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_39992.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注