Nginx从入门到精通

一、Nginx入门

1.Nginx背景

和Apache一样都是WEB服务器,基于REST架构风格,以统一资源描述符URI或者统一资源定位符URL作为沟通依据,通过HTTP协议提供各种网络服务。
Apache的发展时期很长,是世界第一大服务器,它稳定、开源、跨平台。但是,由于它兴起的年代,互联网行业远远比不上现在,所以它被设计为一个重量级的。不支持高并发的服务器。
这些都决定了Apache不可能成为高性能WEB服务器,轻量级高并发服务器Nginx就应运而生了。

2.概述

是一个高性能的HTTP和反向代理web服务器,是轻量级的。nginx提供了IMAP/POP3/SMTP服务。发布于2004年10月4日(第一个公开版本0.1.0)Nginx的1.4.0稳定版已经于2013年4月24日发布。它用C语言编写,是一个跨平台服务器。
Nginx有主见的函数库(需要装这些库),并且除了zlib、PCRE和OpenSSL之外,标准模块只是用系统C库函数。而且,如果不需要或者考虑到潜在的授权冲突,可以不适用这些第三方库。

3.优势

占用内存少(在3万并发连接中,开启10个nginx进程消耗内存大约150M)。
高并发能力强(官方测试能够支撑5W并发连接,在实际生产环境中能到2-3W并发连接数),单机支持10W并发连接(还不是上限),具体的并发能力还要看服务器的配置。
简单(配置文件通俗易懂),免费、开源,支持Rewriter重写(能够根据域名、URL的不同,将HTTP请求分到不同的后端服务器群组),内置健康检查(如果nginx后端有几个服务宕机了,不会影响前端访问,能自动检测服务状态),稳定性高,反向代理,很少宕机。
中国大陆使用nginx网站用户有:百度,京东,新浪,网易。腾讯,淘宝等。

4.功能

1.web服务器、轻量级
2.负载、均衡
3.缓存
4.高并发

5.应用场景

1.代理服务器
2.IP负载、静态负载
3.动静分离
4.限流、健康监控

6.Linux下安装Nginx

yum install gcc-c++   (c语言的依赖)
yum -y install pcre pcre-devel (pcre的依赖,关于正则)
yum -y install zlib zlib-devel (zlib的依赖,压缩)
yum install -y openssl openssl-devel (openssl的依赖,ssl证书)
以上命令都是安装第三方依赖。-y 命令是如果已经安装了就覆盖,没加-y就是有了就不安装了
wget http://nginx.org/download/nginx-1.16.1.tar.gz  (在线下载,地址可以自己去官网找)
tar -xzvf nginx-1.16.1.tar.gz (解压文件)
./configuer -prefix=/opt/nginx (将编译后的文件输出到哪)
make  (编译,在源码根目录下执行)
make install(编译输出)

7.Linux下Nginx相关命令

cd sbin/
启动nginx ,sbin目录下 ./nginx
强制停止,相当于查出进程id然后kill掉  ./nginx -s stop
进程处理完毕后停止, ./nginx -s quit
重启, ./nginx -s reload
开启端口,让防火墙不拦截80端口  /sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT    (如果本地访问不到端口,则要开启)
如果开启之后,还访问不到,则需关闭本地防火墙(公用网络防火墙)

8.整体架构

在这里插入图片描述

二、Nginx实战应用

1.配置文件模块

核心模块:
	1、HTTP模块(代理、缓存、日志定义和第三方模块)
	2、EVENTS模块(网络连接)
	3、全局模块(全局指令,日志路径、PID路径、用户信息等)
基础模块:
	1、HTTP全局模块
	2、HTTP FastCGI模块
	3、HTTP Gzip模块
	4、HTTP server模块(虚拟主机,一个http,可以有多个server)
	5、HTTP location模块(请求的路由,各种页面的处理)
	6、HTTP Rewrite模块
第三方模块:
	1、HTTP Upstream Request Hash模块
	2、Notice模块
	3、HTTP Access Key模块

2.代理模式

1.正向代理(默认,使用少):
	特点:
		1.客户端无法直接访问到数据服务器
		2.客户端可以通过访问代理服务器获取数据服务器的资源
		3.代理服务器可以知道客户端的操作行为并隐藏
		4.数据服务器不知道真正访问的客户端是谁,只知道是代理服务器在访问
	作用:
		1.访问本来无法访问的资源(客户端访问代理服务器,代理服务器访问数据服务器,然后将数据返回给客户端)
		2.可以做缓存,加速访问资源(不流行,了解)
		3.对客户端访问授权,上网进行认证
		4.代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息。(如果代理服务器被客户端完全控制,则惯以“肉鸡”术语称呼)
2.反向代理(使用多):
	特点:
		1.对于客户端来说,访问的代理服务器就是最终的服务器
		2.对于数据服务器来说,代理服务器就是真正的客户端
	作用:
		1.保证内网的安全,可以使用反向代理提供WAF功能,阻止web攻击(攻击的其实是代理服务器)
		2.负载均衡,通过反向代理服务器来优化网站的负载(通过算法分配集群中的服务器)
	注意:
		nginx配置文件中只要出现了“upstream”关键字就是反向代理,否则就是正向代理
3.透明代理(了解)
	对于客户端来说根本不需要知道有代理服务器的存在,它改编你的报文,并会传送真实IP。也就是谁都知道谁了。

3.配置web应用集群

	1.配置负载均衡(转发请求)
#在nginx.conf配置文件中,在http模块下(与server同级)新增如下伪代码
upstream localhost(localhost是别名){ 
			配置服务器URL;(多台服务器用“;”分割)
		}

然后将http模块下的server 模块下将location模块中的地址改成

location /{
	proxy-pass http:localhost;#(这样通过访问代理服务器就可以转发到我们配置的localhost配置的地址,这里的location就是我们上面配置的别名)
}

2.负载均衡策略
1)轮询法(默认):
轮流分配到后端服务器上,而不关心服务器实际的连接数和当前的系统负载。

upstream server_name{
	server 192.168.10.11:8080 (weight=1);#(权重,轮询法可省略)
	server 192.168.10.12:8080 (weight=1);
}

2)加权轮询法(weight权重法)
由于服务器性能可能不一样,可以根据服务器性能来配置权重,加权轮询能很好地将请求顺序且安装权重分配到后端。weight的值越大分配到的访问概率越高。

	upstream server_name{
		server 192.168.10.11:8080 weight=1;
		server 192.168.10.12:8080 weight=2;
}

3)源地址哈希法
根据获取客户端的IP地址,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客户端要访问服务器的序号。
采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问,可以保证来自同一IP的请求被打到固定的机器上,可以解决session问题。

upstream server_name{
	ip_hash;
	server 192.168.10.11:8080 weight=1;
	server 192.168.10.12:8080 weight=1;
}

4)最小连接数法(least_conn)
根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。

upstream server_name{
	least_conn;
	server 192.168.10.11:8080 weight=1;
	server 192.168.10.12:8080 weight=1;
}

5)Fair(调度算法)
Nginx本身不支持Fair(第三方),如果需要这种调度算法,则必须安装upstream_fair模块,下载安装步骤如下:

Fair插件安装:
	下载地址:https://github.com/gnosek/nginx-upstream-fair/tree/master
	• 解压zip:unzip nginx-upstream-fair-master.zip 
	• 增加模块(源码目录): ./configure --prefix=/opt/nginx --add-module=/opt/nginx-upstream-fair-master
	• defalut_port问题修改:cd nginx-upstream-fair-master
	• sed -i 's/default_port/no_port/g' ngx_http_upstream_fair_module.c  (在下载的插件目录下执行)
	• make
	• make install
比weight、ip_hash更智能的负载均衡算法。
可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream server_name{
	fair;
	server 192.168.10.11:8080 weight=1;
	server 192.168.10.12:8080 weight=1;
}

6)url_hash
按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器。可以进一步提高后端缓存服务器的效率。
Nginx本身不支持url_hash(第三方),如果需要这种调度算法,则必须安装Nginx的hash软件包,下载安装步骤:

hash插件安装
	下载地址:https://github.com/evanmiller/nginx_upstream_hash
	• 解压zip:unzip nginx_upstream_hash-master.zip
	• 增加模块(源码目录): ./configure --prefix=/opt/nginx --add-module=/opt/ nginx_upstream_hash-master
	• make
	• make install
upstream server_name{
	hash $request_uri;
	server 192.168.10.11:8080 weight=1;
	server 192.168.10.12:8080 weight=1;
}

4.配置日志

一、好处
	1.可以得到用户地域来源、跳转来源、使用终端、某个URL访问量等相关信息
	2.可以得到系统某个服务或server的性能瓶颈
	3.日志生成到根目录logs/access.log文件,默认使用“main”日志格式,也可以自定义格式
二、格式
	默认“main“日志格式(“log_format”是关键词不能动 ,“main”是格式名称 ):
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

属性说明:
$remote_addr: 客户端的ip地址(代理服务器,显示代理服务ip) $remote_user: 用于记录远程客户端的用户名称(一般为“-”) $time_local: 用于记录访问时间和时区。
$request: 用于记录请求的url以及请求方法。
$status: 响应状态码,例如:200成功、404页面找不到等。
$body_bytes_sent: 给客户端发送的文件主体内容字节数。
$http_user_agent: 用户所使用的代理(一般为浏览器)。
$http_x_forwarded_for: 可以记录客户端IP,通过代理服务器来记录客户端的ip地址。
$http_referer: 可以记录用户是从哪个链接访问过来的。

三、日志切割
	在现实环境下,记录的日志往往是非常庞大的,日志默认是记录在access.log文件下,如果把所有的内容都记录在这一个文件下,那么一旦出现了问题,去查找日志就会是一件非常恐怖的事情,所以我们一般会把日志切割,一般按天来记录日志,这么一来查找日志就相对容易了许多。
但是,nginx的日志文件没有rotate(切割)功能,	我们可以写一个nginx日志切割脚本来自动切割日志文件
步骤:
	1.重命名日志文件(不用担心重命名后nginx找不到日志文件而丢失日志。在你未重新打开原名字的日志文件前,nginx还是会向你重命名的文件写日志,Linux是靠文件描述符而不是文件名定位文件)
	2.向nginx主进程发送USR1信号
		1)nginx主进程接到信号后会从配置文件中读取日志文件名称
		2)重新打开日志文件(以配置文件中的日志名称命名),并以工作进程的用户作为日志文件的所有者
		3)重新打开日志文件后,nginx主进程会关闭重命名的日志文件并通知工作进程使用新打开的日志文件
		4)工作进程立刻打开新的日志文件并关闭重命名的日志文件
		5)然后你就可以处理旧的日志文件了。(或者重启nginx服务)
切割脚本:
	nginx日志按每分钟自动切割脚本如下 :
	新建shell脚本:
vi /opt/nginx/nginx_log.sh 
#!/bin/bash 
#设置日志文件存放目录 
LOG_HOME="/opt/nginx/logs/"
#备分文件名称 
LOG_PATH_BAK="$(date -d yesterday +%Y%m%d%H%M)".access.log 
#重命名日志文件 
mv ${LOG_HOME}/access.log ${LOG_HOME}/${LOG_PATH_BAK}.log 
#向nginx主进程发信号重新打开日志 
kill -USR1 `cat /opt/nginx/logs/nginx.pid`

创建crontab设置作业:
设置日志文件存放目录

crontab -e
#将以下代码写入保存
1 */1 * * * * sh /opt/nginx/nginx_log.sh
#启动cron定时任务(重新启动定时任务的命令)
restart crond.service

五、动静分离

我们在实际开发中,通常会把静态资源文件直接存放在nginx服务器上,把动态请求放在数据服务器上,这样可以减轻数据服务器的压力,当用户请求静态资源的时候(如:图片,js,css等),直接从nginx代理服务器上取就好。把动态请求和静态请求分开,可以理解成使用Nginx处理静态页面,tomcat处理动态页面。
实现方式
1.纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案
2.动态跟静态文件混合一起发布,通过nginx来分开(了解,一般不这么操作)
配置文件更改:

	server {
	listen 80;
 	server_name a; 
	location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ 
	{
		#到哪个目录下加载
		root /opt/nginx/static; 
		#缓存有效期
		expires 30d;  
	 }
 }

六、限流配置
为什么需要限流,比如说,我一台服务器最多只能处理5W个请求,而来了7W个请求,那么就可能会导致我这台服务器直接挂掉,这样是非常糟糕的,那么我们进行了限流配置,比如配置了只接受4W个请求,那么其余的3W请求就会直接被拒绝了,返回503错误信息,也就是牺牲了个别请求,来保证我们的服务器不会宕机。

1、limit_conn_zone(了解)控制连接数限流:
http{
	#limit_conn_zone关键词,$binary_remote_addr用户ip,zone=one开辟一个空间叫one(可以随便取),20m是空间的大小20兆(限流)
	limit_conn_zone $binary_remote_addr zone=one:20m;
	server
	{
		……
		#限制连接数 one要和前面命名的空间名相同,运行10个连接
		limit_conn one 10; 
		……
	}
}

其中“limit_conn one 10;”既可以放在server层对整个server有效,也可以放在location中支队单独delocation有效
该配置表明:客户端的并发连接数只能是10个

2、limit_req_zone(推荐)控制请求速度限流:
http{
	#rate=1r/s 每秒请求一次
	limit_req_zone $binary_remote_addr zone=req_one:10m rate=1r/s;
	server
	{
		……
		#burst=120 令牌桶一共有120块令牌,并且每秒钟只新增1块令牌,120块牌发完后,多出来的请求就会返回503,令牌桶的数量就是支持的并发数

		limit_conn req_one burst=120; 
		……
	}
}

既可以放在server层对整个server有效,也可以放在location中支队单独delocation有效
该配置表明:客户端的并发连接数只能是10个。

注意:前两种只能对客户端限流(即单一ip限流)。

3.ngx_http_upstream_module(推荐):
upstream xxx{
	server 127.0.0.1:8080 max_conns=10;
	server 127.0.0.1:8081 max_conns=10;
}
	该模块提供后台服务限流功能
	该模块有一个参数:max_conns可以对服务器进行限流,在nginx1.11.5版本以后,可以使用
测试工具:
	Ab工具(简单好用)
		Centos安装:yum install httpd-tools -y
		测试:ab -c 10 -n 1000 http://www.test.com/    (请求的地址,意思是10个用户,发送1000次请求)
		返回的结果
			DocumentPath 测试的页面
			Document Length 页面大小
			Concurrency Level 并发数量、并发用户数
			Time taken for tests 测试消费总时间
			Complete requests 请求总量、并发连接数
			Failed requests 请求失败的数量
			Write errors 错误数量
			Requests per second 每秒钟的请求量、吞吐率
			Time per request 每次请求需要时间、响应时间

七、高并发下安全配置

服务器的安全往往是最重要的,那么我们在高并发下如何保证安全呢,有以下几种方式:

1.版本安全
在请求nginx服务器的时候,在浏览器F12可以在Response Headers里看到nginx的版本号,那么每个Nginx的版本都有几个明显的漏洞,如果暴露出来,别有用心的人可能就会对这个版本的漏洞进行攻击。
	http{
	#隐藏nginx版本号
	server_tokens off;
}
2.IP安全
	1)白名单配置
		限制了可以访问的ip地址,只对信任的ip开放,大大增加了安全性。
location / {
	#只允许这个ip可以访问
	allow 192.168.136.1;
	#其他ip不可访问
	deny all;
}
	2)黑名单配置
	禁止了不信任的ip地址,和白名单相反,除了禁止的ip其他ip都可以访问。
	location / {
	#只禁止这个ip不可以访问
	deny 192.168.136.1;
	#其他ip都可访问
	allow all;
}
3.文件安全
对相关文件访问路径进行限制,可以防止别人获取到我们不希望被展示的文件内容
#一般会在logs后面增加一些其他的后缀,只有知道这个目录才可以访问
location /logs {
	#展示目录on是开启,off是关闭除非知道文件名称
	autoindex on;
	#在这个目录下
	root /opt/nginx/;
}
#配置展示文件内容
#正则,匹配所有的前缀+/logs+所有的后缀+以log和txt结尾的文件
location ^/logs~*\.(log|txt) {
	#以目录的形式
	add_header Content-Type text/plain;
	#在这个目录下
	root /opt/nginx/;
}
4.连接安全
	HTTPS 开启(只有注册过ssl认证的才可以访问),还可以设置连接有效期,响应时间等

八、配置进程数、并发数、系统优化
常见的一些配置,了解一下:

nginx.conf(调整主配置文件,增加并发量)
worker_processes 2; 这个属性一般调整到与CPU数量一致
event{
	worker_connection 65535; #每个worker最大并发连接数,默认是1024,一般用1024乘以CPU数的结果
}
调整内核参数:
ulimit -a   #查看所有的属性值
ulimit -Hn 100000  #临时设置硬限制
ulimit -Sn 100000  #临时设置软限制
vim /etc/security/limits.comf   #永久生效需要更改这个配置文件
添加上:
	*		 soft     	nofile   		100000
	*		 hard    	nofile   		100000
 # 用户/组 	软/硬限制  	需要限制的项目   	限制的值

九、长连接(了解)

nginx长连接短连接,可以增强服务器的容灾能力
想要做到长连接必须做到2点
	1.client到nginx是长连接
	2.nginx到server时长连接
配置
	1.client发送过来的请求携带“keep-alive" header(浏览器默认携带)
	2.nginx设置支持keep-alive
		event模块和http模块下都有keepalive_timeout属性,配置该属性(不宜太长)

十、文件压缩
gzip压缩作用:将响应报文发送至客户端之前可以启用压缩功能,这能够有效地节约带宽,并提高响应至客户端的速度,压缩会消耗nginx的cpu性能
gzip压缩可以配置http,server和location模块下
必配项
在这里插入图片描述
一般不配项
在这里插入图片描述

十一、状态监控

在nginx,conf里的server模块下添加
location /NginxStatus{		#请求地址
	stub_status on;		#开启监控功能
	access_log off;		#是否将监控信息加入日志中
}

#配置完成后重启(有可能reload不生效,需要先stop,再启动)
要安装监控包(在nginx源码包的configure目录下执行):
./configure --prefix=/opt/nginx/ --with-http_stub_status_module
参数说明
#活跃的连接数量
active connections
#总共处理了n个连接 , 成功创建n次握手, 总共处理了n个请求
server accepts handled requests
#每个连接有三种状态waiting、reading、writing
reading —读取客户端的Header信息数.这个操作只是读取头部信息,读取完后马上进入writing状态,因此时间很短
writing — 响应数据到客户端的Header信息数.这个操作不仅读取头部,还要等待服务响应,因此时间比较长。
waiting — 开启keep-alive后等候下一次请求指令的驻留连接.
正常情况下waiting数量是比较多的,并不能说明性能差。反而如果reading+writing数量比较多说明服务并发有问题。
相关查看命令及返回
查看Nginx并发进程数:ps -ef|grep nginx | wc -l
查看Web服务器TCP连接状态:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
解析:
CLOSED //无连接是活动的或正在进行
LISTEN //服务器在等待进入呼叫
SYN_RECV //一个连接请求已经到达,等待确认
SYN_SENT //应用已经开始,打开一个连接
ESTABLISHED //正常数据传输状态/当前并发连接数
FIN_WAIT1 //应用说它已经完成
FIN_WAIT2 //另一边已同意释放
ITMED_WAIT //等待所有分组死掉
CLOSING //两边同时尝试关闭
TIME_WAIT //另一边已初始化一个释放
LAST_ACK //等待所有分组死掉
查看Web服务器TCP连接状态:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

猜你喜欢

转载自blog.csdn.net/qq_32285039/article/details/104175265