学习tomcat——如何建立连接,处理请求

-> new Http11NioProtocol()

public Http11NioProtocol() {

super(new NioEndpoint());

}

指定服务终端处理模型非阻塞nio类

=================================================================================

org.apache.tomcat.util.net.NioEndpoint

-> new NioEndPoint()

创建之后如何被启动?见springboot启动tomcat方式

终端处理线程和线程池初始化

=============================================================================

启动之后

NioEndpoint执行bind()方法,

一些初始化,绑定端口

@Override

public void bind() throws Exception {

initServerSocket();

setStopLatch(new CountDownLatch(1));

// Initialize SSL if needed

initialiseSsl();

selectorPool.open(getName());

}

//socket相关 initServerSocket()具体如下

// Separated out to make it easier for folks that extend NioEndpoint to

// implement custom [server]sockets

protected void initServerSocket() throws Exception {

//…

//根据平台不同,反回具体底层类对象(windows,linux,unix)

serverSock = ServerSocketChannel.open();

socketProperties.setProperties(serverSock.socket());

//绑定地址和端口号

InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset());

serverSock.socket().bind(addr,getAcceptCount());

//…

}

NioEndpoint初始化之后,调用start()执行startInternal()

代码如下

// Create worker collection

if (getExecutor() == null) {

//创建线程池

createExecutor();

}

initializeConnectionLatch();

// Start poller thread

// 创建客户端队列(客户端过来的请求)

poller = new Poller();

Thread pollerThread = new Thread(poller, getName() + “-ClientPoller”);

pollerThread.setPriority(threadPriority);

pollerThread.setDaemon(true);

pollerThread.start();

//创建接收远程请求线程

startAcceptorThread();

初始化线程池配置

========================================================================

-> createExecutor() 用于处理用户请求

指定 备用线程,对大线程数,队列类型,超时时间,和线程工厂

public void createExecutor() {

internalExecutor = true;

TaskQueue taskqueue = new TaskQueue();

TaskThreadFactory tf = new TaskThreadFactory(getName() + “-exec-”, daemon, getThreadPriority());

executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);

taskqueue.setParent( (ThreadPoolExecutor) executor);

}

创建Poller线程

==========================================================================

poller = new Poller();

Thread pollerThread = new Thread(poller, getName() + “-ClientPoller”);

pollerThread.setPriority(threadPriority);

pollerThread.setDaemon(true);

pollerThread.start();

创建Acceptor线程

protected void startAcceptorThread() {

acceptor = new Acceptor<>(this);

String threadName = getName() + “-Acceptor”;

acceptor.setThreadName(threadName);

Thread t = new Thread(acceptor, threadName);

t.setPriority(getAcceptorThreadPriority());

t.setDaemon(getDaemon());

t.start();

}

处理请求的相关对象(线程)

=============================================================================

Acceptor类

=========================================================================

org.apache.tomcat.util.net.Acceptor

Acceptor 负责循环等待远程请求,将请求以socket形式携带信息,调用setSocketOptions()将socket包装配置为socketWrapper,

setSocketOptions: 对socket包装处理配置,使用poller对象注册到队列,让poller线程做后续的处理

Acceptor 类的run方法:

public void run() {

int errorDelay = 0;

//…以下省略部分代码

try {

// Loop until we receive a shutdown command

// 一直循环等待远程请求

while (!stopCalled) {

// Accept the next incoming connection from the server socket

// 1 接收请求

socket = endpoint.serverSocketAccept();

// setSocketOptions() will hand the socket off to

// 2 处理请求,setSocketOptions() 内部调用poller 将新请求任务放入队列

if (!endpoint.setSocketOptions(socket)) {

endpoint.closeSocket(socket);

}

}

} finally {

stopLatch.countDown();

}

state = AcceptorState.ENDED;

}

Poller类

=======================================================================

org.apache.tomcat.util.net.NioEndpoint.Poller

Poller负责接收包装后的socket请求,放入队列,

并在run方法中循环去poll()请求任务,将与流读写有关的组件IOChannel Selector socketWrapper 绑定关联

再通过selector获取selectionKeys

迭代循环获取对应的socket,提交任务(线程),线程读写处理socketWrapper等后续操作

public void run() {

// Loop until destroy() is called

while (true) {

// poller队列任务处理 将IOChannel Selector socketWrapper 关联

hasEvents = events();

//…省略

Iterator iterator =

keyCount > 0 ? selector.selectedKeys().iterator() : null;

// Walk through the collection of ready keys and dispatch

// 非阻塞io api 任务处理

while (iterator != null && iterator.hasNext()) {

SelectionKey sk = iterator.next();

iterator.remove();

NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment();

// Attachment may be null if another thread has called

// cancelledKey()

if (socketWrapper != null) {

// 如果有等待处理的任务,则处理

processKey(sk, socketWrapper);

//processKey内部会调用processSocket方法,最终用线程池提交任务

}

}

// Process timeouts

timeout(keyCount,hasEvents);

}

getStopLatch().countDown();

}

其他

==================================================================

events队列

private final SynchronizedQueue events =

new SynchronizedQueue<>(); //事件队列(socket请求)

//注册请求到队列

public void rigister(final NioSocketWrapper socketWrapper)

{

event = new PollerEvent(socketWrapper, OP_REGISTER);

addEvent(event);

}

private void addEvent(PollerEvent event) {

events.offer(event);

if (wakeupCounter.incrementAndGet() == 0) {

selector.wakeup();

}

}

events()绑定及后面的 processSocket()最终提交实际处理任务到线程

/**

  • Processes events in the event queue of the Poller.

  • @return true if some events were processed,

  • false if queue was empty

*/

public boolean events() {

boolean result = false;

PollerEvent pe = null;

for (int i = 0, size = events.size(); i < size && (pe = events.poll()) != null; i++ ) {

result = true;

NioSocketWrapper socketWrapper = pe.getSocketWrapper();

SocketChannel sc = socketWrapper.getSocket().getIOChannel();

int interestOps = pe.getInterestOps();

if (sc == null) {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后总结

搞定算法,面试字节再不怕,有需要文章中分享的这些二叉树、链表、字符串、栈和队列等等各大面试高频知识点及解析

最后再分享一份终极手撕架构的大礼包(学习笔记):分布式+微服务+开源框架+性能优化

image

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
5%以上Java开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后总结

搞定算法,面试字节再不怕,有需要文章中分享的这些二叉树、链表、字符串、栈和队列等等各大面试高频知识点及解析

最后再分享一份终极手撕架构的大礼包(学习笔记):分布式+微服务+开源框架+性能优化

[外链图片转存中…(img-OtZRbkhz-1713640543459)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 12
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值