当前位置: 首页 > article >正文

长连接的原理

Apollo的长连接实现是

  • Spring的DeferredResult来实现的,先看怎么用

import ...

@RestController
@RequestMapping("deferredResult")
public class DeferredResultController {

    private Map<String, Consumer<DeferredResultResponse>> taskMap = new HashMap<>();

    private String requestId = "demo";
    @GetMapping("get")
    public DeferredResult<DeferredResultResponse> deferredResult(){
        DeferredResult<DeferredResultResponse> ret = new DeferredResult<>();
        ret.onTimeout(() -> {
            DeferredResultResponse deferredResultResponse = new DeferredResultResponse();
            deferredResultResponse.setCode(HttpStatus.REQUEST_TIMEOUT.value());
            deferredResultResponse.setMsg(DeferredResultResponse.Msg.TIMEOUT.getDesc());
            ret.setResult(deferredResultResponse);
        });
        taskMap.put(requestId, ret::setResult);
        return ret;
    }

    @GetMapping("set")
    public void setResult(){
        DeferredResultResponse deferredResultResponse = new DeferredResultResponse();
        deferredResultResponse.setCode(HttpStatus.OK.value());
        deferredResultResponse.setMsg(DeferredResultResponse.Msg.SUCCESS.getDesc());
        taskMap.get(requestId).accept(deferredResultResponse);
        taskMap.remove(requestId);
    }

    public static class DeferredResultResponse{
        private Integer code;
        private String msg;

	   ...

        public enum Msg {
            TIMEOUT("超时"),
            FAILED("失败"),
            SUCCESS("成功");
            private String desc;

           ...
            Msg(String desc) {
                this.desc = desc;
            }
        }
    }
}

  • 这时候请求get接口,客户端是卡住的
    在这里插入图片描述

  • 当有结果设置的时候才会响应,调set接口来设置结果
    在这里插入图片描述

  • 如果一直没有结果设置,就会等到超时的时候才会响应
    在这里插入图片描述

  • 对于Apollo的客户端来说请求流程也是这样的
    调用notification/v3接口等待获取变更的数据(namespace),如果一直没有变更,就会等到60秒超时的时候才响应。

原理

在了解原理之前,问几个问题?

  • 这个客户端阻塞是怎么实现的?
  • 超时是怎么唤醒的?
  • 设置值的时候如果找到原来的请求

回答

  • 阻塞是通过socket来实现的,只要socket请求之后不往回写response,就会一直等待
    spring判断controller是DeferredResult异步请求,就会把这个请求挂起,请求的信息先保存起来,不返回response
  • 超时唤醒是利用tomcat的能力,tomcat会启动线程去扫描队列里面挂起的请求,如果有超时时间到的,会重新dispatch
  • setResult会AsyncManager保存的request,把结果设置之后,重新dispatch

http://www.kler.cn/a/105210.html

相关文章:

  • Linux--进程等待
  • 光流法动目标检测
  • 网络安全—自学笔记
  • HttpClient快速入门
  • selenium模拟登录无反应
  • 电商时代,VR全景如何解决实体店难做没流量?
  • 输入/输出应用程序接口和设备驱动程序接口
  • Java学习笔记(三)
  • 使用VisualStudio生成类图结构图for高效阅读代码
  • 【LeetCode】881 救生艇 中等题
  • OPC UA:工业领域的“HTML”
  • kafka3.X基本概念和使用
  • LeetCode 面试题 16.01. 交换数字
  • Linux C语言开发-D9输入输出
  • 【2024秋招】万得后端开发java 2023-7-13 2.30pm 一二面面经(附答案)
  • FreeRTOS学习2018.6.27
  • Kafka - 异步/同步发送API
  • 使用spring boot的程序主线程中异步访问外部接口
  • Python---练习:使用for循环嵌套实现打印九九乘法表
  • 【异常】理解Java中的异常处理机制