0

我有一个要求,我通过 Vertx 客户端将一个微服务连接到另一个微服务。在代码中,我正在检查另一个微服务是否关闭,然后在失败时它应该创建一些 JsonObject,其中 solrError 作为键,失败消息作为值。如果有一个 solr 错误,我的意思是如果其他微服务关闭,它通过负载平衡调用 solr,那么它应该抛出一些错误响应。但是 Vertx 客户端需要一些时间来检查故障,并且当检查条件时,jsonobject 中没有 solrError,因为 Vertx 客户端需要一些时间来检查故障,因此条件失败并且 resp 为空。为了避免这种情况,可以做些什么让 Vertx 客户端在检查 solrError 的条件之前失败并返回内部服务器错误响应?

下面是代码:

 solrQueryService.executeQuery(query).subscribe().with(jsonObject -> {
        ObjectMapper objMapper = new ObjectMapper();
        SolrOutput solrOutput = new SolrOutput();
        List<Doc> docs = new ArrayList<>();
        try {
            if(null != jsonObject.getMap().get("solrError")){
             resp = Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                        .entity(new BaseException(
                                exceptionService.processSolrDownError(request.header.referenceId))
                                        .getResponse()).build();
            }
            solrOutput = objMapper.readValue(jsonObject.toString(), SolrOutput.class);
            if (null != solrOutput.getResponse()
                    && CollectionUtils.isNotEmpty(solrOutput.getResponse().getDocs())) {
                docs.addAll(solrOutput.getResponse().getDocs());
                                    uniDocList  = Uni.createFrom().item(docs);
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    });
    
    if(null!=resp && resp.getStatus() !=200) {
        return resp ;
    }
    
    SolrQueryService is preparing query and send out URL and query to Vertx web client as below :
    
    public Uni<JsonObject> search(URL url, SolrQuery query,Integer timeout) {
    int port = url.getPort();
    if (port == -1 && "https".equals(url.getProtocol())) {
        port = 443;
    }
    if (port == -1 && "http".equals(url.getProtocol())) {
        port = 80;
    }
    HttpRequest<Buffer> request = client.post(port, url.getHost(), url.getPath()).timeout(timeout);
    return request.sendJson(query).map(resp -> {
        return resp.bodyAsJsonObject();
    }).onFailure().recoverWithUni(f -> {
        return Uni.createFrom().item(new JsonObject().put("solrError", f.getMessage()));
    });

}
4

1 回答 1

1

我没有使用 Vertx 客户端,但假设它是反应式和非阻塞的。假设是这种情况,您的代码似乎混合了命令式和反应式结构。第一行中的 subscribe 是响应式的,当服务器响应客户端请求时,将调用您提供的 lambda。但是,在订阅之后,您将拥有在 lambda 甚至有机会被调用之前运行的命令式代码,因此您的检查和对“resp”对象的访问永远不会是 lambda 本身发生的事情的结果。

您需要将所有代码移动到 lambda 中,或者至少将后续代码链添加到订阅的结果中。

于 2021-06-26T10:45:21.267 回答