开发者社区> 问答> 正文

配置中心长轮询实现中怎样实现服务端?

配置中心长轮询实现中怎样实现服务端?

展开
收起
Aries- 2022-05-10 17:23:19 284 0
来自:阿里技术
1 条回答
写回答
取消 提交回答
  • @RestController @Slf4j @SpringBootApplication public class ConfigServer {

    @Data private static class AsyncTask { // 长轮询请求的上下文,包含请求和响应体 private AsyncContext asyncContext; // 超时标记 private boolean timeout;

    public AsyncTask(AsyncContext asyncContext, boolean timeout) { this.asyncContext = asyncContext; this.timeout = timeout; } }

    // guava 提供的多值 Map,一个 key 可以对应多个 value private Multimap<String, AsyncTask> dataIdContext = Multimaps.synchronizedSetMultimap(HashMultimap.create());

    private ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("longPolling-timeout-checker-%d") .build(); private ScheduledExecutorService timeoutChecker = new ScheduledThreadPoolExecutor(1, threadFactory);

    // 配置监听接入点 @RequestMapping("/listener") public void addListener(HttpServletRequest request, HttpServletResponse response) {

    String dataId = request.getParameter("dataId");

    // 开启异步 AsyncContext asyncContext = request.startAsync(request, response); AsyncTask asyncTask = new AsyncTask(asyncContext, true);

    // 维护 dataId 和异步请求上下文的关联 dataIdContext.put(dataId, asyncTask);

    // 启动定时器,30s 后写入 304 响应 timeoutChecker.schedule(() -> { if (asyncTask.isTimeout()) { dataIdContext.remove(dataId, asyncTask); response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); asyncContext.complete(); } }, 30000, TimeUnit.MILLISECONDS); }

    // 配置发布接入点 @RequestMapping("/publishConfig") @SneakyThrows public String publishConfig(String dataId, String configInfo) { log.info("publish configInfo dataId: [{}], configInfo: {}", dataId, configInfo); Collection asyncTasks = dataIdContext.removeAll(dataId); for (AsyncTask asyncTask : asyncTasks) { asyncTask.setTimeout(false); HttpServletResponse response = (HttpServletResponse)asyncTask.getAsyncContext().getResponse(); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println(configInfo); asyncTask.getAsyncContext().complete(); } return "success"; }

    public static void main(String[] args) { SpringApplication.run(ConfigServer.class, args); }

    }

    2022-05-10 20:01:38
    赞同 展开评论 打赏
问答地址:
来源圈子
更多
收录在圈子:
+ 订阅
问答排行榜
最热
最新

相关电子书

更多
探索连接的最后十秒”落时”的网关 立即下载
基于RocketMQ Connect 构建全新数据流转处理平 立即下载
从“连接”到“交互” 立即下载