Appearance
JsonToGrpc 网关过滤器工厂
概述
JsonToGrpc 它能够将 JSON 格式的请求负载转换为 gRPC 请求。这个过滤器解决了微服务架构中不同协议之间的通信问题,特别是当前端使用 HTTP/JSON,而后端服务使用 gRPC 时的协议转换需求。
业务场景
在现代微服务架构中,我们经常遇到以下场景:
- 前端应用:使用 HTTP/JSON 协议进行 API 调用
- 后端微服务:基于性能考虑使用 gRPC 协议
- 网关层:需要在两种协议之间进行转换
JsonToGrpc 过滤器让您可以在不修改前端代码的情况下,将后端服务迁移到高性能的 gRPC 协议。
配置参数
JsonToGrpc 过滤器支持以下配置参数:
必需参数
protoDescriptor: Proto 描述符文件路径protoFile: Proto 定义文件路径service: 处理请求的服务短名称method: 服务中处理请求的方法名称
生成 Proto 描述符文件
Proto 描述符文件可以使用 protoc 工具生成,需要指定 --descriptor_set_out 标志:
bash
protoc --proto_path=src/main/resources/proto/ \
--descriptor_set_out=src/main/resources/proto/hello.pb \
src/main/resources/proto/hello.proto当前版本不支持 `streaming` 流式传输。
配置示例
Java DSL 配置
kotlin
@Configuration
class GatewayRouteConfig {
@Bean
fun routes(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("json-grpc") { r ->
r.path("/json/hello")
.filters { f ->
val protoDescriptor = "file:src/main/proto/hello.pb"
val protoFile = "file:src/main/proto/hello.proto"
val service = "HelloService"
val method = "hello"
f.jsonToGRPC(protoDescriptor, protoFile, service, method)
}
.uri("https://localhost:6565/testhello")
}
.build()
}
}java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("json-grpc", r -> r.path("/json/hello").filters(f -> {
String protoDescriptor = "file:src/main/proto/hello.pb";
String protoFile = "file:src/main/proto/hello.proto";
String service = "HelloService";
String method = "hello";
return f.jsonToGRPC(protoDescriptor, protoFile, service, method);
}).uri("https://localhost:6565/testhello"))
.build();
}YAML 配置
yaml
spring:
cloud:
gateway:
routes:
- id: json-grpc
uri: https://localhost:6565/testhello
predicates:
- Path=/json/**
filters:
- name: JsonToGrpc
args:
protoDescriptor: file:proto/hello.pb
protoFile: file:proto/hello.proto
service: HelloService
method: hello工作原理
当通过网关向 /json/hello 发送请求时,处理流程如下:
- 接收 JSON 请求:网关接收来自客户端的 HTTP JSON 请求
- 协议转换:使用
hello.proto中的定义将 JSON 转换为 gRPC 格式 - 服务调用:向
HelloService/hello发送 gRPC 请求 - 响应转换:将 gRPC 响应转换回 JSON 格式
- 返回结果:将 JSON 响应返回给客户端
SSL/TLS 配置
默认情况下,JsonToGrpc 过滤器使用默认的 TrustManagerFactory 创建 NettyChannel。您可以通过创建 GrpcSslConfigurer 类型的 Bean 来自定义 TrustManager:
kotlin
@Configuration
class GrpcSslConfiguration {
@Bean
fun grpcSslContext(): GrpcSslContext {
// 创建自定义的 TrustManager
val trustManager = createCustomTrustManager()
return GrpcSslContext(trustManager)
}
private fun createCustomTrustManager(): TrustManager {
// 实现自定义的信任管理器逻辑
// 注意:在生产环境中不要使用 trustAllCerts()
return trustAllCerts()
}
}java
@Configuration
public class GRPCLocalConfiguration {
@Bean
public GRPCSSLContext sslContext() {
TrustManager trustManager = trustAllCerts();
return new GRPCSSLContext(trustManager);
}
}在生产环境中,请确保使用适当的 SSL/TLS 配置,不要使用 `trustAllCerts()` 这样的不安全配置。
实际应用示例
场景:电商订单服务
假设我们有一个电商系统,前端需要创建订单,后端使用 gRPC 服务处理订单逻辑:
1. 定义 Proto 文件
protobuf
// order.proto
syntax = "proto3";
package order;
service OrderService {
rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse);
}
message CreateOrderRequest {
string user_id = 1;
repeated OrderItem items = 2;
string delivery_address = 3;
}
message OrderItem {
string product_id = 1;
int32 quantity = 2;
double price = 3;
}
message CreateOrderResponse {
string order_id = 1;
string status = 2;
double total_amount = 3;
}2. 网关配置
yaml
spring:
cloud:
gateway:
routes:
- id: order-service
uri: grpc://localhost:9090
predicates:
- Path=/api/orders/**
filters:
- name: JsonToGrpc
args:
protoDescriptor: file:proto/order.pb
protoFile: file:proto/order.proto
service: OrderService
method: CreateOrder
- RewritePath=/api/orders/create, /order.OrderService/CreateOrder3. 前端调用示例
javascript
// 前端 JavaScript 代码
const createOrder = async (orderData) => {
const response = await fetch("/api/orders/create", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
user_id: "user123",
items: [
{
product_id: "prod456",
quantity: 2,
price: 29.99,
},
],
delivery_address: "123 Main St, City, Country",
}),
});
return await response.json();
};注意事项与最佳实践
JsonToGrpc 过滤器主要用于单向的请求-响应模式,不支持 gRPC 的流式传输功能。
最佳实践
- Proto 文件管理:将 Proto 文件集中管理,确保版本一致性
- 错误处理:合理配置错误处理机制,确保协议转换异常能够正确返回给客户端
- 性能监控:监控转换过程的性能,避免成为系统瓶颈
- 安全配置:在生产环境中正确配置 SSL/TLS
常见问题
Details
协议转换失败的排查步骤
- 检查 Proto 文件路径是否正确
- 验证 Proto 描述符文件是否最新
- 确认服务名称和方法名称拼写正确
- 检查 JSON 数据结构是否与 Proto 定义匹配
总结
JsonToGrpc 网关过滤器工厂是 Spring Cloud Gateway 中实现协议转换的重要工具,它解决了微服务架构中 HTTP/JSON 与 gRPC 协议之间的转换问题。通过合理的配置和使用,可以让您在享受 gRPC 高性能的同时,保持前端 API 的简洁性。
在设计微服务架构时,可以考虑在网关层统一处理协议转换,这样既能保持各个服务的技术栈独立性,又能提供统一的 API 接口。