首先connector实现了lifecycle接口,在启动jetty服务器时,会调用其的start方法,用于初始化connector内部状态,并打开connector以接受客户端的请求(调用open方法);而在停止jetty服务器时会调用其stop方法,以关闭connector以及内部元件(如connection等)以及做一些清理工作。因而open、close方法是connector中用于处理生命周期的方法;对每个connector都有name字段用于标记该connector,默认值为:hostname:port;connector中还有server的引用,可以从中获取threadpool,并作为handler的容器被使用(在创建httpconnection时,server实例作为构造函数参数传入,并在handlerequest()方法中将解析出来的request、response传递给server注册的handler);connector还定义了一些用于配置当前connector的方法,如buffer size、max idle time、low resource max idle time,以及一些统计信息,如当前connector总共处理过的请求数、总共处理过的连接数、当前打开的连接数等信息。
connector的接口定义如下:
public interface connector extends lifecycle {
// connector名字,默认值hostname:port
string getname();
// 打开当前connector
void open() throws ioexception;
// 关闭当前connector
void close() throws ioexception;
// 对server的引用
void setserver(server server);
server getserver();
// 在处理请求消息头时使用的buffer大小
int getrequestheadersize();
void setrequestheadersize(int size);
// 在处理响应消息头时使用的buffer大小
int getresponseheadersize();
void setresponseheadersize(int size);
// 在处理请求消息内容时使用的buffer大小
int getrequestbuffersize();
void setrequestbuffersize(int requestbuffersize);
// 在处理响应消息内容使用的buffer大小
int getresponsebuffersize();
void setresponsebuffersize(int responsebuffersize);
// 在处理请求消息时使用的buffer工厂
buffers getrequestbuffers();
// 在处理响应消息时使用的buffer工厂
buffers getresponsebuffers();
// user data constraint的配置可以是none、integral、confidential,对这三种值的解释:
// none:a value of none means that the application does not require any transport guarantees.
// integral:a value of integral means that the application requires the data sent between the client and server to be sent in such a way that it can't be changed in transit.
// confidential:a value of confidential means that the application requires the data to be transmitted in a fashion that prevents other entities from observing the contents of the transmission on.
// 如果配置了user-data-constraint为integral或confidential表示所有相应请求都会重定向到使用integral/confidential schema/port构建的新的url中。
int getintegralport();
string getintegralscheme();
boolean isintegral(request request);
int getconfidentialport();
string getconfidentialscheme();
boolean isconfidential(request request);
// 在将httpconnection交给server中的handlers处理前,根据当前connector,自定义一些endpoint和request的配置,如设置endpoint的maxidletime,request的timestamp,
// 清除selectchannelendpoint中的idletimestamp,检查forward头等。
void customize(endpoint endpoint, request request) throws ioexception;
// 主要用于selectchannelconnector中,重置selectchannelendpoint中的idletimestamp,即重新计时idle的时间。
// 它在每个request处理结束,endpoint还未关闭,并且当前连接属于keep-alive类型的时候被调用。
void persist(endpoint endpoint) throws ioexception;
// 底层的链接实例,如serversocket、serversocketchannel等。
object getconnection();
//是否对"x-forwarded-for"头进行dns名字解析
boolean getresolvenames();
// 当前connector绑定的主机名、端口号等。貌似在connector的实现中没有一个默认的主机名。
// 由于端口号可以设置为0,表示由操作系统随机的分配一个还没有被使用的端口,因而这里由localport用于存储connector实际上绑定的端口号;
// 其中-1表示这个connector还未开启,-2表示connector已经关闭。
string gethost();
void sethost(string hostname);
void setport(int port);
int getport();
int getlocalport();
// socket的最大空闲时间,以及在资源比较少(如线程池中的任务数比最大可用线程数要多)的情况下的最大空闲时间,当空闲时间超过这个时间后关闭当前连接(socket)。
int getmaxidletime();
void setmaxidletime(int ms);
int getlowresourcemaxidletime();
void setlowresourcemaxidletime(int ms);
// 是否当前connector处于lowresources状态,即线程池中的任务数比最大可用线程数要多
public boolean islowresources();
/* ------------------------以下是一些获取和当前connector相关的统计信息------------------------------------ */
// 打开或关闭统计功能
public void setstatson(boolean on);
// 统计功能的开闭状态
public boolean getstatson();
// 重置统计数据,以及统计开始时间
public void statsreset();
// 统计信息的开启时间戳
public long getstatsonms();
// 当前connector处理的请求数
public int getrequests();
// 当前connector接收到过的连接数
public int getconnections() ;
// 当前connector所有当前还处于打开状态的连接数
public int getconnectionsopen() ;
// 当前connector历史上同时处于打开状态的最大连接数
public int getconnectionsopenmax() ;
// 当前connector所有连接的持续时间总和
public long getconnectionsdurationtotal();
// 当前connector的最长连接持续时间
public long getconnectionsdurationmax();
// 当前connector平均连接持续时间
public double getconnectionsdurationmean() ;
// 当前connector所有连接持续时间的标准偏差
public double getconnectionsdurationstddev() ;
// 当前connector的所有连接的平均请求数
public double getconnectionsrequestsmean() ;
// 当前connector的所有连接的请求数标准偏差
public double getconnectionsrequestsstddev() ;
// 当前connector的所有连接的最大请求数
public int getconnectionsrequestsmax();
}
jetty中所有的connector都继承自abstractconnector,而它自身继承自httpbuffers,httpbuffers包含了request、response的buffer工厂的创建以及相应size的配置。abstractconnector还包含了name、server、maxidletime以及一些统计信息的引用,用于实现connector接口中的方法,只是一些get、set方法,不详述。除了connector接口相关的配置,abstractconnector还为定义了两个字段:_acceptqueuesize用于表示serversocket 或serversocketchannel中最大可等待的请求数,_acceptors用于表示用于调用serversocket或serversocketchannel中accept方法的线程数,建议这个数字小于或等于可用处理器的2倍。
在abstractconnector中还定义了acceptor内部类,它实现了runnable接口,在其run方法实现中,它将自己的thread实例赋值给abstractconnector中的_acceptorthread数组中acceptor号对应的bucket,并更新线程名为:<name> acceptor<index> <connector.tostring>。然后根据配置的_acceptorpriorityoffset设置当前线程的priority。只要当前connector处于running状态,并且底层链接实例不为null,不断的调用accept方法()。在退出的finally语句快中清理_acceptorthread数组中相应的bucket值为null,并将线程原来的name、priority设置回来。
abstractconnector实现了dostart()方法,它首先保证server实例的存在;然后打开当前connector(调用其open()方法),并调用父类的dostart方法(这里是httpbuffers,用于初始化对应的buffers);如果没有自定义的threadpool,则从server中获取threadpool;最后根据acceptors的值创建_acceptorthread数组,将acceptors个acceptor实例dispatch给threadpool。在dostop方法实现中,它首先调用close方法,然后对非server中的threadpool调用其stop方法,再调用父类的dostop方法清理buffers的引用,最后遍历_acceptorthread数据,调用每个thread的interrupt方法。
在各个子类的accept方法实现中,他们在获取客户端过来的socket连接后,都会对该socket做一些配置,即调用abstractconnector的configure方法,它首先设置socket的tcp_nodelay为true,即禁用nagle算法(关于禁用的理由可以参考:http://jerrypeng.me/2013/08/mythical-40ms-delay-and-tcp-nodelay/#sec-4-2,简单的,如果该值为false,则tcp的数据包要么达到tcp segment size,要么收到一个ack,才会发送出去,即有delay);然后如果设置了_solingertime,则开启socket中so_linger选项,否则,关闭该选项(so_linger选项用于控制关闭一个socket的行为,如果开启了该选项,则在关闭socket时会等待_solingertime时间,此时如果有数据还未发送完,则会发送这些数据;如果关闭了该选项,则socket的关闭会立即返回,此时也有可能继续发送未发送完成的数据,具体参考:http://blog.csdn.net/factor2000/article/details/3929816)。
在serversocket和serversocketchannel中还有一个so_reuseaddr的配置,一般来说当一个端口被释放后会等待两分钟再被使用,此时如果重启服务器,可能会导致启动时的绑定错误,设置该值可以让端口释放后可以立即被使用(具体参考:http://www.cnblogs.com/mydomain/archive/2011/08/23/2150567.html)。在abstractconnector中可以使用setreuseaddress方法来配置,默认该值设置为true。
abstractconnector中还实现了customize方法,它在forwarded设置为true的情况下设置相应的attribute:javax.servlet.request.cipher_suite, javax.servlet.request.ssl_session_id,以及request中对应host、server等头信息。这个逻辑具体含义目前还不是很了解。。。。
最后关于统计数据的更新方法,abstractconnector定义了如下方法:
protected void connectionopened(connection connection)
protected void connectionupgraded(connection oldconnection, connection newconnection)
protected void connectionclosed(connection connection)
有了abstractconnector的实现,socketconnector的实现就变的非常简单了,它保存了一个endpoint的set,表示所有在这个connector下正在使用的endpoint,然后是serversocket,在open方法中创建,并在getconnection()方法中返回,还有一个localport字段,当serversocket被创建时从serversocket实例中获取,并在getlocalport()方法中返回。在close方法中关闭serversocket,并设置localport为-2;在accept方法中,调用serversocket的accept方法,返回一个socket,调用configure方法对新创建的socket做一些基本的配置,然后使用该socket创建connectorendpoint,并调用其dispatch方法;在customize方法中,在调用abstractconnector的customize方法的同时还设置connectorendpoint的maxidletime,即设置socket的so_timeout选项,用于配置该socket的空闲可等待时间;在dostart中会先清理connectorendpoint的集合,而在dostop中会关闭所有还处于打开状态的connectorendpoint。
selectchannelconnector内部使用serversocketchannel,在open方法中创建serversocketchannel,配置其为非blocking模式,并设置localport值;在accept方法中调用serversocket的accept方法获得一个socketchannel,配置该channel为非blocking模式,调用abstractchannel的configure方法做相应socket配置,最后将该socketchannel注册给connectorselectmanager;在dostart方法中,它会初始化connectorselectmanager的selectsets值为acceptors值、maxidletime、lowresourceconnections、lowresourcesmaxidletime等值,并启动该manager,并dispatch acceptors个线程,不断的调用manager的doselect方法;在close方法中会先stop connectorselectmanager,然后关闭serversocketchannel,设置localport为-2;在customize方法中会清除selectchannelendpoint的idletimestamp,重置其maxidletime以及重置request中的timestamp的值;在persist方法中会重置selectchannelendpoint中idletimestamp的值。
blockingchannelconnector实现类似socketconnector,不同的是它使用serversocketchannel,并且其endpoint为blockingchannelendpoint。所不同的是它需要在dostart方法中启动一个线程不断的检查所有还在connections集合中的blockingchannelendpoint是否已经超时,每400ms检查一次,如果超时则关闭该endpoint。
其他的connector的实现都比较类似,而ssl相关的connector需要也只是加入了ssl相关的逻辑,这里不再赘述。