Web服务器常指的是(world wide web ,www)服务器、也是HTTP服务器,主要用于提供网上信息浏览。
我们大部分人接触互联网,都基本上是通过浏览器访问互联网中各种资源。
Web 网络服务是一种被动访问的服务程序,即只有接收到互联网中其他主机发出的 请求后才会响应,最终用于提供服务程序的 Web 服务器会通过 HTTP(超文本传输协议)或 HTTPS(安全超文本传输协议)把请求的内容传送给用户。
Unix和Linux平台下的常用Web服务器常见有:
其中最为广泛的是Nginx,在Windows平台上最常用的是微软的IIS(Internet Information Server,互联网信息服务)是 Windows 系统中默认的 Web 服务程序。
Apache是世界主流的Web服务器,世界上大多著名网站都是Apache搭建,优势在于开放源代码,开发维护团队强大、支持跨平台应用(Unix、Linux、Windows),强大的移植性等优点。
Apache属于重量级产品,功能以模块化定制,消耗内存较高,性能稍弱于其他轻量级Web服务器。
Lighttpd是一款高安全性、快速、且灵活的Web服务器产品,专为高性能环境而设计,相比其他Web服务器,内存占用量小,能够有效管理CPU负载,支持(FastCGI、SCGI,Auth,输出压缩,url重写,别名)等重要功能,是Nginx的重要对手之一。
Tomcat是一个开源、运行基于Java的Web应用软件的容器,Tomcat Server根据servlet和JSP规范执行,但是Tomcat对于平台文件、高并发处理较弱。要使用Tomcat需要对Java的应用部署有足够的了解。
WebSphere Applicaiton Server是一种强大的Web应用服务器,基于Java的应用环境、建立、部署和管理网站应用。
微软的IIS是一种灵活,安全易管理的Web服务器,从流媒体到Web应用程序,IIS提供了图形化的管理界面,用于配置和管理网络服务。
IIS是一整套Web组件,包含了Web服务器,FTP服务器,SMTP服务器等常用的网页浏览、文件传输,邮件新闻等功能。
缺点是只能运行在Windows平台,还得购买商业化的操作系统。
Nginx是俄罗斯人Igor Sysoev(伊戈尔·塞索耶夫)开发的一款高性能的HTTP和反向代理服务器。
Nginx以高效的epoll、kqueue、eventport作为网络IO模型,在高并发场景下,Nginx能够轻松支持5w并发连接数的响应,并且消耗的服务器内存、CPU等系统资源消耗却很低,运行非常稳定。
国内著名站点,新浪博客、网易、淘宝、豆瓣、迅雷等大型网站都在使用Nginx作为Web服务器
或是反向代理服务器
。
在互联网的快速普及,全球化、物联网的迅速发展,世界排名前3的分别是Apache、IIS、Nginx,而Nginx一直在呈现增长趋势。
官方提供的测试数据,Nginx能支持5W的并发连接,在实际生产环境下可支撑2~4W的并发连接数。
Apache使用的网络I/O模型是传统的select模型,以Prefork多进程模式运转,需要经常派生子进程,消耗系统资源要比Nginx高得多。且一个进程在同一时间只会处理一个请求。
如Apache Web Server支撑这日均千万PV的网站,服务器平均负载在50~60,CPU消耗在70%~90%,而整体迁移到Nginx后,系统平均负载降低至1~4,CPU使用率在20%~40%,效果可见。
常见LNMP(linux、Nginx、Mysql、PHP)服务器在3万并发连接下,开启10个Nginx进程消耗不过(15MB*10=150MB)
内存。就算开启64个php-cgi进程,也就消耗20MB*64=1280MB
,总共后台进程使用不到2GB内存,且服务器如果内存较小,开启php-cgi进程数量可以再少点。
在压力测试,3W的并发连接下,Nginx+PHP的程序任然能够飞速运转,从Nginx的日志统计下(每分钟的第15秒有多少条日志),单机处理请求能力在700次/秒,那么日承受访问量在700*60*60*24=6048,0000
,且服务器的负载不会太高。
Nginx强大功能其一在于反向代理、负载均衡,属于是软件负载均衡,企业购买硬件的F5、NetScaler
等硬件负载均衡设备价格昂贵,而Nginx属于开源软件,遵循BSD协议,可以免费试用,甚至二次开发用于商业用途。
BSD协议指的是给与用户更自由的协议,可以自由试用、修改源代码
内核空间/用户空间
内核:操作系统的核心是内核,独立于普通的应用程序,可以操作底层硬件,处理受保护的内存空间。
操作系统为了保护内核,使得用户进程无法直接操作内核(kernel),操作系统单独开辟了两个虚拟内存空间,一是内核空间,二是用户空间。
进程切换
为了控制进程执行,操作系统内核得有能力挂起CPU上运行的进程,或是恢复之前已挂起的进程,这种行为称之为进程切换。
进程阻塞
正在执行的进程,由于某些事件的等待,如请求资源加载中,资源加载失败等,系统自动执行阻塞语句,block,让该进程处于阻塞状态,因此进程的阻塞是一种主动行为,因此也之后又处于运行状态的进程(获取到CPU)才能转变为阻塞状态,阻塞状态下不吃CPU资源。
文件描述符
这是计算机科学里的一个术语,表述指向文件引用的一个抽象概念。它是一个索引值,指向内核为每一个进程打开文件的记录表。
程序打开一个文件,系统内核就向该进程发送一个文件描述符。
Linux IO模型
数据的IO操作,例如读取文件,数据会被拷贝到操作系统内核的缓冲区,然后从缓冲区拷贝到应用程序的内存空间。
一个读取操作,经历两个阶段
1.等待数据准备
2.数据从内核拷贝到进程
对于网络IO
1.等待网络上的数据分段到达,然后复制到内核的缓冲区
2.数据从内核缓存区拷贝到进程
网络应用主要处理两个问题,网络IO,数据计算
网络IO的延迟等待,是最主要的性能瓶颈。
为何选择Nginx,重点在于网络模型的区别
常见的IO模型
网络IO指的是输入、输出,本质上是socket读取,socket在linux中被抽象为流,IO就是对流的操作。
超哥和媳妇在麦当劳点餐,点过之后不知道什么时候能做好,只能坐在餐厅等待,直到用餐结束才离开。
但是媳妇其实还想去买个包包的,但是不知道饭菜什么时候好,只能慢慢等,浪费了时间,也没去逛街买包。
在linux下默认所有的socket都是blocking阻塞的,阻塞指的是进程被等待了,CPU处理其他任务了。
用户进程调用recv()进行系统调用,内核开始IO第一个阶段,准备数据(网络IO情况下,内核要等待所有数据接收完毕)。
这个过程指的是,数据拷贝到操作系统内核是需要一定时间的。
用户进程这里整个进程被阻塞,当内核数据准备好之后,将数据从内核中再拷贝到用户内存,内核返回结果后,用户进程解除block阻塞状态,重新运行。
同步阻塞IO特点是,IO执行的2个阶段都是阻塞的,用户空间发起调用,内核准备数据阻塞,内核拷贝数据到用户空间阻塞。
同步阻塞模型,优/缺点是
1.能够及时返回数据,无延迟
2.对于开发人员负担较低
3.对用户不友好,性能较弱
超哥和媳妇还是在麦当劳,点好了餐,但是不愿意白等着,又想去逛会商场,又害怕餐好了来迟了。
因此我们去逛一会,回来问一下客服,餐做好没
没好的话,待会再来问一遍
同步非阻塞就是每隔一会检索一次
的轮询polling方式。
在网络IO时候,非阻塞IO同样进行recvform系统调用,且检查数据是否准备好了,这里和阻塞IO不一样,非阻塞模式将整个阻塞时间片
拆分成N小的阻塞,CPU仍有机会不断的操作该进程。
当用户进程发起read操作,内核若是没有数据,不会立即阻塞用户进程,而是立即返回了error报错
对于用户进程而言,这就不再是等待了,而是立即有了一个结果,已知是error的时候,知道了数据还未准备好,于是再次发起系统调用。
一旦内核准备好了数据,且在此收到用户的系统调用,内核立即将数据拷贝到用户内存,然后返回给用户进程。
区别就在于发起recvfrom时候的阻塞拆分了,用户进程需要不断的主动询问内核数据是否准备好
同步阻塞和非阻塞的区别
非阻塞优点是,能够在等待某一任务的时间里继续处理其他任务,也包括继续提交新任务
非阻塞缺点缺点是:任务完成的延迟变大,因为要多次轮询系统调用操作,而有可能任务就在轮询过程中完成了,造成整体数据吞吐量降低。
超哥还是和媳妇在餐厅吃饭点餐,这回餐厅装了电子屏,可以显示食物制作进度,这样超哥和他媳妇逛街一回,回来不用再去问服务员了,可能服务员压根不想理你呢,直接看电子屏即可快速知道结果
由于刚才所说的同步非阻塞
需要不断的主动轮询,轮询会消耗大量CPU时间。
计算机系统后台可能存在N个任务,如果能循环的查询多个任务的进度,并且这个轮询还不是用户进程发起的(不是超哥反复回来询问),而是有人帮忙查询,那可太方便了。
因此Linux下的select、poll、epoll就是做这个事的,且epoll效率最高
select
select轮询方式
和非阻塞轮询
区别在于
select轮询可以同时监听多个socket,当一个socket的数据准备好了,即可进行IO操作,进程发起recvform系统调用,将数据由内核拷贝到用户进程,这个过程是阻塞的。
但是这里的select或是poll阻塞进程,和同步IO的阻塞不一样,同步IO的阻塞是数据全部准备好,一次性处理,而select是有一部分数据就调用用户进程来处理。
IO多路复用,就是轮询多个socket,好比餐厅的电子屏,监控着多个食品订单的完成情况
IO多路复用指的就是linux下的select,poll,epoll,也被称作事件驱动IO
它们的好处在于:单进程就可以同时处理多个socket连接。原理就是select,poll,epoll这个函数会不断的轮询负责的所有socket,当某个socket有数据到达了,就通知用户进程。
当用户进程调用了select这个函数,整个进程就会被阻塞了,kernel内核会监视所有select负责的socket,有一个socket准备好了数据,select就返回给用户进程,用户进程发起系统调用,数据拷贝到用户进程。
其实IO多路复用和阻塞IO并没有太大的区别,有可能还更差一点,因为还额外的调用了select,有了额外的消耗。好处就是select可以同时处理多个连接。
如果连接数不是很多的情况下,用IO多路复用还不如使用(多线程+阻塞IO)的性能更好。
IO多路复用优势在于同时处理更多的连接,而不是处理速度
超哥媳妇不想逛街了,又不想在餐厅等着,因此他俩直接选择回家休息。拿起手机点外卖,饭好了外卖员直接送到家,这也太舒服了,又不用干等着,还能做些别的事,饭菜就能送来了。
用户进程发起aio_read系统调用,无论内核数据是否准备好,都会直接返回给用户进程,用户进程可以继续做其他事情。等待socket数据准备好了,内核直接复制给用户进程,接着向进程发出通知,整个过程都是非阻塞的。
1.阻塞和非阻塞的区别
阻塞IO会一直阻塞对应的进程,直到数据操作完毕,
非阻塞IO在内核准备数据阶段就立刻返回
2.同步IO和异步IO的区别
区别在于,同步IO在IO操作的时候会被进程阻塞,blocking io,non-blocking io,IO multiplexing都属于同步IO
异步IO,在进程发起IO操作之后,内核就直接返回了,直到内核发送一个信号,告诉进程IO完成了,整个进程完全没有被阻塞。
Nginx如今分为商业版,开源版,支持Linux与Windows平台下载使用
nginx.com 商业版
nginx.org 开源版
https://tengine.taobao.org/
【环境准备】
操作系统:CentOS Linux release 7.3.1611 (Core)
GCC编译环境:yum install -y gcc gcc-c++ autoconf automake make
模块依赖性:Nginx支持的功能模块需要有第三方的库支持,例如gzip的zlib库,rewrite重写需要的pcre库,HTTPS需要的openssl库等等。
yum install zlib zlib-devel openssl openssl-devel pcre pcre-devel wget httpd-tools vim
系统基础开发环境:yum groupinstall "Development Tools" "Basic Web Server"
确保防火墙关闭 iptables -F
关闭selinux
yum源配置正确
网络连接状态正常
【Nginx下载】
1.下载Nginx源代码 nginx.org官网
[root@chaogelinux Learn_Nginx]# wget nginx.org/download/nginx-1.14.0.tar.gz
2.解压缩Nginx源代码
[root@chaogelinux Learn_Nginx]# tar -zxf nginx-1.14.0.tar.gz
3.复制Nginx默认提供的vim语法插件
[root@chaogelinux nginx-1.14.0]# mkdir ~/.vim
[root@chaogelinux nginx-1.14.0]# cp -r contrib/vim/* ~/.vim/
4.Nginx源代码目录介绍
auto 检测系统模块
CHANGES nginx更改记录文件
conf 存放nginx配置文件
configure 释放编译文件的定制脚本
contrib 提供了perl与vim插件
html 存放标准html页面语法
src 存放nginx源码
5.开始编译Nginx,扩展编译模块
#列出Nginx的编译选项,如制定安装路径,配置文件、日志文件等路径,指定开启模块功能等
[root@chaogelinux nginx-1.14.0]# ./configure --help
#编译Nginx初步,
[root@chaogelinux nginx-1.14.0]# ./configure --prefix=/home/Learn_Nginx/nginx/ --with-http_ssl_module --with-http_flv_module --with-http_gzip_static_module --with-http_stub_status_module --with-threads --with-file-aio
6.执行make编译
make
7.首次编译安装,生成Nginx的可执行命令
make install
8.检查Prefix指定的安装目录
[root@chaogelinux nginx-1.14.0]# ls /home/Learn_Nginx/
nginx nginx-1.14.0 nginx-1.14.0.tar.gz
9.Nginx的程序目录
[root@chaogelinux nginx]# pwd
/home/Learn_Nginx/nginx
[root@chaogelinux nginx]# ls
conf html logs sbin
依次是配置文件,静态文件,日志,二进制命令目录
10.创建nginx的环境变量文件,修改如下,创建/etc/profile.d/nginx.sh脚本文件便于以后维护
[root@chaogelinux ~]# cat /etc/profile.d/nginx.sh
export PATH=/home/Learn_Nginx/nginx/sbin:$PATH
11.退出会话,重新登录终端,此时可以正常使用nginx
[root@chaogelinux ~]# echo $PATH
/home/Learn_Nginx/nginx/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
12.检查nginx的编译模块信息
[root@chaogelinux ~]# nginx -V
nginx version: nginx/1.14.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/home/Learn_Nginx/nginx114/ --with-http_ssl_module --with-http_flv_module --with-http_gzip_static_module --with-http_stub_status_module --with-threads --with-file-aio
$变量
使用变量######Nginx配置文件nginx.conf中文详解#####
#定义Nginx运行的用户和用户组
user www www;
#nginx进程数,建议设置为等于CPU总核心数。
worker_processes 8;
#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
error_log /usr/local/nginx/logs/error.log info;
#进程pid文件
pid /usr/local/nginx/logs/nginx.pid;
#指定进程可以打开的最大描述符:数目
#工作模式与连接数上限
#这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。
#现在在linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。
#这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。
worker_rlimit_nofile 65535;
events
{
#参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型
#是Linux 2.6以上版本内核中的高性能网络I/O模型,linux建议epoll,如果跑在FreeBSD上面,就用kqueue模型。
#补充说明:
#与apache相类,nginx针对不同的操作系统,有不同的事件模型
#A)标准事件模型
#Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择select或poll
#B)高效事件模型
#Kqueue:使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。
#Epoll:使用于Linux内核2.6版本及以后的系统。
#/dev/poll:使用于Solaris 7 11/99+,HP/UX 11.22+ (eventport),IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
#Eventport:使用于Solaris 10。 为了防止出现内核崩溃的问题, 有必要安装安全补丁。
use epoll;
#单个进程最大连接数(最大连接数=连接数*进程数)
#根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。每个进程允许的最多连接数,理论上每台nginx服务器的最大连接数为。
worker_connections 65535;
#keepalive超时时间。
keepalive_timeout 60;
#客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
#分页大小可以用命令getconf PAGESIZE 取得。
#[root@web001 ~]# getconf PAGESIZE
#4096
#但也有client_header_buffer_size超过4k的情况,但是client_header_buffer_size该值必须设置为“系统分页大小”的整倍数。
client_header_buffer_size 4k;
#这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
open_file_cache max=65535 inactive=60s;
#这个是指多长时间检查一次缓存的有效信息。
#语法:open_file_cache_valid time 默认值:open_file_cache_valid 60 使用字段:http, server, location 这个指令指定了何时需要检查open_file_cache中缓存项目的有效信息.
open_file_cache_valid 80s;
#open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive时间内一次没被使用,它将被移除。
#语法:open_file_cache_min_uses number 默认值:open_file_cache_min_uses 1 使用字段:http, server, location 这个指令指定了在open_file_cache指令无效的参数中一定的时间范围内可以使用的最小文件数,如果使用更大的值,文件描述符在cache中总是打开状态.
open_file_cache_min_uses 1;
#语法:open_file_cache_errors on | off 默认值:open_file_cache_errors off 使用字段:http, server, location 这个指令指定是否在搜索一个文件是记录cache错误.
open_file_cache_errors on;
}
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http
{
#文件扩展名与文件类型映射表
include mime.types;
#默认文件类型
default_type application/octet-stream;
#默认编码
#charset utf-8;
#服务器名字的hash表大小
#保存服务器名字的hash表是由指令server_names_hash_max_size 和server_names_hash_bucket_size所控制的。参数hash bucket size总是等于hash表的大小,并且是一路处理器缓存大小的倍数。在减少了在内存中的存取次数后,使在处理器中加速查找hash表键值成为可能。如果hash bucket size等于一路处理器缓存的大小,那么在查找键的时候,最坏的情况下在内存中查找的次数为2。第一次是确定存储单元的地址,第二次是在存储单元中查找键 值。因此,如果Nginx给出需要增大hash max size 或 hash bucket size的提示,那么首要的是增大前一个参数的大小.
server_names_hash_bucket_size 128;
#客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
client_header_buffer_size 32k;
#客户请求头缓冲大小。nginx默认会用client_header_buffer_size这个buffer来读取header值,如果header过大,它会使用large_client_header_buffers来读取。
large_client_header_buffers 4 64k;
#设定通过nginx上传文件的大小
client_max_body_size 8m;
#开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
#sendfile指令指定 nginx 是否调用sendfile 函数(zero copy 方式)来输出文件,对于普通应用,必须设为on。如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络IO处理速度,降低系统uptime。
sendfile on;
#开启目录列表访问,合适下载服务器,默认关闭。
autoindex on;
#此选项允许或禁止使用socke的TCP_CORK的选项,此选项仅在使用sendfile的时候使用
tcp_nopush on;
tcp_nodelay on;
#长连接超时时间,单位是秒
keepalive_timeout 120;
#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
#gzip模块设置
gzip on; #开启gzip压缩输出
gzip_min_length 1k; #最小压缩文件大小
gzip_buffers 4 16k; #压缩缓冲区
gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_comp_level 2; #压缩等级
gzip_types text/plain application/x-javascript text/css application/xml; #压缩类型,默认就已经包含textml,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
gzip_vary on;
#开启限制IP连接数的时候需要使用
#limit_zone crawler $binary_remote_addr 10m;
#负载均衡配置
upstream pythonav.cn {
#upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
server 192.168.80.121:80 weight=3;
server 192.168.80.122:80 weight=2;
server 192.168.80.123:80 weight=3;
#nginx的upstream目前支持4种方式的分配
#1、轮询(默认)
#每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
#2、weight
#指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
#例如:
#upstream bakend {
# server 192.168.0.14 weight=10;
# server 192.168.0.15 weight=10;
#}
#2、ip_hash
#每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
#例如:
#upstream bakend {
# ip_hash;
# server 192.168.0.14:88;
# server 192.168.0.15:80;
#}
#3、fair(第三方)
#按后端服务器的响应时间来分配请求,响应时间短的优先分配。
#upstream backend {
# server server1;
# server server2;
# fair;
#}
#4、url_hash(第三方)
#按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
#例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
#upstream backend {
# server squid1:3128;
# server squid2:3128;
# hash $request_uri;
# hash_method crc32;
#}
#tips:
#upstream bakend{#定义负载均衡设备的Ip及设备状态}{
# ip_hash;
# server 127.0.0.1:9090 down;
# server 127.0.0.1:8080 weight=2;
# server 127.0.0.1:6060;
# server 127.0.0.1:7070 backup;
#}
#在需要使用负载均衡的server中增加 proxy_pass http://bakend/;
#每个设备的状态设置为:
#1.down表示单前的server暂时不参与负载
#2.weight为weight越大,负载的权重就越大。
#3.max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误
#4.fail_timeout:max_fails次失败后,暂停的时间。
#5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
#nginx支持同时设置多组的负载均衡,用来给不用的server来使用。
#client_body_in_file_only设置为On 可以讲client post过来的数据记录到文件中用来做debug
#client_body_temp_path设置记录文件的目录 可以设置最多3层目录
#location对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡
}
#虚拟主机的配置
server
{
#监听端口
listen 80;
#域名可以有多个,用空格隔开
server_name www.w3cschool.cn w3cschool.cn;
index index.html index.htm index.php;
root /data/www/w3cschool;
#对******进行负载均衡
location ~ .*.(php|php5)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
#图片缓存时间设置
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 10d;
}
#JS和CSS缓存时间设置
location ~ .*.(js|css)?$
{
expires 1h;
}
#日志格式设定
#$remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
#$remote_user:用来记录客户端用户名称;
#$time_local: 用来记录访问时间与时区;
#$request: 用来记录请求的url与http协议;
#$status: 用来记录请求状态;成功是200,
#$body_bytes_sent :记录发送给客户端文件主体内容大小;
#$http_referer:用来记录从那个页面链接访问过来的;
#$http_user_agent:记录客户浏览器的相关信息;
#通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';
#定义本虚拟主机的访问日志
access_log /usr/local/nginx/logs/host.access.log main;
access_log /usr/local/nginx/logs/host.access.404.log log404;
#对 "/" 启用反向代理
location / {
proxy_pass http://127.0.0.1:88;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#以下是一些反向代理的配置,可选。
proxy_set_header Host $host;
#允许客户端请求的最大单文件字节数
client_max_body_size 10m;
#缓冲区代理缓冲用户端请求的最大字节数,
#如果把它设置为比较大的数值,例如256k,那么,无论使用firefox还是IE浏览器,来提交任意小于256k的图片,都很正常。如果注释该指令,使用默认的client_body_buffer_size设置,也就是操作系统页面大小的两倍,8k或者16k,问题就出现了。
#无论使用firefox4.0还是IE8.0,提交一个比较大,200k左右的图片,都返回500 Internal Server Error错误
client_body_buffer_size 128k;
#表示使nginx阻止HTTP应答代码为400或者更高的应答。
proxy_intercept_errors on;
#后端服务器连接的超时时间_发起握手等候响应超时时间
#nginx跟后端服务器连接超时时间(代理连接超时)
proxy_connect_timeout 90;
#后端服务器数据回传时间(代理发送超时)
#后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据
proxy_send_timeout 90;
#连接成功后,后端服务器响应时间(代理接收超时)
#连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)
proxy_read_timeout 90;
#设置代理服务器(nginx)保存用户头信息的缓冲区大小
#设置从被代理服务器读取的第一部分应答的缓冲区大小,通常情况下这部分应答中包含一个小的应答头,默认情况下这个值的大小为指令proxy_buffers中指定的一个缓冲区的大小,不过可以将其设置为更小
proxy_buffer_size 4k;
#proxy_buffers缓冲区,网页平均在32k以下的设置
#设置用于读取应答(来自被代理服务器)的缓冲区数目和大小,默认情况也为分页大小,根据操作系统的不同可能是4k或者8k
proxy_buffers 4 32k;
#高负荷下缓冲大小(proxy_buffers*2)
proxy_busy_buffers_size 64k;
#设置在写入proxy_temp_path时数据的大小,预防一个工作进程在传递文件时阻塞太长
#设定缓存文件夹大小,大于这个值,将从upstream服务器传
proxy_temp_file_write_size 64k;
}
#设定查看Nginx状态的地址
location /NginxStatus {
stub_status on;
access_log on;
auth_basic "NginxStatus";
auth_basic_user_file confpasswd;
#htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
}
#本地动静分离反向代理配置
#所有jsp的页面均交由tomcat或resin处理
location ~ .(jsp|jspx|do)?$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
}
#所有静态文件由nginx直接读取不经过tomcat或resin
location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|
pdf|xls|mp3|wma)$
{
expires 15d;
}
location ~ .*.(js|css)?$
{
expires 1h;
}
}
}
######Nginx配置文件nginx.conf中文详解#####
nginx.conf详解
nginx.conf重要的指令块
核心功能都在于http{}指令块里,http{}块还包含了以下指令
启停指令
nginx帮助指令
[root@chaogelinux nginx114]# nginx -h
nginx version: nginx/1.14.0
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]
Options:
-?,-h : this help #帮助信息
-v : show version and exit #显示版本
-V : show version and configure options then exit #显示编译信息与版本
-t : test configuration and exit #测试配置文件语法
-T : test configuration, dump it and exit #测试语法且输出内容
-q : suppress non-error messages during configuration testing
-s signal : send signal to a master process: stop, quit, reopen, reload #发送信号,stop立即停止,quit优雅停止,reload重读配置文件,reopen重新记录日志
-p prefix : set prefix path (default: /home/Learn_Nginx/nginx114//)
-c filename : set configuration file (default: conf/nginx.conf) #使用指定配置文件
-g directives : set global directives out of configuration file #覆盖默认参数
配置文件重读
在nginx正在运行时,如实修改了nginx.conf或是新增了一些功能配置,让其生效,可能需要重启整个nginx进程、
但是你不能保证某个时间段没有用户在访问nginx,重启会断开用户的连接,造成莫名的故障
因此nginx提供了reload重载功能,不停止服务,更新配置文件
1.修改nginx.conf
worker_processes 3; #定义nginx工作进程数的
2.重载配置文件
nginx -s reload
3.检查linux进程
[root@chaogelinux nginx114]# vim conf/nginx.conf
[root@chaogelinux nginx114]#
[root@chaogelinux nginx114]# ps -ef|grep nginx
root 6191 1 0 10:33 ? 00:00:00 nginx: master process nginx
nobody 6213 6191 0 10:33 ? 00:00:00 nginx: worker process
nobody 6214 6191 0 10:33 ? 00:00:00 nginx: worker process
nobody 6215 6191 0 10:33 ? 00:00:00 nginx: worker process
root 6345 5283 0 10:38 pts/0 00:00:00 grep --color=auto nginx
nginx进程信号传递如图
1.master不处理请求,而是分配worker进程,负责重启,热部署,重载等功能。
2.master根据worker_processes 定义开始的workers数量
3.worker运行后,master处于挂起状态,等待信号
4.可以发送kill,或者nginx -s 参数发出信号
信号集
nginx -s 对应参数 | 信号 | 含义 | English |
---|---|---|---|
stop | TERM | 强制关闭整个服务 | Shut down quickly. |
null | INT | 强制关闭整个服务 | Shut down quickly. |
quit | QUIT | 优雅地关闭整个服务 | Shut down gracefully. |
reopen | USR1 | 重新打开日志记录 | Reopen log files. |
reload | HUP | 重新读取配置文件,并且优雅地退出老的worker | Reload configuration, start the new worker process with a new configuration, and gracefully shut down old worker processes. |
null | USR2 | 平滑升级到新版本 | Upgrade the nginx executable on the fly. |
null | WINCH | 优雅地关闭worker(在热更新的时候必用) | Shut down worker processes gracefully. |
热部署
nginx作为一个优秀的反向代理服务器,同时具备高可用的特性,Nginx也支持热部署。
热部署指的是在不重启或关闭进程情况下,新应用直接替换掉旧的应用
热部署大致流程
1.备份旧的二进制文件
2.编译安装新的二进制文件,覆盖旧的二进制文件
3.发送USR2信号给旧master进程
4.发送WINCH信号给旧master进程
5.发送QUIT信号给旧master进程
环境准备:
1.旧nginx版本 nginx version: nginx/1.14.0
2.新nginx版本 nginx version: nginx/1.17.8
【nginx热部署】
nginx工作模式是master-worker(包工头-工人)
刚才所说的nginx支持reload重载
仅仅是nginx的master进程,检查配置文件语法是否正确,错则返回错误、正确也不会改变
已经建立连接的worker,只得等待worker处理完毕请求之后,杀死旧配置文件的worker,启动新配置文件的worker
。
但是Nginx这里提提供了热部署功能,就是在不影响用户体验下,进行软件版本升级
,也就是不主动杀死worker,替换软件的二进制文件。
1.目前运行的是旧的nginx版本,如下检查
[root@chaogelinux sbin]# ps -ef|grep nginx
root 20311 1 0 15:12 ? 00:00:00 nginx: master process nginx
nobody 20312 20311 0 15:12 ? 00:00:00 nginx: worker process
root 20314 13589 0 15:12 pts/0 00:00:00 grep --color=auto nginx
[root@chaogelinux sbin]#
[root@chaogelinux sbin]#
[root@chaogelinux sbin]# curl 127.0.0.1/123 #访问错误页面,返回nginx版本了
404 Not Found
404 Not Found
nginx/1.14.0
如果出现发送 kill -USR2信号后,未出现新的master进程
是因为:
旧的nginx必须用绝对路径启动,然后再发送kill -USR2信号
具体解释看图
1.备份旧版本的nginx二进制文件
[root@chaogelinux sbin]# pwd
/home/Learn_Nginx/nginx/sbin
[root@chaogelinux sbin]# mv nginx nginx.old
[root@chaogelinux sbin]# ls
nginx.old
2.检查旧版本nginx的编译参数
[root@chaogelinux Learn_Nginx]# nginx.old -V
nginx version: nginx/1.14.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/home/Learn_Nginx/nginx/ --with-http_ssl_module --with-http_flv_module --with-http_gzip_static_module --with-http_stub_status_module --with-threads --with-file-aio
3.编译安装新版本nginx
#下载新nginx源码
[root@chaogelinux Learn_Nginx]# wget http://nginx.org/download/nginx-1.17.8.tar.gz
#编译安装新版本nginx
[root@chaogelinux Learn_Nginx]# tar -zxf nginx-1.17.8.tar.gz
#开始编译
[root@chaogelinux Learn_Nginx]# cd nginx-1.17.8/
[root@chaogelinux nginx-1.17.8]#
[root@chaogelinux nginx-1.17.8]# ./configure --prefix=/home/Learn_Nginx/nginx/ --with-http_ssl_module --with-http_flv_module --with-http_gzip_static_module --with-http_stub_status_module --with-threads --with-file-aio
#编译安装
[root@chaogelinux nginx-1.17.8]# make && make install
4.此时发现已存在2个版本nginx程序
[root@chaogelinux sbin]# ls
nginx nginx.old
5.替换旧的nginx可执行文件
[root@chaogelinux sbin]# cp -a /home/Learn_Nginx/nginx-1.17.8/objs/nginx /home/Learn_Nginx/nginx/sbin/
cp:是否覆盖"/home/Learn_Nginx/nginx/sbin/nginx"? y
5.1检查旧的nginx进程,请注意,这里用绝对路径启动nginx
请注意,这里用绝对路径启动nginx
请注意,这里用绝对路径启动nginx
例如
/home/Learn_Nginx/nginx/sbin/nginx
注意这里的PID和PPID(pid是当前进程的id号,ppid是启动该进程的pid,也就是父ID,可知该pid由谁启动)
[root@chaogelinux sbin]# ps -ef|grep nginx
root 20311 1 0 15:12 ? 00:00:00 nginx: master process nginx
nobody 20312 20311 0 15:12 ? 00:00:00 nginx: worker process
root 20314 13589 0 15:12 pts/0 00:00:00 grep --color=auto nginx
6.发送USR2信号给旧版本主进程,使得nginx旧版本停止接收请求,切换为新nginx版本
[root@chaogelinux sbin]# kill -USR2 `cat ../logs/nginx.pid `
7.检查此时的nginx进程
nginx-master首先会重命名pid文件,在文件后面添加.oldbin后缀
然后会再启动一个新的master进程以及worker,且使用的是新版Nginx
nginx能够自动将新来的请求,过度到新版master进程下,实现平滑过度
#可以发现新的master进程由旧master启动,由PPID可看出
[root@chaogelinux sbin]# ps -ef|grep nginx
root 20311 1 0 15:12 ? 00:00:00 nginx: master process nginx
nobody 20312 20311 0 15:12 ? 00:00:00 nginx: worker process
root 20335 20311 0 15:13 ? 00:00:00 nginx: master process nginx
nobody 20336 20335 0 15:13 ? 00:00:00 nginx: worker process
root 20338 13589 0 15:13 pts/0 00:00:00 grep --color=auto nginx
[root@chaogelinux sbin]# ls ../logs/
access.log error.log nginx.pid nginx.pid.oldbin
8.发送WINCH信号给旧master进程,优雅的关闭旧worker进程
[root@chaogelinux sbin]# kill -WINCH `cat ../logs/nginx.pid.oldbin`
#再次检查进程情况,旧master的worker已经关闭了,旧master不会自己退出,用作版本回退
[root@chaogelinux sbin]# ps -ef|grep nginx
root 20311 1 0 15:12 ? 00:00:00 nginx: master process nginx
root 20335 20311 0 15:13 ? 00:00:00 nginx: master process nginx
nobody 20336 20335 0 15:13 ? 00:00:00 nginx: worker process
root 20607 13589 0 15:25 pts/0 00:00:00 grep --color=auto nginx
9.如果你觉得没问题了,可以关闭旧master进程
[root@chaogelinux sbin]# ps -ef|grep nginx
root 20335 1 0 15:13 ? 00:00:00 nginx: master process nginx
nobody 20336 20335 0 15:13 ? 00:00:00 nginx: worker process
root 20665 13589 0 15:28 pts/0 00:00:00 grep --color=auto nginx
日志切割是线上很常见的操作,控制单个文件大小,便于管理日志
1.查看当前nginx日志
[root@chaogelinux logs]# ll
总用量 12
-rw-r--r-- 1 root root 1645 2月 11 15:30 access.log
-rw-r--r-- 1 root root 2370 2月 11 15:30 error.log
-rw-r--r-- 1 root root 6 2月 11 15:13 nginx.pid
#大致看下日志内容
[root@chaogelinux logs]# tail -2 access.log
192.168.178.12 - - [11/Feb/2020:15:32:22 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"
192.168.178.12 - - [11/Feb/2020:15:32:23 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"
2.给文件重命名,注意用mv而不是cp(涉及到文件inode知识)
[root@chaogelinux logs]# mv access.log access.log$(date +"%Y-%m-%d--%H:%M:%S")
[root@chaogelinux logs]# ll
总用量 16
-rw-r--r-- 1 root root 4630 2月 11 15:32 access.log2020-02-11--15:43:49
-rw-r--r-- 1 root root 2370 2月 11 15:30 error.log
-rw-r--r-- 1 root root 6 2月 11 15:13 nginx.pid
3.发送USR1信号给nginx-master,重新打开日志记录,生成新的日志文件
nginx -s reopen #等同于 Kill -USR1 nginx.pid
4.注意,在以上的nginx重命名日志切割,不要着急立即对文件修改,且要sleep 等待1秒
由于nginx的工作模式,master下发指令给worker只是做了标记,当业务量大的时候,这个修改操作可能会慢一点,不会理解生效
5.在生产环境下,主要以crontab形式,执行cut_nginx_log.sh脚本的
[root@bogon sbin]# pwd
/opt/nginx/sbin
[root@bogon sbin]# cat cut_nginx_log.sh
#!/bin/bash
# 脚本写入crontab,每天0点执行,这是一个nginx日志切割脚本
#nginx日志存放点
logs_path="/opt/tngx232/logs/"
mkdir -p ${logs_path}$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +"%m")
mv ${logs_path}access.log ${logs_path}$(date -d "yesterday" +"%Y")/$(date -d "yesterday" +"%m")/access_$(date -d "yesterday" +"%Y-%m-%d").log
kill -USR1 `cat /opt/tngx232/logs/nginx.pid`
6.写入crontab
crontab -l
0 0 * * * /bin/bash /opt/nginx/sbin/cut_nginx_log.sh