文章目录
web请求处理机制
1、多进程方式:服务器每接受到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务器资源耗尽而无法提供请求
2、多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程来个客户方进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定
同步和异步、阻塞与非阻塞:
1、同步与异步:主要是针对应用程序与内核的交互方式而言的:
同步:进程发出数据后,等内核返回响应以后才继续下一个请求,即如果内核一直不返回数据,那么进程就一直等,直到天荒地老,死机error。
异步:进程发出数据后,不等内核返回响应,接着处理下一个请求,Nginx是异步的
2.阻塞与非阻塞
可以理解为内核与IO设备的交互方式,当内核收到进程请求IO数据时候的处理方式
也可以简单理解为内核需要做一件事能不能立即得到返回应答,如果不能立即获得返回,需要等待,那就阻塞了,否则就可以理解为非阻塞
阻塞:IO调用不能立即返回结果,即一个进程发起的IO请求不能得到立即满足时,进程就要一直等到内核响应,内核要把数据从IO设备复制到内核空间,再返回给进程,这是阻塞。
非阻塞:IO调用可以立即返回结果,一个进程发起的IO进程不能立即满足时,不在等待,而是一遍一遍的轮训查看IO是否完成
I/O多路复用
如果一个I/O流进来,我们就开启一个进程处理这个I/O流。那么假设现在有一百万个I/O流进来,那我们就需要开启一百万个进程一一对应处理这些I/O流(——这就是传统意义下的多进程并发处理)。思考一下,一百万个进程,你的CPU占有率会多高,这个实现方式及其的不合理。所以人们提出了I/O多路复用这个模型,一个线程,通过记录I/O流的状态来同时管理多个I/O,可以提高服务器的吞吐能力
水平触发 如果你一直不去读写,它会一直通知你
边沿触发 它只会通知你一次
1.阻塞型IO
一直处在等待状态直到处理结束
举例子:一个厨师开了一家餐厅,负责店里的各种事情,客户去店里吃饭,要一直在厨师旁边等待,直到厨师把这位客户的菜完成
2.非阻塞型IO
不会一直处在等待状态,但是会时常回来查看
客户让厨师做菜,客户可以离开一会儿,但是客户会经常回来查看自己的饭菜好了没有
3.IO复用
SELECT 、POL Epoll
SELECT :有链接数限制1024并且要进行遍历
比如现在你不用一直等厨师做好饭菜,厨房师父只能处理1024个菜单,并且他在做好饭菜之后需要将每个人都看一遍,来知道这个菜是谁的
POLL:没有链接数的限制,但是仍然要进行遍历
厨房师父处理的菜单数量不限,但还是需要做好饭菜之后需要将每个人都看一遍,来知道这个菜是谁的
Epoll:不限制链接数,也不用进行遍历
厨房师父处理的菜单数量不限,而且不需要进行遍历,会给每个客户发一个号码,通过叫号,不需要进行一一遍历。
源码安装nginx
nginx大部分常用模块,编译时./configure --help以--without开头的都默认安装。
--prefix=PATH : 指定nginx的安装目录。默认 /usr/local/nginx
--conf-path=PATH : 设置nginx.conf配置文件的路径。nginx允许使用不同的配置文件启动,通过命令行中的-c选项。默认为prefix/conf/nginx.conf
--user=name: 设置nginx工作进程的用户。安装完成后,可以随时在nginx.conf配置文件更改user指令。默认的用户名是nobody。--group=name类似
--with-pcre : 设置PCRE库的源码路径,如果已通过yum方式安装,使用--with-pcre自动找到库文件。使用--with-pcre=PATH时,需要从PCRE网站下载pcre库的源码(版本4.4 - 8.30)并解压,剩下的就交给Nginx的./configure和make来完成。perl正则表达式使用在location指令和 ngx_http_rewrite_module模块中。
--with-zlib=PATH : 指定 zlib(版本1.1.3 - 1.2.5)的源码解压目录。在默认就启用的网络传输压缩模块ngx_http_gzip_module时需要使用zlib 。
--with-http_ssl_module : 使用https协议模块。默认情况下,该模块没有被构建。前提是openssl与openssl-devel已安装
--with-http_stub_status_module : 用来监控 Nginx 的当前状态
--with-http_realip_module : 通过这个模块允许我们改变客户端请求头中客户端IP地址值(例如X-Real-IP 或 X-Forwarded-For),意义在于能够使得后台服务器记录原始客户端的IP地址
--add-module=PATH : 添加第三方外部模块,如nginx-sticky-module-ng或缓存模块。每次添加新的模块都要重新编译(Tengine可以在新加入module时无需重新编译)
#1.下载nginx
#1.下载nginx
#2.tar zxf nginx-1.14.0.tar.gz
#3.cd nginx-1.14.0 ##讲解里面各目录的意义
1)auto目录:里面有4个子目录,cc是编译使用的,os是判断操作系统类型的,其他都是辅助configure编译的,也就是操作系统有什么特性供nginx使用
2)CHANGES:各版本的改变,bug修复等信息
CHANGES.ru:nginx作者是俄罗斯人,这是俄罗斯版本
3)conf: 为了方便运维配置,conf目录里有示例文件,安装好后会拷贝到安装目录
4)configure:
5)contrib:提供nginx语法检测字体
cp -r contrib/vim/* ~/.vim ##家目录下如果没有.vim目录,手动新建
6)html:默认发布目录,50x.html是报500错误时的页面
7) src:源码目录
8) 编译完成后会生成一个中间目录objs,里面有个ngx_modules.c,表示编译进nginx的模块,可以打开看一下
9)make完成后再看objs目录,又有新文件#2.tar zxf nginx-1.14.0.tar.gz
#3.cd nginx-1.14.0 ##讲解里面各目录的意义
1)auto目录:里面有4个子目录,cc是编译使用的,os是判断操作系统类型的,其他都是辅助configure编译的,也就是操作系统有什么特性供nginx使用
2)CHANGES:各版本的改变,bug修复等信息
CHANGES.ru:nginx作者是俄罗斯人,这是俄罗斯版本
3)conf: 为了方便运维配置,conf目录里有示例文件,安装好后会拷贝到安装目录
4)configure:
5)contrib:提供nginx语法检测字体
cp -r contrib/vim/* ~/.vim ##家目录下如果没有.vim目录,手动新建
6)html:默认发布目录,50x.html是报500错误时的页面
7) src:源码目录
8) 编译完成后会生成一个中间目录objs,里面有个ngx_modules.c,表示编译进nginx的模块,可以打开看一下
9)make完成后再看objs目录,又有新文件
1:nginx平滑升级、回退
升级
1)首先将之前的1.14版本的启动脚本备份
cd /usr/local/nginx/sbin
cp nginx nginx.old
2)再编译新版本1.15 ‘configure make结束不要make install,这会覆盖原来的nginx’
cd /root/nginx-1.15.8/objs
cp -f nginx /usr/local/nginx/sbin/nginx
3)向原来的nginx的master进程发送信号,不再接收新的请求,新的nginx程序开启worker进程,并且开始接收请求
kill -USR2 3607 ##这个时候ps -ef看到两个master进程和其对应的worker进程
kill -WINCH 3607 ##这个时候ps -ef看到老的worker进程结束,但master进程还在,不影响,是为了升级不成功时版本回退
4)执行/usr/local/nginx/sbin/nginx -v ##看到版本已经更新
/usr/local/nginx/sbin/nginx -V ##还可以看到编译的模块
回退
1)先还原nginx脚本
cd /usr/local/nginx/sbin
cp -f nginx.old nginx
2)重新唤起旧版本的master进程,让其接收请求
kill -HUP 3607 #-HUP相当于reload
3)让新版本的master进程不接收请求,关闭worker进程
kill -USR2 6146
kill -WINCH 6146
4)再查看nginx版本,回退到旧版本
/usr/local/nginx/sbin/nginx -v ##查看nginx版本
/usr/local/nginx/sbin/nginx -V ##查看nginx版本及编译参数等
一次全部编译
./configure --prefix=/usr/local/nginx --with-http_realip_module --with-http_image_filter_module=dynamic --with-http_ssl_module
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
nginx日志切割
因为nginx的access.log日志会保存所有客户端连接信息,普通网站每天请求量很大,所以要每天切割(可以用nginx自带的reopen)
1)先查看nginx的access.log日志大小
[root@server1 logs]# du -sh access.log
20K access.log
2)多次请求页面,再查看日志大小
[kiosk@foundation65 ~]$ ab -c 1 -n 100000 http://www.westos.org/index.html ##1个并发,100000次请
3)再次查看日志大小
[root@server1 logs]# du -sh access.log
16M access.log
4)首先保存之前的日志
[root@server1 logs]# mv access.log `date +%F -d -1day`_access.log ##因为第二天肯定是备份前一天的日志
[root@server1 logs]# /usr/local/nginx/sbin/nginx -s reopen
#发现重新生成了一个access.log,新的请求信息会到新日志里
#可以把命令写在crontab里,每天执行一次
systemd方式,nginx启动脚本
1)系统启动脚本都在/usr/lib/systemd/system目录下,但是自己配置的服务官方不建议放在此目录下,放在/etc/systemd/system目录下
2)用httpd服务启动脚本做参考
cp /usr/lib/systemd/system/httpd.service /etc/systemd/system/nginx.service
vim /etc/systemd/system/nginx.service
[Unit]
Description=The Nginx HTTP Server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true
[Install]
WantedBy=multi-user.target
3)启动nginx
systemctl start nginx
##nginx相关参数
1)最大连接数
worker_connections 65535 ##当nginx做反向代理时,这个数字要除以2来看最大连接数
2)然后查看系统最大打开文件数:
sysctl -a | grep file
fs.file-max = 200603 ##最大打开文件数为200603,一个连接也是一个文件(socket文件,linux思想一切皆文件)
3)查看系统默认打开文件数
ulimit -a
open files (-n) 1024 ##默认1024个
然后修改系统参数:
vim /etc/security/limits.conf
nginx - nofile 65535 ##加在最后
新建nginx用户:
useradd -M -d /usr/local/nginx -s /sbin/nologin nginx
我们经常会遇到这种情况,服务器流量异常,负载过大等等。对于大流量恶意的攻击访问,会带来带宽的浪费,服务器压力,影响业务,往往考虑对同一个ip的连接数,并发数进行限制
2)限制链接数 ##看管网,docs.nginx.com --> NGINX Plus --> Admin Guide --> Security Controls --> Limiting Access to Proxied HTTP Resources
vim nginx.conf
...ls
keepalive_timeout 65;
#gzip on;
#limit_conn_zone 用来限制同一时间连接数,即并发限制
#limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 “leaky bucket”
$binary_remote_addr是限制同一客户端ip地址
zone=one:10m表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息
# 定义一个名为addr的limit_conn_zone $binary_remote_addr是限制同一客户端ip地址
#以下两条语句写在server之上
limit_conn_zone $binary_remote_addr zone=addr:10m; #大小是10M内存 10M的内存来对于IP传输开销
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; #1s中不超过一个请求
...
location / {
root html;
index index.html index.htm;
}
location /download {
limit_conn addr 1; ##只能一个并发,多了会报错
limit_rate 50k; ##限制带宽,每秒最多50k
}
mkdir /usr/local/nginx/html/download
#给download目录里放一个vim.jpg(约400k)
ab -c 10 -n 1000 http://172.25.136.1/download/vim.jpg
##每次发送10个并发的请求数,请求数总数为100
[root@server1 logs]# cat access.log |grep 200
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
172.25.65.250 - - [12/Apr/2019:23:11:29 -0400] "GET /download/vim.jpg HTTP/1.0" 200 611847 "-" "ApacheBench/2.3"
@@@可以看到请求成功的200数量远远少于503的请求错误
如何让nginx获取源地址
通常上网访问路径(比如说用阿里云主机): client(172.25.0.1) --> ADSL(拨号上网192.168.0.1) --> cdn(10.0.0.1) --> SLB(阿里云负载11.0.0.1) --> nginx(12.0.0.1)
‘上面的ip都是举例,不是真实的’
./configure --prefix=/usr/local/nginx --with-http_realip_module #会报错 ,因为模块没有编译
vim nginx.conf
#在配置最后添加虚拟主机
server {
listen 80;
server_name server1.example.org;
set_real_ip_from 172.25.136.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on; ##这里off就获取不到源地址,可以先改为off看效果,再打开
location / {
return 200 "client real ip: $remote_addr\n";
}
}
#尝试访问
curl -H "X-Forwarded-For: 1.1.1.1,172.25.136.1" server1.example.org ##X-Forwarded-For可以保存每一级的ip头
结果可以获取到1.1.1.1这个ip
##深入:自己再开一台虚拟机模拟反向代理,测试这个配置是否生效
server1配置:###就写在配置文件本来的sever下面就行了
server {
listen 80;
server_name localhost;
set_real_ip_from 172.25.0.2;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
server2配置(做代理):
upstream westos {
server 172.25.0.101:80; #上游真实服务器
}
server {
listen 80;
server_name www.westos.org;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://westos;
}
}
测试:
再用物理机访问www.westos.org,然后在server1上查看access.log,可以看到请求来自172.25.136.250
不管一个系统或网站的大与小,都存在相应的图片处理,生成缩略图、为图片加水印等等,如果涉及到APP端,这个图片的处理需求变得更加重要了,因为在目前看来,客户端的屏幕大小不一,会导致以下问题:
1、图片过大导致APP加载图片速度慢;
2、消耗用户过多流量。
nginx图片过滤模块
图片过滤模块(有时一张高清图片太大,页面加载时间太长,需要压缩)
1.需要重新编译nginx
./configure --prefix=/usr/local/nginx --with-http_realip_module --with-http_image_filter_module=dynamic
编译报错,没有gd-devel包
yum list gd ##看到系统gd版本是2.0.35-26,所以自己下载的gd-devel也得是这个版本
yum install -y gd-devel-2.0.35-26.el7.x86_64.rpm
再编译
make && make install
cd /root/nginx-1.15.8/objs
cp nginx /usr/local/nginx/sbin/
静态模块需要手动新建目录,把模块放进去
mkdir /usr/local/nginx/modules
cp ngx_http_image_filter_module.so /usr/local/nginx/modules/
修改配置文件
load_module modules/ngx_http_image_filter_module.so; ##加在最开头
location /download/ {
limit_conn addr 1;
#limit_rate 50k;
#limit_req zone=one burst=5;
image_filter resize 150 100; #就是重新调整图片的尺寸(像素)
}
然后在浏览器上打开访问,没有变化先清理缓存
http://ip/download/vim.jpg #注意:路径一定要输入全
按F12,点击network->file可以看到图片大小变为不到2k,之前400多k
ssl模块
重新编译nginx
./configure --prefix=/usr/local/nginx --with-http_realip_module --with-http_image_filter_module=dynamic --with-http_ssl_module
/root/nginx-1.15.8/objs
cp nginx /usr/local/nginx/sbin
重新编译完,之前的模块需要再重新拷贝到模块目录,不然启动会报错
cp ngx_http_image_filter_module.so /usr/local/nginx/modules/
修改配置文件
vim nginx.conf
server {
listen 443 ssl;
server_name www.westos.org;
ssl_certificate cert.pem;
ssl_certificate_key cert.pem; ####注意注意:此处和配置文件默认的不同
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root /web;
index index.html index.htm;
}
}
可以先不写 与这个https的实验没有关系
server {
listen 80;
server_name www.westos.org;
location / {
root /web;
index index.html;
}
}
生成自签名证书
cd /etc/pki/tls/certs
make cert.pem
cn -> shaanxi -> xi'an -> westos -> linux-> server1 ##注意主机名字 -> root@westos.org
cp cert.pem /usr/local/nginx/conf/
mkdir /web
vim /web/index.html
server1.westos.org
nginx -s reload
浏览器访问
确认安全
在设置里选preference -> Advanced -> Certificates -> View Certificates
可以在里面找到自签名的证书