手写一个民用Tomcat (03)

2024-04-10 10:52
文章标签 tomcat 03 手写 民用

本文主要是介绍手写一个民用Tomcat (03),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们完成了这个 小型Tomcat 基本功能,但是他处理请求还是 一个一个的执行,并不能做到并行处理。 我们仿照Tomcat的思路来进行 一比一精准优化。

 首先看一下我们的JxdHttpConnector 有什么改进,他可以理解成一个快递站领导,统一指挥JxdHttpProcessor 进行 工作。

JxdHttpConnector引入一个队列池,每接到一个请求,就冲队列池中取出来,执行这个请求,执行完之后再放回队列池中,继续等待下一个处理。

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayDeque;
import java.util.Deque;public class JxdHttpConnector implements Runnable {int minProcessors = 3;int maxProcessors = 10;int curProcessors = 0;//存放多个processor的池子Deque<JxdHttpProcessor> processorDeque = new ArrayDeque<>();@Overridepublic void run() {ServerSocket serverSocket = null;int port = 8080;try {serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));} catch (IOException e) {e.printStackTrace();System.exit(1);}//初始化池子 最开始三个initProcessorDeque();while (true) {Socket socket = null;try {//这是单线程 一个请求一个请求获取socketsocket = serverSocket.accept();//得到一个新的processor,这个processor从池中获取(池中有可能新建)JxdHttpProcessor processor = createProcessor();if (processor == null) {socket.close();continue;}processor.assign(socket);} catch (Exception e) {e.printStackTrace();}}}public void start() {Thread thread = new Thread(this);thread.start();}//从池子中获取一个processor,如果池子为空且小于最大限制,则新建一个private JxdHttpProcessor createProcessor() {synchronized (processorDeque) {if (processorDeque.size() > 0) {return processorDeque.pop();}if (curProcessors < maxProcessors) {return newProcessor();} else {return null;}}}private void initProcessorDeque(){for (int i = 0; i < minProcessors; i++) {JxdHttpProcessor processor = new JxdHttpProcessor(this);processor.start();processorDeque.push(processor);}curProcessors = minProcessors;}private JxdHttpProcessor newProcessor() {JxdHttpProcessor jxdHttpProcessor = new JxdHttpProcessor(this);jxdHttpProcessor.start();processorDeque.push(jxdHttpProcessor);curProcessors++;return processorDeque.pop();}public void recycle(JxdHttpProcessor processor) {processorDeque.push(processor);}
}
processorDeque这就是队列池,刚开始的时候 会创建三个,随着业务访问了增加 最多增加10个 ,

你们发现了吗  JxdHttpProcessor 为啥要.start()多线程进行处理,因为 你 虽然引入队列池但是还是不能 解决并行处理问题,所以要让每一个真正的执行者(员工)。进行并行处理。

JxdHttpProcessor 代码:

public class JxdHttpProcessor implements Runnable {boolean available = false;Socket socket;JxdHttpConnector connector;public JxdHttpProcessor(JxdHttpConnector connector) {this.connector = connector;}private void process(Socket socket) { //服务器循环等待请求并处理try {Thread.sleep(3000);} catch (InterruptedException e1) {e1.printStackTrace();}InputStream input = null;OutputStream output = null;try {input = socket.getInputStream();output = socket.getOutputStream();// create Request object and parseJxdRequest request = new JxdRequest(input);request.parse();// create Response objectJxdResponse response = new JxdResponse(output);if (request.getUri().startsWith("/servlet/")) {//加载动态资源JxdServletProcessor jxdServletProcessor = new JxdServletProcessor();jxdServletProcessor.process(request, response);} else {//加载静态资源StaticResourceProcessor staticResourceProcessor = new StaticResourceProcessor();staticResourceProcessor.process(request, response);}//因为是多线程所以只能交给httpProcessor 来关闭socket.close();} catch (Exception ea) {ea.printStackTrace();}}@Overridepublic void run() {while (true) {// 等待socket分配过来Socket socket = await();if (socket == null) continue;// 处理请求process(socket);// 回收processor,员工归队      connector.recycle(this);}}public void start() {Thread thread = new Thread(this);thread.start();}private synchronized Socket await() {// 等待connector提供一个新的socketwhile (!available) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}// 获得这个新的SocketSocket socket = this.socket;//设置标志为falseavailable = false;//通知另外的线程notifyAll();return (socket);}public synchronized void assign(Socket socket) {// 等待connector提供一个新的socketwhile (available) {try {wait();} catch (InterruptedException e) {}}// 获取到这个新的Socketthis.socket = socket;// 把标志设置回去available = true;//通知另外的线程notifyAll();}
}
JxdHttpProcessor 真正的执行者 实现了 Runnable 接口 同时引入了 await()和assign()方法和available 标识。先说await()方法 ,available 默认为false 也就是线程启动的时候进入 等待状态,一直等,等谁呢 他在等待一个指令,就类似于 员工快递站工作,等来了快递 才工作 没有快递 就休息。

在说一下 assign()方法,他的入参是Socket ,表示 快递来了 ,因为available 默认为false所以他会继续走 ,把标志available 默认为true 然后 通知await()中等待的 员工要开始工作了 。

这就是 形成了一套 运行 机制,我通知你干活,你干完活之后 告诉我 ,我们在02那篇文章的时候是这样的,JxdHttpConnector 领导一直紧跟着JxdHttpProcessor 员工,直到员工干完活,一个领导盯着一个员工很累的,现在是 这个领导 统一指挥一个 团队,员工自己干完活之后反馈给领导。

socket.close(); 还记得这个吗。之前是 有JxdHttpConnector 来关闭的,现在由 员工JxdHttpProcessor来关闭了,为啥 因为领导 一致盯着 员工直到 结束,但是现在 盯不住了 ,只能员工自己 才知道什么时候结束 。

备注:其他类不展示 基本每改动。

看一下运行结果吧。 

public class JxdHttpServer {public static final String WEB_ROOT = System.getProperty("user.dir");public static final String FILE_ROOT = "D:\\";public static void main(String[] args) {JxdHttpConnector connector = new JxdHttpConnector();connector.start();}
}

这篇关于手写一个民用Tomcat (03)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/890859

相关文章

最新版IDEA配置 Tomcat的详细过程

《最新版IDEA配置Tomcat的详细过程》本文介绍如何在IDEA中配置Tomcat服务器,并创建Web项目,首先检查Tomcat是否安装完成,然后在IDEA中创建Web项目并添加Web结构,接着,... 目录配置tomcat第一步,先给项目添加Web结构查看端口号配置tomcat    先检查自己的to

Apache Tomcat服务器版本号隐藏的几种方法

《ApacheTomcat服务器版本号隐藏的几种方法》本文主要介绍了ApacheTomcat服务器版本号隐藏的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需... 目录1. 隐藏HTTP响应头中的Server信息编辑 server.XML 文件2. 修China编程改错误

若依部署Nginx和Tomcat全过程

《若依部署Nginx和Tomcat全过程》文章总结了两种部署方法:Nginx部署和Tomcat部署,Nginx部署包括打包、将dist文件拉到指定目录、配置nginx.conf等步骤,Tomcat部署... 目录Nginx部署后端部署Tomcat部署出现问题:点击刷新404总结Nginx部署第一步:打包

Nginx、Tomcat等项目部署问题以及解决流程

《Nginx、Tomcat等项目部署问题以及解决流程》本文总结了项目部署中常见的four类问题及其解决方法:Nginx未按预期显示结果、端口未开启、日志分析的重要性以及开发环境与生产环境运行结果不一致... 目录前言1. Nginx部署后未按预期显示结果1.1 查看Nginx的启动情况1.2 解决启动失败的

tomcat在nginx中的配置方式

《tomcat在nginx中的配置方式》文章介绍了如何在Linux系统上安装和配置Tomcat,并通过Nginx进行代理,首先,下载并解压Tomcat压缩包,然后启动Tomcat并查看日志,接着,配置... 目录一、下载安装tomcat二、启动tomcat三、配置nginx总结提示:文章写完后,目录可以自动

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

详解Tomcat 7的七大新特性和新增功能(1)

http://developer.51cto.com/art/201009/228537.htm http://tomcat.apache.org/tomcat-7.0-doc/index.html  Apache发布首个Tomcat 7版本已经发布了有一段时间了,Tomcat 7引入了许多新功能,并对现有功能进行了增强。很多文章列出了Tomcat 7的新功能,但大多数并没有详细解释它们

Tomcat性能参数设置

转自:http://blog.csdn.net/chinadeng/article/details/6591542 Tomcat性能参数设置 2010 - 12 - 27 Tomcat性能参数设置 博客分类: Java Linux Tomcat 网络应用 多线程 Socket 默认参数不适合生产环境使用,因此需要修改一些参数   1、修改启动时内存参数、并指定J

TL-Tomcat中长连接的底层源码原理实现

长连接:浏览器告诉tomcat不要将请求关掉。  如果不是长连接,tomcat响应后会告诉浏览器把这个连接关掉。    tomcat中有一个缓冲区  如果发送大批量数据后 又不处理  那么会堆积缓冲区 后面的请求会越来越慢。