欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java Servlet3.0異步處理問(wèn)題

 更新時(shí)間:2017年12月07日 09:23:17   投稿:laozhang  
這篇文章主要介紹了Java中Servlet3.0異步處理的原理以及遇到的問(wèn)題分析,需要的朋友參考一下。

通過(guò)本篇文章主要給大家講解了在JAVA開(kāi)發(fā)中Servlet3.0異步處理遇到的問(wèn)題以及處理辦法,以下是具體內(nèi)容:

Servlet 3.0 開(kāi)始提供了AsyncContext用來(lái)支持異步處理請(qǐng)求,那么異步處理請(qǐng)求到底能夠帶來(lái)哪些好處?

Web容器一般來(lái)說(shuō)處理請(qǐng)求的方式是:為每個(gè)request分配一個(gè)thread。我們都知道thread的創(chuàng)建不是沒(méi)有代價(jià)的,Web容器的thread pool都是有上限的。
那么一個(gè)很容易預(yù)見(jiàn)的問(wèn)題就是,在高負(fù)載情況下,thread pool都被占著了,那么后續(xù)的request就只能等待,如果運(yùn)氣不好客戶(hù)端會(huì)報(bào)等待超時(shí)的錯(cuò)誤。
在AsyncContext出現(xiàn)之前,解決這個(gè)問(wèn)題的唯一辦法就是擴(kuò)充Web容器的thread pool。

但是這樣依然有一個(gè)問(wèn)題,考慮以下場(chǎng)景:

有一個(gè)web容器,線程池大小200。有一個(gè)web app,它有兩個(gè)servlet,Servlet-A處理單個(gè)請(qǐng)求的時(shí)間是10s,Servlet-B處理單個(gè)請(qǐng)求的時(shí)間是1s。
現(xiàn)在遇到了高負(fù)載,有超過(guò)200個(gè)request到Servlet-A,如果這個(gè)時(shí)候請(qǐng)求Servlet-B就會(huì)等待,因?yàn)樗蠬TTP thread都已經(jīng)被Servlet-A占用了。
這個(gè)時(shí)候工程師發(fā)現(xiàn)了問(wèn)題,擴(kuò)展了線程池大小到400,但是負(fù)載依然持續(xù)走高,現(xiàn)在有400個(gè)request到Servlet-A,Servlet-B依然無(wú)法響應(yīng)。

看到問(wèn)題了沒(méi)有,因?yàn)镠TTP thread和Worker thread耦合在了一起,所以導(dǎo)致了當(dāng)大量request到一個(gè)耗時(shí)操作時(shí),就會(huì)將HTTP thread占滿(mǎn),導(dǎo)致整個(gè)Web容器就會(huì)無(wú)法響應(yīng)。

但是如果使用AsyncContext,我們就可以將耗時(shí)的操作交給另一個(gè)thread去做,這樣HTTP thread就被釋放出來(lái)了,可以去處理其他請(qǐng)求了。

注意,只有使用AsyncContext才能夠達(dá)到上面所講的效果,如果直接new Thread()或者類(lèi)似的方式的,HTTP thread并不會(huì)歸還到容器。

下面是一個(gè)官方的例子:

@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true)
public class AsyncServlet extends HttpServlet {
 /* ... Same variables and init method as in SyncServlet ... */
 @Override
 public void doGet(HttpServletRequest request, 
      HttpServletResponse response) {
  response.setContentType("text/html;charset=UTF-8");
  final AsyncContext acontext = request.startAsync();
  acontext.start(new Runnable() {
   public void run() {
   String param = acontext.getRequest().getParameter("param");
   String result = resource.process(param);
   HttpServletResponse response = acontext.getResponse();
   /* ... print to the response ... */
   acontext.complete();
   }
  });
 }
}

陷阱

在這個(gè)官方例子里,每個(gè)HTTP thread都會(huì)開(kāi)啟另一個(gè)Worker thread來(lái)處理請(qǐng)求,然后把HTTP thread就歸還給Web容器。但是看AsyncContext.start()方法的javadoc:

Causes the container to dispatch a thread, possibly from a managed thread pool, to run the specified Runnable.

實(shí)際上這里并沒(méi)有規(guī)定Worker thread到底從哪里來(lái),也許是HTTP thread pool之外的另一個(gè)thread pool?還是說(shuō)就是HTTP thread pool?

The Limited Usefulness of AsyncContext.start()文章里寫(xiě)道:不同的Web容器對(duì)此有不同的實(shí)現(xiàn),不過(guò)Tomcat實(shí)際上是利用HTTP thread pool來(lái)處理AsyncContext.start()的。

這也就是說(shuō),我們?cè)臼窍脶尫臜TTP thread的,但實(shí)際上并沒(méi)有,因?yàn)橛蠬TTP thread依然被用作Worker thread,只不過(guò)這個(gè)thread和接收請(qǐng)求的HTTP thread不是同一個(gè)而已。

這個(gè)結(jié)論我們也可以通過(guò)AsyncServlet1和SyncServlet的Jmeter benchmark看出來(lái),兩者的throughput結(jié)果差不多。啟動(dòng)方法:?jiǎn)?dòng)Main,然后利用Jmeter啟動(dòng)benchmark.jmx(Tomcat默認(rèn)配置下HTTP thread pool=200)。

使用ExecutorService

前面看到了Tomcat并沒(méi)有單獨(dú)維護(hù)Worker thread pool,那么我們就得自己想辦法搞一個(gè),見(jiàn)AsyncServlet2,它使用了一個(gè)帶Thread pool的ExecutorService來(lái)處理AsyncContext。

其他方式

所以對(duì)于AsyncContext的使用并沒(méi)有固定的方式,你可以根據(jù)實(shí)際需要去采用不同的方式來(lái)處理,為此你需要一點(diǎn)Java concurrent programming的知識(shí)。

對(duì)于性能的誤解

AsyncContext的目的并不是為了提高性能,也并不直接提供性能提升,它提供了把HTTP thread和Worker thread解藕的機(jī)制,從而提高Web容器的響應(yīng)能力。

不過(guò)AsyncContext在某些時(shí)候的確能夠提高性能,但這個(gè)取決于你的代碼是怎么寫(xiě)的。
比如:Web容器的HTTP thread pool數(shù)量200,某個(gè)Servlet使用一個(gè)300的Worker thread pool來(lái)處理AsyncContext。
相比Sync方式Worker thread pool=HTTP thread pool=200,在這種情況下我們有了300的Worker thread pool,所以肯定能夠帶來(lái)一些性能上的提升(畢竟干活的人多了)。

相反,如果當(dāng)Worker thread的數(shù)量<=HTTP thread數(shù)量的時(shí)候,那么就不會(huì)得到性能提升,因?yàn)榇藭r(shí)處理請(qǐng)求的瓶頸在Worker thread。
你可以修改AsyncServlet2的線程池大小,把它和SyncServlet比較benchmark結(jié)果來(lái)驗(yàn)證這一結(jié)論。

一定不要認(rèn)為Worker thread pool必須比HTTP thread pool大,理由如下:

兩者職責(zé)不同,一個(gè)是Web容器用來(lái)接收外來(lái)請(qǐng)求,一個(gè)是處理業(yè)務(wù)邏輯

thread的創(chuàng)建是有代價(jià)的,如果HTTP thread pool已經(jīng)很大了再搞一個(gè)更大的Worker thread pool反而會(huì)造成過(guò)多的Context switch和內(nèi)存開(kāi)銷(xiāo)

AsyncContext的目的是將HTTP thread釋放出來(lái),避免被操作長(zhǎng)期占用進(jìn)而導(dǎo)致Web容器無(wú)法響應(yīng)

所以在更多時(shí)候,Worker thread pool不會(huì)很大,而且會(huì)根據(jù)不同業(yè)務(wù)構(gòu)建不同的Worker thread pool。

比如:Web容器thread pool大小200,一個(gè)慢速Servlet的Worker thread pool大小10,這樣一來(lái),無(wú)論有多少請(qǐng)求到慢速操作,它都不會(huì)將HTTP thread占滿(mǎn)導(dǎo)致其他請(qǐng)求無(wú)法處理。

相關(guān)文章

  • JDK8中新增的原子性操作類(lèi)LongAdder詳解

    JDK8中新增的原子性操作類(lèi)LongAdder詳解

    這篇文章主要給大家介紹了關(guān)于JDK8中新增的原子性操作類(lèi)LongAdder的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-08-08
  • 詳解Spring Boot 項(xiàng)目中的 parent

    詳解Spring Boot 項(xiàng)目中的 parent

    這篇文章主要介紹了Spring Boot中parent作用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 詳解MyBatis中主鍵回填的兩種實(shí)現(xiàn)方式

    詳解MyBatis中主鍵回填的兩種實(shí)現(xiàn)方式

    這篇文章主要介紹了詳解MyBatis中主鍵回填的兩種實(shí)現(xiàn)方式,主鍵回填其實(shí)是一個(gè)非常常見(jiàn)的需求,特別是在數(shù)據(jù)添加的過(guò)程中,我們經(jīng)常需要添加完數(shù)據(jù)之后,需要獲取剛剛添加的數(shù)據(jù) id,有興趣的可以參考一下
    2019-04-04
  • Java 用兩個(gè)線程交替打印數(shù)字和字母

    Java 用兩個(gè)線程交替打印數(shù)字和字母

    這篇文章主要介紹了Java 用兩個(gè)線程交替打印數(shù)字和字母的方法,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-03-03
  • Java應(yīng)用層協(xié)議WebSocket實(shí)現(xiàn)消息推送

    Java應(yīng)用層協(xié)議WebSocket實(shí)現(xiàn)消息推送

    后端向前端推送消息就需要長(zhǎng)連接,首先想到的就是websocket,下面這篇文章主要給大家介紹了關(guān)于java后端+前端使用WebSocket實(shí)現(xiàn)消息推送的詳細(xì)流程,需要的朋友可以參考下
    2023-02-02
  • 詳解Java中雪花算法的實(shí)現(xiàn)

    詳解Java中雪花算法的實(shí)現(xiàn)

    雪花算法是一種分布式的id生成算法。原理是將long分成若干個(gè)區(qū)段分別管理。本文將利用Java簡(jiǎn)單的實(shí)現(xiàn)雪花算法,感興趣的可以了解一下
    2022-12-12
  • Java跨域問(wèn)題的幾種后端解決方式舉例詳解

    Java跨域問(wèn)題的幾種后端解決方式舉例詳解

    跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本,它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript實(shí)施的安全限制,這篇文章主要給大家介紹了關(guān)于Java跨域問(wèn)題的幾種后端解決方式的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • Vue實(shí)現(xiàn)驗(yàn)證碼登錄的超詳細(xì)步驟

    Vue實(shí)現(xiàn)驗(yàn)證碼登錄的超詳細(xì)步驟

    這篇文章主要給大家介紹了關(guān)于Vue實(shí)現(xiàn)驗(yàn)證碼登錄的超詳細(xì)步驟,我們?cè)谑褂胿ue進(jìn)行前端開(kāi)發(fā)時(shí)都需要登錄驗(yàn)證,文中通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • SpringBoot整合Drools的實(shí)現(xiàn)步驟

    SpringBoot整合Drools的實(shí)現(xiàn)步驟

    Drools是一個(gè)易于訪問(wèn)企業(yè)策略、易于調(diào)整以及易于管理的開(kāi)源業(yè)務(wù)規(guī)則引擎,符合業(yè)內(nèi)標(biāo)準(zhǔn),速度快、效率高。業(yè)務(wù)分析師或?qū)徍巳藛T可以利用它輕松查看業(yè)務(wù)規(guī)則,從而檢驗(yàn)是否已編碼的規(guī)則執(zhí)行所需的業(yè)務(wù)規(guī)則。本文將講述SpringBoot整合Drools的步驟
    2021-05-05
  • springcloud如何用Redlock實(shí)現(xiàn)分布式鎖

    springcloud如何用Redlock實(shí)現(xiàn)分布式鎖

    本文主要介紹了springcloud如何用Redlock實(shí)現(xiàn)分布式鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11

最新評(píng)論