4

使用 Finagle 客户端时,我想将被调用的远程主机记录到 STDOUT。但据我所知,这是不可能的com.twitter.finagle.http.filter.LoggingFilter;它的#format(示例见下文)方法无法访问实际主机:

  • request.remoteHost()返回0.0.0.0
  • request.remoteAddress()返回一个基本上包含上述 IP 的对象
  • request.host()返回一个None对象

我的第一个猜测是/是因为Finagle 的客户端负载平衡发生在堆栈的更深处,所以无法访问主机。

这是我使用的测试代码:

    LoggingFilter<Request> loggingFilter = new LoggingFilter<>(
            new Logger(this.getClass().getSimpleName(), java.util.logging.Logger.getLogger(this.getClass().getSimpleName())),

            new LogFormatter<Request, Response>() {
                @Override
                public String format(Request request, Response reply, Duration replyTime) {
                    return null;
                }

                @Override
                public String formatException(Request request, Throwable throwable, Duration replyTime) {
                    return null;
                }
            });

    Service<Request, Response> service = Http.client().newService("localhost:8090,localhost:8091");
    Future<Response> response = loggingFilter.andThen(service).apply(Request.apply("/profiles/me"));
4

1 回答 1

6

请求发送到的实际端点由负载均衡器决定。所以确实记录远程主机只能在负载平衡模块之后完成。

负载平衡器模块使参数Transporter.EndpointAddr可用。该参数包含实际地址。为了使用这个参数,你应该在 HTTP 客户端堆栈中添加一个模块,就在负载平衡模块之后。

斯卡拉的一个例子:

创建您的日志过滤器:

class MyLoggingFilter(addr: Address) extends SimpleFilter[Request, Response] {
  override def apply(request: Request, service: Service[Request, Response]) = {
    println(s"Sending request to $addr")
    service(request)
  }
}

定义新模块

def endpointLoggerModule: Stackable[ServiceFactory[Request, Response]] =
  new Stack.Module1[Transporter.EndpointAddr, ServiceFactory[Request, Response]] {
    val role: Role = Role("EndpointLogger")
    val description = "Log remote address"
    def make(_addr: Transporter.EndpointAddr, 
             next: ServiceFactory[Request, Response]) = {
      val Transporter.EndpointAddr(addr) = _addr
      new MyLoggingFilter(addr).andThen(next)
    }
  }

在堆栈中使用此模块创建一个新的 Http 客户端:

val stackWithLogging = Http.client.stack
  .insertAfter(LoadBalancerFactory.role, endpointLoggerModule)
val service = Http.client.copy(stack = stackWithLogging)
  .newService("localhost:8090,localhost:8091")

然后,这个创建的服务应该记录请求发送到的实际地址。

有关模块组合的更多信息,请参阅 Finagle 官方文档。

于 2017-08-17T13:48:18.913 回答