PageRenderTime 29ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/jetty-8.1.5.v20120716/jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java

#
Java | 329 lines | 202 code | 37 blank | 90 comment | 10 complexity | f1560c1041ad5ae790ec4e28b37de201 MD5 | raw file
Possible License(s): Apache-2.0
  1. // ========================================================================
  2. // Copyright (c) 2003-2009 Mort Bay Consulting Pty. Ltd.
  3. // ------------------------------------------------------------------------
  4. // All rights reserved. This program and the accompanying materials
  5. // are made available under the terms of the Eclipse Public License v1.0
  6. // and Apache License v2.0 which accompanies this distribution.
  7. // The Eclipse Public License is available at
  8. // http://www.eclipse.org/legal/epl-v10.html
  9. // The Apache License v2.0 is available at
  10. // http://www.opensource.org/licenses/apache2.0.php
  11. // You may elect to redistribute this code under either of these licenses.
  12. // ========================================================================
  13. package org.eclipse.jetty.server.nio;
  14. import java.io.IOException;
  15. import java.net.InetSocketAddress;
  16. import java.net.Socket;
  17. import java.nio.channels.SelectionKey;
  18. import java.nio.channels.ServerSocketChannel;
  19. import java.nio.channels.SocketChannel;
  20. import org.eclipse.jetty.continuation.Continuation;
  21. import org.eclipse.jetty.io.AsyncEndPoint;
  22. import org.eclipse.jetty.io.ConnectedEndPoint;
  23. import org.eclipse.jetty.io.Connection;
  24. import org.eclipse.jetty.io.EndPoint;
  25. import org.eclipse.jetty.io.nio.AsyncConnection;
  26. import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
  27. import org.eclipse.jetty.io.nio.SelectorManager;
  28. import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
  29. import org.eclipse.jetty.server.AsyncHttpConnection;
  30. import org.eclipse.jetty.server.Request;
  31. import org.eclipse.jetty.util.thread.ThreadPool;
  32. /* ------------------------------------------------------------------------------- */
  33. /**
  34. * Selecting NIO connector.
  35. * <p>
  36. * This connector uses efficient NIO buffers with a non blocking threading model. Direct NIO buffers
  37. * are used and threads are only allocated to connections with requests. Synchronization is used to
  38. * simulate blocking for the servlet API, and any unflushed content at the end of request handling
  39. * is written asynchronously.
  40. * </p>
  41. * <p>
  42. * This connector is best used when there are a many connections that have idle periods.
  43. * </p>
  44. * <p>
  45. * When used with {@link org.eclipse.jetty.continuation.Continuation}, threadless waits are supported.
  46. * If a filter or servlet returns after calling {@link Continuation#suspend()} or when a
  47. * runtime exception is thrown from a call to {@link Continuation#undispatch()}, Jetty will
  48. * will not send a response to the client. Instead the thread is released and the Continuation is
  49. * placed on the timer queue. If the Continuation timeout expires, or it's
  50. * resume method is called, then the request is again allocated a thread and the request is retried.
  51. * The limitation of this approach is that request content is not available on the retried request,
  52. * thus if possible it should be read after the continuation or saved as a request attribute or as the
  53. * associated object of the Continuation instance.
  54. * </p>
  55. *
  56. * @org.apache.xbean.XBean element="nioConnector" description="Creates an NIO based socket connector"
  57. */
  58. public class SelectChannelConnector extends AbstractNIOConnector
  59. {
  60. protected ServerSocketChannel _acceptChannel;
  61. private int _lowResourcesConnections;
  62. private int _lowResourcesMaxIdleTime;
  63. private int _localPort=-1;
  64. private final SelectorManager _manager = new ConnectorSelectorManager();
  65. /* ------------------------------------------------------------------------------- */
  66. /**
  67. * Constructor.
  68. *
  69. */
  70. public SelectChannelConnector()
  71. {
  72. _manager.setMaxIdleTime(getMaxIdleTime());
  73. addBean(_manager,true);
  74. setAcceptors(Math.max(1,(Runtime.getRuntime().availableProcessors()+3)/4));
  75. }
  76. @Override
  77. public void setThreadPool(ThreadPool pool)
  78. {
  79. super.setThreadPool(pool);
  80. // preserve start order
  81. removeBean(_manager);
  82. addBean(_manager,true);
  83. }
  84. /* ------------------------------------------------------------ */
  85. @Override
  86. public void accept(int acceptorID) throws IOException
  87. {
  88. ServerSocketChannel server;
  89. synchronized(this)
  90. {
  91. server = _acceptChannel;
  92. }
  93. if (server!=null && server.isOpen() && _manager.isStarted())
  94. {
  95. SocketChannel channel = server.accept();
  96. channel.configureBlocking(false);
  97. Socket socket = channel.socket();
  98. configure(socket);
  99. _manager.register(channel);
  100. }
  101. }
  102. /* ------------------------------------------------------------ */
  103. public void close() throws IOException
  104. {
  105. synchronized(this)
  106. {
  107. if (_acceptChannel != null)
  108. {
  109. removeBean(_acceptChannel);
  110. if (_acceptChannel.isOpen())
  111. _acceptChannel.close();
  112. }
  113. _acceptChannel = null;
  114. _localPort=-2;
  115. }
  116. }
  117. /* ------------------------------------------------------------------------------- */
  118. @Override
  119. public void customize(EndPoint endpoint, Request request) throws IOException
  120. {
  121. request.setTimeStamp(System.currentTimeMillis());
  122. endpoint.setMaxIdleTime(_maxIdleTime);
  123. super.customize(endpoint, request);
  124. }
  125. /* ------------------------------------------------------------------------------- */
  126. @Override
  127. public void persist(EndPoint endpoint) throws IOException
  128. {
  129. AsyncEndPoint aEndp = ((AsyncEndPoint)endpoint);
  130. aEndp.setCheckForIdle(true);
  131. super.persist(endpoint);
  132. }
  133. /* ------------------------------------------------------------ */
  134. public SelectorManager getSelectorManager()
  135. {
  136. return _manager;
  137. }
  138. /* ------------------------------------------------------------ */
  139. public synchronized Object getConnection()
  140. {
  141. return _acceptChannel;
  142. }
  143. /* ------------------------------------------------------------------------------- */
  144. public int getLocalPort()
  145. {
  146. synchronized(this)
  147. {
  148. return _localPort;
  149. }
  150. }
  151. /* ------------------------------------------------------------ */
  152. public void open() throws IOException
  153. {
  154. synchronized(this)
  155. {
  156. if (_acceptChannel == null)
  157. {
  158. // Create a new server socket
  159. _acceptChannel = ServerSocketChannel.open();
  160. // Set to blocking mode
  161. _acceptChannel.configureBlocking(true);
  162. // Bind the server socket to the local host and port
  163. _acceptChannel.socket().setReuseAddress(getReuseAddress());
  164. InetSocketAddress addr = getHost()==null?new InetSocketAddress(getPort()):new InetSocketAddress(getHost(),getPort());
  165. _acceptChannel.socket().bind(addr,getAcceptQueueSize());
  166. _localPort=_acceptChannel.socket().getLocalPort();
  167. if (_localPort<=0)
  168. throw new IOException("Server channel not bound");
  169. addBean(_acceptChannel);
  170. }
  171. }
  172. }
  173. /* ------------------------------------------------------------ */
  174. @Override
  175. public void setMaxIdleTime(int maxIdleTime)
  176. {
  177. _manager.setMaxIdleTime(maxIdleTime);
  178. super.setMaxIdleTime(maxIdleTime);
  179. }
  180. /* ------------------------------------------------------------ */
  181. /**
  182. * @return the lowResourcesConnections
  183. */
  184. public int getLowResourcesConnections()
  185. {
  186. return _lowResourcesConnections;
  187. }
  188. /* ------------------------------------------------------------ */
  189. /**
  190. * Set the number of connections, which if exceeded places this manager in low resources state.
  191. * This is not an exact measure as the connection count is averaged over the select sets.
  192. * @param lowResourcesConnections the number of connections
  193. * @see #setLowResourcesMaxIdleTime(int)
  194. */
  195. public void setLowResourcesConnections(int lowResourcesConnections)
  196. {
  197. _lowResourcesConnections=lowResourcesConnections;
  198. }
  199. /* ------------------------------------------------------------ */
  200. /**
  201. * @return the lowResourcesMaxIdleTime
  202. */
  203. @Override
  204. public int getLowResourcesMaxIdleTime()
  205. {
  206. return _lowResourcesMaxIdleTime;
  207. }
  208. /* ------------------------------------------------------------ */
  209. /**
  210. * Set the period in ms that a connection is allowed to be idle when this there are more
  211. * than {@link #getLowResourcesConnections()} connections. This allows the server to rapidly close idle connections
  212. * in order to gracefully handle high load situations.
  213. * @param lowResourcesMaxIdleTime the period in ms that a connection is allowed to be idle when resources are low.
  214. * @see #setMaxIdleTime(int)
  215. */
  216. @Override
  217. public void setLowResourcesMaxIdleTime(int lowResourcesMaxIdleTime)
  218. {
  219. _lowResourcesMaxIdleTime=lowResourcesMaxIdleTime;
  220. super.setLowResourcesMaxIdleTime(lowResourcesMaxIdleTime);
  221. }
  222. /* ------------------------------------------------------------ */
  223. /*
  224. * @see org.eclipse.jetty.server.server.AbstractConnector#doStart()
  225. */
  226. @Override
  227. protected void doStart() throws Exception
  228. {
  229. _manager.setSelectSets(getAcceptors());
  230. _manager.setMaxIdleTime(getMaxIdleTime());
  231. _manager.setLowResourcesConnections(getLowResourcesConnections());
  232. _manager.setLowResourcesMaxIdleTime(getLowResourcesMaxIdleTime());
  233. super.doStart();
  234. }
  235. /* ------------------------------------------------------------ */
  236. protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
  237. {
  238. SelectChannelEndPoint endp= new SelectChannelEndPoint(channel,selectSet,key, SelectChannelConnector.this._maxIdleTime);
  239. endp.setConnection(selectSet.getManager().newConnection(channel,endp, key.attachment()));
  240. return endp;
  241. }
  242. /* ------------------------------------------------------------------------------- */
  243. protected void endPointClosed(SelectChannelEndPoint endpoint)
  244. {
  245. connectionClosed(endpoint.getConnection());
  246. }
  247. /* ------------------------------------------------------------------------------- */
  248. protected AsyncConnection newConnection(SocketChannel channel,final AsyncEndPoint endpoint)
  249. {
  250. return new AsyncHttpConnection(SelectChannelConnector.this,endpoint,getServer());
  251. }
  252. /* ------------------------------------------------------------ */
  253. /* ------------------------------------------------------------ */
  254. /* ------------------------------------------------------------ */
  255. private final class ConnectorSelectorManager extends SelectorManager
  256. {
  257. @Override
  258. public boolean dispatch(Runnable task)
  259. {
  260. ThreadPool pool=getThreadPool();
  261. if (pool==null)
  262. pool=getServer().getThreadPool();
  263. return pool.dispatch(task);
  264. }
  265. @Override
  266. protected void endPointClosed(final SelectChannelEndPoint endpoint)
  267. {
  268. SelectChannelConnector.this.endPointClosed(endpoint);
  269. }
  270. @Override
  271. protected void endPointOpened(SelectChannelEndPoint endpoint)
  272. {
  273. // TODO handle max connections and low resources
  274. connectionOpened(endpoint.getConnection());
  275. }
  276. @Override
  277. protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection)
  278. {
  279. connectionUpgraded(oldConnection,endpoint.getConnection());
  280. }
  281. @Override
  282. public AsyncConnection newConnection(SocketChannel channel,AsyncEndPoint endpoint, Object attachment)
  283. {
  284. return SelectChannelConnector.this.newConnection(channel,endpoint);
  285. }
  286. @Override
  287. protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey sKey) throws IOException
  288. {
  289. return SelectChannelConnector.this.newEndPoint(channel,selectSet,sKey);
  290. }
  291. }
  292. }