国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
使用jetty做為server提供多線程文件下載

背景

  最近在做的一個(gè)項(xiàng)目,兩個(gè)java進(jìn)程之間會(huì)涉及一個(gè)大數(shù)據(jù)量的傳遞過(guò)程,基本都是圖片文件,(做了壓縮后還是會(huì)比較大,最大的有超過(guò)600MB)。其次這兩個(gè)java進(jìn)程是在跨機(jī)房,比如中國(guó)和美國(guó)機(jī)房,網(wǎng)絡(luò)待框也就幾百kB。

 

  這就是本文的項(xiàng)目背景

分析

1.  600MB的文件,都是A進(jìn)程運(yùn)行時(shí)根據(jù)需要生成的(下載需要的圖片文件)。所以無(wú)法預(yù)先處理,而且公司總圖片文件都是以TB計(jì)算,所以全量同步的方案也不靠譜

2.  從A進(jìn)程到B進(jìn)程的數(shù)據(jù)傳遞,首先想到用socket進(jìn)行傳遞,但單socket的數(shù)據(jù)同步無(wú)法滿足需求,多線程數(shù)據(jù)傳遞會(huì)涉及數(shù)據(jù)的切片和數(shù)據(jù)的合并等,代碼相對(duì)會(huì)比較復(fù)雜

 

老的項(xiàng)目實(shí)現(xiàn):

  • A先臨時(shí)保存文件到一指定目錄
  • A進(jìn)程機(jī)器上啟動(dòng)一個(gè)http服務(wù)(比如nginx,lighttpd)
  • B進(jìn)程外部調(diào)用一個(gè)多線程下載客戶端,下載數(shù)據(jù)到一臨時(shí)目錄
  • B進(jìn)程等下載完成后,再操縱臨時(shí)目錄的數(shù)據(jù)
項(xiàng)目的工程代碼都是以java,引入了多線程服務(wù)和下載客戶端之后,增加了項(xiàng)目的部署和維護(hù)成本。所以在項(xiàng)目重構(gòu)時(shí),想的一個(gè)辦法是用嵌入式的jetty,去替換nginx提供http服務(wù)。

過(guò)程

涉及到多線程下載和斷點(diǎn)續(xù)載,首先得了解一個(gè)Http協(xié)議的內(nèi)容。

 

Byte Ranges: 文檔http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1

 

大致的內(nèi)容,可以在Http的Header頭中進(jìn)行添加,可以指定文件下載byte的start和end的位置,幾個(gè)例子:

Java代碼  
  1. bytes=100-499    
  2. bytes=-300  
  3. bytes=100-  
  4. bytes=1-2,2-3,6-,-2  

 

最后,通過(guò)tcpdump進(jìn)行數(shù)據(jù)抓包分析,多線程下載客戶端的Http協(xié)議的內(nèi)容。基本的思路是根據(jù)線程數(shù),計(jì)算出每個(gè)線程的bytes-range,然后每個(gè)線程發(fā)起一個(gè)獨(dú)立的請(qǐng)求。后端每個(gè)處理線程單獨(dú)處理bytes-range的數(shù)據(jù)下載。

至于斷點(diǎn)續(xù)傳,其實(shí)也相對(duì)比較簡(jiǎn)單了。就是記錄好分出去的每個(gè)bytes-range成功與否,失敗的重新再做,已經(jīng)做完的可以直接跳過(guò)。

 

抓取的Http協(xié)議內(nèi)容:

Java代碼  
  1. GET /source.tar.gz HTTP/1.1  
  2. User-Agent: aria2/1.13.0  
  3. Accept: */*  
  4. Host: 10.20.156.49:8080  
  5. Pragma: no-cache  
  6. Cache-Control: no-cache  
  7. Range: bytes=258998272-387973119  

java版的多線程下載支持

一提到做java版的多線程下載,首先就會(huì)想到j(luò)etty和tomcat。tomcat只能以外部server的方式進(jìn)行啟動(dòng),和nginx沒(méi)有太多的區(qū)別。

最后我選擇了jetty,并在項(xiàng)目中做為嵌入式進(jìn)行啟動(dòng),提供http多線程下載服務(wù)。

 

按照前面的分析,要做多線程下載,無(wú)非就是要實(shí)現(xiàn)一個(gè)bytes-range的處理。還好我用的jetty版本(7.0.1)已經(jīng)解析了bytes-range,具體解析類:InclusiveByteRange

 

再仔細(xì)翻了下它的代碼,發(fā)現(xiàn)jetty已經(jīng)默認(rèn)提供了一個(gè)servlet支持多線程下載,就是DefaultServlet,甚喜。

 

最后,按照我項(xiàng)目的需求適當(dāng)?shù)牟眉袅艘恍┐a,最后完成了:DownloadServlet,具體代碼見(jiàn)附件。

 

類中使用了java版的sendfile,推薦看一下:http://stackoverflow.com/questions/1605332/java-nio-filechannel-versus-fileoutputstream-performance-usefulness

 


將jetty引入做為嵌入式啟動(dòng)的步驟

1. 引入相關(guān)的jar

 

Xml代碼  
  1. <dependency>  
  2.   <groupId>com.alibaba.external</groupId>  
  3.   <artifactId>server.jetty.jetty-servlet</artifactId>  
  4.   <version>${jetty_verion}</version>  
  5. </dependency>  
  6. <dependency>  
  7.   <groupId>com.alibaba.external</groupId>  
  8.   <artifactId>server.jetty.jetty-xml</artifactId>  
  9.   <version>${jetty_verion}</version>  
  10. </dependency>  
  11. <dependency>  
  12.   <groupId>com.alibaba.external</groupId>  
  13.   <artifactId>server.jetty.jetty-server</artifactId>  
  14.   <version>${jetty_verion}</version>  
  15. </dependency>  

 

2.  配置jetty.xml (我選擇了xml的配置方式,但沒(méi)有使用war包,我只需要一個(gè)Http服務(wù)功能即可)

Java代碼  
  1. <Configure id="Server" class="org.eclipse.jetty.server.Server">  
  2.   
  3.     <!-- =========================================================== -->  
  4.     <!-- Server Thread Pool                                          -->  
  5.     <!-- =========================================================== -->  
  6.     <Set name="ThreadPool">  
  7.       <!-- Default queued blocking threadpool -->  
  8.       <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">  
  9.         <Set name="minThreads">10</Set>  
  10.         <Set name="maxThreads">250</Set>  
  11.       </New>  
  12.     </Set>  
  13.   
  14.     <!-- =========================================================== -->  
  15.     <!-- Set connectors                                              -->  
  16.     <!-- =========================================================== -->  
  17.     <!-- -->  
  18.     <Call name="addConnector">  
  19.       <Arg>  
  20.           <New class="org.eclipse.jetty.server.bio.SocketConnector">  
  21.             <Set name="port"><Property name="jetty.bio.port" default="8080"/></Set>  
  22.             <Set name="forwarded">true</Set>  
  23.             <Set name="forwardedHostHeader">ignore</Set>  
  24.             <Set name="forwardedServerHeader">ignore</Set>  
  25.             <Set name="acceptQueueSize">256</Set>  
  26.             <Set name="statsOn">false</Set>  
  27.             <Set name="maxIdleTime">600000</Set>  
  28.             <Set name="lowResourcesMaxIdleTime">5000</Set>  
  29.             <Set name="requestHeaderSize">8192</Set>  
  30.         <Set name="responseHeaderSize">8192</Set>  
  31.           </New>  
  32.       </Arg>  
  33.     </Call>  
  34.     <!--   
  35.     <Call name="addConnector">  
  36.       <Arg>  
  37.           <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">  
  38.             <Set name="host"><Property name="jetty.host" /></Set>  
  39.             <Set name="port"><Property name="jetty.port" default="8080"/></Set>  
  40.             <Set name="forwarded">true</Set>  
  41.             <Set name="forwardedHostHeader">ignore</Set>  
  42.             <Set name="forwardedServerHeader">ignore</Set>  
  43.             <Set name="maxIdleTime">600000</Set>  
  44.             <Set name="Acceptors">2</Set>  
  45.             <Set name="acceptQueueSize">256</Set>  
  46.             <Set name="statsOn">false</Set>  
  47.             <Set name="confidentialPort">8443</Set>  
  48.             <Set name="lowResourcesConnections">2000</Set>  
  49.             <Set name="lowResourcesMaxIdleTime">5000</Set>  
  50.             <Set name="requestHeaderSize">8192</Set>  
  51.             <Set name="responseHeaderSize">8192</Set>  
  52.           </New>  
  53.       </Arg>  
  54.     </Call>  
  55.      -->  
  56.     <!-- =========================================================== -->  
  57.     <!-- Set handler Collection Structure                            -->  
  58.     <!-- =========================================================== -->  
  59.     <Set name="handler">  
  60.       <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">  
  61.         <Set name="handlers">  
  62.          <Array type="org.eclipse.jetty.server.Handler">  
  63.            <Item>  
  64.              <New id="ServletHandler" class="org.eclipse.jetty.servlet.ServletContextHandler">  
  65.                 <Set name="contextPath">/</Set>  
  66.                 <Call name="addServlet">  
  67.                     <Arg>com.alibaba.otter.task.biz.common.jetty.DownloadServlet</Arg>  
  68.                     <Arg>/*</Arg>  
  69.                 </Call>  
  70.                 <Get name="initParams">  
  71.                     <Put name="org.eclipse.jetty.servlet.Default.resourceBase">/tmp/</Put>  
  72.                     <Put name="org.eclipse.jetty.servlet.Default.gzip">false</Put>  
  73.                 </Get>  
  74.              </New>  
  75.            </Item>  
  76.          </Array>  
  77.         </Set>  
  78.       </New>  
  79.     </Set>  
  80.   
  81.     <!-- =========================================================== -->  
  82.     <!-- extra options                                               -->  
  83.     <!-- =========================================================== -->  
  84.     <Set name="stopAtShutdown">true</Set>  
  85.     <Set name="sendServerVersion">false</Set>  
  86.     <Set name="sendDateHeader">true</Set>  
  87.     <Set name="gracefulShutdown">1000</Set>  
  88. </Configure>  

說(shuō)明: 主要的配置見(jiàn)handler,配置了對(duì)應(yīng)的DownloadServlet

 

3. 啟動(dòng)入口 (使用了xml配置后就灰常的簡(jiǎn)潔了)

 

Java代碼  
  1. Resource jetty_xml = Resource.newSystemResource("jetty/jetty.xml");  
  2. XmlConfiguration configuration = new XmlConfiguration(jetty_xml.getInputStream());  
  3. Server server = (Server) configuration.configure();  
  4. server.start();  

 

測(cè)試

 

  最后選擇了幾個(gè)多線程下載的客戶端進(jìn)行了測(cè)試,我這里選擇了aria2c(http://aria2.sourceforge.net/)  和 axel(http://www.axel.com/uk2/)

 

aria2c測(cè)試

參數(shù):

Java代碼  
  1. --no-conf -x 10 -s 10 -j 10 --timeout=600 --max-tries=5 --stop=1800 --allow-overwrite=true --enable-http-keep-alive=true --log-level=warn  

下載1.1GB的文件:

   apache : 28s

   nginx  : 27s

   jetty   : 27s


axel測(cè)試
參數(shù):
Java代碼  
  1. -n 10 -a -v <span style="white-space: normal;"> </span>  

下載1.1GB的文件: 

   apache : 87s
   nginx  : 87s

   jetty : 88s

 

總結(jié)

并沒(méi)有做非常詳盡的性能測(cè)試,不過(guò)從幾次跑的結(jié)果來(lái)看,基本上也有數(shù)了。

  1. jetty實(shí)現(xiàn)的servlet性能基本和nginx,apache下載接近。而且測(cè)試過(guò)程中瓶頸已經(jīng)不在應(yīng)用本身,基本都在網(wǎng)絡(luò)帶寬上了,我是百M(fèi)B網(wǎng)卡,基本可以滿負(fù)荷運(yùn)轉(zhuǎn)。
  2. jetty的nio和bio版本,nio在context switch切換上會(huì)相對(duì)比較多(因?yàn)橛写罅康腞EAD/WRITE事件響應(yīng),線程切換反而不如bio來(lái)得少),建議部署bio模式
  3. 多線程下載aria2c工具的確不錯(cuò),推薦使用
后續(xù),會(huì)嘗試使用java寫(xiě)一個(gè)多線程的客戶端,如果性能還ok的話,可以直接替換aria2c,到時(shí)候就是一些jar包,沒(méi)有了外部軟件的依賴,部署和維護(hù)也會(huì)相對(duì)比較簡(jiǎn)單。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Jetty學(xué)習(xí)七:配置安全
jetty的基本介紹 | 知行天下
jetty虛擬目錄
Linux下的jetty報(bào)java.lang.OutOfMemoryError: PermGen space及Jetty內(nèi)存配置調(diào)優(yōu)解決方案分享
Jetty的配置
Jetty學(xué)習(xí)總結(jié)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服