Java Web容器篇之Tomcat & Nginx
Java Web系列文章汇总贴: Java Web知识总结汇总TomcatTomcat的顶层架构Tomcat的两个核心组件:Connector & Container。多个Connector和一个Container就形成了Service,而Service包括整个Tomcat的生命周期由Server控制。Connector负责接受请求,Container负责处理这些请求,Ser...
Java Web系列文章汇总贴: Java Web知识总结汇总
Tomcat
Tomcat的顶层架构
Tomcat的两个核心组件:Connector & Container。
多个Connector和一个Container就形成了Service,而Service包括整个Tomcat的生命周期由Server控制。
Connector负责接受请求,Container负责处理这些请求,Service主要负责关联两者,同时会初始化它下面的其他组件。所有组件的声明周期在一个Lifecycle的接口中控制。
Server提供一个接口让其他程序能够访问到这个Service集合,同时要维护它包含的所有Service的生命周期,包括如何初始化、如何结束服务、如何找到别人要访问的Service。
Connector架构分析
Connector就是使用ProtocolHandler来处理请求的,不同的ProtocolHandler代表不同的连接类型,比如:Http11Protocol使用的是普通Socket来连接的,Http11NioProtocol使用的是NioSocket来连接的。
其中ProtocolHandler由包含了三个部件:Endpoint、Processor、Adapter。
(1)Endpoint用来处理底层Socket的网络连接,Processor用于将Endpoint接收到的Socket封装成Request,Adapter用于将Request交给Container进行具体的处理。
(2)Endpoint由于是处理底层的Socket网络连接,因此Endpoint是用来实现TCP/IP协议的,而Processor用来实现HTTP协议的,Adapter将请求适配到Servlet容器进行具体的处理。
(3)Endpoint的抽象实现AbstractEndpoint里面定义的Acceptor和AsyncTimeout两个内部类和一个Handler接口。Acceptor用于监听请求,AsyncTimeout用于检查异步Request的超时,Handler用于处理接收到的Socket,在内部调用Processor进行处理。
Container架构分析
4个子容器的作用分别是:
(1)Engine:引擎,用来管理多个站点,一个Service最多只能有一个Engine;
(2)Host:代表一个站点,也可以叫虚拟主机,通过配置Host就可以添加站点;
(3)Context:代表一个应用程序,对应着平时开发的一套程序,或者一个WEB-INF目录以及下面的web.xml文件;
(4)Wrapper:每一Wrapper封装着一个Servlet;
参考:
四张图带你了解Tomcat系统架构
Tomcat的系统架构与工作流程简介
Servlet的工作原理
Nginx
什么是C10K问题
C10K问题由来
随着互联网的普及,应用的用户群体几何倍增长,此时服务器性能问题就出现。最初的服务器是基于进程/线程模型。新到来一个TCP连接,就需要分配一个进程。假如有C10K,就需要创建1W个进程,可想而知单机是无法承受的。那么如何突破单机性能是高性能网络编程必须要面对的问题,进而这些局限和问题就统称为C10K问题,最早是由Dan Kegel进行归纳和总结的,并且他也系统的分析和提出解决方案。
C10K问题的本质
C10K问题的本质上是操作系统的问题。对于Web 1.0/2.0时代的操作系统,传统的同步阻塞I/O模型处理方式都是requests per second。当创建的进程或线程多了,数据拷贝频繁(缓存I/O、内核将数据拷贝到用户进程空间、阻塞,进程/线程上下文切换消耗大, 导致操作系统崩溃,这就是C10K问题的本质。
可见, 解决C10K问题的关键就是尽可能减少这些CPU资源消耗。
C10K问题的解决方案
从网络编程技术的角度来说,主要思路:
- 每个连接分配一个独立的线程/进程
- 同一个线程/进程同时处理多个连接
摘自:
C10K问题
正向代理和反向代理
正向代理:
正向代理通过下面的图理解其实就是用户想从服务器拿资源数据,但是只能通过proxy服务器才能拿到,所以用户A只能去访问proxy服务器然后通过proxy服务器去服务器B拿数据,这种情况用户是明确知道你要访问的是谁,在我们生活中最典型的案例就是“翻墙“了,也是通过访问代理服务器最后访问外网的。
反向代理:
反向代理其实就是客户端去访问服务器时,他并不知道会访问哪一台,感觉就是客户端访问了Proxy一样,而实则就是当proxy关口拿到用户请求的时候会转发到代理服务器中的随机(算法)某一台。而在用户看来,他只是访问了Proxy服务器而已,典型的例子就是负载均衡了。
图示:
参考:
谈一谈正向代理和反向代理
Nginx中常用的几种负载均衡策略
策略 | 释义 |
---|---|
轮询 | 默认方式 |
weight | 权重方式 |
ip_hash | 根据ip分配方式 |
least_conn | 最少连接方式 |
fair(第三方) | 响应时间方式 |
url_hash(第三方) | 根据URL分配方式 |
扩展:Web的负载均衡策略
几种负载均衡方式
- HTTP重定向实现负载均衡
- DNS负载均衡
- 反向代理负载均衡
负载均衡组件
- apache
- nginx
- lvs
- HAProxy
- keepalived
常见的几种负载均衡算法
- 1、轮询
- 2、加权轮询
- 3、随机
- 4、加权随机
- 5、Hash法:根据客户端的IP,或者请求的“Key”,计算出一个hash值,然后对节点数目取模
- 6、最少连接
更多:
高并发解决方案之一 ——负载均衡
Web应用的负载均衡、集群、高可用(HA)解决方案整理总结
关于负载均衡的一切:总结与思考
Nginx架构及工作原理
Nginx架构
大致上Nginx的架构就是这样:
1.Nginx启动后,会产生一个主进程,主进程执行一系列的工作后会产生一个或者多个工作进程;
2.在客户端请求动态站点的过程中,Nginx服务器还涉及和后端服务器的通信。Nginx将接收到的Web请求通过代理转发到后端服务器,由后端服务器进行数据处理和组织;
3.Nginx为了提高对请求的响应效率,降低网络压力,采用了缓存机制,将历史应答数据缓存到本地。保障对缓存文件的快速访问;
工作进程
工作进程的主要工作有以下几项:
- 接收客户端请求;
- 将请求一次送入各个功能模块进行过滤处理;
- IO调用,获取响应数据;
- 与后端服务器通信,接收后端服务器处理结果;
- 数据缓存
- 响应客户端请求;
进程交互
Nginx服务器在使用Master-Worker模型时,会涉及到主进程和工作进程的交互和工作进程之间的交互。这两类交互都依赖于管道机制。
1.Master-Worker交互
这条管道与普通的管道不同,它是由主进程指向工作进程的单向管道,包含主进程向工作进程发出的指令,工作进程ID等;同时主进程与外界通过信号通信;
2.worker-worker交互
这种交互是和Master-Worker交互是基本一致的。但是会通过主进程。工作进程之间是相互隔离的,所以当工作进程W1需要向工作进程W2发指令时,首先找到W2的进程ID,然后将正确的指令写入指向W2的通道。W2收到信号采取相应的措施。
Nginx优化
Nginx与Apache
Nginx特点
- epoll 异步非阻塞
- nginx在开启时,会生成一个master进程,然后,master进程会fork多个worker子进程,最后每个用户的请求由worker的子线程处理。
- 可以配置nginx的upstream实现nginx的反向代理。
- 支持7层负载均衡
- 静态文件、反向代理、前端缓存等处理方便
- 支持高并发连接,每秒最多的并发连接请求理论可以达到 50000 个
- 配置文件简单
- 用线程处理用户请求,而线程是共享内存的,只需要开启少量进程,多个线程就可以共享进程的内存,占用内存小
- 一个进程死掉时,会影响到多个用户的使用,稳定性差
Apache特点
- 稳定
- rewrite强大
- select 同步阻塞
- 一个连接对应一个进程
- 用进程处理用户请求,用MPM(多处理模块)来绑定到网络端口上,接受请求,调度子进程处理请求
- 当用户请求过多时,开启的进程较多,占用内存大,每秒最多的并发连接请求最多不超过 3000 个
- 一个进程死掉时,不会影响其他的用户
Nginx模块化
-
(1)核心模块;
核心模块是Nginx服务器正常运行必不可少的模块,如同操作系统的内核。它提供了Nginx最基本的核心服务。像进程管理、权限控制、错误日志记录等; -
(2)标准HTTP模块;
标准HTTP模块支持标准的HTTP的功能; -
(3)可选HTTP模块;
可选HTTP模块主要用于扩展标准的HTTP功能,让Nginx能处理一些特殊的服务; -
(4)邮件服务模块;
邮件服务模块主要用于支持Nginx的邮件服务; -
(5)第三方模块;
第三方模块是为了扩展Nginx服务器应用,完成开发者想要的功能;
Nginx配置
#运行用户
user nobody;
#启动进程,通常设置成和cpu的数量相等
worker_processes 1;
#全局错误日志及PID文件
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
#工作模式及连接数上限
events {
#epoll是多路复用IO(I/O Multiplexing)中的一种方式,
#仅用于linux2.6以上内核,可以大大提高nginx的性能
use epoll;
#单个后台worker process进程的最大并发链接数
worker_connections 1024;
# 并发总数是 worker_processes 和 worker_connections 的乘积
# 即 max_clients = worker_processes * worker_connections
# 在设置了反向代理的情况下,max_clients = worker_processes * worker_connections / 4 为什么
# 为什么上面反向代理要除以4,应该说是一个经验值
# 根据以上条件,正常情况下的Nginx Server可以应付的最大连接数为:4 * 8000 = 32000
# worker_connections 值的设置跟物理内存大小有关
# 因为并发受IO约束,max_clients的值须小于系统可以打开的最大文件数
# 而系统可以打开的最大文件数和内存大小成正比,一般1GB内存的机器上可以打开的文件数大约是10万左右
# 我们来看看360M内存的VPS可以打开的文件句柄数是多少:
# $ cat /proc/sys/fs/file-max
# 输出 34336
# 32000 < 34336,即并发连接总数小于系统可以打开的文件句柄总数,这样就在操作系统可以承受的范围之内
# 所以,worker_connections 的值需根据 worker_processes 进程数目和系统可以打开的最大文件总数进行适当地进行设置
# 使得并发总数小于操作系统可以打开的最大文件数目
# 其实质也就是根据主机的物理CPU和内存进行配置
# 当然,理论上的并发总数可能会和实际有所偏差,因为主机还有其他的工作进程需要消耗系统资源。
# ulimit -SHn 65535
}
http {
#设定mime类型,类型由mime.type文件定义
include mime.types;
default_type application/octet-stream;
#设定日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
#sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,
#对于普通应用,必须设为 on,
#如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,
#以平衡磁盘与网络I/O处理速度,降低系统的uptime.
sendfile on;
#tcp_nopush on;
#连接超时时间
#keepalive_timeout 0;
keepalive_timeout 65;
tcp_nodelay on;
#开启gzip压缩
gzip on;
gzip_disable "MSIE [1-6].";
#设定请求缓冲
client_header_buffer_size 128k;
large_client_header_buffers 4 128k;
#设定虚拟主机配置
server {
#侦听80端口
listen 80;
#定义使用 www.nginx.cn访问
server_name www.nginx.cn;
#定义服务器的默认网站根目录位置
root html;
#设定本虚拟主机的访问日志
access_log logs/nginx.access.log main;
#默认请求
location / {
#定义首页索引文件的名称
index index.php index.html index.htm;
}
# 定义错误提示页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
#静态文件,nginx自己处理
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
#过期30天,静态文件不怎么更新,过期可以设大一点,
#如果频繁更新,则可以设置得小一点。
expires 30d;
}
#PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
#禁止访问 .htxxx 文件
location ~ /.ht {
deny all;
}
}
}
更多推荐
所有评论(0)