当传入流量使用 Load Balancer URL 时,如何捕获用于满足请求的服务器?

How to capture the server used to fulfill a request when incoming traffic is using Load Balancer URL?

我有一个 Spring Boot Java REST 应用程序,其中有许多 API 暴露给我们的客户和 UI。我的任务是实现一个事务日志框架,该框架将捕获传入的事务以及我们发送的响应。

我使用 Spring AOP 和 Around inspect 进行这项工作,目前我正在利用 HttpServletRequest 和 HttpServletResponse 对象来获取我需要的大量数据。

在我的本地系统中,我在捕获所使用的服务器时没有任何问题,因为我直接连接到我的系统。然而,一旦我部署了我的代码,我就看到负载均衡器 URL 被捕获而不是实际的服务器名称。

我还使用 Eureka 按名称发现 API,因为它只是 HAProxy 上的一个应用程序 运行。

想象一下这个流程:

 /*
 UI -> https://my-lb-url/service-sidecar/createUser

 HAProxy directs traffic to -> my-lb-url/service-sidecar/ to one of below:
      my-server-1:12345
      my-server-2:12345
      my-server-3:12345


 Goal  : http://my-server-1:1235/createUser
 Actual: https://my-lb-url/createUser

这是我用来获取传入的代码 URL。

 String url = httpRequest.getRequestURL().toString();
 if(httpRequest.getQueryString() != null){
      transaction.setApi(url + "?" + httpRequest.getQueryString());
 } else {
      transaction.setApi(url);
 }

注:

我对 HAProxy/Eurkea/etc 不太熟悉。正如我所愿。如果上述内容似乎不对或不对,那么我深表歉意。我们的系统管理员配置了这些并将开发人员拒之门外。


更新

这是我用来构造请求的新代码 URL,但我仍然看到相同的输出。

// Utility Class

public static String constructRequestURL(HttpServletRequest httpRequest) {

    StringBuilder url = new StringBuilder(httpRequest.getScheme());
    url.append("://").append(httpRequest.getServerName());

    int port = httpRequest.getServerPort();
    if(port != 80 && port != 443) {
        url.append(":").append(port);
    }
    url.append(httpRequest.getContextPath()).append(httpRequest.getServletPath());

    if(httpRequest.getPathInfo() != null) {
        url.append(httpRequest.getPathInfo());
    }
    if(httpRequest.getQueryString() != null) {
        url.append("?").append(httpRequest.getQueryString());
    }
    return url.toString();
}

// Service Class

transaction.setApi(CommonUtil.constructRequestURL(httpRequest));

我找到了解决此问题的方法,但这不是最干净的方法,如果可能的话,我很乐意采纳其他建议。

  1. 我正在自动连接 application.yml 的端口号。
  2. 我在托管应用程序的 Linux 服务器上 运行 "hostname" 命令以确定满足请求的服务器。

现在存储在事务日志中的 URL 是准确的。

--

@Autowired
private int serverPort; 

/*
 * ... 
 */

private String constructRequestURL(HttpServletRequest httpRequest) {

    StringBuilder url = new StringBuilder(httpRequest.getScheme())
            .append("://").append(findHostnameFromServer()).append(":").append(serverPort)
            .append(httpRequest.getContextPath()).append(httpRequest.getServletPath());

    if(httpRequest.getPathInfo() != null) {
        url.append(httpRequest.getPathInfo());
    }
    if(httpRequest.getQueryString() != null) {
        url.append("?").append(httpRequest.getQueryString());
    }
    return url.toString();
}

private String findHostnameFromServer(){

    String hostname = null;
    LOGGER.info("Attempting to Find Hostname from Server...");
    try {
        Process process = Runtime.getRuntime().exec(new String[]{"hostname"});
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            hostname = reader.readLine();
        }

    } catch (IOException e) {
        LOGGER.error(CommonUtil.ERROR, e);
    }
    LOGGER.info("Found Hostname: {}", hostname);
    return hostname;
}