@Get("/api/v2/traceMany")
  @Blocking
  public AggregatedHttpResponse getTraces(@Param("traceIds") String traceIds) throws IOException {
    if (traceIds.isEmpty()) {
      return AggregatedHttpResponse.of(BAD_REQUEST, ANY_TEXT_TYPE, "traceIds parameter is empty");
    }

    Set<String> normalized = new LinkedHashSet<>();
    for (String traceId : traceIds.split(",", 1000)) {
      if (normalized.add(Span.normalizeTraceId(traceId))) continue;
      return AggregatedHttpResponse.of(BAD_REQUEST, ANY_TEXT_TYPE, "redundant traceId: " + traceId);
    }

    if (normalized.size() == 1) {
      return AggregatedHttpResponse.of(BAD_REQUEST, ANY_TEXT_TYPE,
        "Use /api/v2/trace/{traceId} endpoint to retrieve a single trace");
    }

    List<List<Span>> traces = storage.traces().getTraces(normalized).execute();
    return jsonResponse(writeTraces(SpanBytesEncoder.JSON_V2, traces));
  }
The Cache-Control max-age (seconds) for /api/v2/services /api/v2/remoteServices and
/api/v2/spans
zipkin-server/src/main/java/zipkin2/server/internal/ZipkinQueryApiV2.java