需要说明的是,一个微服务,如果仅仅对外提供服务就是Provider,如果仅仅是请求其他微服务就是Consumer,两者都涉及,那么这个微服务,既是Provider又是Consumer,如Edge网关,就是这样,它接收外部的请求,此时是Provider角色,把请求转给下游的其他微服务,此时是Consumer角色。通常不会存在仅仅是Consumer角色的微服务,因为单纯是Consumer实际应用中没有意义。
请求处理过程
- Producer服务启动后,会部署vertx服务,监听端口,等待Client连接,并且客户端请求路由配置到VertxRestDispatcher.
- Client发起请求,请求被vertx路由到VertxRestDispatcher,经过用户配置的HttpServerFilter进行接收请求后的预处理操作。其中ServerRestArgsFilter是ServiceComb内置的filter,专门用来反序列化请求和序列化响应体的。
- 经过HttpServerFilter的afterReceiveRequest处理后,正式进入Handler链,进行具体的业务处理,用户可以自定义多个Handler,但最后一个Handler是ProducerOperationHandler,这个是ServiceComb内置的Handler,它负责通过反射调用请求对应的operation,对请求进行处理,得到response.
- 得到response后,回调处理response的方法sendResponseQuietly(resp)
- 这个方法做的事是,调用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); }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。