05|Server性能提升:设计多个Processor
项目结构
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了如何通过设计多个Processor来提升Server性能。作者指出了当前Server运行模式的不足之处,提出了引入池的概念,增强Processor的复用性,同时将Processor异步化,支持一个Connector服务于多个Processor的计划。在项目结构方面,作者针对原有的HttpConnector和HttpProcessor类进行了改造,使用ArrayDeque存放构造完毕的HttpProcessor对象,实现了多个Processor的池化管理。通过对HttpConnector类的改造,作者展示了如何初始化Processor池,并在接收到Socket时从池中获取Processor,处理完毕后再放回池中,从而实现了一次请求响应。文章通过具体的代码示例和解释,清晰地阐述了如何设计多个Processor来提升Server性能,为读者提供了一种优化Server性能的思路和方法。文章内容涉及了引入池化技术以及Processor多线程,从优化对象构造、持续复用的角度,以及并发的角度,使Connector能同时服务于多个Processor,减少了原来因等待Processor处理而产生的时间消耗,但是也需要仔细编写线程同步代码。
《手把手带你写一个 MiniTomcat》,新⼈⾸单¥59
全部留言(11)
- 最新
- 精选
- 马以思考题:tomcat的线程池模型和JDK自带线程池模型在核心线程池用完后的实现方式上是不同的;JDK的线程池在达到核心线程池数量后,后续的请求会进入到等待队列(微观上看属于阻塞),因为tomcat作为servlet服务请求,本质上只能并发处理有限个(核心线程数)的并发数,这显然是不合理的;所以tomcat的线程池模型是达到核心线程池后会继续启动新线程处理请求,直到达到最大线程数;
作者回复: 赞。
2024-01-04归属地:广东3 - 像少年样飞驰这里面线程同步机制需要这样写么? 直接参考线程池的设计,用一个阻塞队列是不是就可以了? 本质上还是一个生产和消费的模型吧
作者回复: 也是可以的,但是jdk线程池不是很适合,所以Tomcat采用了这个方式(有人也有类似问题,见别的解答)。对我个人来说,是忠于Tomcat的原始实现,以后学习者读到Tomcat这一段源代码的时候不会觉得难以理解。
2023-12-24归属地:上海1 - so longjdk线程池,在并发数超过核心线程数后,会先将请求任务添加到队列中,而不是创建新的线程处理请求任务,所以会存在一定的延迟
作者回复: 是的。jdk线程池用的普通队列,不适合io型多任务处理。
2023-12-18归属地:浙江1 - 无心avaliable的 ture 和 false 语意是不是反了
作者回复: 没反。就是一个闸门,控制两边。看你从哪面去看这个问题。
2024-03-09归属地:广东 - Geek_b7bd01为什么connector调用processor.assign()方法,这样不会导致connector线程进行等待吗?为何不直接将任务丢给processor。
作者回复: 直接丢给processor不行,生产者消费者之间要同步。
2024-01-31归属地:广东2 - Geek_b7bd01这样connector不是必须得等待processor执行完成之后才能继续往下走吗,不影响效率吗?
作者回复: 并不会等processor执行完,那就成了串行了。互锁机制解决生产者消费者同步问题。
2024-01-31归属地:广东 - cttHttpProcessor initprocessor = new HttpProcessor(); processors.push(initprocessor); curProcessors++; return ((HttpProcessor) processors.pop()); 请问这段代码为什么push完就立即pop了呢
作者回复: 因为本质上是需要拿出一个processor.只是没有的时候会临时新建一个。
2023-12-24归属地:广东 - C.Tomcat 为什么用一个简单的 queue 来实现多线程而不是用 JDK 自带的线程池? 1.自定义可以更好地控制,还有后期的优化 2.历史原因,可能当时内置线程池功能没那么完善 现在,应该也支持使用JDK自带的线程池 交个作业:https://github.com/caozhenyuan/mini-tomcat
作者回复: 你的理解原则上是正确的。具体一点,jdk线程池标准模式当核心线程数超过后直接进队列,不是新建线程,这个方式不适合io型多任务。
2023-12-19归属地:江苏 - peter请教老师几个问题: Q1:用notifyAll唤醒所有线程,不对吧。 假如有5个线程,connector同时启动这5个线程,5个线程处于wait状态。假设此时来了一个连接请求,由其中的一个线程A处理,那么,connector应该只唤醒这线程A吧。用notifyall会唤醒全部5个线程,难道5个线程处理同一个请求吗? Q2:recycle方法有多线程问题吗? 假设有5个线程在处理5个请求,这5个线程都会调用recycle方法,此时会存在并发问题吗? Q3:线程池的大小一般为多大? 有经验公式吗?
作者回复: 都是好问题。notifyall会唤醒全部,但是代码中一旦标志不符合就会继续等待,不会出现几个同时处理,你仔细跟代码。recycle我也认为会出现并发问题,你这个观察很好,这段代码取自Tomcat4源代码,应该是有问题。 线程池大小,很复杂,大师们有个公式,依赖于核还有计算时间等待时间,但是实际系统复杂,很不好估算计算时间等待时间,并且还有别的进程共用CPU,所以呢,不好回答,我一般拍脑袋就是讲线程池大小设置为核的数量。
2023-12-18归属地:北京4 - HH🐷🐠🌝🌝自带JDK线程池初始化指定线程数, 共用这些线程, 可能这次在A线程执行, 下次在B线程执行,上下文切来切去造成性能不必要的开销,在网络中这点开销算是很大了。 只能想到这个点,不知道是否正确
作者回复: 简单来讲,jdk线程池使用普通队列,当并发任务数超过了核心大小后,直接进队列等待,这种方式比较适合CPU型多任务。但是servlet的应用场景是io型的,所以Tomcat要自己实现。我们也可以比较简单地重写jdk队列的offer方法,数量没有达到最大线程数就返回false,让线程池新建线程。
2023-12-18归属地:广东