上次说了NioReceiver,这次看看NioSender,NioSender的体系结构比较复杂的,但感觉不用这么复杂,先看下类图:
这里觉得ParallelNioSender和PooledParallelSender之间有一个类可以去掉,如去了PooledParallelSender,PooledSender类设计成接口,这样的话会比较简洁.
ChannelCoordinator使用的是PooledParallelSender,最后面最重要的是还是NioSender。
NioSender是个状态机,看注释:
* - NOT_CONNECTED -> connect() -> CONNECTED
* - CONNECTED -> setMessage() -> READY TO WRITE
* - READY_TO_WRITE -> write() -> READY TO WRITE | READY TO READ
* - READY_TO_READ -> read() -> READY_TO_READ | TRANSFER_COMPLETE
* - TRANSFER_COMPLETE -> CONNECTED
这样可以循环的利用:
public boolean process(SelectionKey key, boolean waitForAck) throws IOException {
int ops = key.readyOps();
key.interestOps(key.interestOps() & ~ops);
//in case disconnect has been called
if ((!isConnected()) && (!connecting)) throw new IOException("Sender has been disconnected, can't selection key.");
if ( !key.isValid() ) throw new IOException("Key is not valid, it must have been cancelled.");
if ( key.isConnectable() ) {
if ( socketChannel.finishConnect() ) {
completeConnect();
if ( current != null ) key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
return false;
} else {
//wait for the connection to finish
key.interestOps(key.interestOps() | SelectionKey.OP_CONNECT);
return false;
}//end if
} else if ( key.isWritable() ) {
boolean writecomplete = write(key);
if ( writecomplete ) {
//we are completed, should we read an ack?
if ( waitForAck ) {
//register to read the ack
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
} else {
//if not, we are ready, setMessage will reregister us for another write interest
//do a health check, we have no way of verify a disconnected
//socket since we don't register for OP_READ on waitForAck=false
read(key);//this causes overhead
setRequestCount(getRequestCount()+1);
return true;
}
} else {
//we are not complete, lets write some more
key.interestOps(key.interestOps()|SelectionKey.OP_WRITE);
}//end if
} else if ( key.isReadable() ) {
boolean readcomplete = read(key);
if ( readcomplete ) {
setRequestCount(getRequestCount()+1);
return true;
} else {
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
}//end if
} else {
//unknown state, should never happen
log.warn("Data is in unknown state. readyOps="+ops);
throw new IOException("Data is in unknown state. readyOps="+ops);
}//end if
return false;
}
首先屏蔽了SelectionKey的interest集合中的ready集合,只有在这一次处理完以后才会恢复,这样的话下一次的数据不会影响到这一次的数,之后就是 SelectionKey的各种状态的处理,其中read()是调用write()后用于接受ack回执的.
从ChannelCoordinator开始,来看看NioSender的调用的流程:
ChannelCoordinator.sendMessage()---->ReplicationTransmitter.sendMessage()---->PooledParallelSender.sendMessage()
---->ParallelNioSender.sendMessage()---->ParallelNioSender.doLoop()---->NioSender.process()
可以吧PooledParallelSender看成一个门面,在这里是NioSender的入口,PooledSender里面主要是一个资源池的作用,这样可以合理利用和控制资源。
看PooledParallelSender的sendMessage()方法:
if ( !connected ) throw new ChannelException("Sender not connected.");
ParallelNioSender sender = (ParallelNioSender)getSender();
if (sender == null) {
ChannelException cx = new ChannelException("Unable to retrieve a data sender, time out error.");
for (int i = 0; i < destination.length; i++) cx.addFaultyMember(destination[i], new NullPointerException("Unable to retrieve a sender from the sender pool"));
throw cx;
} else {
try {
sender.sendMessage(destination, message);
sender.keepalive();
} catch (ChannelException x) {
sender.disconnect();
throw x;
} finally {
returnSender(sender);
if (!connected) disconnect();
}
}
这个地方调用了ParallelNioSender的sendMessage()方法后,还调用了keepalive(),这个方法去除NioSender的集合中不在存活状态的NioSender.最后归还NioSender.
看下ParallelNioSender的sendMessage()方法,主要是先拿到需要传播的NioSender数组,之后一个个的去传送。
如果NioSender数组在超时的时间限制内没有发送完成的话,就会抛出异常.主要是在doLoop()方法里面执行的,这里如果出现异常的话,还有NioSender重连等机制试图恢复NioSender的功能
看tomcat的设计,关于资源池的设计,基本上有两个集合,一个是已经使用的集合,一个是未使用的集合,当未使用集合还有资源的话,现在未使用的集合,当没有的话,在小于最大限度的情况下,可以重新new一个,当一个资源使用完毕的话,放入到未使用的集合可以重新利用。有些时候,一个资源是否可以放入未使用集合是有考虑的,比如他的持续的服务时间是否过长,如果过长就不会放在,因为这个资源过老的话,可能利用的资源不能得到释放,最坏的情况是资源被耗尽,如内存泄漏等,这样还不如重新new一个新的,这些都是我们设计资源池需要考虑的
- 大小: 7.8 KB
分享到:
相关推荐
Tomcat7、Tomcat8和Tomcat9是不同版本的Tomcat,每个版本都有其特性和改进。 **Tomcat7**: Tomcat7是2011年发布的,它主要支持Java Servlet 3.0和JSP 2.2规范。这个版本引入了一些重要改进,包括增强的安全性、更...
Tomcat是Apache软件基金会下的一个开源项目,是一个广泛使用的Java Servlet容器,特别因为其轻量级、高效能和稳定性而闻名。它实现了Java Servlet和JavaServer Pages(JSP)规范,使得开发者能够用Java语言来编写...
Tomcat 7 和 Tomcat 8 是两个非常重要的版本,它们是Apache软件基金会开发的开源Java Servlet容器,主要用于运行Java Web应用程序。这两个版本都遵循Java EE(Enterprise Edition)规范,但各自具有不同的特点和改进...
tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat最新客户端tomcat...
《深入理解Tomcat-Redis-Session-Manager:在Tomcat7和Tomcat8中的应用》 在现代Web应用程序开发中,session管理是一个至关重要的环节,它涉及到用户会话的持久化和跨请求的数据共享。传统的session管理方式在高...
《Tomcat深入剖析》这本书是理解Apache Tomcat服务器工作原理的宝贵资料,它由美国作者撰写并被翻译成中文,适合各个层次的开发者阅读。通过深入学习,读者能够对Tomcat的内部机制有全面而深入的理解,从而更好地...
**Idea Tomcat Runner插件详解** 在Java开发领域,IntelliJ IDEA是一款备受推崇的集成开发环境(IDE),尤其以其高效、智能的代码编辑功能和丰富的插件生态而著称。对于使用Java Web应用的开发者来说,Tomcat服务器...
### Tomcat打补丁方法详解 #### 一、前言 Apache Tomcat是一款开源的Servlet容器,它能够作为Web服务器独立运行,也可以与Apache等其他Web服务器配合使用。Tomcat因其简单性和灵活性,在中小型项目中得到了广泛...
Apache Tomcat 7.0是Java Servlet和JavaServer Pages(JSP)的开源Web应用程序服务器,由Apache软件基金会开发和维护。它是最流行的轻量级应用服务器,特别适合部署Java Web应用程序。Tomcat 7.0是7.x系列的一个版本...
《SmartTomcat插件在IDEA中的安装与使用详解》 SmartTomcat是专为IntelliJ IDEA(简称IDEA)设计的一款强大的Tomcat服务器管理插件,版本为3.8.5。它极大地简化了开发者在IDEA中部署、运行和调试Java Web应用程序的...
Apache Tomcat是一款开源的Java Servlet容器,主要用于运行Java Web应用程序,包括JSP和Servlet。Tomcat8.5是其在2017年发布的一个稳定版本,提供了许多增强的功能和性能改进。在这个“apache-tomcat-8.5.23.tar.gz...
在Linux(CentOS7)操作系统中安装Apache Tomcat并将其设置为开机启动是一项常见的任务,特别是在部署Java web应用时。本篇文章将详细讲解如何在CentOS7上安装Tomcat8并将其配置为自启动服务。 首先,我们来了解...
tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-...
标题中的“tomcat7.0下的64位的tomcat7.exe 和tomcat7w.exe”指的是Apache Tomcat服务器在7.0版本中为64位操作系统提供的可执行文件。Tomcat是Apache软件基金会的一个开源项目,它是一个流行的Java Servlet容器,...
在Java Web应用中,Tomcat是一个广泛使用的开源应用服务器,它提供了Servlet容器和JSP引擎等核心功能。在处理数据库连接方面,Tomcat提供了一种高效且可管理的数据源实现,名为“tomcat-jdbc数据源”。这个数据源是...
Apache Tomcat是一个开源的Java Servlet容器,主要用于运行Java Web应用程序,包括JSP和Servlet。Tomcat8.5.23是该服务器的一个特定版本,专为Windows 64位操作系统设计,提供高效、稳定和安全的平台来部署Web服务。...
Java 代码启动 Tomcat 在 Java 中,使用 Tomcat 服务器来发布 Web 应用程序是一种常见的做法。下面,我们将详细介绍如何使用 Java 代码来启动 Tomcat 服务器,并实现远程控制 Tomcat。 标题: Java 代码启动 ...
Apache Tomcat是一款开源的Java Servlet容器,主要用于实现Java EE中的Web应用服务。它是一个轻量级的应用服务器,特别适合用于小型到中型的Java Web应用程序。在这个特定的版本——7.0.82中,我们关注的是Linux平台...
Spring Boot 单独升级 Tomcat 在 Spring Boot 项目中,Tomcat 的升级是非常重要的,因为低版本的 Tomcat 存在漏洞,可能会导致安全问题。在本文中,我们将详细介绍如何单独升级 Tomcat,以解决漏洞问题。 知识点 1...
Apache Tomcat 7是Apache软件基金会的一个开源项目,专门用于实现Java Servlet和JavaServer Pages(JSP)技术的标准,以及Java EE的Web应用程序部署。这个最新版本,即7.0.109,包含了对先前版本的改进和修复,旨在...