gpt4 book ai didi

java - gRPC 在发送请求之前覆盖remote-addr 属性

转载 作者:行者123 更新时间:2023-12-02 08:50:13 25 4
gpt4 key购买 nike

我有一个相当奇怪的用例,我想在发送请求之前覆盖客户端的属性 Grpc.TRANSPORT_ATTR_REMOTE_ADDR

在服务器端,我接收来自许多客户端的请求,并使用此属性提取它们的来源。然后,我将源添加到缓存中,以维持服务器上的状态,直到缓存过期。

现在我想做一些服务器端的负载测试,并且我想在同一主机上启动许多客户端来执行此操作。我尝试在 docker 容器中启动这些客户端,但是请求到达服务器时的 remote-addr 属性始终是运行容器的计算机的外部 ip,这意味着它不是唯一的并将被服务器以这种方式对待。

以下是我获取服务器上的原始 IP 的方法:

@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(final ServerCall<ReqT, RespT> call,
final Metadata headers,
final ServerCallHandler<ReqT, RespT> next) {

if (call.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR) != null) {
final InetSocketAddress remoteAddress = (InetSocketAddress) call.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
if (remoteAddress == null) {
throw DeviceModuleException.create(null,"Could not get remote address of grpc client");
}
final Context context = Context.current().withValue(ORIGIN_IP, remoteAddress.getHostName());
return Contexts.interceptCall(context, call, headers, next);
}
return next.startCall(call, headers);
}

这是我在客户端尝试做的事情:

return BaseApiGrpc.newBlockingStub(NettyChannelBuilder.forAddress(BRIDGE_HOST, BRIDGE_DEVICE_MODULE_PORT)
.sslContext(buildSslContext())
.intercept(new ClientInterceptor() {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return new ForwardingClientCall.SimpleForwardingClientCall<>(next.newCall(method, callOptions)) {
@Override
public Attributes getAttributes() {
return Attributes.newBuilder()
.setAll(super.getAttributes())
.set(Grpc.TRANSPORT_ATTR_REMOTE_ADDR, new InetSocketAddress("fakeip", 1337))
.set(Grpc.TRANSPORT_ATTR_LOCAL_ADDR, new InetSocketAddress("fakeip", 1337))
.build();
}
};
}
})
.build());

但是,服务器仍然只接收我所在主机的实际IP。我猜测拦截器的应用晚于我的拦截器,并且覆盖了 remote-addr 属性。

但是我怎样才能实现这个目标呢?它会破坏东西吗?

我不想在服务器端做出任何异常(exception)或特殊解决方案,如果可能的话,我希望保持不变。

最佳答案

Attributes客户端和服务器之间不传输。 gRPC 库不调用ClientCall.getAttributes() ;它实现了它。因此,您的拦截器正在更改该值,但只有您的应用程序有机会看到不同的值。

但这实际上就是您想要的!唯一的问题是你应该使用 ServerInterceptor而不是ClientInterceptor !您还应该确保这个新的拦截器在现有的 ServerInterceptor 之前执行。将远程 IP 复制到 ORIGIN_IP上下文键。

class FakeAddressInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall<ReqT, RespT> interceptCall(
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return new ForwardingServerCall.SimpleForwardingServerCall<>(next.newCall(method, callOptions)) {
@Override
public Attributes getAttributes() {
return super.getAttributes().toBuilder()
.set(Grpc.TRANSPORT_ATTR_REMOTE_ADDR, new InetSocketAddress("fakeip", 1337))
.set(Grpc.TRANSPORT_ATTR_LOCAL_ADDR, new InetSocketAddress("fakeip", 1337))
.build();
}
};
}
}
...
// Your existing interceptor
serverBuilder.interceptor(new OriginIpContextInterceptor());
// Later interceptors are "nearer" the network, as they wrap your
// service, not the library
serverBuilder.interceptor(new FakeAddressInterceptor());

关于java - gRPC 在发送请求之前覆盖remote-addr 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60833234/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com