文章目录
Nginx
一、基础概念
-
Nginx是一个高效的HTTP和反向代理服务器。作用于动静分离、API服务器和反向代理。反向代理里有负载均衡和缓存等功能。支持高并发5w/s,与keepalived联合使用支持高可用。
-
优点:高性能,支持高并发、高可用,多模块和热部署。
高性能的原因:多进程单线程结构,io多路复用。
高可用,防止单点故障。可以配合keepalived一起使用
与Apache的区别Apache则是一个进程对应一个连接,进程的创建切换是非常耗费资源低效的,代价太高,不可能应对几万几十万的流量。
-
日志文件
配置文件nginx.conf、访问日志access.log和错误日志error.log。
查看日志的工具goAccess
-
动静分离,api服务
比如一个静态文件,html,css等可以直接由Nginx服务器提供服务,充当静态服务器,
若涉及简单的缓存服务器,比如redis,也可以提供api服务去调用缓存服务器。
OpenResty是对Nginx的封装,有很多lua语言的模块。
-
正向代理和反向代理
nginx可以7也可以4层
4层用的是NAT技术
7层代理:需要读取并解析http请求内容,双向建立http连接,3次握手4次挥手
它的反向代理有7层和4层,7层有http,cgi,fastcgi等,简单的memcached。4层tcp,udp等。使用的steam模块。对客户端Http,对真实服务器各自的。
CGI程序的每一次web请求都会有启动和退出过程,也就是最为人诟病的fork-and-execute模式。
fastcgi使用FastCGI进程管理器, 启动多个CGI解释器进程(php-cgi),等待来自Web Server的连接。
正向代理通俗的说是代理客户端的,对于用而言需要配置代理服务器的相关信息。比如访问谷歌需要的特殊软件。对于服务器是透明的,服务器不知道真实的请求人是谁。反向代理是代理的是服务器,有反向代理服务器来决定请求由哪个具体的服务器处理。这个过程对于用户是无感的,客户不知道真实的服务器是哪台。
下图所示,正向代理,代理服务器和客户端是一个整体。而反向代理相反。
-
缓存
Nginx缓存有proxy-store、proxy-cache和memcached
1.proxy-cache更加高级,存储路径设置,内存+磁盘,内存实际上是建立索引文件key,实际文件在磁盘,这都是在Nginx初始化的时候做的事情。同时它还有一些功能,比如什么情况不读取缓存,什么情况不缓存等,设置过期时间等高级功能,还有就是建立缓存索引和更新缓存。
2.proxy-store可以理解是一个缓存镜像,仅仅缓存,没有就请求后端。不支持高级功能。
3.memcached是一个缓存应用,在Nginx是可以作为一个简单的七层代理,可以简单的获取值。可以作为缓存功能。
1、强缓存Expires、Cache-Control,协商缓存etag和if-none-match, last-modifid(服务端)和if-modified-since(客户端)。304,200
Nginx缓存有proxy-store、proxy-cache和memcached
二、进阶理论
1、多进程单线程结构,io多路复用
-
多进程单线程
nginx是多进程单线程的,一主master多从worker。
master进程,管理和创建工作进程,接受信号等。起到一个全局管理者,一个进程挂了,则主进程会里面生成一个新的工作进程。
worker进程,接受并处理连接。与cpu核心数一致。
cache manager进程 :管理缓存
cache loader进程:启动的时候,加载缓存。加载完就退出了。
nginx是多进程单线程结构,而不是基于一个进程的多线程。
原因:
1、多线程模型中,某个线程的中断错误,会导致整个进程挂掉,这不符合nginx高可用高可靠的设计
2、多线程有共享同一个地址空间,会产生锁等,阻塞等各种原因。效率不高。
并发数,worker的个数*最大连接数之后除以2或者4
-
io多路复用
一主master多从worker的。一般worker的与CPU核数一致最好。一个worker有一个主线程是来处理请求的,而该线程使用的IO多路复用,具体的事件驱动模型是epoll。
linux一切皆文件
一个连接过来就会有一个文件描述符FD
IO多路复用,就是用一个线程去监听多个socket。
select、poll、epoll
1、select存放文件描述符有限,1024,使用bitmap。结构体不可重用。每次都全部遍历。每次都复制到内核态。
2、poll则解决了数量和结构体重用,使用链表,但是还是要复制(用户到内核的开销)和遍历O(n)。
3、epoll使用红黑树解决了数量和重用的问题,使用共享内存解决了用户态和内核态复制的问题。
epoll的结构
epoll_create:创建一个eventpoll结构体,里面有2个重要的数据结构,红黑树和链表
epoll_ctl:每一个连接都是一个文件描述符fd,则调用control方法可以对fd增删改,并添加事件回调函数,有读写事件发生的时候,就放入到就绪队列中。
epoll_wait:返回就绪队列中的,也就是有读写事件的fd,给线程去处理。
水平触发:读写事件,若缓冲区还有数据没读,或者没写完,下次epoll_wait继续返回该fd。
边缘触发:读写事件,若缓冲区还有数据没读,或者没写完,下次epoll_wait不再继续返回该fd,直到有新的读写事件才会返回fd。
- 惊群
原因:
一个socket的新连接进来,多个进程都想去accpet() 到这个连接,但只有一个进程能成功,这会消耗系统资源
解决:Nginx提供了一个accept_mutex这个东西,这是一个加在accept上的一把互斥锁。即每个worker进程在执行accept()之前都需要先获取锁,accept()成功之后再解锁。有了这把锁,同一时刻,只会有一个进程执行accpet(),这样就不会有惊群问题了。
accept_mutex是一个可控选项,我们可以显示地关掉,默认是打开的
2、负载均衡算法
-
算法
它是指将请求负载分发到各个不同的服务器中
Nginx的分发规则有
轮询,加权轮询:平均的轮到每一个。加权之后,有的机器性能好,可以加权重,使其承担更多。
iphash:根据请求ip进行hash,支持session。普通就是对个数取模,更优秀的是一致性哈希。
least最少链接数
fair最短处理时间
lvs: 轮询、加权轮询、基于请求ip的hash,基于目标ip的hash,最少链接,加权最少链接操作系统的进程调度:先来先服务,最短处理时间,时间片、优先级。
3、内存管理
-
内存池是在真正使用内存之前,预先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够用时**,再继续申请新的内存**。内存池的好处有减少向系统申请和释放内存的时间开销,解决内存频繁分配产生的碎片,提示程序性能,减少程序员在编写代码中对内存的关注等。
nginx为每一个层级都会创建一个内存池,进行内存的管理,比如一个模板,tcp连接,http请求等,在对应的生命周期结束的时候会摧毁整个内存池,把分配的内存一次性归还给操作系统。 -
内存池的结构中有三个链表,分别是小数据的next指针,大数据的large指针和清洗数据的cleanup指针,分别都是一个链表。
-
连接池,worker_connections
4、通信—共享内存
-
worker进程之间的通信方式,比如一些fair策略的时候,共享这个信息。
-
内存的管理,SLAB内存管理器。那么内存的管理是基于BESTFIT策略,其中每页中的Slot就是为了内存对齐;共享内存,worker之间通信,比如负载均衡的最小相应时间策略fair,都是基于共享内存。
5、通信—信号管理
- 各个指令
名字 | 信号(kill) | 命令行 |
---|---|---|
直接退出 | TERM / INT | stop |
优雅的退出 | QUIT | quit |
重载配置文件 | HUP | reload |
日志切割 | USR1 | reopen |
热部署 | USR2 | |
让老master进程 发送信息 关闭老worker | WINCH |
-
热加载配置文件的流程
-
热部署的流程
三、模块和优化
1、http请求的11个过程
typedef enum {
NGX_HTTP_POST_READ_PHASE = 0, // 接收到完整的HTTP头部后处理的阶段
NGX_HTTP_SERVER_REWRITE_PHASE, // URI与location匹配前,改动URI的阶段,用于重定向
NGX_HTTP_FIND_CONFIG_PHASE, // 依据URI寻找匹配的location块配置项
NGX_HTTP_REWRITE_PHASE, // 上一阶段找到location块后再改动URI
NGX_HTTP_POST_REWRITE_PHASE, // 防止重写URL后导致的死循环
NGX_HTTP_PREACCESS_PHASE, // 下一阶段之前的准备
NGX_HTTP_ACCESS_PHASE, // 让HTTP模块推断是否同意这个请求进入Nginx服务器
NGX_HTTP_POST_ACCESS_PHASE, // 向用户发送拒绝服务的错误码,用来响应上一阶段的拒绝
NGX_HTTP_TRY_FILES_PHASE, // 为訪问静态文件资源而设置
NGX_HTTP_CONTENT_PHASE, // 处理HTTP请求内容的阶段,大部分HTTP模块介入这个阶段
NGX_HTTP_LOG_PHASE // 处理完请求后的日志记录阶段
} ngx_http_phases;
简化版本的过程
0.listen、内存池
1.rewrite:找到location;rewrite指令修改url,return返回新url。
2.鉴权和限流:
限流limit_rate,指定向客户端传输数据的速度;
限制并发数limit_conn,进行流量缓冲limit_req等,burst=5,设置了一个大小为5的缓冲队列,在缓冲队列中的请求会等待慢慢处理;
控制访问ip等,白名单黑名单
权限控制等;
3.请求后端:请求真实服务器,注意2点,请求内容和相应内容是否等待全部加载完。
4.过滤,对响应的内容进行修改,比如替换,新增相应头,gzip压缩等。日志:记录日志。
2、常见模块
upstream代理模块 ngx_http_upstream_module模块
缓存模块proxy_cache,proxy_store
还有就是简化过程中的各个步骤,如rewrite
gzip压缩模块ngx_http_gzip_module
ssl安全连接模块ngx_http_ssl_module
3、nginx优化
1、硬件
扩容机器,参数更高
2、软件
- CPU:解决惊群问题。分情况使用zip压缩,静态资源提前压缩。
- 内存:小数据块的空间利用率不高。还有sendfile,用户态和内核态来回切换。
- 磁盘IO:分片,客户端只要断点下载的时候,不需要全部下载到硬盘,硬盘转到内存。
4、高可用,高并发
本身高可用
多进程,一个worker挂了,master会里面生成一个新的。
主备的高可用
可以使用使用keepalived和Nginx,vrrp心跳检查来主备。
--检测脚本,主要是判断Nginx是否存活
vrrp_script chk_http_port {
script "/usr/local/src/nginx_check.sh"
interval 2 #(检测脚本执行的间隔)
weight 2
}
>--虚拟IP的配置
vrrp_instance VI_1 {
state BACKUP # 主还是备MASTER
priority 100 # 主备优先级
virtual_ipaddress {
192.168.17.131/24 dev ens33 label ens33:1 # 虚拟的IP,主备一致
}
}
高并发和高可用
根据lvs和keepalived的联合使用实现高可用,对多台Nginx进行负载均衡实现高并发。
前4后4,具体看LVS和keepalived基础笔记——简单明了。
四、配置文件
1、静态服务器
#user nobody;
worker_processes 2;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
# 新服务(静态网站)
server {
location / {
root /data/www;
index index.html index.php;
}
location /movie/ {
root /data1; # 加上movie
}
location /images/ {
alias /data2;# 不加上images,去除location配置的路径
}
}
}
2、api调用
本身自己就一个服务器,提供api调用。利用openresty提供lua语言的一个服务器,lua语言可以编写逻辑进行处理。
3、反向代理-负载均衡-缓存
#定义nginx运行的用户和用户组
user qsm qsm;
#设置nginx进程数,一般设置为cpu核心数,auto为自动检测
worker_processes auto;
error_log /var/log/nginx/error.log;
events {
#单个进程最大连接数(最大连接数=连接数*进程数)
worker_connections 2048;
#设置用于复用客户端线程的轮训方法
use epoll;
#设置网路连接序列化,防止惊群现象发生,默认为on
accept_mutex on;
}
http {
#文件扩展名与文件类型映射表
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"';
#设置nginx是否存储访问日志,关闭这个可以让读取磁盘IO操作更快
access_log /var/log/nginx/access.log main;
#开启高效文件传输模式,优化磁盘IO设置
sendfile on;
#设置nginx在一个数据包里发送所有头文件,而不是一个接一个的发送
tcp_nopush on;
# HTTP1.1支持持久连接alive
# 降低每个连接的alive时间可在一定程度上提高可响应连接数量,所以一般可适当降低此值
keepalive_timeout 60;
#压缩
#gzip on;
#缓存地址
proxy_cache_path /path/to/cache levels=1:2 keys_zone=mycache:10m max_size=10g inactive=60m use_temp_path=off;
upstream insure_server_upstream {
ip_hash;
server 192.168.11.68:20201;
server 192.168.11.69:20201 weight=100 down;
server 192.168.11.70:20201 weight=100;
server 192.168.11.71:20201 weight=100 backup;
server 192.168.11.72:20201 weight=100 max_fails=3 fail_timeout=30s;
}
upstream express_server_upstream {
server 192.168.11.30 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.11.31 weight=5 max_fails=3 fail_timeout=30s;
}
#虚拟主机配置
server {
listen 80;
#多域名用空格隔开
server_name localhost qsm.net www.qsm.net;
#设置默认访问首页
index index.php index.html;
#默认编码
charset utf-8;
#定义本虚拟主机的访问日志
access_log logs/access.log;
location /jd/insure {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#使用缓存,默认get和head缓存
proxy_cache mycache;
proxy_cache_key $scheme$proxy_host$request_uri;
proxy_pass http://insure_server_upstream; #引用upstream
}
location /jd/express {
proxy_pass http://express_server_upstream; #引用upstream
}
#错误设置
error_page 500 502 503 504 /404.html;
location = /404.html {
root html;
}
}
#虚拟主机配置
server {
listen 8080;
#多域名用空格隔开
server_name localhost qsm.net www.qsm.net;
#设置默认访问首页
index index.php index.html;
#默认编码
charset utf-8;
#定义本虚拟主机的访问日志
access_log logs/access.log;
location /jd/insure {
proxy_pass http://insure_server_upstream; #引用upstream
}
location /jd/express {
proxy_pass http://express_server_upstream; #引用upstream
deny 127.0.0.1; #拒绝的ip
allow 172.18.5.54; #允许的ip
}
#错误设置
error_page 500 502 503 504 /404.html;
location = /404.html {
root html;
}
}
}
4、配置格式
1、配置文件的全局块:配置服务器整体运行的配置指令,比如worker的个数
2、events块:影响 Nginx 服务器与用户的网络连接,比如每个worker的最大连接数等
3、http 块
1、http 全局块:日志(格式、位置等)自定义等配置
2、server 块:相当于一个虚拟服务器,配置监听本虚拟主机的名称或IP配置等
1、location 块(多个):根据请求路径正则判断给不同的真实服务器请求。proxy_pass
查看版本号:./nginx -v
启动: ./nginx
停止: ./nginx -s stop
重新加载: ./nginx -s reload
以上都是在sbin命令中
【完】
喜欢就个赞吧
正在去BAT的路上修行