亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java Servlet3.0異步處理問題

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

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

Servlet 3.0 開始提供了AsyncContext用來支持異步處理請求,那么異步處理請求到底能夠帶來哪些好處?

Web容器一般來說處理請求的方式是:為每個request分配一個thread。我們都知道thread的創(chuàng)建不是沒有代價的,Web容器的thread pool都是有上限的。
那么一個很容易預見的問題就是,在高負載情況下,thread pool都被占著了,那么后續(xù)的request就只能等待,如果運氣不好客戶端會報等待超時的錯誤。
在AsyncContext出現之前,解決這個問題的唯一辦法就是擴充Web容器的thread pool。

但是這樣依然有一個問題,考慮以下場景:

有一個web容器,線程池大小200。有一個web app,它有兩個servlet,Servlet-A處理單個請求的時間是10s,Servlet-B處理單個請求的時間是1s。
現在遇到了高負載,有超過200個request到Servlet-A,如果這個時候請求Servlet-B就會等待,因為所有HTTP thread都已經被Servlet-A占用了。
這個時候工程師發(fā)現了問題,擴展了線程池大小到400,但是負載依然持續(xù)走高,現在有400個request到Servlet-A,Servlet-B依然無法響應。

看到問題了沒有,因為HTTP thread和Worker thread耦合在了一起,所以導致了當大量request到一個耗時操作時,就會將HTTP thread占滿,導致整個Web容器就會無法響應。

但是如果使用AsyncContext,我們就可以將耗時的操作交給另一個thread去做,這樣HTTP thread就被釋放出來了,可以去處理其他請求了。

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

下面是一個官方的例子:

@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();
   }
  });
 }
}

陷阱

在這個官方例子里,每個HTTP thread都會開啟另一個Worker thread來處理請求,然后把HTTP thread就歸還給Web容器。但是看AsyncContext.start()方法的javadoc:

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

實際上這里并沒有規(guī)定Worker thread到底從哪里來,也許是HTTP thread pool之外的另一個thread pool?還是說就是HTTP thread pool?

The Limited Usefulness of AsyncContext.start()文章里寫道:不同的Web容器對此有不同的實現,不過Tomcat實際上是利用HTTP thread pool來處理AsyncContext.start()的。

這也就是說,我們原本是想釋放HTTP thread的,但實際上并沒有,因為有HTTP thread依然被用作Worker thread,只不過這個thread和接收請求的HTTP thread不是同一個而已。

這個結論我們也可以通過AsyncServlet1和SyncServlet的Jmeter benchmark看出來,兩者的throughput結果差不多。啟動方法:啟動Main,然后利用Jmeter啟動benchmark.jmx(Tomcat默認配置下HTTP thread pool=200)。

使用ExecutorService

前面看到了Tomcat并沒有單獨維護Worker thread pool,那么我們就得自己想辦法搞一個,見AsyncServlet2,它使用了一個帶Thread pool的ExecutorService來處理AsyncContext。

其他方式

所以對于AsyncContext的使用并沒有固定的方式,你可以根據實際需要去采用不同的方式來處理,為此你需要一點Java concurrent programming的知識。

對于性能的誤解

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

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

相反,如果當Worker thread的數量<=HTTP thread數量的時候,那么就不會得到性能提升,因為此時處理請求的瓶頸在Worker thread。
你可以修改AsyncServlet2的線程池大小,把它和SyncServlet比較benchmark結果來驗證這一結論。

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

兩者職責不同,一個是Web容器用來接收外來請求,一個是處理業(yè)務邏輯

thread的創(chuàng)建是有代價的,如果HTTP thread pool已經很大了再搞一個更大的Worker thread pool反而會造成過多的Context switch和內存開銷

AsyncContext的目的是將HTTP thread釋放出來,避免被操作長期占用進而導致Web容器無法響應

所以在更多時候,Worker thread pool不會很大,而且會根據不同業(yè)務構建不同的Worker thread pool。

比如:Web容器thread pool大小200,一個慢速Servlet的Worker thread pool大小10,這樣一來,無論有多少請求到慢速操作,它都不會將HTTP thread占滿導致其他請求無法處理。

相關文章

  • JDK8中新增的原子性操作類LongAdder詳解

    JDK8中新增的原子性操作類LongAdder詳解

    這篇文章主要給大家介紹了關于JDK8中新增的原子性操作類LongAdder的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面跟著小編來一起學習學習吧。
    2017-08-08
  • 詳解Spring Boot 項目中的 parent

    詳解Spring Boot 項目中的 parent

    這篇文章主要介紹了Spring Boot中parent作用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • 詳解MyBatis中主鍵回填的兩種實現方式

    詳解MyBatis中主鍵回填的兩種實現方式

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

    Java 用兩個線程交替打印數字和字母

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

    Java應用層協(xié)議WebSocket實現消息推送

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

    詳解Java中雪花算法的實現

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

    Java跨域問題的幾種后端解決方式舉例詳解

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

    Vue實現驗證碼登錄的超詳細步驟

    這篇文章主要給大家介紹了關于Vue實現驗證碼登錄的超詳細步驟,我們在使用vue進行前端開發(fā)時都需要登錄驗證,文中通過代碼示例介紹的非常詳細,需要的朋友可以參考下
    2023-09-09
  • SpringBoot整合Drools的實現步驟

    SpringBoot整合Drools的實現步驟

    Drools是一個易于訪問企業(yè)策略、易于調整以及易于管理的開源業(yè)務規(guī)則引擎,符合業(yè)內標準,速度快、效率高。業(yè)務分析師或審核人員可以利用它輕松查看業(yè)務規(guī)則,從而檢驗是否已編碼的規(guī)則執(zhí)行所需的業(yè)務規(guī)則。本文將講述SpringBoot整合Drools的步驟
    2021-05-05
  • springcloud如何用Redlock實現分布式鎖

    springcloud如何用Redlock實現分布式鎖

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

最新評論