Java 启动rpc server_gRPC创建Java RPC服务

1.说明

本文介绍使用gRPC创建Java版本的RPC服务,

包括通过.proto文件生成Java代码的方法,

以及服务端和客户端代码使用示例。

2.创建生成代码工程

创建Maven工程,grpc-compile。

2.1.修改pom.xml

引入生成代码需要的jar包依赖,

以及构建依赖配置:

io.grpc

grpc-protobuf

1.32.1

io.grpc

grpc-stub

1.32.1

kr.motd.maven

os-maven-plugin

1.6.2

org.xolstice.maven.plugins

protobuf-maven-plugin

0.6.1

com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}

grpc-java

io.grpc:protoc-gen-grpc-java:1.32.1:exe:${os.detected.classifier}

compile

compile-custom

2.2.创建.proto文件

在src\main下面新建proto目录,

在里面创建helloworld.proto文件:

// 显示声明使用proto3, 否则使用默认的proto2

syntax = "proto3";

// 生成类的包名

option java_package = "com.asiainfo.yuwen.grpc.helloworld";

// 生成类的文件名,否则默认生成的类名为proto文件名的驼峰命名

option java_outer_classname = "HelloWorldProto";

// 定义的所有消息、枚举和服务生成对应的多个类文件,而不是以内部类的形式出现

option java_multiple_files = false;

// greeting服务定义

service Greeter {

// sayHello方法,格式为"方法名 请求参数 返回参数"

rpc SayHello (HelloRequest) returns (HelloReply) {}

// 另一个sayHello方法

rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}

}

// 方法请求,包含用户名

message HelloRequest {

string name = 1;

}

// 方法响应,包含响应的消息

message HelloReply {

string message = 1;

}

2.3.生成Java代码

在grpc-compile下执行Maven编译命令:

mvn clean compile

会在target目录下生成代码:

f9437c8e015c

主要关注generated-sources目录:

generated-sources\protobuf\grpc-java目录下生成了

com\asiainfo\yuwen\grpc\helloworld\GreeterGrpc.java;

generated-sources\protobuf\java目录下生成了

com\asiainfo\yuwen\grpc\helloworld\HelloWorldProto.java。

其中GreeterGrpc.java对应greeting服务定义,

如果有多个服务,会对应生成多个java类,

HelloWorldProto.java对应消息、枚举等对象的定义。

由于生成的代码内容太多了,这里就不贴出来了。

3.创建服务端工程

创建Maven工程,grpc-server。

3.1.修改pom.xml

引入使用gRPC需要依赖的jar包:

io.grpc

grpc-netty-shaded

1.32.1

io.grpc

grpc-protobuf

1.32.1

io.grpc

grpc-stub

1.32.1

3.2.拷贝生成的代码

把上面生成的Java代码,

GreeterGrpc.java和HelloWorldProto.java,

拷贝到grpc-server的src/main/java目录下,

可以从com这一层目录开始拷贝,

这样就不用再手动创建包路径了。

3.3.创建greeting服务实现类

为了实现greeting服务定义的两个sayHello方法,

需要继承GreeterGrpc.GreeterImplBase接口,

创建实现类GreeterImpl.java:

package com.asiainfo.yuwen.grpc.helloworld.controller.impl;

import com.asiainfo.yuwen.grpc.helloworld.GreeterGrpc;

import com.asiainfo.yuwen.grpc.helloworld.HelloWorldProto.HelloReply;

import com.asiainfo.yuwen.grpc.helloworld.HelloWorldProto.HelloRequest;

import io.grpc.stub.StreamObserver;

/**

*

 
 

* greeting服务实现类

*

*/

public class GreeterImpl extends GreeterGrpc.GreeterImplBase {

@Override

public void sayHello(HelloRequest req, StreamObserver responseObserver) {

HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();

responseObserver.onNext(reply);

responseObserver.onCompleted();

}

@Override

public void sayHelloAgain(HelloRequest req, StreamObserver responseObserver) {

HelloReply reply = HelloReply.newBuilder().setMessage("Hello again " + req.getName()).build();

responseObserver.onNext(reply);

responseObserver.onCompleted();

}

}

3.4.创建服务端启动类

为了对外提供gRPC服务,

需要创建服务端启动类GRPCServer.java:

package com.asiainfo.yuwen.grpc.server;

import java.io.IOException;

import java.util.concurrent.TimeUnit;

import com.asiainfo.yuwen.grpc.helloworld.controller.impl.GreeterImpl;

import io.grpc.Server;

import io.grpc.ServerBuilder;

/**

* gRPC服务启动类,启动时注册添加需要对外提供的服务类

*/

public class GRPCServer {

private Server server;

private void start() throws IOException {

// 服务运行端口

int port = 50051;

// 注册对外提供的服务

server = ServerBuilder.forPort(port).addService(new GreeterImpl()).build().start();

System.out.println("Server started, listening on " + port);

Runtime.getRuntime().addShutdownHook(new Thread() {

@Override

public void run() {

// 使用标准错误输出,因为日志记录器有可能在JVM关闭时被重置

System.err.println("*** shutting down gRPC server since JVM is shutting down");

try {

GRPCServer.this.stop();

} catch (InterruptedException e) {

e.printStackTrace(System.err);

}

System.err.println("*** server shut down");

}

});

}

private void stop() throws InterruptedException {

if (server != null) {

server.shutdown().awaitTermination(30, TimeUnit.SECONDS);

}

}

/**

* 在主线程上等待终止,因为grpc库使用守护进程。

*/

private void blockUntilShutdown() throws InterruptedException {

if (server != null) {

server.awaitTermination();

}

}

/**

* 启动服务Main方法

*/

public static void main(String[] args) throws IOException, InterruptedException {

final GRPCServer server = new GRPCServer();

server.start();

server.blockUntilShutdown();

}

}

3.5.服务端启动

通过执行GRPCServer的main方法,

就能启动服务了,

启动成功打印日志:

Server started, listening on 50051

4.创建服务端工程

创建Maven工程,grpc-client。

4.1.修改pom.xml

操作步骤和上面服务端相同。

4.2.拷贝生成的代码

操作步骤和上面服务端相同。

由于客户端和服务端都依赖了生成的代码,

以及依赖相同的jar包,

可以提取到common公共工程里面,

这样方便其他工程依赖和后续修改。

4.3.创建客户端调用类

创建一个简单的客户端,

用于测试greeting服务,

创建GRPCClient.java:

package com.asiainfo.yuwen.grpc.client;

import java.util.concurrent.TimeUnit;

import com.asiainfo.yuwen.grpc.helloworld.GreeterGrpc;

import com.asiainfo.yuwen.grpc.helloworld.HelloWorldProto.HelloReply;

import com.asiainfo.yuwen.grpc.helloworld.HelloWorldProto.HelloRequest;

import io.grpc.Channel;

import io.grpc.ManagedChannel;

import io.grpc.ManagedChannelBuilder;

import io.grpc.StatusRuntimeException;

/**

* 一个简单的客户端,测试greeting服务

*/

public class GRPCClient {

private final GreeterGrpc.GreeterBlockingStub greeterBlocStub;

/**

* 构造使用现有通道访问服务端的客户端

*/

public GRPCClient(Channel channel) {

// 'channel'在这里是Channel,而不是ManagedChannel,所有它负责关闭

// 向代码传递通道可以使代码更容易测试,也可以更容易地重用通道。

// 同时这里创建的是同步(阻塞)RPC服务。

greeterBlocStub = GreeterGrpc.newBlockingStub(channel);

}

/** 向服务端发送请求 */

public void greet(String name) {

System.out.println("Will try to greet " + name + " ...");

HelloRequest request = HelloRequest.newBuilder().setName(name).build();

HelloReply response;

try {

response = greeterBlocStub.sayHello(request);

} catch (StatusRuntimeException e) {

System.out.println("WARNING, RPC failed: Status=" + e.getStatus());

return;

}

System.out.println("Greeting: " + response.getMessage());

}

/**

* 客户端启动入口,可以支持填写2个参数,否则使用默认值。 第1个参数是用户名。 第2个参数是目标服务器,格式IP:Port。

*/

public static void main(String[] args) throws Exception {

String user = "world";

// 访问本机在50051端口上运行的服务

String target = "localhost:50051";

// 命令行用法帮助,允许将用户名和目标服务器作为命令行参数传入。

if (args.length > 0) {

if ("--help".equals(args[0])) {

System.err.println("Usage: [name [target]]");

System.err.println("");

System.err.println(" name The name you wish to be greeted by. Defaults to " + user);

System.err.println(" target The server to connect to. Defaults to " + target);

System.exit(1);

}

user = args[0];

}

if (args.length > 1) {

target = args[1];

}

// 创建到服务器的通信通道,通道是线程安全的和可重用的。

// 通常在应用程序开始时创建通道,并重用直到应用程序关闭。

ManagedChannel channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build();

try {

GRPCClient client = new GRPCClient(channel);

client.greet(user);

} finally {

// ManagedChannel使用像线程和TCP连接这样的资源。

// 为了防止泄漏这些资源,通道应该在不再使用时关闭。

channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);

}

}

}

4.4.客户端启动

通过执行GRPCClient的main方法,

就能启动客户端了,

通过gRPC调用服务端成功后打印日志:

Will try to greet world ...

Greeting: Hello world

5.参考文档

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java + gRPC + grpc-gateway 的实践主要分为以下几个步骤: 1. 定义 proto 文件 在 proto 文件中定义需要调用的服务以及方法,同时指定请求和响应的数据类型。例如: ``` syntax = "proto3"; package example; service ExampleService { rpc ExampleMethod (ExampleRequest) returns (ExampleResponse) {} } message ExampleRequest { string example_field = 1; } message ExampleResponse { string example_field = 1; } ``` 2. 使用 protoc 编译 proto 文件 使用 protoc 编译 proto 文件,生成 Java 代码。例如: ``` protoc --java_out=./src/main/java ./example.proto ``` 3. 实现 gRPC 服务Java 代码中实现定义的 gRPC 服务,例如: ``` public class ExampleServiceImpl extends ExampleServiceGrpc.ExampleServiceImplBase { @Override public void exampleMethod(ExampleRequest request, StreamObserver<ExampleResponse> responseObserver) { // 实现具体逻辑 ExampleResponse response = ExampleResponse.newBuilder().setExampleField("example").build(); responseObserver.onNext(response); responseObserver.onCompleted(); } } ``` 4. 启动 gRPC 服务器 使用 gRPC 提供的 ServerBuilder 构建 gRPC 服务器,并启动服务器。例如: ``` Server server = ServerBuilder.forPort(8080).addService(new ExampleServiceImpl()).build(); server.start(); ``` 5. 集成 grpc-gateway 使用 grpc-gateway 可以将 gRPC 服务转换为 HTTP/JSON API。在 proto 文件中添加以下内容: ``` import "google/api/annotations.proto"; service ExampleService { rpc ExampleMethod (ExampleRequest) returns (ExampleResponse) { option (google.api.http) = { post: "/example" body: "*" }; } } ``` 在 Java 代码中添加以下内容: ``` Server httpServer = ServerBuilder.forPort(8081).addService(new ExampleServiceImpl()).build(); httpServer.start(); String grpcServerUrl = "localhost:8080"; String httpServerUrl = "localhost:8081"; ProxyServerConfig proxyConfig = new ProxyServerConfig(grpcServerUrl, httpServerUrl, "/example"); HttpProxyServer httpProxyServer = new HttpProxyServer(proxyConfig); httpProxyServer.start(); ``` 6. 测试 使用 HTTP/JSON API 调用 gRPC 服务,例如: ``` POST http://localhost:8081/example Content-Type: application/json { "example_field": "example" } ``` 以上就是 Java + gRPC + grpc-gateway 的实践步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值