当前位置:   article > 正文

JAVA和Python的GRPC远程调用_java使用grpc和python

java使用grpc和python

JAVA和Python的GRPC远程调用

1.使用springboot项目搭建Java端

1.1pom.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.grpc</groupId>
    <artifactId>server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>java_server</name>
    <description>JAVa的grpc端</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.26.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>1.26.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>1.26.0</version>
        </dependency>
        <!--        lombok插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.11.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.26.0:exe:${os.detected.classifier}</pluginArtifact>
                    <!--默认值-->
                    <protoSourceRoot>${project.basedir}/src/main/resources/proto</protoSourceRoot>
                    <outputDirectory>${project.basedir}/src/main/java/com/grpc/shiyun</outputDirectory>
                    <!--设置是否在生成java文件之前清空outputDirectory的文件,默认值为true,设置为false时也会覆盖同名文件-->
                    <clearOutputDirectory>true</clearOutputDirectory>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</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
  • 91
  • 92
  • 93

image-20210326195928580

1.2书写proto文件autochat.proto

syntax = "proto3";

option java_multiple_files = true;
package shiyun;

// The greeting service definition.
service AutoChat {
  // Sends a greeting
  rpc autoChat (AutoChatRequest) returns (AutoChatReply) {}
}

// The request message containing the user's name.
message AutoChatRequest {
  string question = 1;
}

// The response message containing the greetings
message AutoChatReply {
  string response = 1;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

1.3使用protobuf插件生成Java代码

首先点击compile命令生成代码,然后再点击compile-custom生成代码,分两次生成。

image-20210326200136256

image-20210326200500587

image-20210326200538783

2.使用Python生成代码

2.1安装protobuf

pip install grpcio
  • 1

2.2使用 protoc 编译 proto 文件, 生成 python 语言的实现

# 安装 python 下的 protoc 编译器
pip install grpcio-tools
  • 1
  • 2

2.3编写autochat.proto文件(和Java的一致)

syntax = "proto3";
#在Python时候不需要这个选项
#option java_multiple_files = true;
package shiyun;

// The greeting service definition.
service AutoChat {
  // Sends a greeting
  rpc autoChat (AutoChatRequest) returns (AutoChatReply) {}
}

// The request message containing the user's name.
message AutoChatRequest {
  string question = 1;
}

// The response message containing the greetings
message AutoChatReply {
  string response = 1;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

image-20210326202315783

2.4编译文件

# 编译 proto 文件
python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. autochat.proto
  • 1
  • 2

python -m grpc_tools.protoc: python 下的 protoc 编译器通过 python 模块(module) 实现, 所以说这一步非常省心
–python_out=. : 编译生成处理 protobuf 相关的代码的路径, 这里生成到当前目录
**–grpc_python_out=. : 编译生成处理 grpc 相关的代码的路径

-I. autochat.proto : proto 文件的路径, 这里的 proto 文件在当前目录

image-20210326202330946

image-20210326202439991

3.编写Java客户端代码

package com.grpc.client;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import shiyun.AutoChatRequest;

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AutoChatClient {
    private static final Logger logger = Logger.getLogger(AutoChatClient.class.getName());

    private final ManagedChannel channel;
    private final shiyun.AutoChatGrpc.AutoChatBlockingStub blockingStub;

    /**
     * Construct client connecting to HelloWorld server at {@code host:port}.
     */
    public AutoChatClient(String host, int port) {
        this(ManagedChannelBuilder.forAddress(host, port)
                // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
                // needing certificates.
                .usePlaintext()
                .build());
    }

    /**
     * Construct client for accessing HelloWorld server using the existing channel.
     */
    AutoChatClient(ManagedChannel channel) {
        this.channel = channel;
        blockingStub = shiyun.AutoChatGrpc.newBlockingStub(channel);
    }

    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    /**
     * Say hello to server.
     */
    public void sendQuestion(String question) {
        AutoChatRequest request = shiyun.AutoChatRequest.newBuilder().setQuestion(question).build();
        shiyun.AutoChatReply response;
        try {
            response = blockingStub.autoChat(request);
            logger.info("接收来自服务器的响应: " + response.getResponse());
        } catch (StatusRuntimeException e) {
            logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
            return;
        }

    }

    /**
     * Greet server. If provided, the first element of {@code args} is the name to use in the
     * greeting.
     */
    public static void main(String[] args) throws Exception {
        // Access a service running on the local machine on port 50052
        AutoChatClient client = new AutoChatClient("localhost", 50052);
        try {
            String user = "world";
            // Use the arg as the name to greet if provided
            if (args.length > 0) {
                user = args[0];
            }
            int i = 0 ;
           while (true){
               client.sendQuestion(user+i++);
               Thread.sleep(1000);
           }
        } finally {
            client.shutdown();
        }
    }
}
  • 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

4.Python服务端代码

from concurrent import futures
import time
import grpc

# 实现 proto 文件中定义的 AutoChatServicer
import autochat_pb2_grpc, autochat_pb2

_ONE_DAY_IN_SECONDS = 60 * 60 * 24


class AutoChatServer(autochat_pb2_grpc.AutoChatServicer):
    def autoChat(self, request, context):
        print("接收到客户端消息:" + request.question)
        return autochat_pb2.AutoChatReply(response= request.question)


def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    autochat_pb2_grpc.add_AutoChatServicer_to_server(AutoChatServer(), server)
    server.add_insecure_port('[::]:50052')
    print("启动服务器等待连接。。。。")
    server.start()
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        server.stop(0)


if __name__ == '__main__':
    serve()
  • 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

5.项目源代码已经同步到GitHub和gitee,如有需要请移步自行下载:

gitee: https://gitee.com/ljf2402901363/grpc.git

github: https://github.com/LJF2402901363/grpc.git

6.本博客已同步到个人博客,如有需要请移步:

http://moyisuiying.com/index.php/javastudy/springboot/479.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/201086
推荐阅读
相关标签