成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

初試Java 7 NIO2:實現高性能的HTTP Server

開發 后端
NIO.2是針對Java中I/O功能的一系列增強,計劃在Java 7中發布。在現在的Java 7里程碑版本中已經可以使用這個功能,本文作者描述了自己利用NIO2特性實現高性能Java HTTP Server的方法。

本文來自DoubleH的BlogJava博客,原文標題為《JDK7 NIO2 實踐: 增加 TransmitFile支持》。對于Java 7 NIO2特性的更多描述,可參考以前Google的一次技術演講

#t#JDK7的NIO2特性或許是我最期待的,我一直想基于它寫一個高性能的Java Http Server.現在這個想法終于可以實施了。

本人基于目前最新的JDK7 b76開發了一個HTTP Server性能確實不錯。

在windows平臺上NIO2采用AccpetEx來異步接受連接,并且讀寫全都關聯到IOCP完成端口。不僅如此,為了方便開發者使用,連IOCP工作線程都封裝好了,你只要提供線程池就OK。

但是要注意,IOCP工作線程的線程池必須是 Fix的,因為你發出的讀寫請求都關聯到相應的線程上,如果線程死了,那讀寫完成情況是不知道的。

作為一個Http Server,傳送文件是必不可少的功能,那一般文件的傳送都是要把程序里的buffer拷貝到內核的buffer,由內核發送出去的。windows平臺上為這種情況提供了很好的解決方案,使用TransmitFile接口

  1. BOOL TransmitFile(  
  2.     SOCKET hSocket,  
  3.     HANDLE hFile,  
  4.     DWORD nNumberOfBytesToWrite,  
  5.     DWORD nNumberOfBytesPerSend,  
  6.     LPOVERLAPPED lpOverlapped,  
  7.     LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,  
  8.     DWORD dwFlags  
  9. ); 

你只要把文件句柄發送給內核就行了,內核幫你搞定其余的,真正做到Zero-Copy.

但是很不幸,NIO2里AsynchronousSocketChannel沒有提供這樣的支持。而為HTTP Server的性能考量,本人只好自己增加這個支持。

要無縫支持,這個必須得表現的跟 Read /Write一樣,有完成的通知,通知傳送多少數據,等等。

仔細讀完sun的IOCP實現以后發現這部分工作他們封裝得很好,基本只要往他們的框架里加東西就好了。

為了能訪問他們的框架代碼,我定義自己的TransmitFile支持類在sun.nio.ch包里,以獲得最大的權限。

  1. package sun.nio.ch;  
  2.  
  3. import java.io.IOException;  
  4. import java.lang.reflect.Field;  
  5. import java.nio.channels.AsynchronousCloseException;  
  6. import java.nio.channels.AsynchronousSocketChannel;  
  7. import java.nio.channels.ClosedChannelException;  
  8. import java.nio.channels.CompletionHandler;  
  9. import java.nio.channels.NotYetConnectedException;  
  10. import java.nio.channels.WritePendingException;  
  11. import java.util.concurrent.Future;  
  12.  
  13.  
  14. /**  
  15.  * @author Yvon  
  16.  *   
  17.  */ 
  18. public class WindowsTransmitFileSupport {  
  19.      
  20.    //Sun's NIO2 channel  implementation class   
  21.     private WindowsAsynchronousSocketChannelImpl channel;  
  22.      
  23.     //nio2 framework core data structure  
  24.     PendingIoCache ioCache;  
  25.  
  26.    //some field retrieve from sun channel implementation class   
  27.     private Object writeLock;  
  28.     private Field writingF;  
  29.     private Field writeShutdownF;  
  30.     private Field writeKilledF; // f  
  31.  
  32.     WindowsTransmitFileSupport()  
  33.     {  
  34.         //dummy one for JNI code  
  35.     }  
  36.  
  37.     /**  
  38.      *   
  39.      */ 
  40.     public WindowsTransmitFileSupport(  
  41.             AsynchronousSocketChannel  
  42.              channel) {  
  43.  
  44.         this.channel = (WindowsAsynchronousSocketChannelImpl)channel;  
  45.         try {  
  46.         // Initialize the fields  
  47.             Field f = WindowsAsynchronousSocketChannelImpl.class 
  48.                     .getDeclaredField("ioCache");  
  49.             f.setAccessible(true);  
  50.             ioCache = (PendingIoCache) f.get(channel);  
  51.             f = AsynchronousSocketChannelImpl.class 
  52.                     .getDeclaredField("writeLock");  
  53.             f.setAccessible(true);  
  54.             writeLock = f.get(channel);  
  55.             writingF = AsynchronousSocketChannelImpl.class 
  56.                     .getDeclaredField("writing");  
  57.             writingF.setAccessible(true);  
  58.  
  59.             writeShutdownF = AsynchronousSocketChannelImpl.class 
  60.                     .getDeclaredField("writeShutdown");  
  61.             writeShutdownF.setAccessible(true);  
  62.  
  63.             writeKilledF = AsynchronousSocketChannelImpl.class 
  64.                     .getDeclaredField("writeKilled");  
  65.             writeKilledF.setAccessible(true);  
  66.  
  67.         } catch (NoSuchFieldException e) {  
  68.             // TODO Auto-generated catch block  
  69.             e.printStackTrace();  
  70.         } catch (SecurityException e) {  
  71.             // TODO Auto-generated catch block  
  72.             e.printStackTrace();  
  73.         } catch (IllegalArgumentException e) {  
  74.             // TODO Auto-generated catch block  
  75.             e.printStackTrace();  
  76.         } catch (IllegalAccessException e) {  
  77.             // TODO Auto-generated catch block  
  78.             e.printStackTrace();  
  79.         }  
  80.     }  
  81.  
  82.       
  83.     /**  
  84.      * Implements the task to initiate a write and the handler to consume the  
  85.      * result when the send file completes.  
  86.      */ 
  87.     private class SendFileTask implements Runnable, Iocp.ResultHandler {  
  88.         private final PendingFuture result;  
  89.         private final long file;//file is windows file HANDLE  
  90.  
  91.         SendFileTask(long file, PendingFuture result) {  
  92.             this.result = result;  
  93.             this.file = file;  
  94.         }  
  95.  
  96.       
  97.  
  98.         @Override 
  99.         // @SuppressWarnings("unchecked")  
  100.         public void run() {  
  101.             long overlapped = 0L;  
  102.             boolean pending = false;  
  103.             boolean shutdown = false;  
  104.  
  105.             try {  
  106.                 channel.begin();  
  107.  
  108.           
  109.  
  110.                 // get an OVERLAPPED structure (from the cache or allocate)  
  111.                 overlapped = ioCache.add(result);  
  112.                 int n = transmitFile0(channel.handle, file, overlapped);  
  113.                 if (n == IOStatus.UNAVAILABLE) {  
  114.                     // I/O is pending  
  115.                     pending = true;  
  116.                     return;  
  117.                 }  
  118.                 if (n == IOStatus.EOF) {  
  119.                     // special case for shutdown output  
  120.                     shutdown = true;  
  121.                     throw new ClosedChannelException();  
  122.                 }  
  123.                 // write completed immediately  
  124.                 throw new InternalError("Write completed immediately");  
  125.             } catch (Throwable x) {  
  126.                 // write failed. Enable writing before releasing waiters.  
  127.                 channel.enableWriting();  
  128.                 if (!shutdown && (x instanceof ClosedChannelException))  
  129.                     x = new AsynchronousCloseException();  
  130.                 if (!(x instanceof IOException))  
  131.                     x = new IOException(x);  
  132.                 result.setFailure(x);  
  133.             } finally {  
  134.                 // release resources if I/O not pending  
  135.                 if (!pending) {  
  136.                     if (overlapped != 0L)  
  137.                         ioCache.remove(overlapped);  
  138.                   
  139.                 }  
  140.                 channel.end();  
  141.             }  
  142.  
  143.             // invoke completion handler  
  144.             Invoker.invoke(result);  
  145.         }  
  146.  
  147.           
  148.  
  149.         /**  
  150.          * Executed when the I/O has completed  
  151.          */ 
  152.         @Override 
  153.         @SuppressWarnings("unchecked")  
  154.         public void completed(int bytesTransferred, boolean canInvokeDirect) {  
  155.       
  156.  
  157.             // release waiters if not already released by timeout  
  158.             synchronized (result) {  
  159.                 if (result.isDone())  
  160.                     return;  
  161.                 channel.enableWriting();  
  162.  
  163.                 result.setResult((V) Integer.valueOf(bytesTransferred));  
  164.  
  165.             }  
  166.             if (canInvokeDirect) {  
  167.                 Invoker.invokeUnchecked(result);  
  168.             } else {  
  169.                 Invoker.invoke(result);  
  170.             }  
  171.         }  
  172.  
  173.         @Override 
  174.         public void failed(int error, IOException x) {  
  175.             // return direct buffer to cache if substituted  
  176.           
  177.  
  178.             // release waiters if not already released by timeout  
  179.             if (!channel.isOpen())  
  180.                 x = new AsynchronousCloseException();  
  181.  
  182.             synchronized (result) {  
  183.                 if (result.isDone())  
  184.                     return;  
  185.                 channel.enableWriting();  
  186.                 result.setFailure(x);  
  187.             }  
  188.             Invoker.invoke(result);  
  189.         }  
  190.  
  191.     }  
  192.  
  193.     public extends Number, A> Future sendFile(long file, A att,  
  194.             CompletionHandlersuper A> handler) {  
  195.  
  196.         boolean closed = false;  
  197.         if (channel.isOpen()) {  
  198.             if (channel.remoteAddress == null)  
  199.                 throw new NotYetConnectedException();  
  200.  
  201.               
  202.             // check and update state  
  203.             synchronized (writeLock) {  
  204.                 try{  
  205.                 if (writeKilledF.getBoolean(channel))  
  206.                     throw new IllegalStateException(  
  207.                             "Writing not allowed due to timeout or cancellation");  
  208.                 if (writingF.getBoolean(channel))  
  209.                     throw new WritePendingException();  
  210.                 if (writeShutdownF.getBoolean(channel)) {  
  211.                     closed = true;  
  212.                 } else {  
  213.                     writingF.setBoolean(channel, true);  
  214.                 }  
  215.                 }catch(Exception e)  
  216.                 {  
  217.                     IllegalStateException ise=new IllegalStateException(" catch exception when write");  
  218.                     ise.initCause(e);  
  219.                     throw ise;  
  220.                 }  
  221.             }  
  222.         } else {  
  223.             closed = true;  
  224.         }  
  225.  
  226.         // channel is closed or shutdown for write  
  227.         if (closed) {  
  228.             Throwable e = new ClosedChannelException();  
  229.             if (handler == null)  
  230.                 return CompletedFuture.withFailure(e);  
  231.             Invoker.invoke(channel, handler, att, null, e);  
  232.             return null;  
  233.         }  
  234.  
  235.  
  236.  
  237.         return implSendFile(file,att,handler);  
  238.     }  
  239.  
  240.  
  241.     extends Number, A> Future implSendFile(long file, A attachment,  
  242.             CompletionHandlersuper A> handler) {  
  243.         // setup task  
  244.         PendingFuture result = new PendingFuture(channel, handler,  
  245.                 attachment);  
  246.         SendFileTask sendTask=new SendFileTask(file,result);  
  247.         result.setContext(sendTask);  
  248.         // initiate I/O (can only be done from thread in thread pool)  
  249.         // initiate I/O  
  250.         if (Iocp.supportsThreadAgnosticIo()) {  
  251.             sendTask.run();  
  252.         } else {  
  253.             Invoker.invokeOnThreadInThreadPool(channel, sendTask);  
  254.         }  
  255.         return result;  
  256.     }  
  257.       
  258.     private native int transmitFile0(long handle, long file,  
  259.             long overlapped);  
  260.       
  261. }  
  262.  

這個操作跟默認實現的里的write操作是很像的,只是最后調用的本地方法不一樣。。

接下來,我們怎么使用呢,這個類是定義在sun的包里的,直接用的話,會報IllegalAccessError,因為我們的類加載器跟初始化加載器是不一樣的。

解決辦法一個是通過啟動參數-Xbootclasspath,讓我們的包被初始加載器加載。我個人不喜歡這種辦法,所以就采用JNI來定義我們的windows TransmitFile支持類。

這樣我們的工作算是完成了,注意,發送文件的時候傳得是文件句柄,這樣做的好處是你可以更好的控制,一般是在發送前,打開文件句柄,完成后在回調通知方法里關閉文件句柄。

有興趣的同學可以看看我的HTTP server項目:

http://code.google.com/p/jabhttpd/

目前基本功能實現得差不多,做了些簡單的測試,性能比較滿意。這個服務器不打算支持servlet api,基本是專門給做基于長連接模式通信的定做的。

責任編輯:yangsai 來源: BlogJava
相關推薦

2009-12-14 10:44:51

Java 7NIO2

2011-12-15 11:39:25

JavaNIO

2020-03-11 10:09:57

JAVA詳解classpath

2023-07-12 08:24:19

Java NIO通道

2011-03-11 09:51:47

Java NIO

2011-12-15 13:28:57

2015-11-10 09:25:05

HTTP2提升性能

2019-03-27 10:50:50

HTTP請求管線式

2011-12-15 09:55:47

javanio

2023-09-06 12:01:50

HTTP協議信息

2024-12-25 14:03:03

2011-12-13 09:12:34

JavaNIO

2011-04-07 13:39:24

WebHTTP

2023-07-28 08:23:05

選擇器Java NIO

2024-09-06 07:55:42

2024-03-20 08:00:00

軟件開發Java編程語言

2021-07-27 16:01:29

高并發定時器高性能

2022-09-14 22:58:58

Push 推薦Java 開發vivo

2024-07-31 08:31:13

2019-04-08 10:09:04

CPU緩存高性能
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美激情久久久久久 | 91久久国产综合久久 | 日韩乱码av | 亚洲精品久久久一区二区三区 | 欧美激情精品久久久久久变态 | 毛片免费看 | 黄色一级毛片 | 欧美在线国产精品 | 伦理午夜电影免费观看 | 国产精品免费一区二区三区四区 | 免费一级做a爰片久久毛片潮喷 | 久久亚洲欧美日韩精品专区 | 久久av网站 | 国产精品中文字幕在线 | 国产日产精品一区二区三区四区 | 无码日韩精品一区二区免费 | 在线中文字幕av | 亚洲欧美一区二区三区在线 | 亚洲一区二区在线视频 | 国产在线一区二区三区 | 波多野结衣先锋影音 | 亚洲欧美激情精品一区二区 | 精品动漫一区 | 啪啪免费 | 成人精品久久日伦片大全免费 | 中文字幕在线观看www | 狠狠的干 | 91成人在线视频 | 久久午夜国产精品www忘忧草 | 亚洲精品高清视频在线观看 | 91精品国产欧美一区二区成人 | 欧美福利一区 | 久久久久久国产 | 中文在线一区二区 | 久久国产精品免费一区二区三区 | 国产免费一区二区三区网站免费 | 成人教育av | 日韩精品成人 | 国产sm主人调教女m视频 | 欧美日韩精品在线免费观看 | 亚洲欧美中文日韩在线v日本 |