Регистрация удаленного хоста в Finagle

Я хотел бы зарегистрировать вызываемый удаленный хост в STDOUT при использовании Finagle Client. Но, насколько я вижу, это невозможно с помощью 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"));

1 ответ

Решение

Фактическая конечная точка, на которую отправляется запрос, определяется в балансировщике нагрузки. Таким образом, регистрация на удаленном хосте может быть выполнена только после модуля балансировки нагрузки.

Модуль балансировки нагрузки делает параметр Transporter.EndpointAddr имеется в наличии. Этот параметр содержит фактический адрес. Чтобы использовать этот параметр, вы должны добавить модуль в стек HTTP-клиента сразу после модуля балансировки нагрузки.

Пример в Scala:

Создайте свой фильтр регистрации:

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 для получения дополнительной информации о составе модуля.

Другие вопросы по тегам