grpc ssl。 python 服务端, go 客户端。

go grpc
python grpc

证书 私钥准备

生成(根)私钥和公钥

openssl req -x509 -nodes -newkey rsa:4096 -keyout ca.key -out ca.pem -subj /O=me

  • ca.key is a private key
  • ca.pem is a public certificate
服务端

openssl req -nodes -newkey rsa:4096 -keyout server.key -out server.csr -subj /CN=whatever -days 36500 && openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -days 36500 -set_serial 1 -out server.pem -extfile <(echo "subjectAltName=DNS:myServerName")
注意 DNS:myServerName, myServerName 在 客户端连接时指定使用

  • server.key is the server’s private key.
  • server.csr is an intermediate file.
  • server.pem is the server’s public certificate.
客户端

openssl req -nodes -newkey rsa:4096 -days 36500 -subj /CN=marketplace -keyout client.key -out client.csr && openssl x509 -req -in client.csr -CA ca.pem -CAkey ca.key -days 36500 -set_serial 1 -out client.pem

  • client.key
  • client.pem

###代码

服务端(py)
def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    recommendations_pb2_grpc.add_RecommendationsServicer_to_server(
        RecommendationService(), server
    )

    with open("server.key", "rb") as fp:
        server_key = fp.read()
    with open("server.pem", "rb") as fp:
        server_cert = fp.read()
    with open("ca.pem", "r") as fp:
        SslCaPem = fp.read()
    creds = grpc.ssl_server_credentials(
    	[(server_key, server_cert)], #  加密
    	root_certificates=bytes(SslCaPem.encode()),  # 认证
        require_client_auth=True,  # 认证
   	)  
    server.add_secure_port("[::]:443", creds)
    server.start()
    server.wait_for_termination()
客户端(go)
	clientPem := "clientPemStr"
	clientKey := "clientKeyStr"
	caPem := "caPemStr"  # 根证书
    // tls.Config中的 ServerName用到生成服务端公钥时指定的
    certificates, err := tls.X509KeyPair([]byte(clientPem), []byte(clientKey))
	if err != nil {
	    log.D().Errorf("failed to load clientPem clientKey",)
	}
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM([]byte(caPem)) {
		log.D().Error("failed to append CA certificate")
	}
	tlsConfig := &tls.Config{
		RootCAs:    certPool, // 认证服务端使用
		ServerName: "myServerName", // 验证对方的(如有变动 需重新生成服务端证书 SAN中的 dns 一起更改)
		Certificates: []tls.Certificate{certificates},  // 客户端证书
	}
	creds := credentials.NewTLS(tlsConfig)
	addr := fmt.Sprintf("%s:%d", ip, conf.Default().Grpc.ServerPort)

	conn, err := grpc.Dial(
		addr,
		grpc.WithTransportCredentials(creds),
	}
<think>好的,我现在需要帮用户解决Java通过gRPC调用Python服务的问题。首先,我得回顾一下gRPC的基本原理,确保自己理解正确。gRPC是基于Protocol Buffers的跨语言RPC框架,所以关键是要定义proto文件,然后生成不同语言的代码。 用户提到已经有一个Python服务,需要Java客户端调用它。那步骤应该是先定义proto文件,然后分别生成Python和Java的代码。Python那边作为服务端已经实现,Java这边需要生成对应的客户端代码。 接下来,我得考虑具体的步骤。首先是编写proto文件,定义服务和方法。比如一个简单的HelloRequest和HelloReply,包含必要的字段。然后使用protoc编译器生成Java的客户端存根。用户提供的引用中提到了Java生成代码的位置,比如target目录,这可能和Maven项目结构有关,需要配置protobuf插件。 然后,Java客户端需要引入gRPC和生成的代码依赖。这部分需要注意版本兼容性,确保gRPC的版本和protobuf的版本匹配,否则可能会有错误。另外,Java的客户端代码需要正确初始化channel,创建stub,并调用远程方法。这里需要处理异常,管理资源,比如关闭channel。 还需要检查Python服务端的启动是否正确,确保端口开放,没有防火墙阻止通信。测试时可能需要先用工具如grpcurl测试服务是否可用,再调试Java客户端。 可能会遇到的问题包括:proto文件不一致导致序列化错误,网络连接问题,依赖版本冲突等。需要提醒用户在生成代码时保持proto文件同步,并检查网络配置。此外,代码中的包名和导入路径是否正确,也是常见的问题点。 最后,应该给出一个简单的Java客户端示例,展示如何调用Python服务。同时,强调步骤中的关键点,比如proto定义、代码生成、依赖管理和连接配置。</think>要实现Java通过gRPC调用Python服务的跨语言通信,需要按照以下步骤操作: ### 一、定义proto文件 创建`helloworld.proto`文件定义服务接口: ```protobuf syntax = "proto3"; package helloworld; option java_package = "com.example.helloworld"; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; } ``` [^1] ### 二、Python服务端实现 已实现的Python服务端代码示例: ```python # 服务端保持运行在50051端口 from concurrent import futures import grpc import helloworld_pb2 import helloworld_pb2_grpc class Greeter(helloworld_pb2_grpc.GreeterServicer): def SayHello(self, request, context): return helloworld_pb2.HelloReply(message='Hello %s!' % request.name) def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) server.add_insecure_port('[::]:50051') server.start() server.wait_for_termination() ``` ### 三、Java客户端实现 1. **生成Java代码** 在Maven项目的`pom.xml`中添加: ```xml <build> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protoSourceRoot>src/main/proto</protoSourceRoot> <outputDirectory>target/generated-sources/protobuf/java</outputDirectory> </configuration> </plugin> </plugins> </build> ``` 执行`mvn compile`生成代码[^2] 2. **客户端代码** ```java import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import com.example.helloworld.GreeterGrpc; import com.example.helloworld.HelloRequest; import com.example.helloworld.HelloReply; public class Client { public static void main(String[] args) { ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051) .usePlaintext() .build(); GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel); HelloReply response = stub.sayHello( HelloRequest.newBuilder().setName("Java Client").build() ); System.out.println("Response: " + response.getMessage()); channel.shutdown(); } } ``` ### 四、关键注意事项 1. **依赖版本对齐** 确保Java和Python使用相同版本的gRPC(建议1.50+)和protobuf(建议3.21+) 2. **网络配置** 若跨机器部署,需在Python服务端开放防火墙端口: ```python server.add_insecure_port('0.0.0.0:50051') # 允许外部访问 ``` 3. **TLS加密(可选)** 生产环境应使用SSL/TLS加密: ```java ManagedChannel channel = ManagedChannelBuilder.forAddress("host", 443) .sslContext(GrpcSslContexts.forClient().trustManager(new File("server.crt")).build()) .build(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值