当前位置: 首页 > wzjs >正文

南京建设公司网站东莞建设网官网首页

南京建设公司网站,东莞建设网官网首页,怎么申请 免费网站空间,wordpress大改动在spring-mvc demo程序运行到DispatcherServlet的mvc处理 一文中,我们实践了浏览器输入一个请求,然后到SpringMvc的DispatcherServlet处理的整个流程. 设计上这些都是tomcat servlet的处理 那么究竟这是怎么到DispatcherServlet处理的,本文将…

在spring-mvc demo程序运行到DispatcherServlet的mvc处理 一文中,我们实践了浏览器输入一个请求,然后到SpringMvc的DispatcherServlet处理的整个流程. 设计上这些都是tomcat servlet的处理

在这里插入图片描述
那么究竟这是怎么到DispatcherServlet处理的,本文将给出。

目录

    • Tomcat架构
      • Connector
        • Http11NioProtocol -> NioEndpoint
          • 接收tcp/ip请求的线程,Acceptor
          • 处理socket连接数据的线程,Poller
          • socket具体的读写处理,Processor(Executor线程池)
            • 具体在抽象类AbstractEndpoint中org.apache.tomcat.util.net.AbstractEndpoint#processSocket
      • org.apache.coyote.http11.Http11Processor#service

Tomcat架构

显然需要先了解tomcat, 可以下载tomcat源码分析。 其处理流程基本如下:
在这里插入图片描述
Tomcat包含几个容器:Engine, Host, Context,Wrapper,Servlet,最后是Servlet实例执行service方法处理请求。

而Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  1. Servlet 通过调用init()方法进行初始化。
  2. Servlet 调用service()方法来处理客户端的请求。
  3. Servlet 通过调用destroy()方法终止(结束)。
  4. 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

service()方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGetdoPostdoPutdoDelete等方法。

Connector

connector是什么?

The HTTP Connector element represents a Connector component that supports the HTTP/1.1 protocol. It enables Catalina to function as a stand-alone web server, in addition to its ability to execute servlets and JSP pages. A particular instance of this component listens for connections on a specific TCP port number on the server.One or more such Connectors can be configured as part of a single Service, each forwarding to the associated Engine to perform request processing and create the response.
(https://tomcat.apache.org/tomcat-8.0-doc/config/http.html)

HTTP Connector 能支持 HTTP/1.1 协议。它使 Catalina 能够作为独立的 Web 服务器运行,此外还能够执行 servlet 和 JSP 页面。此组件的特定实例会侦听服务器上特定 TCP 端口号上的连接。可以将一个或多个这样的 Connector 配置为单个服务的一部分,每个 Connector 都会转发到关联的 Engine 以执行请求处理并创建响应。

 public Connector(String protocol) {setProtocol(protocol);// Instantiate protocol handlerProtocolHandler p = null;try {Class<?> clazz = Class.forName(protocolHandlerClassName);p = (ProtocolHandler) clazz.getConstructor().newInstance();} catch (Exception e) {log.error(sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"), e);} finally {this.protocolHandler = p;}if (Globals.STRICT_SERVLET_COMPLIANCE) {uriCharset = StandardCharsets.ISO_8859_1;} else {uriCharset = StandardCharsets.UTF_8;}// Default for Connector depends on this (deprecated) system propertyif (Boolean.parseBoolean(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "false"))) {encodedSolidusHandling = EncodedSolidusHandling.DECODE;}}

第一句 setProtocol就根据配置了socket编程协议类型

/*** Set the Coyote protocol which will be used by the connector.** @param protocol The Coyote protocol name** @deprecated Will be removed in Tomcat 9. Protocol must be configured via*             the constructor*/@Deprecatedpublic void setProtocol(String protocol) {boolean aprConnector = AprLifecycleListener.isAprAvailable() &&AprLifecycleListener.getUseAprConnector();if ("HTTP/1.1".equals(protocol) || protocol == null) {if (aprConnector) {setProtocolHandlerClassName("org.apache.coyote.http11.Http11AprProtocol");} else {setProtocolHandlerClassName("org.apache.coyote.http11.Http11NioProtocol");}} else if ("AJP/1.3".equals(protocol)) {if (aprConnector) {setProtocolHandlerClassName("org.apache.coyote.ajp.AjpAprProtocol");} else {setProtocolHandlerClassName("org.apache.coyote.ajp.AjpNioProtocol");}} else {setProtocolHandlerClassName(protocol);}}
Http11NioProtocol -> NioEndpoint
接收tcp/ip请求的线程,Acceptor
protected final void startAcceptorThreads() {int count = getAcceptorThreadCount();acceptors = new Acceptor[count];for (int i = 0; i < count; i++) {acceptors[i] = createAcceptor();String threadName = getName() + "-Acceptor-" + i;acceptors[i].setThreadName(threadName);Thread t = new Thread(acceptors[i], threadName);t.setPriority(getAcceptorThreadPriority());t.setDaemon(getDaemon());t.start();}
}

直接:java.nio.channels.ServerSocketChannel#accept (所以时刻都要知道socket编程和tcp协议,IO基础可复习:https://doctording.blog.csdn.net/article/details/145839941)

/**
* The background thread that listens for incoming TCP/IP connections and
* hands them off to an appropriate processor.
*/
protected class Acceptor extends AbstractEndpoint.Acceptor {@Override
public void run() {int errorDelay = 0;// Loop until we receive a shutdown commandwhile (running) {// Loop if endpoint is pausedwhile (paused && running) {state = AcceptorState.PAUSED;try {Thread.sleep(50);} catch (InterruptedException e) {// Ignore}}if (!running) {break;}state = AcceptorState.RUNNING;try {//if we have reached max connections, waitcountUpOrAwaitConnection();SocketChannel socket = null;try {// Accept the next incoming connection from the server// socketsocket = serverSock.accept();} catch (IOException ioe) {// We didn't get a socketcountDownConnection();if (running) {// Introduce delay if necessaryerrorDelay = handleExceptionWithDelay(errorDelay);// re-throwthrow ioe;} else {break;}}// Successful accept, reset the error delayerrorDelay = 0;// Configure the socketif (running && !paused) {// setSocketOptions() will hand the socket off to// an appropriate processor if successfulif (!setSocketOptions(socket)) {closeSocket(socket);}} else {closeSocket(socket);}} catch (Throwable t) {ExceptionUtils.handleThrowable(t);log.error(sm.getString("endpoint.accept.fail"), t);}}state = AcceptorState.ENDED;
}
处理socket连接数据的线程,Poller

Acceptor的到的连接socket,进行如下处理

/**
* Process the specified connection.
* @param socket The socket channel
* @return <code>true</code> if the socket was correctly configured
*  and processing may continue, <code>false</code> if the socket needs to be
*  close immediately
*/
protected boolean setSocketOptions(SocketChannel socket) {// Process the connectiontry {//disable blocking, APR style, we are gonna be polling itsocket.configureBlocking(false);Socket sock = socket.socket();socketProperties.setProperties(sock);NioChannel channel = nioChannels.pop();if (channel == null) {SocketBufferHandler bufhandler = new SocketBufferHandler(socketProperties.getAppReadBufSize(),socketProperties.getAppWriteBufSize(),socketProperties.getDirectBuffer());if (isSSLEnabled()) {channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);} else {channel = new NioChannel(socket, bufhandler);}} else {channel.setIOChannel(socket);channel.reset();}getPoller0().register(channel);} catch (Throwable t) {ExceptionUtils.handleThrowable(t);try {log.error("",t);} catch (Throwable tt) {ExceptionUtils.handleThrowable(tt);}// Tell to close the socketreturn false;}return true;
}

Pollor类定义如下:

Pollor负责轮询网络连接上的数据。在 NIO 或 NIO2 模型中,Poller 线程会检查注册在其上的 Channel(例如,SocketChannel)是否有数据可读或可写。

其中使用了java nio的Selector,即允许一个单一的线程来操作多个 Channel.

/*** Poller class.*/
public class Poller implements Runnable {private Selector selector;private final SynchronizedQueue<PollerEvent> events =new SynchronizedQueue<>();private volatile boolean close = false;private long nextExpiration = 0;//optimize expiration handlingprivate AtomicLong wakeupCounter = new AtomicLong(0);private volatile int keyCount = 0;public Poller() throws IOException {this.selector = Selector.open();}
socket具体的读写处理,Processor(Executor线程池)

Poller判断连接是否有读写,交给Processor具体处理

protected void processKey(SelectionKey sk, NioSocketWrapper attachment) {try {if ( close ) {cancelledKey(sk);} else if ( sk.isValid() && attachment != null ) {if (sk.isReadable() || sk.isWritable() ) {if ( attachment.getSendfileData() != null ) {processSendfile(sk,attachment, false);} else {unreg(sk, attachment, sk.readyOps());boolean closeSocket = false;// Read goes before writeif (sk.isReadable()) {if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {closeSocket = true;}}if (!closeSocket && sk.isWritable()) {if (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) {closeSocket = true;}}if (closeSocket) {cancelledKey(sk);}}}} else {//invalid keycancelledKey(sk);}} catch ( CancelledKeyException ckx ) {cancelledKey(sk);} catch (Throwable t) {ExceptionUtils.handleThrowable(t);log.error("",t);}
}

背后是扩展的Executor线程池处理

 /*** This class is the equivalent of the Worker, but will simply use in an* external Executor thread pool.*/protected class SocketProcessor extends SocketProcessorBase<NioChannel> {public SocketProcessor(SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {super(socketWrapper, event);}@Overrideprotected void doRun() {NioChannel socket = socketWrapper.getSocket();SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());try {int handshake = -1;try {if (key != null) {if (socket.isHandshakeComplete()) {// No TLS handshaking required. Let the handler// process this socket / event combination.handshake = 0;} else if (event == SocketEvent.STOP || event == SocketEvent.DISCONNECT ||event == SocketEvent.ERROR) {// Unable to complete the TLS handshake. Treat it as// if the handshake failed.handshake = -1;} else {handshake = socket.handshake(key.isReadable(), key.isWritable());// The handshake process reads/writes from/to the// socket. status may therefore be OPEN_WRITE once// the handshake completes. However, the handshake// happens when the socket is opened so the status// must always be OPEN_READ after it completes. It// is OK to always set this as it is only used if// the handshake completes.event = SocketEvent.OPEN_READ;}}} catch (IOException x) {handshake = -1;if (log.isDebugEnabled()) log.debug("Error during SSL handshake",x);} catch (CancelledKeyException ckx) {handshake = -1;}if (handshake == 0) {SocketState state = SocketState.OPEN;// Process the request from this socketif (event == null) {state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);} else {state = getHandler().process(socketWrapper, event);}if (state == SocketState.CLOSED) {close(socket, key);}} else if (handshake == -1 ) {getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);close(socket, key);} else if (handshake == SelectionKey.OP_READ){socketWrapper.registerReadInterest();} else if (handshake == SelectionKey.OP_WRITE){socketWrapper.registerWriteInterest();}} catch (CancelledKeyException cx) {socket.getPoller().cancelledKey(key);} catch (VirtualMachineError vme) {ExceptionUtils.handleThrowable(vme);} catch (Throwable t) {log.error("", t);socket.getPoller().cancelledKey(key);} finally {socketWrapper = null;event = null;//return to cacheif (running && !paused) {processorCache.push(this);}}}}
具体在抽象类AbstractEndpoint中org.apache.tomcat.util.net.AbstractEndpoint#processSocket
/*** Process the given SocketWrapper with the given status. Used to trigger* processing as if the Poller (for those endpoints that have one)* selected the socket.** @param socketWrapper The socket wrapper to process* @param event         The socket event to be processed* @param dispatch      Should the processing be performed on a new*                          container thread** @return if processing was triggered successfully*/
public boolean processSocket(SocketWrapperBase<S> socketWrapper,SocketEvent event, boolean dispatch) {try {if (socketWrapper == null) {return false;}SocketProcessorBase<S> sc = processorCache.pop();if (sc == null) {sc = createSocketProcessor(socketWrapper, event);} else {sc.reset(socketWrapper, event);}Executor executor = getExecutor();if (dispatch && executor != null) {executor.execute(sc);} else {sc.run();}} catch (RejectedExecutionException ree) {getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);return false;} catch (Throwable t) {ExceptionUtils.handleThrowable(t);// This means we got an OOM or similar creating a thread, or that// the pool and its queue are fullgetLog().error(sm.getString("endpoint.process.fail"), t);return false;}return true;
}

(可能不同版本不一样,如上是在tomcat-8.5.57源码中)

org.apache.coyote.http11.Http11Processor#service

具体的processor处理,则依据配置和socket连接,如Http11Processor处理如下:

 @Overridepublic SocketState service(SocketWrapperBase<?> socketWrapper)throws IOException {RequestInfo rp = request.getRequestProcessor();rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);// Setting up the I/OsetSocketWrapper(socketWrapper);// FlagskeepAlive = true;openSocket = false;readComplete = true;boolean keptAlive = false;SendfileState sendfileState = SendfileState.DONE;while (!getErrorState().isError() && keepAlive && !isAsync() && upgradeToken == null &&sendfileState == SendfileState.DONE && !endpoint.isPaused()) {// Parsing the request headertry {if (!inputBuffer.parseRequestLine(keptAlive)) {if (inputBuffer.getParsingRequestLinePhase() == -1) {return SocketState.UPGRADING;} else if (handleIncompleteRequestLineRead()) {break;}}// Process the Protocol component of the request line// Need to know if this is an HTTP 0.9 request before trying to// parse headers.prepareRequestProtocol();if (endpoint.isPaused()) {// 503 - Service unavailableresponse.setStatus(503);setErrorState(ErrorState.CLOSE_CLEAN, null);} else {keptAlive = true;// Set this every time in case limit has been changed via JMXrequest.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());// Don't parse headers for HTTP/0.9if (!http09 && !inputBuffer.parseHeaders()) {// We've read part of the request, don't recycle it// instead associate it with the socketopenSocket = true;readComplete = false;break;}if (!disableUploadTimeout) {socketWrapper.setReadTimeout(connectionUploadTimeout);}}

关键处理在getAdapter().service(request, response);


文章转载自:

http://tRepPt1i.rjrnx.cn
http://0BQAdpDM.rjrnx.cn
http://8QvbcrHq.rjrnx.cn
http://W7eGhOmD.rjrnx.cn
http://wYf9ZXaJ.rjrnx.cn
http://ZKQR03jt.rjrnx.cn
http://9UOQENA9.rjrnx.cn
http://uIO78CJ3.rjrnx.cn
http://BSK9wR3L.rjrnx.cn
http://8AacOkw7.rjrnx.cn
http://vv54RtZc.rjrnx.cn
http://PIsJzGLa.rjrnx.cn
http://cct5rm5P.rjrnx.cn
http://IQCukoco.rjrnx.cn
http://u7Oy3Ren.rjrnx.cn
http://iRSjihQx.rjrnx.cn
http://Vjaz10n1.rjrnx.cn
http://08enpCEM.rjrnx.cn
http://H5fTjxjs.rjrnx.cn
http://TvWPXr7S.rjrnx.cn
http://9N9KGbAC.rjrnx.cn
http://tZfL4J7Z.rjrnx.cn
http://gSJxJgS1.rjrnx.cn
http://BjqmStkz.rjrnx.cn
http://FKr7vZZM.rjrnx.cn
http://IOTFcEgx.rjrnx.cn
http://5lghBGyl.rjrnx.cn
http://25vZWRwA.rjrnx.cn
http://ZWpqzJOC.rjrnx.cn
http://xnrZmysn.rjrnx.cn
http://www.dtcms.com/wzjs/706182.html

相关文章:

  • 为什么大公司开发网站黄骅市属于
  • 公司网站建设费用会计科目建境模型公司官网
  • 南昌做网站哪里好网站建设工作室图片
  • 微网站可以自己做吗哪个网站做视频收益高
  • 佛山营销网站建设制作网站功能模块结构图
  • 怎么看一个网站好坏wordpress仿堆糖
  • 成都建站程序影视后期制作培训班价格
  • 哪个地区网站建设好云南建设厅网站设计
  • 长沙市住房与城乡建设厅网站网站模板 扁平化
  • 循化网站建设公司wordpress接入七牛云
  • 网站建站管理系统oa系统下载
  • 网站改版 升级的目的是什么意思成品免费观看网站
  • 扬州做机床公司网站展示网站模板下载
  • 现在淘客做网站还行吗沈阳制作网站企业
  • 汕头网站建设开发苏州优化平台
  • 千博医院网站模板网络培训平台有哪些
  • 昆明官方网站建设东莞人才网官方网站
  • 在哪进入网站后台邢台网拓信息技术服务有限公司
  • 公司网站制作工作室鞍山制作网站的公司
  • 自建服务器做网站要备案宁阳网站seo推广
  • 个人做网站需要资质吗化妆品网页设计论文
  • 成都做网站设计哪家便宜小程序源码如何部署到服务器
  • 好网站用户体验网站开发后端论文
  • 百度公司做网站优化多少钱自己做的网站怎么挂广告
  • cn域名知名网站贵阳营销型网站建设
  • 建站公司哪个好临海网站制作好了如何上线
  • 网站建设推销拜访客户怎么开头本地wordpress后台
  • 文件传输协议登录网站郑州无痛人流哪家医院好
  • mt4外汇网站建设wordpress福利
  • 2345浏览器网站进入网站首页适合vue做吗