- 浏览: 882481 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (509)
- android (55)
- CSS (23)
- eclipse (25)
- Data Structes and Algorithms (53)
- J2SE (87)
- Java_面试学习_j2se (26)
- java_面试学习_非技术 (13)
- java_gui (2)
- java_设计模式 (27)
- JDBC (10)
- java_web (15)
- hibernate (5)
- Oracle (37)
- Struts2 (7)
- Word-----dos (24)
- Jbpm (3)
- java小技巧 (8)
- math (1)
- flex (12)
- WebService (4)
- 生活 (9)
- 小框架或小语言 (27)
- spring (1)
- 面试~~~软实力 (7)
- jstat的用法 (1)
- jmap (1)
- 数据链路层和传输层的流量控制区别 (1)
- shell (0)
- 财商 (1)
- javascript (0)
- js研究 (1)
- 代码收集 (0)
最新评论
-
海尔群:
http://jingyan.baidu.com/articl ...
android加密 -
完美天龙:
------------------------- ...
asm----字节码操纵 -
houniao1990:
大神,请问 string 类型 定义为 oracle的 cha ...
hibernate注解 -
JamesQian:
Line:103
f.doFilter(msg);
是否需 ...
责任链模式_过滤器模式 -
sacoole:
好评
interview--- 如何从N个数中选出最大(小)的n个数?
org.apache.tomcat.util.net包的内容都与网络连接和socket有关,比较主要和常见的是JIOEndpoint这个类,前面提到Coyote连接器的时候,就有涉及到JIOEndpoint,它用于监听某个socket端口、将socket对象交给coyote,并提供基本的线程池功能。除了JIOEndpoint,还有AprEndpoint、NioEndpoint等。由于对apr和nio不熟悉,所以只研究了一下JIOEndpoint
org.apache.tomcat.util.net.JIoEndpoint
JIOEndpoint其实和我们本科时上计算机网络或者分布式系统,做实验写的socket服务器差不多,结构也是经典的“Listen-Accept-Handle”,这里简单描述一下:JIOEndpoint使用JDK的ServerSocket类监听某个端口,有socket连接进来的时候便返回一个socket对象,交给专门的处理器。当然,具体的实现没那么简单,下面会按照socket的处理过程,详细说明其中的机理。
初始化
public void init()
throws Exception {
if (initialized)
return;
// Initialize thread count defaults for acceptor
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
if (serverSocketFactory == null) {
serverSocketFactory = ServerSocketFactory.getDefault();
}
if (serverSocket == null) {
try {
if (address == null) {
serverSocket = serverSocketFactory.createSocket(port, backlog);
} else {
serverSocket = serverSocketFactory.createSocket(port, backlog, address);
}
} catch (BindException be) {
throw new BindException(be.getMessage() + ":" + port);
}
}
//if( serverTimeout >= 0 )
// serverSocket.setSoTimeout( serverTimeout );
initialized = true;
}
在这里,利用serverSocketFactory新建了一个serverSocket对象,用于监听特定的端口
启动JIOEndpoint
// Create worker collection
if (executor == null) {
workers = new WorkerStack(maxThreads);
}
// Start acceptor threads
for (int i = 0; i < acceptorThreadCount; i++) {
Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
acceptorThread.setPriority(threadPriority);
acceptorThread.setDaemon(daemon);
acceptorThread.start();
}
这里有几个类:worker,workerStack,Acceptor。这些都是JIOEndpoint的一些内部类,下面按照处理顺序依次讲述
Acceptor内部类
Acceptor实现了Runnable接口,只有一个方法run,做的事情就是通过ServerSocket.accept方法,得到socket,然后调用JIOEndpoint的processSocket方法
protected boolean processSocket(Socket socket) {
try {
if (executor == null) {
getWorkerThread().assign(socket);
} else {
executor.execute(new SocketProcessor(socket));
}
} catch (Throwable t) {
// This means we got an OOM or similar creating a thread, or that
// the pool and its queue are full
log.error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
在这里,JIOEndpoint有两种处理socket的方式:使用JDK5的executor,或者内部的worker类。executor怎么用大家可以直接翻书了,我们继续讨论第二种方法。
首先我们要通过getWorkerThread()方法,得到一个Worker对象。具体逻辑是,看看WorkerStack(存放所有worker的一个堆栈)里面有没有空余的worker,有则直接拿来用,无则看看能不能新建一个worker线程,假如不能(比如超出了最大线程数限制),则返回null,那样就只能委屈一下这个acceptor,稍微等一下了(wait()方法),直到有新的worker可用时,通过notify方法唤醒等待的acceptor
/**
* Return a new worker thread, and block while to worker is available.
*/
protected Worker getWorkerThread() {
// Allocate a new worker thread
Worker workerThread = createWorkerThread();
while (workerThread == null) {
try {
synchronized (workers) {
workers.wait();
}
} catch (InterruptedException e) {
// Ignore
}
workerThread = createWorkerThread();
}
return workerThread;
}
如下,当有worker被回收后,通知等待的acceptor
protected void recycleWorkerThread(Worker workerThread) {
synchronized (workers) {
workers.push(workerThread);
curThreadsBusy--;
workers.notify();
}
}
ok,回到前面的processSocket方法,得到worker后,通过worker.assign方法,将socket对象传递给worker
Worker内部类
Worker也实现了runnable接口,有三个方法:assign、await、start和run
所谓的start方法,就是new一个Thread对象,把worker自己传进去,我们知道这个thread就开始执行run方法了。
public void run() {
// Process requests until we receive a shutdown signal
while (running) {
// Wait for the next socket to be assigned
Socket socket = await();
if (socket == null)
continue;
// Process the request from this socket
if (!setSocketOptions(socket) || !handler.process(socket)) {
// Close socket
try {
socket.close();
} catch (IOException e) {
}
}
// Finish up this request
socket = null;
recycleWorkerThread(this);
}
}
run方法首先调用await方法
private synchronized Socket await() {
// Wait for the Connector to provide a new Socket
while (!available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Notify the Connector that we have received this Socket
Socket socket = this.socket;
available = false;
notifyAll();
return (socket);
}
通过标记位available,如果当前的worker是“非available”的,则线程会开始等待。直到我们调用的assign方法,把一个可用的socket给worker后,才会notifyall,唤醒一个线程,进而取得assign过来的socekt
synchronized void assign(Socket socket) {
// Wait for the Processor to get the previous Socket
while (available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Store the newly available Socket and notify our thread
this.socket = socket;
available = true;
notifyAll();
}
所以,assign和await方法相当于生产者和消费者方法,两者通过available进行互斥,而this.socket则相当于被竞争的资源
现在,又回到Worker.run方法。在取得socket后,通过setSocketOptions(socket)方法设置socket的相关选项(例如超时值),最后通过handler.process(socket),终于把socket这个接力棒交给coyote了!
handler是什么?就是个简单的接口,如下:
/**
* Bare bones interface used for socket processing. Per thread data is to be
* stored in the ThreadWithAttributes extra folders, or alternately in
* thread local fields.
*/
public interface Handler {
public boolean process(Socket socket);
}
回顾一下org.apache.coyote.http11.Http11Protocol 的Http11ConnectionHandler内部类,实现的正是这个接口
org.apache.tomcat.util.net.JIoEndpoint
JIOEndpoint其实和我们本科时上计算机网络或者分布式系统,做实验写的socket服务器差不多,结构也是经典的“Listen-Accept-Handle”,这里简单描述一下:JIOEndpoint使用JDK的ServerSocket类监听某个端口,有socket连接进来的时候便返回一个socket对象,交给专门的处理器。当然,具体的实现没那么简单,下面会按照socket的处理过程,详细说明其中的机理。
初始化
public void init()
throws Exception {
if (initialized)
return;
// Initialize thread count defaults for acceptor
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
if (serverSocketFactory == null) {
serverSocketFactory = ServerSocketFactory.getDefault();
}
if (serverSocket == null) {
try {
if (address == null) {
serverSocket = serverSocketFactory.createSocket(port, backlog);
} else {
serverSocket = serverSocketFactory.createSocket(port, backlog, address);
}
} catch (BindException be) {
throw new BindException(be.getMessage() + ":" + port);
}
}
//if( serverTimeout >= 0 )
// serverSocket.setSoTimeout( serverTimeout );
initialized = true;
}
在这里,利用serverSocketFactory新建了一个serverSocket对象,用于监听特定的端口
启动JIOEndpoint
// Create worker collection
if (executor == null) {
workers = new WorkerStack(maxThreads);
}
// Start acceptor threads
for (int i = 0; i < acceptorThreadCount; i++) {
Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
acceptorThread.setPriority(threadPriority);
acceptorThread.setDaemon(daemon);
acceptorThread.start();
}
这里有几个类:worker,workerStack,Acceptor。这些都是JIOEndpoint的一些内部类,下面按照处理顺序依次讲述
Acceptor内部类
Acceptor实现了Runnable接口,只有一个方法run,做的事情就是通过ServerSocket.accept方法,得到socket,然后调用JIOEndpoint的processSocket方法
protected boolean processSocket(Socket socket) {
try {
if (executor == null) {
getWorkerThread().assign(socket);
} else {
executor.execute(new SocketProcessor(socket));
}
} catch (Throwable t) {
// This means we got an OOM or similar creating a thread, or that
// the pool and its queue are full
log.error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
在这里,JIOEndpoint有两种处理socket的方式:使用JDK5的executor,或者内部的worker类。executor怎么用大家可以直接翻书了,我们继续讨论第二种方法。
首先我们要通过getWorkerThread()方法,得到一个Worker对象。具体逻辑是,看看WorkerStack(存放所有worker的一个堆栈)里面有没有空余的worker,有则直接拿来用,无则看看能不能新建一个worker线程,假如不能(比如超出了最大线程数限制),则返回null,那样就只能委屈一下这个acceptor,稍微等一下了(wait()方法),直到有新的worker可用时,通过notify方法唤醒等待的acceptor
/**
* Return a new worker thread, and block while to worker is available.
*/
protected Worker getWorkerThread() {
// Allocate a new worker thread
Worker workerThread = createWorkerThread();
while (workerThread == null) {
try {
synchronized (workers) {
workers.wait();
}
} catch (InterruptedException e) {
// Ignore
}
workerThread = createWorkerThread();
}
return workerThread;
}
如下,当有worker被回收后,通知等待的acceptor
protected void recycleWorkerThread(Worker workerThread) {
synchronized (workers) {
workers.push(workerThread);
curThreadsBusy--;
workers.notify();
}
}
ok,回到前面的processSocket方法,得到worker后,通过worker.assign方法,将socket对象传递给worker
Worker内部类
Worker也实现了runnable接口,有三个方法:assign、await、start和run
所谓的start方法,就是new一个Thread对象,把worker自己传进去,我们知道这个thread就开始执行run方法了。
public void run() {
// Process requests until we receive a shutdown signal
while (running) {
// Wait for the next socket to be assigned
Socket socket = await();
if (socket == null)
continue;
// Process the request from this socket
if (!setSocketOptions(socket) || !handler.process(socket)) {
// Close socket
try {
socket.close();
} catch (IOException e) {
}
}
// Finish up this request
socket = null;
recycleWorkerThread(this);
}
}
run方法首先调用await方法
private synchronized Socket await() {
// Wait for the Connector to provide a new Socket
while (!available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Notify the Connector that we have received this Socket
Socket socket = this.socket;
available = false;
notifyAll();
return (socket);
}
通过标记位available,如果当前的worker是“非available”的,则线程会开始等待。直到我们调用的assign方法,把一个可用的socket给worker后,才会notifyall,唤醒一个线程,进而取得assign过来的socekt
synchronized void assign(Socket socket) {
// Wait for the Processor to get the previous Socket
while (available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Store the newly available Socket and notify our thread
this.socket = socket;
available = true;
notifyAll();
}
所以,assign和await方法相当于生产者和消费者方法,两者通过available进行互斥,而this.socket则相当于被竞争的资源
现在,又回到Worker.run方法。在取得socket后,通过setSocketOptions(socket)方法设置socket的相关选项(例如超时值),最后通过handler.process(socket),终于把socket这个接力棒交给coyote了!
handler是什么?就是个简单的接口,如下:
/**
* Bare bones interface used for socket processing. Per thread data is to be
* stored in the ThreadWithAttributes extra folders, or alternately in
* thread local fields.
*/
public interface Handler {
public boolean process(Socket socket);
}
回顾一下org.apache.coyote.http11.Http11Protocol 的Http11ConnectionHandler内部类,实现的正是这个接口
发表评论
-
jdbc--批处理
2012-06-08 18:15 1131http://jdgnewtouch.iteye.com/bl ... -
jdbc
2012-06-07 20:51 915http://www.iteye.com/topic/6466 ... -
j2se----jdk6---httpServer
2012-06-05 20:42 1412package com.tdt.server.httpse ... -
j2se基础---ThreadLocal
2012-06-02 20:47 1096package cn.itcast.heima2; ... -
获取运行时的堆栈信息
2011-12-11 11:00 2165public class Hi { public st ... -
简说XML的解析方式(DOM,SAX,StAX)
2011-09-30 08:44 933一般来说,解析XML文件存在着两种方式,一种是event-ba ... -
j2se----Java异步socket
2011-07-11 17:10 1440用异步输入输出流编写Socket进程通信程序 在Merlin ... -
j2se----socket的缓冲区讨论
2011-07-08 19:52 1772关于socket的发送缓冲区 ... -
翻转句子中单词的顺序
2011-07-07 22:42 1753题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺 ... -
j2se---同步的Map
2011-07-07 20:50 1003顾名思义LinkedHashMap是比HashMap多了一个链 ... -
j2se---同步的Map
2011-07-07 20:48 10Map<String String> map = ... -
asm----字节码操纵
2011-06-30 09:14 3938想通过asm的代码生成来写.class文件至少得了解下面的 ... -
j2se----java中,如何获得用户当前的工作目录
2011-05-11 09:44 1880获得当前路径, get java current dire ... -
j2se-----zip
2011-05-10 09:05 1053private InitData getInitFile( ... -
j2se-----可变参数列表
2011-04-01 10:53 887public static void main(Strin ... -
UML
2010-12-31 09:42 897组合: 一种强聚合 class Bird{ ... -
j2se-----metadata
2010-12-19 17:14 1013DatabaseMetaData的用法 ... -
python------一小时学会
2010-12-08 16:28 1924先上java与python的相互调用 如何在Java中调用Jy ... -
j2ee------download.jsp
2010-12-08 13:39 1120Logger logger = C ... -
effective------equals , hashCode
2010-11-22 12:04 1047覆盖equals时总是覆盖hashCode :你都认为他 ...
相关推荐
Apache服务器错误问题 Apache服务器错误问题 Apache服务器错误问题
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent....
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) at org.apache.catalina.core....
588) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:662) 网络解决办法: (虽然该办法可行,但是本人并不提倡。具体原因在之后解释。...
* $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/StringManager.java,v 1.2 2001/07/22 20:25:14 pier Exp $ * $Revision: 1.2 $ * $Date: 2001/07/22 20:25:14 $ * * =...
Apache Tomcat 8 是一个广泛使用的开源Java应用服务器,它主要负责部署和运行Java Servlets和JavaServer Pages(JSP)。在某些情况下,为了提高性能,开发者可能会选择启用Apache Portable Runtime (APR) 模块。APR...
总的来说,Tomcat Native 1.2.21是一个为了提升Apache Tomcat性能而设计的重要组件,通过结合APR库,它能够实现更高效的网络通信、内存管理和多线程处理。通过深入理解和使用Tomcat Native的源码,开发者可以更好地...
例如,他们会将编译后的APR和apr-util库与Tomcat的JNI(Java Native Interface)部分结合,通过JK2连接器实现Apache和Tomcat的高性能连接。这个过程中可能涉及到修改Tomcat的配置文件,以及正确设置系统环境变量。...
在开始之前,我们先来了解一下 LAMP 架构的基本概念:LAMP 是一个开源软件组合,由 Linux(操作系统)、Apache(Web 服务器)、MySQL(数据库管理系统)和 PHP(脚本语言)四部分组成,常用于搭建 Web 应用服务。...
Java Archive (JAR) 文件是Java平台上的一个标准文件格式,用于封装多个类文件、资源文件和其他相关数据,便于分发和执行。"常用的jar"这个主题涉及到的是在开发Java应用时经常使用的JAR库,这些库提供了各种功能,...
- **并发工具类**:如java.util.concurrent包下的Semaphore、CountDownLatch、CyclicBarrier等,用于协调多个线程间的同步。 4. **Java NIO(非阻塞I/O)**: - **通道(Channel)和缓冲区(Buffer)**:NIO引入...
- 日志框架:如Log4j或java.util.logging,用于记录程序运行日志,便于调试和问题排查。 3. Apache相关: - Tomcat:这是一个流行的开源Java应用服务器,用于部署和运行Java Web应用。 - Maven:项目管理和构建...
Java中的`java.net`包提供了Socket和ServerSocket类,用于实现客户端和服务器之间的通信。 3. **并发处理**:为了支持多人同时在线聊天,程序需要处理多个并发连接。Java提供了线程(Thread)和并发工具类(如`java...
本项目“基于Java的一个支持Servlet的Web服务器”是一个实现此类功能的自定义服务器,允许开发者在不依赖大型Web容器(如Apache Tomcat或Jetty)的情况下运行Servlet应用。 1. **Java基础知识**:Java是一种跨平台...
- 线程的调度由线程池管理,Java的java.util.concurrent包提供了强大的线程池支持。 - Java提供了synchronized和volatile关键字用于处理线程同步问题。 7. Java网络编程 - Java通过***包提供了对网络编程的支持...
安装Apache的时候,为什么要安装apr和apr-util呢 要测APR给tomcat带来的好处最好的方法是在慢速网络上(模拟Internet),将Tomcat线程数开到300以上的水平,然后模拟一大堆并发请求。如果不配APR,基本上300个线程狠...
2. **Java Network Programming**: Java的`java.net`包提供了Socket编程接口,可以创建客户端和服务器应用程序,这对于构建分布式系统至关重要。 3. **Java多线程**: Java内置对多线程的支持,允许并发执行任务,这...
简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 ...
Java的负载均衡策略可以通过Servlet容器(如Tomcat)的配置实现,也可以使用开源库如Apache Ignite或Netflix Ribbon。 4. **容错与复制**:为了保证高可用性,分布式系统通常需要具备故障恢复和数据复制的能力。...