Jetty之SocketConnector
来源:互联网 发布:沈阳seo公司 编辑:程序博客网 时间:2024/06/05 22:49
首先说一下connector这东西是干嘛用的。。。。
其实按照字面的意思大概就能知道它是用于接收和维护与远程的连接的。。。。它会利用建立的serversocket。。。
这里还需要说明一下。。。一般情况下不应该使用这个类型的。。因为还有NIO的实现。。。但是我之所以先看SocketConnector是因为它的实现更简单一些。。先从简单的做起嘛。。毕竟他们上层的接口都是一样的。。。。。
那么还是先来看看它的继承体系吧:
这里又想说一下整个jetty的继承体系还是很简单的。。。
这里有一个Buffers的接口,其实可以将其理解为buffer的池子,它用于维护许多已经建立好的buffer,供以后的使用,这样可以减少以后需要创建buffer的次数。。。复用。。。
那么先来看看Buffers接口的定义吧:
- //可以看成是buffer的池
- public interface Buffers
- {
- public Buffer getBuffer(int size); //获取相应大小的buffer
- public void returnBuffer(Buffer buffer); //返回一个buffer
- }
够简单吧,就两个方法,第一个是从buffer池中获取一个size大小的buffer
另外一个就是将一个已经用完的buffer还给buffer池。。。。
那么接下来来看看Connector接口的定义,这是一个大接口啊:
- //用于接收客户端的连接请求,然后对其进行处理,将会运行在线程池中
- public interface Connector extends LifeCycle, Buffers
- {
- //当前connector的名字,默认是host:port
- String getName();
- //打开当前的connector
- void open() throws IOException;
- //关闭当前的connector
- void close() throws IOException;
- //设置当前connector的server
- void setServer(Server server);
- //返回当前connector所属的server
- Server getServer();
- //用于接收报文头的buffer的大小
- int getHeaderBufferSize();
- //设置接收报文头部的buffer大小
- void setHeaderBufferSize(int headerBufferSize);
- //request的缓冲大小
- int getRequestBufferSize();
- //报文body的buffer大小
- void setRequestBufferSize(int requestBufferSize);
- int getResponseBufferSize();
- //response的body的buffer的大小
- void setResponseBufferSize(int responseBufferSize);
- int getIntegralPort();
- //用于对错误的请求进行重定向的
- String getIntegralScheme();
- //判断当前的请求是否合格
- boolean isIntegral(Request request);
- //用于验证的端口,从定向
- int getConfidentialPort();
- //用于验证的从定向scheme
- String getConfidentialScheme();
- //是否验证
- boolean isConfidential(Request request);
- //为request设置endpoint
- void customize(EndPoint endpoint, Request request) throws IOException;
- //讲一个endpoint持久化?
- void persist(EndPoint endpoint) throws IOException;
- Continuation newContinuation();
- String getHost();
- void setHost(String hostname);
- void setPort(int port); //设置端口
- int getPort();
- int getLocalPort(); //返回本地的一个端口
- int getMaxIdleTime(); //最大空闲的事件
- void setMaxIdleTime(int ms);
- int getLowResourceMaxIdleTime(); //慢速情况下的最大时间
- void setLowResourceMaxIdleTime(int ms);
- Object getConnection(); //返回底层的socket或者channel
- boolean getResolveNames();
- public int getRequests();//处理过的请求量
- public long getConnectionsDurationMin();
- public long getConnectionsDurationTotal();
- public int getConnectionsOpenMin();
- public int getConnectionsRequestsMin();
- public int getConnections() ;
- public int getConnectionsOpen() ;
- public int getConnectionsOpenMax() ;
- public long getConnectionsDurationAve() ;
- public long getConnectionsDurationMax();
- public int getConnectionsRequestsAve() ;
- //一个connection的最大请求数量
- public int getConnectionsRequestsMax();
- public void statsReset();
- public void setStatsOn(boolean on);
- public boolean getStatsOn();
- //开启的时间
- public long getStatsOnMs();
- }
其实感觉这个接口中并没有定义太多的干货内容,主要都是一些基本属性的获取和设置,例如socket的最大空闲时间,buffer的大小设置啥的。。。。
那么我们接下来看看AbstractBuffers的定义吧:
- public abstract class AbstractBuffers extends AbstractLifeCycle implements Buffers {
- //默认的一些buffer的大小,这里会默认的包含一些buffer,减少buffer的创建
- private int _headerBufferSize=4*1024; //用于接收头的buffer大小,4kb
- private int _requestBufferSize=8*1024; //用于接收请求body的大小,8kb
- private int _responseBufferSize=24*1024; //responseBody的大小,24kb
- //相应的buffer数组的定义
- private transient ArrayList _headerBuffers=new ArrayList();
- protected transient int _loss;
- private transient ArrayList _requestBuffers; //request的buffer
- private transient ArrayList _responseBuffers;
- //返回头buffer默认大小
- public int getHeaderBufferSize() {
- return _headerBufferSize;
- }
- public void setHeaderBufferSize(int headerBufferSize) {
- _headerBufferSize = headerBufferSize;
- }
- public int getRequestBufferSize() {
- return _requestBufferSize;
- }
- public void setRequestBufferSize(int requestBufferSize) {
- _requestBufferSize = requestBufferSize;
- }
- public int getResponseBufferSize() {
- return _responseBufferSize;
- }
- public void setResponseBufferSize(int responseBufferSize) {
- _responseBufferSize = responseBufferSize;
- }
- //子类重载这个方法,用于创建buffer
- protected abstract Buffer newBuffer(int size);
- //获取一个size大小的buffer,如果已经保存的没有的话,那么需要重新创建一个
- public Buffer getBuffer(int size)
- {
- //根据要获取的buffer的大小,来在相应的地方来获取,如果都不合适,那么就new一个出来
- if (size==_headerBufferSize) {
- synchronized(_headerBuffers)
- {
- if (_headerBuffers.size()>0)
- return (Buffer) _headerBuffers.remove(_headerBuffers.size()-1);
- }
- return newBuffer(size);
- }
- else if (size==_responseBufferSize) {
- synchronized(_responseBuffers)
- {
- if (_responseBuffers.size()==0)
- return newBuffer(size);
- return (Buffer) _responseBuffers.remove(_responseBuffers.size()-1);
- }
- }
- else if (size==_requestBufferSize) {
- synchronized(_requestBuffers)
- {
- if (_requestBuffers.size()==0)
- return newBuffer(size);
- return (Buffer) _requestBuffers.remove(_requestBuffers.size()-1);
- }
- }
- return newBuffer(size); //创建新的buffer
- }
- //相当于是一个buffer已经用完了,将这个buffer重新放到这个池子里面去
- public void returnBuffer(Buffer buffer) {
- buffer.clear(); //首先clear一下
- if (!buffer.isVolatile() && !buffer.isImmutable()) {
- int c=buffer.capacity();
- if (c==_headerBufferSize) {
- synchronized(_headerBuffers) {
- _headerBuffers.add(buffer);
- }
- }
- else if (c==_responseBufferSize) {
- synchronized(_responseBuffers)
- {
- _responseBuffers.add(buffer);
- }
- }
- else if (c==_requestBufferSize) {
- synchronized(_requestBuffers)
- {
- _requestBuffers.add(buffer);
- }
- }
- }
- }
- //启动,说白了就是创建相应的队列
- protected void doStart() throws Exception {
- super.doStart();
- if (_headerBuffers!=null)
- _headerBuffers.clear();
- else
- _headerBuffers=new ArrayList();
- if (_requestBuffers!=null)
- _requestBuffers.clear();
- else
- _requestBuffers=new ArrayList();
- if (_responseBuffers!=null)
- _responseBuffers.clear();
- else
- _responseBuffers=new ArrayList();
- }
- }
其实可以看出,其实内置的只有三种大小的buffer,4kb,8kb和24kb的,分别用于干不同的事情。。。
这里有一些需要补充:AbstratBuffers继承了AbstractLifeCycle,在上面的类图中没有表现出来
那么也就表示它也是一个组件,应该有doStart和doStop方法,用于组件的停止和启动。。
这里获取buffer的方法和返回buffer的方法实现也很简单吧,无非就是对arraylist的操作。。。
另外这里真正创建buffer的操作其实是留给接下来的子类来实现的。。。。
接下来我们就来看AbstractConnector的定义吧,由于它的定义太长了,而且大多数也都是get和set一些属性的值,那么这里我们只看看它的一些重要部分吧,首先来看看他的doStart方法,它用于组件的启动:
- protected void doStart() throws Exception {
- if (_server==null)
- throw new IllegalStateException(“No server”);
- //开启监听
- open();
- super.doStart(); //父类的启动,其实也就是abstractBuffer的启动
- if (_threadPool==null)
- _threadPool=_server.getThreadPool(); //这里相当于是获取线程池
- if (_threadPool!=_server.getThreadPool() && (_threadPool instanceof LifeCycle))
- ((LifeCycle)_threadPool).start(); //线程池的启动
- // Start selector thread
- synchronized(this)
- {
- _acceptorThread=new Thread[getAcceptors()]; //用于运行监听器的线程数组,当具体的在线程池中运行了以后才会具体设置线程
- for (int i=0;i<_acceptorThread.length;i++)
- {
- if (!_threadPool.dispatch(new Acceptor(i))) //这里相当于是将监听器运行起来
- {
- Log.warn(”insufficient maxThreads configured for {}”,this);
- break;
- }
- }
- }
- Log.info(”Started {}”,this);
- }
这里可以看到先是调用open方法开始对serversocket的监听,然后创建了一个acceptor,可以将其理解为一个task,它将会被分配到线程池中进行运行,主要是调用accept方法,用于获取远程的连接。。。
那么我们就来看看这个acceptor的定义吧:
- //acceptor,说白了就是用于接收远程的连接的tast,可以理解为一个独占的线程,用于accept
- private class Acceptor implements Runnable {
- int _acceptor=0;
- Acceptor(int id)
- {
- _acceptor=id; //id
- }
- public void run()
- {
- Thread current = Thread.currentThread(); //获取当前运行的线程
- synchronized(AbstractConnector.this) //加锁当前acceptor所属的connector
- {
- if (_acceptorThread==null)
- return;
- _acceptorThread[_acceptor]=current; //设置线程
- }
- String name =_acceptorThread[_acceptor].getName();
- current.setName(name+” - Acceptor”+_acceptor+“ ”+AbstractConnector.this);
- int old_priority=current.getPriority();
- try
- {
- current.setPriority(old_priority-_acceptorPriorityOffset);
- while (isRunning() && getConnection()!=null) //不断的进行循环,接收远程连接
- {
- try
- {
- accept(_acceptor); //开始运行accept方法,用于获取远程的连接,其实访问的是Connector的方法
- }
- catch(EofException e)
- {
- Log.ignore(e);
- }
- catch(IOException e)
- {
- Log.ignore(e);
- }
- catch(ThreadDeath e)
- {
- Log.warn(e);
- throw e;
- }
- catch(Throwable e)
- {
- Log.warn(e);
- }
- }
- }
- finally
- {
- current.setPriority(old_priority);
- current.setName(name);
- try
- {
- if (_acceptor==0)
- close();
- }
- catch (IOException e)
- {
- Log.warn(e);
- }
- synchronized(AbstractConnector.this)
- {
- if (_acceptorThread!=null)
- _acceptorThread[_acceptor]=null;
- }
- }
- }
- }
这里就可以看到,其实它就是一个task吧,不断的在while中循环,调用accept方法,这个方法是在AbstractConnector中定义的,但是具体的实现会在SocketConnector里面实现。。。它主要是不断的在ServerSocket上面调用accept方法,然后进行一些处理。。。
说白了就是专门分配一个线程用于accept、、、、、、
那么到最后我们来看看SocketConnector的定义吧:
- public class SocketConnector extends AbstractConnector {
- protected ServerSocket _serverSocket; //用于接收用户连接的serversocket
- protected Set _connections; //所有已经建立的连接
- public SocketConnector() {}
- //返回当前的底层的serversocket
- public Object getConnection() {
- return _serverSocket;
- }
- //说白了就是创建一个serversocket
- public void open() throws IOException {
- // Create a new server socket and set to non blocking mode
- if (_serverSocket==null || _serverSocket.isClosed())
- _serverSocket= newServerSocket(getHost(),getPort(),getAcceptQueueSize());
- _serverSocket.setReuseAddress(getReuseAddress());
- }
- //用于创建serversocket的函数,host是主机地址,port是端口,backlog是连接队列
- protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException {
- ServerSocket ss= host==null?
- new ServerSocket(port,backlog): //第二个参数是接收队列的大小
- new ServerSocket(port,backlog,InetAddress.getByName(host));
- return ss;
- }
- //其实是关闭底层的socket
- public void close() throws IOException {
- if (_serverSocket!=null)
- _serverSocket.close();
- _serverSocket=null;
- }
- //用于接收远程的连接,而且还要讲接收到的连接进行封装和调度
- public void accept(int acceptorID) //在acceptor中调用这个方法,id是acceptor的id
- throws IOException, InterruptedException {
- Socket socket = _serverSocket.accept(); //获取到远程的连接
- configure(socket); //进行一些配置
- Connection connection=new Connection(socket); //将其封装成connection,也是endPoint
- connection.dispatch(); //在线程池中调度
- }
- //创建一个httpconnection
- protected HttpConnection newHttpConnection(EndPoint endpoint) {
- return new HttpConnection(this, endpoint, getServer());
- }
- //用于创建buffer的方法,在AbstractBuffers中会调用这个方法来创建buffer
- protected Buffer newBuffer(int size) {
- return new ByteArrayBuffer(size);
- }
- //对接收到的socket进行一些设置
- public void customize(EndPoint endpoint, Request request)
- throws IOException {
- Connection connection = (Connection)endpoint;
- if (connection._sotimeout!=_maxIdleTime) {
- connection._sotimeout=_maxIdleTime; //最大空闲时间
- ((Socket)endpoint.getTransport()).setSoTimeout(_maxIdleTime); //相当于是设置底层的socket超时时间
- }
- super.customize(endpoint, request);
- }
- //获取底层的serversocket监听的端口
- public int getLocalPort() {
- if (_serverSocket==null || _serverSocket.isClosed())
- return -1;
- return _serverSocket.getLocalPort();
- }
- //开启当前的组件
- protected void doStart() throws Exception {
- _connections=new HashSet(); //创建一个hashset用于存放建立的连接
- super.doStart();
- }
- //停止当前的组件
- protected void doStop() throws Exception {
- super.doStop();
- Set set=null;
- synchronized(_connections) {
- set= new HashSet(_connections);
- }
- Iterator iter=set.iterator();
- while(iter.hasNext()) { //将所有已经建立的连接关闭
- Connection connection = (Connection)iter.next();
- connection.close();
- }
- }
- //accept之后会用socket来创建这种connection
- protected class Connection extends SocketEndPoint implements Runnable {
- boolean _dispatched=false; //是否已经调度
- HttpConnection _connection; //httpconnection
- int _sotimeout; //超时时间
- protected Socket _socket; //真正用到的socket
- public Connection(Socket socket) throws IOException {
- super(socket);
- _connection = newHttpConnection(this); //创建httpConnection
- _sotimeout=socket.getSoTimeout(); //
- _socket=socket; //保存当前这个socket
- }
- //可以了裂解为调度这个task,说白了就是在线程池中选取合适的线程然后调用run方法
- public void dispatch() throws InterruptedException, IOException {
- if (!getThreadPool().dispatch(this)) {
- Log.warn(”dispatch failed for {}”,_connection);
- close();
- }
- }
- //重载了父类的fill方法,用于从底层的socket读取数据,存放到buffer,这里其实相当于加多了一层验证
- public int fill(Buffer buffer) throws IOException {
- int l = super.fill(buffer);
- if (l<0)
- close();
- return l;
- }
- //说白了就是开启整个http的处理流程
- public void run() {
- try {
- connectionOpened(_connection);
- synchronized(_connections) {
- _connections.add(this); //将其加入到当前的连接中
- }
- while (isStarted() && !isClosed()) {
- if (_connection.isIdle()) { //如果当前的socket已经空闲了,那么给他设置超时
- if (getServer().getThreadPool().isLowOnThreads()) {
- int lrmit = getLowResourceMaxIdleTime();
- if (lrmit>=0 && _sotimeout!= lrmit) {
- _sotimeout=lrmit;
- _socket.setSoTimeout(_sotimeout);
- }
- }
- }
- _connection.handle(); //处理当前这个httpconnection
- }
- }
- catch (EofException e)
- {
- Log.debug(”EOF”, e);
- try{close();}
- catch(IOException e2){Log.ignore(e2);}
- }
- catch (HttpException e)
- {
- Log.debug(”BAD”, e);
- try{close();}
- catch(IOException e2){Log.ignore(e2);}
- }
- catch(Throwable e)
- {
- Log.warn(”handle failed”,e);
- try{close();}
- catch(IOException e2){Log.ignore(e2);}
- }
- finally
- {
- connectionClosed(_connection);
- synchronized(_connections)
- {
- _connections.remove(this);
- }
- }
- }
- }
- }
其实本身还是很简单吧,先来看看它的newBuffer方法,这里可以看到其实它实际上是使用的ByteArrayBuffer的。。。
另外就是它的doStart方法,这里可以看到它先创建了一个set,用于保存当前所有的连接,另外就是执行AbstractConnector的start,而上面我们已经可以知道它将会在线程池中调配一个线程专门来处理serversocket的accept。。。
那么接下来就是accept方法,其实很简单,无非是通过serversocket获取远程的连接,然后将其进行一些封装,最后还要对其进行调度。。。
看看Connection类型的定义就知道了,因为它也是一个runnable,将它调度到线程池中就是整个http处理的流程的开始。。。。而且它还会封装出HttpConnection,由其来完成接下来的http处理流程。。。。
到这里真个SocketConnector的内容就差不多了。。
其实对整个jetty的连接请求处理也知道的差不多了。。。。
- jetty之SocketConnector
- Jetty之SocketConnector
- Jetty之SocketConnector
- jetty之嵌入式运行jetty
- Jetty实战之 嵌入式运行Jetty
- Jetty实战之 嵌入式Jetty运行Servlet
- Jetty实战之 嵌入式Jetty运行Servlet
- Jetty实战之 嵌入式Jetty运行Servlet
- Jetty实战之 嵌入式运行Jetty
- Jetty实战之 嵌入式Jetty运行Servlet
- Jetty实战之 嵌入式Jetty运行Servlet
- Jetty实战之 嵌入式Jetty运行Servlet
- Jetty实战之 嵌入式运行Jetty
- Jetty实战之 嵌入式Jetty运行Servlet
- Jetty实战(1)之嵌入式运行Jetty
- Jetty实战之 嵌入式Jetty运行Servlet
- 嵌入式Jetty开发之代码启动Jetty
- jetty介绍之handler
- hduProblem-1754线段树的应用
- 2016年度总结(下)及展望
- JRuby--Java和Ruby的强强联合 Centos7.X
- threejs纹理
- 内存分页
- Jetty之SocketConnector
- activemq推送学习
- Ubuntu16.04安装sublime text 3
- js跨域请求服务器数据
- 动态库和静态库的创建
- C语言中结构体的位域(bit-fields)
- 数据结构::关于哈希表
- Android自定义可拖动进度条
- 4种方法让SpringMVC接收多个对象