1
需要说明的是,一个微服务,如果仅仅对外提供服务就是Provider,如果仅仅是请求其他微服务就是Consumer,两者都涉及,那么这个微服务,既是Provider又是Consumer,如Edge网关,就是这样,它接收外部的请求,此时是Provider角色,把请求转给下游的其他微服务,此时是Consumer角色。通常不会存在仅仅是Consumer角色的微服务,因为单纯是Consumer实际应用中没有意义。

请求处理过程

image.png

  1. Producer服务启动后,会部署vertx服务,监听端口,等待Client连接,并且客户端请求路由配置到VertxRestDispatcher.
  2. Client发起请求,请求被vertx路由到VertxRestDispatcher,经过用户配置的HttpServerFilter进行接收请求后的预处理操作。其中ServerRestArgsFilter是ServiceComb内置的filter,专门用来反序列化请求和序列化响应体的。
  3. 经过HttpServerFilter的afterReceiveRequest处理后,正式进入Handler链,进行具体的业务处理,用户可以自定义多个Handler,但最后一个Handler是ProducerOperationHandler,这个是ServiceComb内置的Handler,它负责通过反射调用请求对应的operation,对请求进行处理,得到response.
  4. 得到response后,回调处理response的方法sendResponseQuietly(resp)
    image.png
  5. 这个方法做的事是,调用HttpServerFilter链上每个filter的beforeSendResponseAsync,进行发送前处理。其中内置的ServerRestArgsFilter会对response对象进行序列化,变成json字符串,响应给client

ServerRestArgsFilter

1.收到请求解析参数

  @Override
  public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
    OperationMeta operationMeta = invocation.getOperationMeta();
    RestOperationMeta restOperationMeta = operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION);
   // 解析参数 
    Map<String, Object> swaggerArguments = RestCodec.restToArgs(requestEx, restOperationMeta);
    invocation.setSwaggerArguments(swaggerArguments);
    return null;
  }

2.发送响应前处理beforeSendResponseAsync

  @Override
  public CompletableFuture<Void> beforeSendResponseAsync(Invocation invocation, HttpServletResponseEx responseEx) {
    ...
    // 设置响应contentType
    responseEx.setContentType(produceProcessor.getName() + "; charset=utf-8");

    CompletableFuture<Void> future = new CompletableFuture<>();
    try (BufferOutputStream output = new BufferOutputStream(Unpooled.compositeBuffer())) {
      // 对响应体进行编码
      produceProcessor.encodeResponse(output, body);
     // 得到编码后的byte,设置到responseEx中,用于发送
      responseEx.setBodyBuffer(output.getBuffer());
      future.complete(null);
    } catch (Throwable e) {
    ...
    }
    return future;
  }

微服务间上下文传递

微服务Consumer与微服务Producer之间,通过rest进行调用,上下文通过调用rest放到header里面实现上下文传递,下面让我们看一下相关代码

  • Consumer invocation的发送: 发送请求前设置header,RestClientInvocation发送处理中setCseContext,header中的key是x-cse-context,代码中的public static final String CSE_CONTEXT = "x-cse-context";

    protected void setCseContext() {
      try {
        clientRequest.putHeader(Const.CSE_CONTEXT, JsonUtils.writeValueAsString(invocation.getContext()));
      } catch (Throwable e) {
        invocation.getTraceIdLogger().error(LOGGER, "Failed to encode and set cseContext, message={}."
            , ExceptionUtils.getExceptionMessageWithoutTrace(e));
      }
    }
  • Producer 对invocation的恢复:AbstractRestInvocation在调用handler之前,创建invocation,并把Consumer传递过来的上下文恢复到invocation中,见this.setContext();

    protected void scheduleInvocation() {
      try {
        createInvocation();
      } catch (Throwable e) {
        sendFailResponse(e);
        return;
      }
    
      try {
        this.setContext();
      } catch (Exception e) {
        LOGGER.error("failed to set invocation context", e);
        sendFailResponse(e);
        return;
      }
     ...
  • Producer最后一个Handler-ProducerOperationHandler,doInvoke业务前,设置invocation到线程上下文,业务处理结束后,移除线程上下文中的invocation。所以,在业务处理中,可以通过上下文获取invocation信息。

    public void syncInvoke(Invocation invocation, SwaggerProducerOperation producerOperation, AsyncResponse asyncResp) {
      ContextUtils.setInvocationContext(invocation);
      Response response = doInvoke(invocation, producerOperation);
      ContextUtils.removeInvocationContext();
      asyncResp.handle(response);
    }

ThinkFault
16 声望2 粉丝