最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java servlet通過事件驅(qū)動(dòng)進(jìn)行高性能長(zhǎng)輪詢?cè)斀?/h1>
 更新時(shí)間:2022年06月16日 09:39:23   作者:hi wei  
這篇文章主要介紹了基于servlet3.0+事件驅(qū)動(dòng)實(shí)現(xiàn)高性能長(zhǎng)輪詢的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧

servlet3.0的異步原理

servlet基礎(chǔ)就不做介紹了,這里就介紹servlet3.0的一個(gè)重要的新特性:異步。

servlet3.0原理圖:

  • tomcat接收到客戶端的請(qǐng)求后會(huì)將請(qǐng)求AsyncContext交給業(yè)務(wù)線程,這樣tomcat工作線程就能釋放出來處理其它請(qǐng)求的連接。
  • 業(yè)務(wù)線程池接收到AsyncContext后,就可以處理請(qǐng)求業(yè)務(wù),完成業(yè)務(wù)邏輯后,根據(jù)AsyncContext獲取response,返回響應(yīng)結(jié)果。
  • AsyncListener會(huì)監(jiān)聽AsyncContext的行為,我們可以根據(jù)具體的行為做出對(duì)應(yīng)的業(yè)務(wù)處理。

servlet3.0將tomcat工作線程和業(yè)務(wù)線程分隔開來,這樣tomcat工作線程就能處理更多的連接請(qǐng)求。業(yè)務(wù)線程主要處理業(yè)務(wù)邏輯。在這種模式下,可以更好的分配業(yè)務(wù)線程的數(shù)量,也能根據(jù)不同的業(yè)務(wù),設(shè)置不同的線程數(shù)量,更加靈活。

注意:tomcat的NIO和servlet3.0的異步?jīng)]有關(guān)系。tomcat NIO模式,是對(duì)于http連接的處理使用,目的是用更少的線程處理更多的連接。servlet3.0是在tomcat工作線程的處理邏輯上實(shí)現(xiàn)異步處理功能。

使用servlet3.0實(shí)現(xiàn)長(zhǎng)輪詢

什么是長(zhǎng)輪詢:

  • 長(zhǎng)輪詢是指客戶端會(huì)一直向服務(wù)端發(fā)起請(qǐng)求,適用與服務(wù)端向客戶端推送數(shù)據(jù)使用。長(zhǎng)輪詢要滿足以下幾點(diǎn): 客戶端發(fā)起請(qǐng)求后,當(dāng)服務(wù)端業(yè)務(wù)沒有數(shù)據(jù)時(shí),不會(huì)立即返回空值,而是hold住連接,等待數(shù)據(jù)生成后立即返回。
  • 請(qǐng)求在服務(wù)端有超時(shí)時(shí)間,不會(huì)一直hold住。當(dāng)超時(shí)后,服務(wù)端會(huì)返回超時(shí)信息,客戶端收到返回后會(huì)再次發(fā)起請(qǐng)求。
  • 每次請(qǐng)求結(jié)束后,客戶端會(huì)再次發(fā)起請(qǐng)求。

短輪詢、長(zhǎng)輪詢和長(zhǎng)連接比較:

  • 短輪詢:客戶端定時(shí)向服務(wù)器發(fā)送Ajax請(qǐng)求,服務(wù)器接到請(qǐng)求后馬上返回響應(yīng)信息并關(guān)閉連接。

優(yōu)點(diǎn):后端程序編寫比較容易,適于小型應(yīng)用。。

缺點(diǎn):請(qǐng)求中有大半是無用,浪費(fèi)帶寬和服務(wù)器資源。

  • 長(zhǎng)輪詢:客戶端向服務(wù)器發(fā)送Ajax請(qǐng)求,服務(wù)器接到請(qǐng)求后hold住連接,直到有新消息才返回響應(yīng)信息并關(guān)閉連接,客戶端處理完響應(yīng)信息后再向服務(wù)器發(fā)送新的請(qǐng)求。

優(yōu)點(diǎn):在無消息的情況下不會(huì)頻繁的請(qǐng)求。

缺點(diǎn):服務(wù)器hold連接會(huì)消耗資源。

  • 長(zhǎng)連接:客戶端與服務(wù)端建立長(zhǎng)連接socket

優(yōu)點(diǎn):可靠性高,實(shí)時(shí)性高。

缺點(diǎn):實(shí)現(xiàn)復(fù)雜,要維護(hù)心跳,服務(wù)器維持連接消耗資源。

長(zhǎng)輪詢實(shí)現(xiàn)

原理圖:

  • 請(qǐng)求過來之后,生成事件,加入對(duì)應(yīng)的事件集合。請(qǐng)求設(shè)置30s超時(shí)時(shí)間,并添加監(jiān)聽。tomcat工作線程釋放。
  • 當(dāng)服務(wù)端數(shù)據(jù)準(zhǔn)備好之后,觸發(fā)對(duì)應(yīng)事件,從容器獲取訂閱事件進(jìn)行執(zhí)行。完成后返回response。
  • 請(qǐng)求超時(shí),listener觸發(fā),返回超時(shí)信息。

下面看下具體實(shí)現(xiàn):

事件定義,這里只是定義一個(gè)簡(jiǎn)單的事件:

package com.hiwe.demo.event;
import javax.servlet.AsyncContext;
public class HttpEvent {
    /**
     * 可以是業(yè)務(wù)數(shù)據(jù)主鍵,這里用請(qǐng)求名稱做個(gè)簡(jiǎn)單demo
     */
    private String requestName;
    private AsyncContext asyncContext;
    public HttpEvent(String requestName,AsyncContext asyncContext){
        this.requestName = requestName;
        this.asyncContext = asyncContext;
    }
    public String getRequestName() {
        return requestName;
    }
    public AsyncContext getAsyncContext() {
        return asyncContext;
    }
}

事件管理器:

package com.hiwe.demo.event;
import javax.servlet.AsyncContext;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
public class EventManager {
    private final static Map<String,HttpEvent> subHttpEvents = new HashMap<>();
    /**
     * 新增事件訂閱
     * @param event
     */
    public static void addHttpEvent(HttpEvent event){
        subHttpEvents.put(event.getRequestName(),event);
    }
    /**
     * 觸發(fā)事件
     * @param requestName
     */
    public static void onEvent(String requestName){
        HttpEvent httpEvent = subHttpEvents.get(requestName);
        if(httpEvent==null){
            return;
        }
        AsyncContext asyncContext = httpEvent.getAsyncContext();
        try {
            PrintWriter writer = asyncContext.getResponse().getWriter();
            writer.print(requestName+" request success!");
            writer.flush();
            asyncContext.complete();
            subHttpEvents.remove(requestName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

異步請(qǐng)求監(jiān)聽器:

package com.hiwe.demo.listener;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebListener;
import java.io.IOException;
import java.io.PrintWriter;
@WebListener
public class AppAsyncListener implements AsyncListener {
    @Override
    public void onComplete(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onComplete");
        // we can do resource cleanup activity here
    }
    @Override
    public void onError(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onError");
        //we can return error response to client
    }
    @Override
    public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
        System.out.println("AppAsyncListener onStartAsync");
        //we can log the event here
    }
    /**
     * 超時(shí)觸發(fā)
     * @param asyncEvent
     * @throws IOException
     */
    @Override
    public void onTimeout(AsyncEvent asyncEvent) throws IOException {
        AsyncContext asyncContext = asyncEvent.getAsyncContext();
        ServletResponse response = asyncEvent.getAsyncContext().getResponse();
        PrintWriter out = response.getWriter();
        //返回code碼,以便前端識(shí)別,并重建請(qǐng)求
        out.write(201+" longPolling timeout");
        out.flush();
        asyncContext.complete();
    }
}

長(zhǎng)輪詢接口:

package com.hiwe.demo.controller;
import com.hiwe.demo.listener.AppAsyncListener;
import com.hiwe.demo.event.EventManager;
import com.hiwe.demo.event.HttpEvent;
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 javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/app")
public class AsyncController {
    /**
     * 長(zhǎng)輪詢接口
     * @param requestName
     * @param request
     * @param response
     */
    @GetMapping("/asyncGet")
    public void getDemo(@RequestParam(value = "requestName") String requestName, HttpServletRequest request, HttpServletResponse response){
        //開啟異步支持
        request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
        AsyncContext asyncContext = request.startAsync();
        //添加監(jiān)聽器
        asyncContext.addListener(new AppAsyncListener());
        //設(shè)置超時(shí)時(shí)間
        asyncContext.setTimeout(30000);
        //添加到事件集合中去
        HttpEvent httpEvent = new HttpEvent(requestName, asyncContext);
        EventManager.addHttpEvent(httpEvent);
    }
    /**
     * 觸發(fā)事件使用
     * @param requestName
     */
    @GetMapping("/trigger")
    public void triggerDemo(@RequestParam(value = "requestName") String requestName){
        EventManager.onEvent(requestName);
    }
}

以上一個(gè)簡(jiǎn)單的長(zhǎng)輪詢就實(shí)現(xiàn)了,我們可以進(jìn)行一下測(cè)試:

啟動(dòng)應(yīng)用后訪問:http://localhost:8080/app/asyncGet?requestName=123

服務(wù)端因?yàn)閿?shù)據(jù)未準(zhǔn)備就緒,所以會(huì)hold住請(qǐng)求。當(dāng)?shù)却?0s后會(huì)返回超時(shí)信息:

我們?cè)?0s內(nèi)觸發(fā)event:http://localhost:8080/app/trigger?requestName=123

返回:

以上整個(gè)長(zhǎng)輪詢實(shí)現(xiàn)完成了,如果有錯(cuò)誤,歡迎指正!

到此這篇關(guān)于Java servlet通過事件驅(qū)動(dòng)進(jìn)行高性能長(zhǎng)輪詢?cè)斀獾奈恼戮徒榻B到這了,更多相關(guān)Java 高性能長(zhǎng)輪詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • jdbc與druid連接池的使用詳解

    jdbc與druid連接池的使用詳解

    這篇文章主要介紹了jdbc與druid連接池的使用詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • SpringBoot3+ShardingJDBC5.5.0 讀寫分離配置的實(shí)現(xiàn)

    SpringBoot3+ShardingJDBC5.5.0 讀寫分離配置的實(shí)現(xiàn)

    本文主要介紹了SpringBoot3+ShardingJDBC5.5.0 讀寫分離配置的實(shí)現(xiàn),最新版5.5.0支持SpringBoot3x現(xiàn)分享給大家,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • 關(guān)于Spring?Ioc和DI注解的問題

    關(guān)于Spring?Ioc和DI注解的問題

    這篇文章主要介紹了Spring?Ioc和DI注解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • Java Web導(dǎo)出等比例圖片到Excel的實(shí)現(xiàn)過程

    Java Web導(dǎo)出等比例圖片到Excel的實(shí)現(xiàn)過程

    我們使用Java導(dǎo)出圖片到Excel,打開成功導(dǎo)出的Excel一看,商品對(duì)應(yīng)的圖片都很規(guī)矩的按照我的設(shè)置鋪滿了整個(gè)單元格,但是,商品圖片卻都變形了,這樣肯定是不行的,于是第一反應(yīng)就是將圖片等比例導(dǎo)出,所以本文本給大家介紹了如何使用Java Web導(dǎo)出等比例圖片到Excel
    2023-11-11
  • 基于Spring整合mybatis注解掃描是否成功的問題

    基于Spring整合mybatis注解掃描是否成功的問題

    這篇文章主要介紹了Spring整合mybatis注解掃描是否成功的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 解決response.setHeader設(shè)置下載文件名無效的問題

    解決response.setHeader設(shè)置下載文件名無效的問題

    這篇文章主要介紹了解決response.setHeader設(shè)置下載文件名無效的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java線程讓步_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java線程讓步_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    yield()的作用是讓步。它能讓當(dāng)前線程由“運(yùn)行狀態(tài)”進(jìn)入到“就緒狀態(tài)”,從而讓其它具有相同優(yōu)先級(jí)的等待線程獲取執(zhí)行權(quán)。下面通過本文給大家介紹Java線程讓步的相關(guān)知識(shí),需要的朋友參考下吧
    2017-05-05
  • SSH框架網(wǎng)上商城項(xiàng)目第19戰(zhàn)之訂單信息級(jí)聯(lián)入庫(kù)以及頁(yè)面緩存問題

    SSH框架網(wǎng)上商城項(xiàng)目第19戰(zhàn)之訂單信息級(jí)聯(lián)入庫(kù)以及頁(yè)面緩存問題

    這篇文章主要介紹了SSH框架網(wǎng)上商城項(xiàng)目第19戰(zhàn)之訂單信息級(jí)聯(lián)入庫(kù)以及頁(yè)面緩存問題,感興趣的小伙伴們可以參考一下
    2016-06-06
  • java實(shí)現(xiàn)微信支付(服務(wù)端)

    java實(shí)現(xiàn)微信支付(服務(wù)端)

    這篇文章主要介紹了java實(shí)現(xiàn)微信支付,針對(duì)服務(wù)端進(jìn)行代碼編寫,感興趣的小伙伴們可以參考一下
    2015-12-12
  • Java集合類中文介紹

    Java集合類中文介紹

    本文首先對(duì)Java集合類框架做了簡(jiǎn)單說明,之后對(duì)主要類和為API做了介紹:Collection、List、Set、AbstractCollection、AbstractList、AbstractSet、Iterator、ListIterator。
    2013-11-11

最新評(píng)論

惠安县| 时尚| 定日县| 米泉市| 虎林市| 丽水市| 南郑县| 鄂伦春自治旗| 九龙县| 湘阴县| 大埔区| 公安县| 南平市| 微博| 沂源县| 平湖市| 德阳市| 胶州市| 肥城市| 禹城市| 南通市| 额济纳旗| 兴和县| 乌苏市| 潮安县| 万全县| 吴忠市| 仙游县| 牟定县| 响水县| 三台县| 平乡县| 新安县| 清苑县| 昌乐县| 昆明市| 保德县| 抚州市| 陆丰市| 萨迦县| 探索|