Jetty Server两个重要的概念一个是Handler,一个是Connector。 我们在内嵌Jetty启动应用时往往会通过WebAppContext来设置上下文,WebAppContext就是一个Handler,我们可以通过Server.setHandler()来赋值我们的上下文。本文主要介绍Connector。它的抽象实现类是AbstractConnector,然后ServerConnector继承了AbstractConnector,这也是重点要介绍的两个类。连接器故名思议主要是用来处理各种类型的请求包括HTTP, HTTP/2 ,WebSocket等等。Jetty 9采用NIO来处理请求,去掉了BIO模块。
下边先贴出一段实用的Jetty内嵌启动代码,方便我们理解Handler和Connector。采用的是9.3版本的jetty jar
/** jetty pom <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.3.0.M0</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>9.3.0.M0</version> </dependency> **/ //内嵌代码------------------ Server server = new Server(); // connector ServerConnector connector = new ServerConnector(server); connector.setPort(port); server.setConnectors(new Connector[] { connector }); //context WebAppContext context = new WebAppContext(); context.setContextPath("/"); //设定webapp,具体的路径根据自己应用来调整 context.setResourceBase("./src/main/webapp"); context.setClassLoader(Thread.currentThread().getContextClassLoader()); context.setParentLoaderPriority(true); server.setHandler(context); server.start(); server.join(); //-----------------------------------------
AbstractConnector是Connector的实现类,它提供了ConnectionFactory机制来创建各种协议(HTTP, SSL)的实例。AbstractConnector封装了几个重要的属性:
Executor:线程池,用来处理接收的连接;
Scheduler:用来监视连接的超时;
ByteBufferPool:ByteBuffer缓冲池,减少对ByteBuffer的创建开销,循环利用ByteBuffer;
ConnectionFactory: 创建各种协议的工厂,包含 SslConnectionFactory,HttpConnectionFactory等等;
Acceptors:来创建接收器的,监听端口过来的请求。AbstractConnector里面 有个 final Thread[] _acceptors 变量 ,这个变量是个线程数组,个数代表你需要创建并发的接收器,多个接收器调用同一个ServerSocketChannel实例上的accept方法,来实现高效的接收请求。AbstractConnector在doStart方法中初始化Acceptor。
protected void doStart() throws Exception { _defaultConnectionFactory = getConnectionFactory(_defaultProtocol); _stopping=new CountDownLatch(_acceptors.length); for (int i = 0; i < _acceptors.length; i++) { Acceptor a = new Acceptor(i); addBean(a); getExecutor().execute(a); //初始化Acceptor就直接放到线程池去执行。 } }
下边我们分析一下Acceptor这个AbstractConnector内部类:
private class Acceptor implements Runnable { private final int _id; private String _name; private Acceptor(int id) { _id = id; } @Override public void run() { //刚刚我们把它放到线程池里,它会取当前执行它的线程放到AbstractConnector中的_acceptors线程数组中 //主要是来判断acceptor是否都停掉 _stopping=new CountDownLatch(_acceptors.length)。 // final Thread thread = Thread.currentThread(); String name=thread.getName(); _name=String.format("%s-acceptor-%d@%x-%s",name,_id,hashCode(),AbstractConnector.this.toString()); thread.setName(_name); int priority=thread.getPriority(); if (_acceptorPriorityDelta!=0) thread.setPriority(Math.max(Thread.MIN_PRIORITY,Math.min(Thread.MAX_PRIORITY,priority+_acceptorPriorityDelta))); synchronized (AbstractConnector.this) { _acceptors[_id] = thread; } try { while (isAccepting()) { try { //!!!这是个抽象方法由具体的实现类ServerConnector来实现。!!! accept(_id); } catch (Throwable e) { if (isAccepting()) LOG.warn(e); else LOG.ignore(e); } } } finally { thread.setName(name); if (_acceptorPriorityDelta!=0) thread.setPriority(priority); synchronized (AbstractConnector.this) { _acceptors[_id] = null; } CountDownLatch stopping=_stopping; if (stopping!=null) stopping.countDown(); } } @Override public String toString() { String name=_name; if (name==null) return String.format("acceptor-%d@%x", _id, hashCode()); return name; } }
下边我们具体介绍accept方法在ServerConnector中的具体实现,ServerConnector有两个重要的方法 open和accept
下边是具体的代码:
//主要是初始化ServerSocketChannel,绑定监听端口。剩下的接收请求交给accept方法来做。 public void open() throws IOException { if (_acceptChannel == null) { ServerSocketChannel serverChannel = null; if (isInheritChannel()) { Channel channel = System.inheritedChannel(); if (channel instanceof ServerSocketChannel) serverChannel = (ServerSocketChannel)channel; } if (serverChannel == null) { serverChannel = ServerSocketChannel.open(); InetSocketAddress bindAddress = getHost() == null ? new InetSocketAddress(getPort()) : new InetSocketAddress(getHost(), getPort()); serverChannel.socket().setReuseAddress(getReuseAddress()); serverChannel.socket().bind(bindAddress, getAcceptQueueSize()); _localPort = serverChannel.socket().getLocalPort(); if (_localPort <= 0) throw new IOException("Server channel not bound"); addBean(serverChannel); } serverChannel.configureBlocking(true); addBean(serverChannel); _acceptChannel = serverChannel; } } //这个方法由AbstractConnector中的accepters调用,并发的处理接收请求。 @Override public void accept(int acceptorID) throws IOException { ServerSocketChannel serverChannel = _acceptChannel; if (serverChannel != null && serverChannel.isOpen()) { SocketChannel channel = serverChannel.accept(); accepted(channel); } } private void accepted(SocketChannel channel) throws IOException { channel.configureBlocking(false); Socket socket = channel.socket(); configure(socket); //交给SelectorManager来对请求过来的Channel处理 _manager.accept(channel); } protected void configure(Socket socket) { try { //禁掉TCP延迟 negle算法 socket.setTcpNoDelay(true); if (_lingerTime >= 0) socket.setSoLinger(true, _lingerTime / 1000); else socket.setSoLinger(false, 0); } catch (SocketException e) { LOG.ignore(e); } }
Connector就介绍到这里,主要是封装了ServerSocketChannel,在多线程环境下监听过来的请求,转发请求给SelectorManager。
转发标注来源:http://my.oschina.net/robinyao/blog/404687
END------------------------------------------------------------------