如何解决“达到 http.client.requests 的 URI 标签最大数量”警告?

问题描述 投票:0回答:2

我在我的应用程序上收到此警告。我正在同时阅读大约 30 位读者的

rfidtags
。每次有标签进入时,我都会访问数据库以查看它是否在其中。我有一个正在使用的 REST API。所以我使用 REST 模板来访问 REST API。

关于如何解决这个问题有什么想法吗?

谢谢!


这是我的一些代码:

private void vehicleRequests(List<Maybevehicle> vehicles) {
    // process list of unique tags to see if they are in the database and linked to a vehicle
    List<Maybevehicle> foundMaybeVehs = new ArrayList<>();
    List<Maybevehicle> notFound = new ArrayList<>();
    if (!vehicles.isEmpty()) {
        for (Maybevehicle v : vehicles) {
            Future<Maybevehicle> r = aService.batchVehTags(v);
            try {
                Maybevehicle m = r.get(2000, TimeUnit.SECONDS);
                if (r.isDone()) {
                    if (!(m.getB().getVin().equals("notindb"))) {
                        foundMaybeVehs.add(m);
                    }
                }
            } catch (InterruptedException | ExecutionException | TimeoutException e) {
                
            }
            
            if (!foundMaybeVehs.isEmpty()) {
                addLocation(foundMaybeVehs);
            }
        } else {
            log.info("no vehicles to check.");
        }
        
}

@Override
public Future<Maybevehicle> batchVehTags(Maybevehicle v) {
    Future<Maybevehicle> future = null;
    try {
        SimpleTaskMaybeveh task = new SimpleTaskMaybeveh(v, appRestTemplate);
        future=dbService.submit(task);
                
    } catch (Exception e) {
        e.printStackTrace();
    }
            
    return future;
}

 

public class SimpleTaskMaybeveh implements Callable<Maybevehicle> {
    
    private RestTemplate appRestTemplate;
    private Maybevehicle veh;
    
    public SimpleTaskMaybeveh(Maybevehicle veh, RestTemplate appRestTemplate) {
        this.veh = veh;
        this.appRestTemplate=appRestTemplate;
    }

    @Override
    public Maybevehicle call() {
      String url="http://url/"+veh.getB().getRfidtag();
        String authString = "";
        byte[] encodedAuth = Base64.encodeBase64(authString.getBytes(Charset.forName("US-ASCII")));
        String authHeader = "Basic " + new String(encodedAuth);

        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        headers.set("Authorization", authHeader);

        HttpEntity<Bmwvehiclemain> requestEntity = new HttpEntity <Bmwvehiclemain>(headers);
        ResponseEntity<Bmwvehiclemain> results = appRestTemplate.exchange(url, HttpMethod.GET, requestEntity, Bmwvehiclemain.class);
        try {
            Bmwvehiclemain n = results.getBody();
            Maybevehicle d = new Maybevehicle(n,veh.getNewtaglocation());
            return d;
        } catch (Exception e) {
            Maybevehicle notveh = new Maybevehicle("notindb");
            return notveh;
        }
    }

}
java spring-boot resttemplate
2个回答
26
投票

因此,Spring 应用程序收集所有入站和出站 API 调用的指标。可以查询这些指标以查看某个 URL 被调用了多少次。

在您的

public Maybevehicle call()
方法中,您通过附加到字符串来构建 url。这会将每个带有唯一 rfidtag 的 URL 放入其自己的 URI 标记存储桶中。

为了避免这个问题,你可以使用uriVariables映射:

String url = “http://url/{rfidtag}”;
Map<String, ?> uriVariables = new HashMap<>();
uriVariables.put(“rfidtag”, veh.getB().getRfidtag();
…
ResponseEntity<Bmwvehiclemain> results = appRestTemplate
        .exchange(url, HttpMethod.GET, requestEntity, Bmwvehiclemain.class, uriVariables);

这使得 Spring 可以收集

http://url/{rfidtag}
上的指标,而不是使用
http://url/rfidtag1
http://url/rfidtag2
http://url/rfidtag3
等的 URI 标签。

这应该会减少您的应用程序创建的 URI 标签的数量。

URI 标签最大数量的默认值为 100。如果您想要更多的指标,您可以通过将其属性值设置为其他值来自定义它。例如,我的 Spring 应用程序是使用我的

projectname-ws/src/main/resources/config/application.yml
文件配置的。在这个文件中我可以放一些类似的东西

management:
  metrics:
    web:
      client:
        max-uri-tags: 200
      server:
        max-uri-tags: 200

增加用于指标的 URI 标签的最大数量。

如果您根本不想要

Reached the maximum number of URI tags for http.client.requests
警告,您可以输入

@SpringBootApplication(exclude = HttpClientMetricsAutoConfiguration.class)

在您运行应用程序的任何类的顶部,它将消除警告消息,但可能无法解决根本问题。


1
投票

事实上,此警告是关于将变量数据连接到 URL 而不是使用变量的 HTTP 请求。 而且,正如 Paul 所解释的,您应该用参数 URL 替换 URL 连接。 另一种方法,使用“流畅的风格”,使用网络客户端来实现这一点是:

webClient
   .method(HttpMethod.GET)
   .uri("/.../...s/{id}/overview", id)
   .retrieve()

但是,请注意,忽略此类警告会产生影响......

例如,如果您使用 Prometheus 从应用程序中抓取指标,则使用此类串联 URL 会产生大量指标,例如

http_client_requests_seconds_count{clientName="...",environment="",method="GET",outcome="SUCCESS",region="",service_name="",status="200",uri="/api/.../1234-5678-90/...",}
(因为 spring 无法判断两个仅“id”不同的此类请求实际上是相同)。
因此,除了向您的 Prometheus 发送垃圾邮件之外,这些指标大多毫无用处。

就我而言,我的应用程序正在使用一个库,而该库又使用网络客户端并连接 URL。 我一直在寻找一种方法来识别这些呼叫,以便我可以要求修复它们。 最终我发现我可以使用

actuator/prometheus
端点来查看所有 Web 客户端指标,由于这个问题,这些指标确实很大。

© www.soinside.com 2019 - 2024. All rights reserved.