nginx介绍
nginx (engine x)
是一个高性能的HTTP和反向代理服务器,特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器(apache、IIS)中表现较好。
nginx重要特性
- 支持高并发:针对静态小文件业务环境能支持几万并发
- 资源消耗少:在3万并发连接下,开启10个 Nginx 线程消耗的内存不到200MB
- 可使用反向代理、负载均衡、动静分离、容错功能、内置对 RS 节点服务器健康检查功能
- 支持异步网络 I/O 事件模型 epoll( Linux 2.6 内核 以上)
- 支持在线修改nginx进行平滑升级,不终端业务访问
- 支持 rewrite 模块,支持 URI 重写及正则表达式匹配
- 支持热部署:可以不停机重载配置,日志文件滚动、升级程序版本
nginx模块、工作原理和模式
nginx工作原理
nginx由内核和模块组成 。内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(location是 nginx配置中的一个指令,用于URL匹配),而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。
nginx的工作模式
非阻塞、事件驱动、由一个master进程生成多个worker线程,每个worker响应n个请求;
可供访问量=worker
* n
nginx的模块
启动Nginx后,Nginx的模块被自动加载
不像在Apache一样,首先将模块编译为一个so文件,然后在配置文件中指定是否进行加载。
在解析配置文件时,Nginx的每个模块都有可能去处理某个请求,但是同一个处理请求只能由一个模块来完成。
nginx的模块从结构上分为核心模块、基础模块和第三方模块
- 核心模块:HTTP模块、EVENT模块和MAIL模块
- 基本模块:HTTP Access模块、HTTP FastCG模块、HTTP Proxy模块和HTTP Rewrite模块
- 第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块,
用户根据自己的需要开发的模块都属于第三方模块。正是有了这么多模块的支撑,Nginx的功能才会如此强大。
nginx 安装、命令和配置文件
yum安装nginx
- 添加阿里云镜像
# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# yum install epel-release
# yum makecache生成缓存
- 安装、启动nginx
# yum install -y nginx
# systemctl restart nginx
编译安装nginx
打开nginx.org官网,点击download
Mainline version
是主线版本,最新更新的(可能会有些bug)
Stable version
是稳定版本,一般下载这个,点击下载
Tips
:由于nginx在外网,下载速度奇慢,建议使用IDM下载。传到linux
源码包内容介绍
[root@VM-0-8-centos nginx-1.18.0]# tree -C -L 2
|-- auto --目录-auto自动辅助nginx编译
| |-- cc --目录-用于编译
| |-- lib --目录-模块检查
| |-- os --目录-判断操作系统
| └── types --目录-编译安装回显
|-- CHANGES --查看当前使用的nginx,支持的特性,修改的内容
|-- CHANGES.ru --同上,俄语版
|-- conf --目录-存放实例文件
| |-- fastcgi.conf
| |-- fastcgi_params
| |-- koi-utf
| |-- koi-win
| |-- mime.types
| |-- nginx.conf
| |-- scgi_params
| |-- uwsgi_params
|-- configure --用来生成中间文件,用来编译的必备动作
|-- contrib --目录-提供两个 .pl脚本,和vim工具特性(nginx语法导入到系统,使其能高亮显示)
| |-- geo2nginx.pl
| |-- README
| |-- unicode2nginx
| `-- vim
|-- html --目录-默认界面、50界面
| |-- 50x.html
| `-- index.html
|-- LICENSE
|-- man --目录-nginx的帮助文件,如#man nginx
| `-- nginx.8
|-- README
`-- src --目录-查看nginx的源代码
|-- core
|-- event
|-- http
|-- mail
|-- misc
|-- os
`-- stream
解压nginx源码包
安装前准备
编译安装前要先安装各种运行环境
#yum install -y zlib zlib-devel openssl openssl-devel
#yum install -y pcre-devel gcc gcc-c++
解压nginx源码包
[root@VM-0-8-centos test]# tar -xvf nginx-1.18.0.tar.gz
编译安装启动nginx
编译一下,看执行环境有没报错
#./configure --prefix=/home/zjz/nginx
没报错,make编译安装
#make && make install
编译安装后,在/home/zjz/nginx目录下会有如下
创建相关目录
#mkdir -pv /var/tmp/nginx/{client,fastcgi,proxy,ursgi}
启动nginx
/usr/local/nginx/sbin/nginx(Nginx的安装目录)
/conf中的文件:当前nginx主配置文件(nginx安装包中的conf文件复制过来的)
/sbin:启动nginx 的地方
访问测试页面 http://ip地址
nginx命令
#./nginx -s reload --启动nginx
nginx -t :测试配置文件
nginx -s stop, quit, reopen, reload ;启动、关闭、重载等
nginx -v:查看版本
nginx -V :查看版本和编译安装的选项
基础部署模块:
--prefix=PATH set installation prefix
--如果直到下面lock-path=PATH无需变动, 指定--prefix=PATH后,
默认就会在下这个--prefix指定的目录下创建相应的文件夹。
查看configure中有哪些参数:
#./configure help | less
添加、卸载模块方式如下
--with-xxx :安装xxx模块
--without-x11x:卸载x11x这个模块
编译安装后/objc 目录内容如下
(/objs/src 目录下的所有文件,是编译过程产生的中间文件)
objs/
├── autoconf.err --记录错误编译内容报错
├── ngx_auto_config.h --记录编译时写入的内容
├── ngx_auto_headers.h --
└── ngx_modules.c --编译进当前的nginx模块显示在这里
nginx实现代码高亮
将contrib目录中vim目录导入到系统中.vim
[root@nginx-study nginx-1.16.0]# cp -r contrib/vim/* /root/.vim/
配置文件详解
常见配置文件
nginx.conf ---------->应用程序的基本配置
mime.types ---------->MIME类型关联扩展文件
fastcgi.conf ---------->与fastcgi相关的配置
proxy.conf ---------->与proxy相关的配置
sites.conf ---------->配置nginx提供的网站,包括虚拟主机
http相关的配置结构
注意:与http模块相关的指令仅能够放置在http、server、location、upstream、if上下文,但有些指令仅应用于这5种上下文中的某种
http{
...
... 各server的公共配置
server {
location URL{
root "path/to/somedir";
''''''''''''
}#类似于httpd中的<Location>,用于定于URL与本地文件系统的映射关系
location URL {
if ...{
}
}
} #每个server类似于httpd中的<virtualhost>
}
server模块配置结构
server {
listen 8080;
server_name www.rj.com; //等于httpd。servername
root "/data/" //等于 documentroot
}
server_name 模块
server_name NAME [...];
server_name example.com www.example.com;
后可跟多个主机:名称还可以使用正则表达式(~)或通配符
配置法则:
- 先做精确匹配检查;
server{
server_name www.zjz.com;
}
- 左侧通配符匹配检查 *.zjz.com
server{
server_name *.zjz.con
}
- 右侧通配符匹配检查。如
www.zjz.*
- 正则表达式匹配检查,如
~^.*\.zjz\.com$
default_server
root 模块
设置资源路径映射,用于指明请求的URL所对应的资源所在的文件系统上的起始路径
location [ = | ~ | ~* | ^~ ] uri { … }
location @name { ... }
location可以嵌套
功能:允许根据用户请求的URI来匹配定义的各location:匹配到时,此请求将被相应的location配置快中的配置所处理,
例如:做访问控制等功能
匹配法则:
=
:精确匹配检查 —> location = / {} 只能匹配到根
(如www.zjz.com/ 要是用www.zjz.com/index.php 则不能匹配到)
~
:正则表达式模式匹配检查,区分字符大小写
~*
:正则表达式模式匹配检查,不区分字符大小写
^~
:URI的前半部分匹配,不支持正则表达式,不检查正则
优先级:精确匹配、^~、~、~*、不带任何字符
server {
listen 80;
server_name www.zjz.com;
location / {
root "/vhost/web1";
}
location /images/ {
root " /vhost/images";
}
location ~* \.php$ {
fcgipass
}
}
总结:输入不同的访问路径,就匹配不同的location去www.zjz.com/index.php
这匹配到 location ~* \.php$ {}
rewrite模块-URI重定向
例如;rewrite ^/image/(.*\.jpg)$ /img/$1 break;
访问以.jpg结尾的路径,全部转到/img目录下 ,悄悄的完成地址装换
http://www.zjz.com/image/a/b/c/1.jpg ---> http://www.zjz.com/img/a/b/c/1.jpg
flag:
last:一旦此rewrite规则重写完成后,就不在被后面其他的rewrite规则进行处理,而是由User Agent重新对重写后的URL再一次发起请求,并从头开始执行类似的过程(循环循环在循环,不满足添加就不找了)
break:一旦此rewrite规则重写完成后,有User Agent 对新的URL重新发起请求(直接跳出循环)
redirect:以302响应码(临时重定向),返回新的URL;
permanent:以301响应码(永久重定向),返回新的URL;
下图的意思:访问www.magedu.com/bbs
就直接跳转到forum下的index.html文件
alias path模块
用于location 配置段,定义路径别名。
location{
root “/vhost/web1";
}
#http://www.zjz.com/images/a.ipg <---/www/web1/images/a.jpg
location /images/ {
alias "/www/pictures"
}
#http://www.zjz.com/image/a.jpg <---/www/pictures/a.jpg
注意:
root表示指明路径为对应的location “/" URL
;
alias表示路径映射,即location指令后定义的URL是相对于alias所指明的路径而言;
upstream 模块
upstream模块按照轮询(默认)方式进行负载,[web]为当前upstream的名称。
server 后面是接着域名或者是IP地址+port
,weight为权重,值越大被分配的几率越大
nginx实例
nginx防盗链
location ~* \.(jgp|gif|jpeg|png)$ {
valid_referer none blocked www.zjz.com;
if($invalid_referer) {
rewrite ^/ http://www.zjz.com/403.html;
}
}
基于IP访问控制
allow 172.16.100.6; 允许某个主机
deny 172.16.100.6; 拒绝某个主机
server {
listen 8080;
server_name _;
location / {
root /home/zjz/nginx/html;
deny 192.168.211.1;
}
}
基于用户的访问控制(开启网页认证)
- 编辑主配置页面
auth_basic
“认证显示名称“;
auth_basic_user_file ”/PATH/TO/PASSWORD_FILE“
—>证书存放的位置
- 安装httpd-tools服务,使用htpasswd 命令
#yum install httpd-tools
htpasswd命令是Apache的Web服务器内置工具,用于创建和更新储存用户名、域和用户基本认证的密码文件。
创建一个名为tom ,密码为Aa123456 的用户及密码
- 测试
#/usr/local/nginx/sbin/nginx -t
检查主配置文件语法有没错误
#/usr/local/nginx/sbin/nginx -s reload
重新启动nginx
https部署
- 生成私钥、生成证书签署请求、并获取证书
#(umask 077; openssl genrsa -out private/cakey.pem 2048)
#openssl req -x509 -new -key /etc/pki/CA/privite/cakey.pem -out /etc/pki/CA/cakey.pem -days
#touch /etc/pki/CA/{index.txt,serial}
#echo 01 > /etc/pki/CA/serial
- nginx.conf 配置如下
nginx-正向代理
工作原理类似于跳板机。
国内想访问www.google.com,是不能访问的。
如果你有一台国外的服务器做代理能访问google.com,你恰巧又能访问国外的服务器。此时可用通过国外服务器进行正向代理,让代理把访问请求返回给我。
从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏来用户的资料,这取决于代理告不告诉服务器端。
结论为:正向代理 客户端 <—> 代理服务器 —> 谷歌
- “谷歌端”配置访问限制,模拟防火墙
在“谷歌端”nginx上配置文件限制,加入一个判断语句,如果访问的 IP 不是 192.3.253.xxx(代理服务器IP)则返回403.
如下命令添加到nginx配置文件中
location / {
if ( $remote_addr !~* "^192\.3\.253\.xxx" )
{ return 403; }
}
-
使用代理服务器
192.3.253.xxx
测试访问,正常
使用客户端访问返回403
-
在代理服务器添加正向代理配置
server {
listen 8080;
server_name localhost;
resolver 8.8.8.8;
location / {
proxy_pass http://$http_host$request_uri;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
- 在window客户端上配置代理,填入代理服务器的IP和端口
5.客户端测试访问
nginx-反向代理
反向代理:客户端 一>代理 <一> 服务端
用户 --> 中介(二房东) <—> 真房东
用户租房找中介(二房东),租房完成
这个流程中用户不知道真房东的存在,这就是反向代理。
正向代理的代理对象是用户,反向代理的代理对象是服务端(真房东)。
- 修改nginx配置文件
在/etc/nginx/conf.d/下新建一个test.conf:
server {
listen 8080;
server_name localhost;
location / {
root /opt/app/demo/html;
index index.html index.htm;
}
error_page 500 502 503 504 404 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
在server中开放了80端口和8081端口,用户不知道8081端口的存在,只开放了80端口,所以此时用户就访问不到8081.
所以我们此时访问test.html结果是访问不到的:
2. 配置nginx代理
server {
listen 80;
server_name localhost nginx.tangll.cn;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#设置代理
location ~ /test.html$ {
proxy_pass http://127.0.0.1:8081;
}
error_page 500 502 503 504 404 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
设置当匹配test.html结尾的URL时就去代理访问本机的8081端口
此时便可访问8081端口配置的资源。
- 测试页面,正常
nginx-负载均衡
-
使用upstream模块,分别添加后端web主机的IP地址,以及权重
并在server区段中的location中加入如下语句:
location / { proxy_pass http://web }
(这个web,对应upstream上的名称,表示使用upstream进行负载均衡。
权重设置为1:3
,访问158一次,在访问178三次进行循环。 -
启动nginx服务,并加入开机启动项中
#systemctl restart nginx | #systemctl enable nginx
-
测试
nginx-动静分离
通过location指定不同的后缀名实现不同的请求转发。通过设置expires参数设置可以使浏览器缓存过期时间,减少与服务器重复的请求和流量。
server {
listen 80;
server_name www.zjz.com;
#静态页面
location ~ \.(png|jpeg|jpg|js|css|ttf)$ {
expires 1h; #一小时
}
#动态页面
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /script$fastcgi_script_name;
include fastcgi_params;
}
}
nginx-高可用集群
- 安装主备nginx
# yum install nginx -y
- 安装主备keepalived
# yum install keepalived -y
- 配置主备keepalived
注意: 备用keepalived需要配置state BACKUP
备用priority 70
应该比主小
[root@master html]# cat /etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.211.1
smtp_connect_timeout 30
# 通过它,可以访问到主机,在hosts文件中,要做映射关系,类似于 127.0.0.1 LVS_DEVEL
router_id LVS_DEVEL
}
vrrp_script chk_http_port {
script "/usr/local/src/nginx_check.sh" # 执行脚本所在的位置
interval 2 #检测脚本执行的间隔,单位秒,每个2秒执行一次脚本
weight 2
}
vrrp_instance VI_1 {
state MASTER # 备份服务器上将 MASTER 改为 BACKUP
interface ens33 # 绑定的网卡
virtual_router_id 51 # 主、备机的 virtual_router_id 必须相同
priority 90 # 主、备机取不同的优先级,主机值较大,备份机值较小
advert_int 1 #每隔一秒发送一次心跳,确保从服务器是否还活着
authentication { # 心跳检测需要的密码
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.211.111 # VRRP 虚拟地址
}
}
- 配置主备nginx服务监控脚本
[root@master html]# cat /usr/local/src/nginx_check.sh
#!/bin/bash
nginxpid=`ps -C nginx --no-headers |wc -l`
if [ $nginxpid -eq 0 ];then
systemctl stop keepalived
exit 1
fi
-
启动nginx/keepalived
# systemctl restart nginx
# systemctl restart keepalived
-
测试-输入虚拟机IP地址
停止master节点的nginx,keepalived会因为上面的脚本也会被关闭。
此时刷新页面,访问的是slave备节点上的内容
nginx原理
nginx 性能优化
网络连接相关配置
(1)keepalive_timeout #;
长连接的超时时长,默认75s;
(2)keepalive_request #;
在一个长连接上所能够允许请求的最大资源数;
(3)keepalive_disable [msie6 | safari | none ];
为指定类型的User Agent禁用长连接;
(4) tcp_nodelay on | off;
是否对长连接使用tcp_nodelay选项;
(5)client_harder_timeout # ;
读取http请求报文的超时时长;
(6)client_body_timeout # ;
读取http请求报文body部分的超时时长
(7)send_timeout #;
发送响应报文的超时时长;
fastcgi的相关配置;
性能优化相关配置:
1.worker_processes #; #代表数字
worker进程的个数,通常应该略少于CPU物理核心数;
2.worker_cpu_affinity cpumask ;
Example:worker_cpu_affinity 00000001 00000010; 绑定使用第一颗和第二颗cpu
作用:将Nginx进程绑定至那颗cpu上
优点:提升缓存的命中率
context switch 进程切换:会产生cpu不必要的消耗
cpumask:
0000 0000
0000 0001 指第一颗CPU
0000 0010 指第二颗CPU
0000 0100 指第三颗CPU
0000 1000 指第四颗CPU
3.timer_resolution
计时器解析度,降低此值,可减少gettimeofday()系统调用的次数;
4.worker_priority number;
指明worker进程的nice值 优先级值越低,优先级越高,越找被CPU调度
Example:worker_priority -10;
事件相关配置:
1.accept_mutex {off|on};
master调度用户请求到各worker进程时使用的负载均衡锁。
on表示能让多个worker轮流地、序列化的响应新请求
2.lock_file file;
accept_mutex 用到的锁文件路径(编译安装时就可指定)
3.use [epoll | rtsig | select | poll ];
知名使用的事件模型。 建议让nginx自选
4.worker_connections #;
设定单个worker进程所能够处理的最大并发数;
worker_connections * work_processes
用户与调试、定位问题
1.daemon {on | off}
是否以守护进程方式运行nginx,打开后nginx的调试信息才会回显到屏幕
2.master_process {on | off};
是否以master/worker模型运行nginx,调试时可以设置为nginx
3.error_log file
error_log 位置 级别;
若用使用debug级别,需要编译nginx时使用了 --with-debug on;选项