1. gRPC概述与环境规划
gRPC是Google开源的高性能RPC框架,基于HTTP/2协议和Protocol Buffers序列化协议。它支持多种编程语言,具有高性能、低延迟、双向流等特点,广泛应用于微服务架构和分布式系统。更多学习教程www.fgedu.net.cn
1.1 gRPC版本说明
gRPC目前主要版本为1.62,本教程以gRPC 1.62为例进行详细讲解。
$ java -jar grpc-server.jar –version
gRPC Java 1.62.0
# 查看protoc版本
$ protoc –version
libprotoc 25.1
# 查看服务状态
$ grpcurl -plaintext 192.168.1.51:50051 list
# 输出示例:
fgedu.FgeduService
grpc.health.v1.Health
grpc.reflection.v1.ServerReflection
1.2 环境规划
本次安装环境规划如下:
IP地址:192.168.1.51
gRPC端口:50051
HTTP端口:8080
安装目录:/opt/grpc
日志目录:/data/grpc/logs
配置目录:/opt/grpc/conf
Java环境:
JDK版本:OpenJDK 17
JAVA_HOME:/usr/lib/jvm/java-17
JVM堆大小:2GB
Protocol Buffers:
protoc版本:25.1
1.3 gRPC核心特性
1. 高性能:基于HTTP/2和Protobuf,性能优异
2. 多语言支持:支持Java、Go、Python、C++等
3. 双向流:支持客户端和服务端双向流式传输
4. 强类型接口:使用Protobuf定义接口,类型安全
5. 拦截器:支持客户端和服务端拦截器
6. 负载均衡:支持多种负载均衡策略
7. 健康检查:内置健康检查协议
8. 服务反射:支持服务发现和调试
2. 硬件环境要求与检查
在安装gRPC之前,需要对服务器硬件环境进行全面检查。学习交流加群风哥微信: itpux-com
2.1 最低硬件要求
CPU:2核心
内存:2GB
磁盘:10GB
推荐配置(生产环境):
CPU:4核心以上
内存:8GB以上
磁盘:50GB以上
高可用配置:
CPU:8核心以上
内存:16GB以上
磁盘:100GB以上
2.2 Java环境检查
$ java -version
openjdk version “17.0.9” 9.0.4
OpenJDK Runtime Environment (Temurin-17.0.9+9) (build 17.0.9+9)
OpenJDK 64-Bit Server VM (build 17.0.9+9, mixed mode, sharing)
# 检查JAVA_HOME
$ echo $JAVA_HOME
/usr/lib/jvm/java-17
# 查看Java安装路径
$ which java
/usr/bin/java
2.3 Protocol Buffers安装
# cd /usr/local/src
# wget https://github.com/protocolbuffers/protobuf/releases/download/v25.1/protoc-25.1-linux-x86_64.zip
# 解压安装
# unzip protoc-25.1-linux-x86_64.zip -d /usr/local/protoc
# 配置环境变量
# vi /etc/profile.d/protoc.sh
export PATH=$PATH:/usr/local/protoc/bin
# 使配置生效
# source /etc/profile.d/protoc.sh
# 验证安装
$ protoc –version
libprotoc 25.1
2.4 系统环境检查
# cat /etc/redhat-release
Red Hat Enterprise Linux release 8.8 (Ootpa)
# 检查内存信息
# free -h
total used free shared buff/cache available
Mem: 15Gi 1.0Gi 13Gi 256Mi 1.0Gi 14Gi
Swap: 7Gi 0B 7Gi
# 检查磁盘空间
# df -h
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/vg_system-lv_root 100G 5.0G 95G 5% /
/dev/mapper/vg_data-lv_data 500G 50G 450G 10% /data
3. gRPC安装步骤
本节详细介绍gRPC 1.62的安装过程。学习交流加群风哥QQ113257174
3.1 创建用户和目录
# groupadd -g 1012 grpc
# useradd -u 1012 -g grpc -d /opt/grpc -s /bin/bash grpc
# passwd grpc
# 创建目录
# mkdir -p /opt/grpc
# mkdir -p /data/grpc/{logs,proto}
# 设置目录权限
# chown -R grpc:grpc /opt/grpc
# chown -R grpc:grpc /data/grpc
3.2 安装grpcurl工具
# cd /usr/local/src
# wget https://github.com/fullstorydev/grpcurl/releases/download/v1.8.9/grpcurl_1.8.9_linux_x86_64.tar.gz
# 解压安装
# tar -xzf grpcurl_1.8.9_linux_x86_64.tar.gz -C /usr/local/bin/
# 验证安装
$ grpcurl –version
grpcurl 1.8.9
# 使用grpcurl测试服务
$ grpcurl -plaintext 192.168.1.51:50051 list
# 输出示例:
fgedu.FgeduService
grpc.health.v1.Health
3.3 配置环境变量
$ vi ~/.bash_profile
# 添加以下内容
export GRPC_HOME=/opt/grpc
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export PATH=$JAVA_HOME/bin:$PATH:/usr/local/protoc/bin
# 使配置生效
$ source ~/.bash_profile
# 验证环境变量
$ echo $GRPC_HOME
/opt/grpc
3.4 Maven项目配置
3.5 定义Proto文件
$ vi /data/grpc/proto/fgedu.proto
syntax = “proto3”;
package fgedu;
option java_multiple_files = true;
option java_package = “com.fgedu.grpc”;
option java_outer_classname = “FgeduProto”;
// 服务定义
service FgeduService {
// 简单RPC
rpc SayHello (HelloRequest) returns (HelloReply) {}
// 服务端流式RPC
rpc ListUsers (UserQuery) returns (stream User) {}
// 客户端流式RPC
rpc UploadUsers (stream User) returns (UploadResult) {}
// 双向流式RPC
rpc Chat (stream ChatMessage) returns (stream ChatMessage) {}
}
// 请求消息
message HelloRequest {
string name = 1;
}
// 响应消息
message HelloReply {
string message = 1;
}
// 用户查询
message UserQuery {
string name = 1;
int32 min_age = 2;
int32 max_age = 3;
}
// 用户信息
message User {
int64 id = 1;
string name = 2;
int32 age = 3;
string email = 4;
}
// 上传结果
message UploadResult {
int32 success_count = 1;
int32 fail_count = 2;
}
// 聊天消息
message ChatMessage {
string from = 1;
string to = 2;
string content = 3;
int64 timestamp = 4;
}
# 编译proto文件
$ protoc –java_out=/data/grpc/proto –grpc-java_out=/data/grpc/proto /data/grpc/proto/fgedu.proto
3.6 配置防火墙
# firewall-cmd –permanent –add-port=50051/tcp
success
# firewall-cmd –permanent –add-port=8080/tcp
success
# firewall-cmd –reload
success
4. gRPC参数配置
gRPC参数配置是性能优化的关键步骤,直接影响系统性能。更多学习教程公众号风哥教程itpux_com
4.1 服务端配置
public class GrpcServerConfig {
public Server buildServer(int port) {
return ServerBuilder.forPort(port)
.executor(Executors.newFixedThreadPool(200))
.addService(new FgeduServiceImpl())
.addService(ProtoReflectionService.newInstance())
.addService(new HealthServiceImpl())
.intercept(new ServerInterceptorImpl())
.maxInboundMessageSize(16 * 1024 * 1024) // 16MB
.maxInboundMetadataSize(1 * 1024 * 1024) // 1MB
.keepAliveTime(30, TimeUnit.SECONDS)
.keepAliveTimeout(10, TimeUnit.SECONDS)
.permitKeepAliveWithoutCalls(true)
.permitKeepAliveTime(5, TimeUnit.MINUTES)
.build();
}
}
# application.yml配置
grpc:
server:
port: 50051
max-inbound-message-size: 16777216
max-inbound-metadata-size: 1048576
keep-alive-time: 30s
keep-alive-timeout: 10s
permit-keep-alive-without-calls: true
permit-keep-alive-time: 5m
4.2 客户端配置
public class GrpcClientConfig {
public ManagedChannel buildChannel(String host, int port) {
return ManagedChannelBuilder.forAddress(host, port)
.usePlaintext()
.executor(Executors.newFixedThreadPool(50))
.maxInboundMessageSize(16 * 1024 * 1024)
.keepAliveTime(30, TimeUnit.SECONDS)
.keepAliveTimeout(10, TimeUnit.SECONDS)
.keepAliveWithoutCalls(true)
.idleTimeout(30, TimeUnit.MINUTES)
.intercept(new ClientInterceptorImpl())
.defaultLoadBalancingPolicy(“round_robin”)
.build();
}
}
# application.yml配置
grpc:
client:
fgedu-service:
address: static://192.168.1.51:50051,192.168.1.52:50051,192.168.1.53:50051
enable-keep-alive: true
keep-alive-time: 30s
keep-alive-timeout: 10s
max-inbound-message-size: 16777216
default-load-balancing-policy: round_robin
4.3 Netty配置
public class NettyServerConfig {
public Server buildNettyServer(int port) {
return NettyServerBuilder.forPort(port)
.bossEventLoopGroup(new NioEventLoopGroup(1))
.workerEventLoopGroup(new NioEventLoopGroup(8))
.channelType(NioServerSocketChannel.class)
.withChildOption(ChannelOption.SO_KEEPALIVE, true)
.withChildOption(ChannelOption.TCP_NODELAY, true)
.withChildOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
.withChildOption(ChannelOption.SO_RCVBUF, 1024 * 1024)
.withChildOption(ChannelOption.WRITE_BUFFER_WATER_MARK,
new WriteBufferWaterMark(32 * 1024, 1024 * 1024))
.build();
}
}
# Netty客户端配置
public ManagedChannel buildNettyChannel(String host, int port) {
return NettyChannelBuilder.forAddress(host, port)
.eventLoopGroup(new NioEventLoopGroup(4))
.channelType(NioSocketChannel.class)
.withOption(ChannelOption.SO_KEEPALIVE, true)
.withOption(ChannelOption.TCP_NODELAY, true)
.withOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
.withOption(ChannelOption.SO_RCVBUF, 1024 * 1024)
.build();
}
5. 服务开发与部署
gRPC提供了完善的服务开发框架,本节介绍常用的开发方法。from:www.itpux.com
5.1 服务端实现
public class FgeduServiceImpl extends FgeduServiceGrpc.FgeduServiceImplBase {
private final UserService userService;
public FgeduServiceImpl(UserService userService) {
this.userService = userService;
}
// 简单RPC
@Override
public void sayHello(HelloRequest request, StreamObserver
String message = “Hello, ” + request.getName() + “! Welcome to gRPC.”;
HelloReply reply = HelloReply.newBuilder()
.setMessage(message)
.build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
// 服务端流式RPC
@Override
public void listUsers(UserQuery request, StreamObserver
List
for (User user : users) {
responseObserver.onNext(user);
}
responseObserver.onCompleted();
}
// 客户端流式RPC
@Override
public StreamObserver
return new StreamObserver
private int successCount = 0;
private int failCount = 0;
@Override
public void onNext(User user) {
try {
userService.save(user);
successCount++;
} catch (Exception e) {
failCount++;
}
}
@Override
public void onError(Throwable t) {
responseObserver.onError(t);
}
@Override
public void onCompleted() {
UploadResult result = UploadResult.newBuilder()
.setSuccessCount(successCount)
.setFailCount(failCount)
.build();
responseObserver.onNext(result);
responseObserver.onCompleted();
}
};
}
// 双向流式RPC
@Override
public StreamObserver
return new StreamObserver
@Override
public void onNext(ChatMessage message) {
// 处理消息并回复
ChatMessage reply = ChatMessage.newBuilder()
.setFrom(“Server”)
.setTo(message.getFrom())
.setContent(“Received: ” + message.getContent())
.setTimestamp(System.currentTimeMillis())
.build();
responseObserver.onNext(reply);
}
@Override
public void onError(Throwable t) {
responseObserver.onError(t);
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
}
5.2 客户端实现
public class FgeduClient {
private final ManagedChannel channel;
private final FgeduServiceGrpc.FgeduServiceBlockingStub blockingStub;
private final FgeduServiceGrpc.FgeduServiceStub asyncStub;
public FgeduClient(String host, int port) {
this.channel = ManagedChannelBuilder.forAddress(host, port)
.usePlaintext()
.build();
this.blockingStub = FgeduServiceGrpc.newBlockingStub(channel);
this.asyncStub = FgeduServiceGrpc.newStub(channel);
}
// 简单RPC调用
public String sayHello(String name) {
HelloRequest request = HelloRequest.newBuilder()
.setName(name)
.build();
HelloReply reply = blockingStub.sayHello(request);
return reply.getMessage();
}
// 服务端流式调用
public void listUsers(UserQuery query) {
Iterator
while (users.hasNext()) {
User user = users.next();
System.out.println(“User: ” + user.getName());
}
}
// 客户端流式调用
public void uploadUsers(List
CountDownLatch latch = new CountDownLatch(1);
StreamObserver
new StreamObserver
@Override
public void onNext(UploadResult result) {
System.out.println(“Success: ” + result.getSuccessCount());
}
@Override
public void onError(Throwable t) {
latch.countDown();
}
@Override
public void onCompleted() {
latch.countDown();
}
});
for (User user : users) {
requestObserver.onNext(user);
}
requestObserver.onCompleted();
latch.await(1, TimeUnit.MINUTES);
}
public void shutdown() throws InterruptedException {
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
}
}
5.3 拦截器实现
public class ServerInterceptorImpl implements ServerInterceptor {
@Override
public
ServerCall
Metadata headers,
ServerCallHandler
// 获取请求头
String token = headers.get(Metadata.Key.of(“token”, Metadata.ASCII_STRING_MARSHALLER));
// 日志记录
System.out.println(“Received call: ” + call.getMethodDescriptor().getFullMethodName());
// 验证token
if (token == null || !validateToken(token)) {
call.close(Status.UNAUTHENTICATED.withDescription(“Invalid token”), headers);
return new ServerCall.Listener
}
return next.startCall(call, headers);
}
private boolean validateToken(String token) {
return “fgedu-token”.equals(token);
}
}
# 客户端拦截器
public class ClientInterceptorImpl implements ClientInterceptor {
@Override
public
MethodDescriptor
CallOptions callOptions,
Channel next) {
return new ForwardingClientCall.SimpleForwardingClientCall
next.newCall(method, callOptions)) {
@Override
public void start(Listener
// 添加请求头
headers.put(Metadata.Key.of(“token”, Metadata.ASCII_STRING_MARSHALLER), “fgedu-token”);
super.start(responseListener, headers);
}
};
}
}
6. 集群配置
gRPC支持多种负载均衡策略,本节介绍常用的集群配置方法。更多学习教程www.fgedu.net.cn
6.1 负载均衡配置
ManagedChannel channel = ManagedChannelBuilder.forTarget(“fgedu-service”)
.defaultLoadBalancingPolicy(“round_robin”)
.build();
# 可用的负载均衡策略:
# – pick_first:选择第一个可用地址
# – round_robin:轮询
# – weighted_round_robin:加权轮询(需要配置权重)
# 使用NameResolver解析服务地址
public class FgeduNameResolver extends NameResolver {
@Override
public void start(Listener listener) {
List
servers.add(new EquivalentAddressGroup(
new InetSocketAddress(“192.168.1.51”, 50051)));
servers.add(new EquivalentAddressGroup(
new InetSocketAddress(“192.168.1.52”, 50051)));
servers.add(new EquivalentAddressGroup(
new InetSocketAddress(“192.168.1.53”, 50051)));
listener.onAddresses(servers, Attributes.EMPTY);
}
@Override
public void refresh() {
// 刷新服务地址
}
@Override
public void shutdown() {
// 关闭
}
}
# 注册NameResolver
NameResolverRegistry.getDefaultRegistry().register(
new NameResolverProvider() {
@Override
public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
return new FgeduNameResolver();
}
@Override
protected boolean isAvailable() {
return true;
}
@Override
protected int priority() {
return 5;
}
@Override
public String getDefaultScheme() {
return “fgedu”;
}
});
6.2 健康检查配置
public class HealthServiceImpl extends HealthGrpc.HealthImplBase {
private final Map
new ConcurrentHashMap<>();
public HealthServiceImpl() {
statusMap.put(“fgedu.FgeduService”, HealthCheckResponse.ServingStatus.SERVING);
}
@Override
public void check(HealthCheckRequest request,
StreamObserver
String service = request.getService();
HealthCheckResponse.ServingStatus status = statusMap.get(service);
if (status == null) {
responseObserver.onError(Status.NOT_FOUND
.withDescription(“Service not found: ” + service)
.asRuntimeException());
return;
}
HealthCheckResponse response = HealthCheckResponse.newBuilder()
.setStatus(status)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
@Override
public void watch(HealthCheckRequest request,
StreamObserver
// 实现健康检查监听
}
public void setStatus(String service, HealthCheckResponse.ServingStatus status) {
statusMap.put(service, status);
}
}
# 使用grpcurl检查健康状态
$ grpcurl -plaintext 192.168.1.51:50051 grpc.health.v1.Health/Check
# 输出示例:
{
“status”: “SERVING”
}
7. 安全配置
gRPC提供了完善的安全框架,本节介绍常用的安全配置方法。学习交流加群风哥微信: itpux-com
7.1 配置TLS
$ keytool -genkeypair -alias grpc -keyalg RSA -keysize 2048 \
-keystore /opt/grpc/ssl/server.jks \
-validity 365 -storepass fgedu123 -keypass fgedu123 \
-dname “CN=fgedudb01.fgedu.net.cn,OU=IT,O=FGedu,L=BJ,ST=BJ,C=CN”
# 导出证书
$ keytool -export -alias grpc \
-keystore /opt/grpc/ssl/server.jks \
-file /opt/grpc/ssl/server.crt -storepass fgedu123
# 服务端TLS配置
public Server buildTlsServer(int port) throws Exception {
InputStream certChain = new FileInputStream(“/opt/grpc/ssl/server.crt”);
InputStream privateKey = new FileInputStream(“/opt/grpc/ssl/server.key”);
return ServerBuilder.forPort(port)
.useTransportSecurity(certChain, privateKey)
.addService(new FgeduServiceImpl())
.build();
}
# 客户端TLS配置
public ManagedChannel buildTlsChannel(String host, int port) throws Exception {
InputStream trustedCert = new FileInputStream(“/opt/grpc/ssl/server.crt”);
return ManagedChannelBuilder.forAddress(host, port)
.useTransportSecurity()
.build();
}
# 使用TLS调用
$ grpcurl -insecure 192.168.1.51:50051 list
7.2 配置认证
public class AuthClientInterceptor implements ClientInterceptor {
private final String token;
public AuthClientInterceptor(String token) {
this.token = token;
}
@Override
public
MethodDescriptor
CallOptions callOptions,
Channel next) {
return new ForwardingClientCall.SimpleForwardingClientCall
next.newCall(method, callOptions)) {
@Override
public void start(Listener
headers.put(Metadata.Key.of(“authorization”, Metadata.ASCII_STRING_MARSHALLER),
“Bearer ” + token);
super.start(responseListener, headers);
}
};
}
}
# 服务端认证拦截器
public class AuthServerInterceptor implements ServerInterceptor {
@Override
public
ServerCall
Metadata headers,
ServerCallHandler
String authorization = headers.get(
Metadata.Key.of(“authorization”, Metadata.ASCII_STRING_MARSHALLER));
if (authorization == null || !validateToken(authorization)) {
call.close(Status.UNAUTHENTICATED.withDescription(“Invalid token”), headers);
return new ServerCall.Listener
}
return next.startCall(call, headers);
}
private boolean validateToken(String authorization) {
return authorization.startsWith(“Bearer “) &&
authorization.substring(7).equals(“fgedu-token”);
}
}
8. 监控与日志
gRPC提供了完善的监控和日志功能,本节介绍常用的监控配置方法。更多学习教程公众号风哥教程itpux_com
8.1 服务反射
Server server = ServerBuilder.forPort(50051)
.addService(new FgeduServiceImpl())
.addService(ProtoReflectionService.newInstance())
.build();
# 使用grpcurl查看服务列表
$ grpcurl -plaintext 192.168.1.51:50051 list
# 输出示例:
fgedu.FgeduService
grpc.health.v1.Health
grpc.reflection.v1.ServerReflection
# 查看服务描述
$ grpcurl -plaintext 192.168.1.51:50051 describe fgedu.FgeduService
# 输出示例:
fgedu.FgeduService is a service:
service FgeduService {
rpc SayHello ( .fgedu.HelloRequest ) returns ( .fgedu.HelloReply );
rpc ListUsers ( .fgedu.UserQuery ) returns ( stream .fgedu.User );
}
# 调用服务
$ grpcurl -plaintext -d ‘{“name”: “World”}’ 192.168.1.51:50051 fgedu.FgeduService/SayHello
# 输出示例:
{
“message”: “Hello, World! Welcome to gRPC.”
}
8.2 监控指标
# 实现监控拦截器
public class MetricsServerInterceptor implements ServerInterceptor {
private final Counter requestCounter = Counter.build()
.name(“grpc_requests_total”)
.help(“Total gRPC requests”)
.labelNames(“method”)
.register();
private final Histogram requestLatency = Histogram.build()
.name(“grpc_request_duration_seconds”)
.help(“gRPC request latency”)
.labelNames(“method”)
.register();
@Override
public
ServerCall
Metadata headers,
ServerCallHandler
String method = call.getMethodDescriptor().getFullMethodName();
Histogram.Timer timer = requestLatency.labels(method).startTimer();
requestCounter.labels(method).inc();
return new ForwardingServerCallListener.SimpleForwardingServerCallListener
next.startCall(call, headers)) {
@Override
public void onComplete() {
timer.observeDuration();
super.onComplete();
}
};
}
}
# 启动Prometheus HTTP Server
HTTPServer server = new HTTPServer(9090);
8.3 日志配置
$ vi /opt/grpc/conf/logback.xml
# 查看日志
$ tail -f /data/grpc/logs/grpc.log
# 输出示例:
2026-04-04 10:00:00,000 [main] INFO io.grpc.Server – Server started on port 50051
2026-04-04 10:00:01,000 [grpc-default-executor-0] INFO FgeduServiceImpl – Received SayHello request: World
9. 升级与迁移
gRPC升级和迁移是运维工作中的重要环节,需要仔细规划和执行。from:www.itpux.com
9.1 版本升级
$ java -jar grpc-server.jar –version
gRPC Java 1.62.0
# 备份配置
$ cp -r /opt/grpc/conf /backup/grpc/conf_$(date +%Y%m%d)
# 停止服务
$ pkill -f grpc-server
# 更新依赖版本
# vi pom.xml
# 重新编译
$ mvn clean package -DskipTests
# 启动新版本
$ java -jar grpc-server.jar &
# 验证版本
$ java -jar grpc-server.jar –version
gRPC Java 1.63.0
9.2 Proto文件迁移
# 使用proto文件版本号管理接口变更
syntax = “proto3”;
package fgedu.v2; // 版本号
option java_package = “com.fgedu.grpc.v2”;
// 新版本服务
service FgeduServiceV2 {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayGoodbye (GoodbyeRequest) returns (GoodbyeReply) {} // 新增方法
}
// 保持向后兼容
message HelloRequest {
string name = 1;
string title = 2; // 新增字段
}
message HelloReply {
string message = 1;
int64 timestamp = 2; // 新增字段
}
# 客户端逐步迁移
// 1. 新客户端使用新版本服务
FgeduServiceV2Grpc.FgeduServiceV2BlockingStub stubV2 =
FgeduServiceV2Grpc.newBlockingStub(channel);
// 2. 旧客户端继续使用旧版本服务
FgeduServiceGrpc.FgeduServiceBlockingStub stubV1 =
FgeduServiceGrpc.newBlockingStub(channel);
// 3. 所有客户端迁移完成后下线旧版本服务
10. 生产环境实战案例
本节提供一个完整的生产环境配置案例,帮助读者更好地理解gRPC的实际应用。更多学习教程www.fgedu.net.cn
10.1 生产环境完整配置
public class FgeduGrpcServer {
public static void main(String[] args) throws Exception {
Server server = NettyServerBuilder.forPort(50051)
.bossEventLoopGroup(new NioEventLoopGroup(1))
.workerEventLoopGroup(new NioEventLoopGroup(8))
.executor(Executors.newFixedThreadPool(500))
.addService(new FgeduServiceImpl())
.addService(new HealthServiceImpl())
.addService(ProtoReflectionService.newInstance())
.intercept(new AuthServerInterceptor())
.intercept(new MetricsServerInterceptor())
.intercept(new LoggingServerInterceptor())
.maxInboundMessageSize(16 * 1024 * 1024)
.keepAliveTime(30, TimeUnit.SECONDS)
.keepAliveTimeout(10, TimeUnit.SECONDS)
.permitKeepAliveWithoutCalls(true)
.permitKeepAliveTime(5, TimeUnit.MINUTES)
.build();
server.start();
server.awaitTermination();
}
}
# 生产环境客户端配置
public class FgeduGrpcClient {
private static final List
“192.168.1.51:50051”,
“192.168.1.52:50051”,
“192.168.1.53:50051”
);
public ManagedChannel createChannel() {
return ManagedChannelBuilder.forTarget(“fgedu-service”)
.defaultLoadBalancingPolicy(“round_robin”)
.nameResolverFactory(new FgeduNameResolverFactory(SERVERS))
.maxInboundMessageSize(16 * 1024 * 1024)
.keepAliveTime(30, TimeUnit.SECONDS)
.keepAliveTimeout(10, TimeUnit.SECONDS)
.keepAliveWithoutCalls(true)
.idleTimeout(30, TimeUnit.MINUTES)
.intercept(new AuthClientInterceptor(“fgedu-token”))
.intercept(new MetricsClientInterceptor())
.build();
}
}
# 创建systemd服务
$ vi /etc/systemd/system/grpc-server.service
[Unit]
Description=gRPC Server
After=network.target
[Service]
Type=simple
User=grpc
Group=grpc
ExecStart=/usr/bin/java -Xms2g -Xmx2g -jar /opt/grpc/grpc-server.jar
Restart=on-failure
[Install]
WantedBy=multi-user.target
# 启用服务
# systemctl enable grpc-server
# systemctl start grpc-server
10.2 高可用集群部署
# gRPC Server节点
# 192.168.1.51:50051
# 192.168.1.52:50051
# 192.168.1.53:50051
# Nginx负载均衡配置
# vi /etc/nginx/nginx.conf
stream {
upstream grpc_backend {
least_conn;
server 192.168.1.51:50051;
server 192.168.1.52:50051;
server 192.168.1.53:50051;
}
server {
listen 50051 http2;
proxy_pass grpc_backend;
proxy_connect_timeout 5s;
proxy_timeout 30s;
}
}
# 客户端连接Nginx
ManagedChannel channel = ManagedChannelBuilder
.forAddress(“192.168.1.100”, 50051)
.usePlaintext()
.build();
10.3 性能调优实战
# vi /etc/sysctl.d/99-grpc.conf
# 网络优化
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# 使配置生效
# sysctl -p /etc/sysctl.d/99-grpc.conf
# JVM优化
JAVA_OPTS=”-server -Xms4g -Xmx4g -Xmn2g”
JAVA_OPTS=”${JAVA_OPTS} -XX:+UseG1GC -XX:MaxGCPauseMillis=200″
JAVA_OPTS=”${JAVA_OPTS} -XX:InitiatingHeapOccupancyPercent=35″
JAVA_OPTS=”${JAVA_OPTS} -XX:+ParallelRefProcEnabled”
JAVA_OPTS=”${JAVA_OPTS} -Dio.netty.leakDetection.level=disabled”
# Netty优化
serverBootstrap.option(ChannelOption.SO_BACKLOG, 32768)
serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true)
serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true)
serverBootstrap.childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
serverBootstrap.childOption(ChannelOption.SO_RCVBUF, 1024 * 1024)
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
