日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java 利用DeferredResult實現http輪詢實時返回數據接口

瀏覽:204日期:2022-08-15 08:38:12

今天這篇文章呢,不難,其實是解答我一直以來心里的一個疑問。是這樣的,之前看五八技術委員會主席沈劍老師的公眾號架構師之路的一篇文章:http 如何像 tcp 一樣實時的收消息,里面其中的一個方案是用 http 短連接輪詢的方式實現“偽長連接”。但是對于輪詢,我們的第一反應肯定是有延時,但是標題不是說的是實時嗎?當然我們可以把輪詢的時長縮短一些,先不說這樣大部分時間的輪詢調用,可能都沒消息返回,造成服務器資源浪費,輪詢時間再短也是有延時啊,所以難道是偽實時?反正一般消息延時個三五秒,甚至十秒八秒一分鐘,大家也不會在意,只會認為對方返回慢,對不起,這是我們程序員的鍋,但是 http 真的不能實現實時嗎?沈劍老師提出了一種方法:首選 webim 和 webserver 之間建立一條 http 連接,專門用作消息通道,這條連接叫 http 消息連接。然后會有如下處理:

1. 沒有消息到達的時候,這個 http 消息連接將被夯住,不返回,由于 http 是短連接,這個 http 消息連接最多被夯住 90 秒,就會被斷開(這是瀏覽器或者 webserver 的行為);

2. 在 1 的情況下,如果 http 消息連接被斷開,立馬再發起一個 http 消息連接;

此時在在 1 和 2 的配合下,瀏覽器與 webserver 之間將永遠有一條消息連接在,然后還有一種情況

3. 每次收到消息時,這個消息連接就能及時將消息帶回瀏覽器頁面,并且在返回后,會立馬再發起一個 http 消息連接

這樣就能做到使用 http 端連接輪詢的方式實現了實時收消息。不過需要說明的是,其實還有一種情況:消息到達時,上一個 http 消息連接正在返回,也就是第二種情況的時候突然來了一個消息,此時沒有 http 消息連接可用。雖然理論上 http 消息連接的返回是瞬時的,沒有消息連接可用出現的概率極小,但是根據墨菲定律我們知道,這種情況肯定會出現,所以這種情況下我們可以將消息暫存入消息池中,下一個消息連接到達后,無需等待,直接去消息池中取消息,將將消息帶回,然后立刻返回生成新的消息連接即可。

不過以上都不是今天這篇文章的重點,和今天這篇文章的標題也沒有任何關系。重點是當時看了沈劍老師的這篇文章后我一直有一個疑問:第一步的時候如何夯???總不能 sleep 吧,這多不優雅啊,由于一直以為沒有遇到過類似的需求,所以這么幾年來我也沒深究這個問題,但是心里確實一直記著,直到前一段時間,聽馬士兵教育的公開課,當時再講類似的問題的時候提到了夯住 http 的連接(具體是哪個問題,還真不記得了),雖然當時上課的老師沒提怎么實現,但是評論區我問了一下,如何夯住不返回?然后有一個同學回復說,用 DeferredResult,然后下課后搜了一下資料,果然可以,如下是實現的筆記,所以這才是重點,希望對有這個疑問的同學也有一點幫助。

1. 消息返回實體類,大家可以根據實際情況,自己定義即可:

package cn.bridgeli.deferredresulttest.entity; import lombok.Data;import lombok.Getter; /** * @author bridgeli */@Datapublic class DeferredResultResponse { private Integer code; private String msg; public enum Msg {TIMEOUT('超時'),FAILED('失敗'),SUCCESS('成功'); @Getterprivate String desc; Msg(String desc) { this.desc = desc;} }}2. controller 接口:

package cn.bridgeli.deferredresulttest.controller; import cn.bridgeli.deferredresulttest.entity.DeferredResultResponse;import cn.bridgeli.deferredresulttest.service.DeferredResultService;import org.springframework.http.HttpStatus;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.context.request.async.DeferredResult; import javax.annotation.Resource; /** * @author bridgeli */@RestController@RequestMapping(value = '/deferred-result')public class DeferredResultController { @Resource private DeferredResultService deferredResultService; /** * 為了方便測試,簡單模擬一個 * 多個請求用同一個requestId會出問題 */ private final String requestId = 'test'; @GetMapping(value = '/get') public DeferredResult<DeferredResultResponse> get(@RequestParam(value = 'timeout', required = false, defaultValue = '10000') Long timeout) {DeferredResult<DeferredResultResponse> deferredResult = new DeferredResult<>(timeout); deferredResultService.process(requestId, deferredResult); return deferredResult; } /** * 設置DeferredResult對象的result屬性,模擬異步操作 * * @param desired * @return */ @GetMapping(value = '/result') public String settingResult(@RequestParam(value = 'desired', required = false, defaultValue = '成功') String desired) {DeferredResultResponse deferredResultResponse = new DeferredResultResponse();if (DeferredResultResponse.Msg.SUCCESS.getDesc().equals(desired)) { deferredResultResponse.setCode(HttpStatus.OK.value()); deferredResultResponse.setMsg(desired);} else { deferredResultResponse.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); deferredResultResponse.setMsg(DeferredResultResponse.Msg.FAILED.getDesc());}deferredResultService.settingResult(requestId, deferredResultResponse); return 'Done'; }}

其中:/get 接口模擬沈劍老師說的消息連接,/result 接口模擬有一條新消息來了,然后 /get 接口會立即返回。主要注意的是 requestId,在實際項目中不能使用同一個,否則會出現問題,這個測一下就知道了,也很容易想到原因。

3. service 實現:

package cn.bridgeli.deferredresulttest.service; import cn.bridgeli.deferredresulttest.entity.DeferredResultResponse;import org.springframework.http.HttpStatus;import org.springframework.stereotype.Service;import org.springframework.web.context.request.async.DeferredResult; import java.util.Map;import java.util.Optional;import java.util.concurrent.ConcurrentHashMap;import java.util.function.Consumer; /** * @author bridgeli */@Servicepublic class DeferredResultService { private Map<String, Consumer<DeferredResultResponse>> taskMap; public DeferredResultService() {taskMap = new ConcurrentHashMap<>(); } /** * 將請求id與setResult映射 * * @param requestId * @param deferredResult */ public void process(String requestId, DeferredResult<DeferredResultResponse> deferredResult) {// 請求超時的回調函數deferredResult.onTimeout(() -> { taskMap.remove(requestId); DeferredResultResponse deferredResultResponse = new DeferredResultResponse(); deferredResultResponse.setCode(HttpStatus.REQUEST_TIMEOUT.value()); deferredResultResponse.setMsg(DeferredResultResponse.Msg.TIMEOUT.getDesc()); deferredResult.setResult(deferredResultResponse);}); Optional.ofNullable(taskMap).filter(t -> !t.containsKey(requestId)).orElseThrow(() -> new IllegalArgumentException(String.format('requestId=%s is existing', requestId))); taskMap.putIfAbsent(requestId, deferredResult::setResult); } /** * 這里相當于異步的操作方法 * 設置DeferredResult對象的setResult方法 * * @param requestId * @param deferredResultResponse */ public void settingResult(String requestId, DeferredResultResponse deferredResultResponse) {if (taskMap.containsKey(requestId)) { Consumer<DeferredResultResponse> deferredResultResponseConsumer = taskMap.get(requestId); // 這里相當于DeferredResult對象的setResult方法 deferredResultResponseConsumer.accept(deferredResultResponse); taskMap.remove(requestId);} } }

文章最后,我想在說明另外一個問題,我們利用 DeferredResult 實現了 http 輪詢返回,其實換個思路想問題,我們是不是也實現了 http 接口延時返回?所以如果你有延時返回的需求,同樣可以借助 DeferredResult 實現。

以上就是Java 利用 DeferredResult 實現 http 輪詢實時返回數據接口的詳細內容,更多關于Java 實現 http 輪詢實時返回數據接口的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
精品三级在线| 日韩欧美美女在线观看| 91综合视频| 蜜臀av免费一区二区三区| 亚洲精品电影| 亚洲免费高清| 18国产精品| 日韩免费一区| 亚洲a成人v| 国产成人久久| 美国三级日本三级久久99 | 日韩va亚洲va欧美va久久| 亚洲精品麻豆| 日韩精品2区| 日本一区二区三区视频在线看| 精品亚洲a∨一区二区三区18| 欧美日韩中文字幕一区二区三区| 综合国产在线| 最近高清中文在线字幕在线观看1| 免费观看不卡av| 久久中文字幕一区二区三区| 午夜欧美精品| 国内精品伊人| 青青草国产成人99久久| 99久久婷婷| 国产成人免费| 欧美久久久网站| 不卡在线一区二区| 精品国产一区二区三区2021| 亚洲网址在线观看| 91高清一区| 肉色欧美久久久久久久免费看| 亚洲五月综合| 亚洲性图久久| 日韩大片在线播放| 久久久91麻豆精品国产一区| 亚洲美女91| 视频在线在亚洲| 午夜免费一区| 欧美aa国产视频| 亚洲va中文在线播放免费| 国产精品九九| 亚洲青青久久| 亚洲影视一区| 亚洲综合婷婷| 亚洲一二av| 中文字幕一区二区av| 午夜在线视频观看日韩17c| 久久精品高清| 久久精品观看| 日韩精品麻豆| 婷婷亚洲综合| 蜜桃久久av| 日韩一区二区三区高清在线观看| 亚洲三级毛片| 国产亚洲一区| 卡一精品卡二卡三网站乱码| 国产精品第一国产精品| 国产精品久久久久久久久久白浆| 欧美激情99| 成人精品中文字幕| 91久久国产| 亚洲免费观看高清完整版在线观| 日韩不卡免费视频| 久久精品资源| 99久久久久国产精品| 亚洲综合电影一区二区三区| 日韩av一级片| 国产不卡一区| 99国产成+人+综合+亚洲欧美| 亚洲一区二区免费在线观看| 欧美亚洲一级| 国产成人77亚洲精品www| 神马日本精品| 精品视频网站| 亚洲精品看片| 国产亚洲欧美日韩精品一区二区三区| 蜜臀精品久久久久久蜜臀| 久久福利影视| 国产日本久久| 国产精品色网| 老司机精品久久| 视频在线在亚洲| 国产精品男女| 午夜久久中文| 亚洲精品国产嫩草在线观看| 播放一区二区| 伊人久久亚洲美女图片| 六月婷婷一区| 中文字幕视频精品一区二区三区| 日韩高清在线一区| 国产日韩一区| 丝袜美腿诱惑一区二区三区 | 麻豆网站免费在线观看| 中文字幕在线看片| 亚洲三级欧美| 无码日韩精品一区二区免费| 牛牛精品成人免费视频| 麻豆精品蜜桃| 欧美亚洲国产日韩| 成人午夜国产| 97精品久久| 午夜欧美视频| 黄色网一区二区| 久久久五月天| 国产精品日韩精品中文字幕| 久久国产中文字幕| 久久99久久人婷婷精品综合| 中文视频一区| 99国产精品免费视频观看| 日本aⅴ免费视频一区二区三区| 日韩在线免费| 国产极品久久久久久久久波多结野 | 久久久噜噜噜| 人人爱人人干婷婷丁香亚洲| 成人午夜网址| 欧美一区激情| 日韩制服丝袜先锋影音| 不卡一区综合视频| japanese国产精品| 蜜桃精品在线| 精品视频网站| 九九99久久精品在免费线bt| 久久国产日韩欧美精品| 欧美1区2区3区| 中文在线免费视频| 国产精品成人一区二区不卡| 日韩一二三区在线观看| 中文日韩欧美| 视频一区在线播放| 欧美日韩免费观看一区=区三区| 国产福利91精品一区二区| 你懂的国产精品永久在线| 国产欧美亚洲精品a| 美女网站久久| 美女久久久久| 亚洲毛片在线| 日韩精品久久久久久久软件91| 日韩av网站免费在线| 亚洲精品在线a| 99成人在线视频| 国产农村妇女精品一二区| 亚洲视频电影在线| 国产精品一区二区免费福利视频| 欧美日韩中文| 精品国产一区二区三区av片| 麻豆精品蜜桃| 合欧美一区二区三区| 美女网站久久| 久久wwww| 亚洲一卡久久| 国产高清视频一区二区| 国产成人精品一区二区免费看京| 成人自拍av| 一区二区国产精品| 久久精品超碰| 色婷婷精品视频| 伊人久久大香伊蕉在人线观看热v| 视频一区日韩精品| 涩涩av在线| 日韩中出av| 久久精品理论片| 亚洲黄页一区| 激情综合婷婷| 亚洲日韩中文字幕一区| 成年男女免费视频网站不卡| 中文视频一区| 亚洲午夜在线| 精品中文字幕一区二区三区| 男女男精品网站| 精品视频99| 亚洲一区二区三区久久久| 国产精品嫩模av在线| 亚洲欧洲另类| 超碰99在线| 精品国产亚洲日本| 日韩福利视频导航| 亚洲一区二区三区高清不卡| 日韩国产一区二区| 国产视频一区二区在线播放| 99xxxx成人网| 婷婷综合激情| 黄色网一区二区| 国产欧美视频在线| 中文字幕一区日韩精品| 国产91在线播放精品| 欧美精品91| 国产精品一区二区免费福利视频| 欧美日韩视频| 免费黄色成人| 日韩和的一区二在线| 欧美国产一级| 高清一区二区| 日本国产精品| 精品国产免费人成网站| 精品国产美女a久久9999| 久久99影视| 国产v日韩v欧美v| 日韩在线中文| 三上悠亚国产精品一区二区三区 |