目录
- 长轮询+deferredResult
- springmvc异步返回Callable
- DefferredResult
- 通知客户端实现方式
- 定时轮询 + 长轮询
注: 细节已迁移至: 分布式配置中心apollo
config端
长轮询+deferredResult(图片来自芋道源码)
芋道源码.pngspringmvc异步返回Callable
- 如果某个操作返回时间长,客户端不需要等待返回,直接可以异步调用。
- 如果某个操作既耗时很长,客户端又必须要等待其返回才能进一步处理时,需要使用Servlet3.0中引入异步请求处理.
- 先看下使用asyncContext执行异步请求
public void method1(HttpServletRequest request, HttpServletResponse response) {
//获取异步上下文 这个在 springmvc传到线程池的过程中可以传过来
AsyncContext asyncContext = request.startAsync();
//开启异步处理过程
asyncContext.start(() -> {
//耗时处理
try {
Thread.sleep(2000);
//通过AsyncContext返回 respsonse
asyncContext.getResponse().getWriter().write("Hello World1!");
} catch (Exception e) {
e.printStackTrace();
}
//异步处理完成
asyncContext.complete();
});
}
- 具体流程
- 客户端请求服务
- SpringMVC调用Controller,Controller返回一个Callback对象
- SpringMVC调用ruquest.startAsync并且将Callback提交到TaskExecutor中去执行
- DispatcherServlet以及Filters等从应用服务器线程中结束,但Response仍旧是打开状态,也就是说暂时还不返回给客户端
- TaskExecutor调用Callback返回一个结果,SpringMVC将请求发送给应用服务器继续处理
- DispatcherServlet再次被调用并且继续处理Callback返回的对象,最终将其返回给客户端
DefferredResult
- 具体流程
- 客户端请求服务
- SpringMVC调用Controller,Controller返回一个DeferredResult对象
- SpringMVC调用ruquest.startAsync
DispatcherServlet以及Filters等从应用服务器线程中结束,但Response仍旧是打开状态,也就是说暂时还不返回给客户端
4.某些其它线程将结果设置到DeferredResult中
,SpringMVC将请求发送给应用服务器继续处理 - DispatcherServlet再次被调用并且继续处理DeferredResult中的结果,最终将其返回给客户端
通知客户端实现方式
通知变化接口,仅返回通知相关的信息,而不包括配置相关的信息。所以 Config Service 需要提供配置读取的接口
- 客户端会发起一个Http 请求到 Config Service 的 notifications/v2接口,也就是NotificationControllerV2 ,参见 RemoteConfigLongPollService 。
- NotificationControllerV2 不会立即返回结果,而是通过 Spring DeferredResult 把请求挂起。
- 如果在 60 秒内没有该客户端关心的配置发布,那么会返回 Http 状态码 304 给客户端。
- 如果有该客户端关心的配置发布,NotificationControllerV2 会调用 DeferredResult 的 setResult 方法,传入有配置变化的 namespace 信息,同时该请求会立即返回。客户端从返回的结果中获取到配置变化的 namespace 后,会立即请求 Config Service 获取该 namespace 的最新配置
网友评论