引言
Nginx 是一个HTTP和反向代理服务器,一个邮件代理服务器和一个通用的TCP/UDP代理服务器。
作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx 为我们选择了 epoll and kqueue 作为开发模型.
作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。
作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙的使用经验。
Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器:Nginx启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下进行软件版本的升级。
下载
windows环境
[官方网站]http://nginx.org/download/nginx-1.22.0.zip)
下载上面的压缩包解压运行nginx即可!
Linux环境
使用命令安装
# centos
运行命令yum install nginx即可完成安装.
# ubuntu
运行命令apt install nginx即可完成安装.
安装完成之后,执行nginx即可启动服务.
默认路径配置:
(1) Nginx配置路径:/etc/nginx/
(2) PID目录:/var/run/nginx.pid
(3) 错误日志:/var/log/nginx/error.log
(4) 访问日志:/var/log/nginx/access.log
(5) 默认站点目录:/usr/share/nginx/html
使用编译安装
若提示weget command not found ,则请执行以下命令,安装weget
yum -y install wget
编译安装所需的额外插件
Gcc:yum install gcc c++ (用于编译c、c++代码)
Pcre:yum install -y pcre pcre-devel(用c语言编写的正则表达式函数库))
Zlib:yum install -y zlib zlib-devel(用于数据压缩的函式库))
OpenSSL:yum install -y openssl openssl-devel安全套接字层密码库))
插件安装命令
yum install -y pcre pcre-devel
yum install -y zlib zlib-devel
yum install -y openssl openssl-devel
编译nginx
tar -zxvf nginx-1.15.tar.gz
cd nginx-1.15
./configure
make
make install
启动nginx
cd /usr/local/nginx/
cd sbin/
./nginx
若想要全局都能执行nginx命令,可以编辑配置文件.将nginx加入到系统变量
1. vim /etc/profile
2. 添加nginx的路径配置
PATH=$PATH:/usr/local/nginx/sbin
export PATH
3.保存退出,执行命令更新配置
source /etc/profile
实操
1.查看安装目录
命令: rpm -ql nginx
rpm是linux的rpm包管理工具,-q代表询问模式,-l 代表返回列表
2.配置说明
执行如下命令,打开配置文件
cd /etc/nginx
vim nginx.conf
内容如下
#运行用户,默认即是nginx,可以不进行设置
user nginx;
#Nginx进程,一般设置为和CPU核数一样
worker_processes 1;
#错误日志存放目录
error_log /var/log/nginx/error.log warn;
#进程pid存放位置
pid /var/run/nginx.pid;
events {
worker_connections 1024; # 单个后台进程的最大并发数
}
http {
include /etc/nginx/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"';
access_log /var/log/nginx/access.log main; #nginx访问日志存放位置
sendfile on; #开启高效传输模式
#tcp_nopush on; #减少网络报文段的数量
keepalive_timeout 65; #保持连接的时间,也叫超时时间
#gzip on; #开启gzip压缩
include /etc/nginx/conf.d/*.conf; #包含的子配置项位置和文件
3.配置组成
全局块
从配置文件到events块之间的内容,主要会设置一些影响nginx服务器整体运行的配置指令,主要包括配置运行Nginx服务器的用户、允许生成的worker process数,进程PID存放路径,日志存放路径和类型以及配置文件的引入等
events块
events块涉及的指令主要影响Nginx服务器与用户的网络连接
http块
Nginx服务器培配置中最频繁的部分、代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都在这里
http全局快配置的指令包括文件引入,MIME-TYPE定义,日志自定义,连接超时时间,单链接请求书上限等
server块
每个server块也分为全局server块,以及可以同时包含多个location块
- 全局server块: 最常见的配置是本虚拟主机的监听配置和本虚拟机的名称或IP配置
- location 块: 一个server可以配置多个location块,这块的主要作用是基于Nginx服务器接收到的请求字符串(例如:server_name/uri-string),对虚拟主机名称之外的字符串进行(例如 前面的uri-string)进匹配,对特定的请求进行处理,地址指向,数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
常用命令
启动nginx
- 直接使用nginx启动
- 使用systemctl start nginx.service启动
查看服务
- 使用ps aux | grep nginx查询
- 使用systemctl status nginx.service查看
停止
- 立即停止服务, nginx -s stop
- 从容停止服务 nginx -s quit
- 杀死进程 killall nginx
重启
systemctl restart nginx.service
更新
nginx -s reload
端口占用
netstat -tlnp
常见配置
1.自定义错误页面和访问限制
错误页面跳转
在nginx.conf文件中,可以针对不同的错误,来进行不同的跳转
- 访问权限控制(配置遵循先出现的设置会覆盖后出现的设置)
- 分块控制权限
- 使用正则表达式设置访问权限
2.使用域名配置虚拟主机
- 配置基于不同端口的监听服务
server{
listen 8010;
server_name _;
root /wangzai/images;
index a.jpg;
}
- 基于域名的监听服务配置
server{
listen 80;
server_name nginx2.jspang.com;
location / {
root /usr/share/nginx/html/html8001;
index index.html index.htm;
}
}
3.代理
正向代理
如果把局域网外的internet想象成一个巨大的资源库,则局域网中的客户端要访问internet,则需要通过代理服务器来访问,这种代理服务就称为正向代理。用作正向代理来代理进行上网等功能。
反向代理
其实客户端对代理是无感知到,因为客户端不需要任何配置就可以访问,我们只需要将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,在返回给客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器IP地址。
反向代理常用指令
proxy_set_header: 在将客户端请求发送给后端服务器之前,更改来自客户端的请求头信息。
proxy_connect_timeout: 配置Nginx与后端代理服务器尝试建立连接的超时时间。
proxy_read_timeout : 配置Nginx向后端服务器组发出read请求后,等待相应的超时时间。
proxy_send_timeout: 配置Nginx向后端服务器组发出write请求后,等待相应的超时时间。
proxy_redirect: 用于修改后端服务器返回的响应头中的Location和Refresh。
负载均衡
单个服务器解决不了,我们增加服务器的数量,然后将请求分发到各个服务器上,将原先请求集中到单个服务器上的情况改为将请求分发到多个服务器上,将负载分发到不同的服务器,也就是我们所说的负载均衡。
upstream lagouServer{
server 111.229.248.243:8080;
server 111.229.248.243:8082;
}
location /abc {
proxy_pass http://lagouServer/;
}
动静分离
为了加快网站的解析速度,可以将动态页面和静态页面由不同的服务器来解析,加快解析速度,降低原来单个服务器的压力
4.设备适配
使用内置变量 $http_user_agent 获取请求客户端的userAgent
server{
listen 80;
server_name nginx2.jspang.com;
location / {
root /usr/share/nginx/pc;
if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
root /usr/share/nginx/mobile;
}
index index.html;
}
}
5.Gzip压缩配置
gzip配置指令
gzip : 该指令用于开启或 关闭gzip模块。
gzip_buffers : 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。
gzip_comp_level : gzip压缩比,压缩级别是1-9,1的压缩级别最低,9的压缩级别最高。压缩级别越高压缩率越大,压缩时间越长。
gzip_disable : 可以通过该指令对一些特定的User-Agent不使用压缩功能。
gzip_min_length:设置允许压缩的页面最小字节数,页面字节数从相应消息头的Content-length中进行获取。
gzip_http_version:识别HTTP协议版本,其值可以是1.1.或1.0.
gzip_proxied : 用于设置启用或禁用从代理服务器上收到相应内容gzip压缩。
gzip_vary : 用于在响应消息头中添加Vary:Accept-Encoding,使代理服务器根据请求头中的Accept-Encoding识别是否启用gzip压缩。
简单示例
6.负载均衡
常用方式
轮询: 默认方式,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务挂了,能自动剔除;
weight: 权重分配,指定轮询几率,权重越高,在被访问的概率越大,用于后端服务器性能不均的情况;
ip_hash: 每个请求按访问 IP 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决动态网页 session 共享问题。负载均衡每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的;
fair: 按后端服务器的响应时间分配,响应时间短的优先分配,依赖第三方插件 nginx-upstream-fair,需要先安装;
简单示例
http {
upstream myserver {
# ip_hash; # ip_hash 方式
# fair; # fair 方式
server 127.0.0.1:8081; # 负载均衡目的服务地址
server 127.0.0.1:8080;
server 127.0.0.1:8082 weight=10; # weight 方式,不写默认为 1
}
server {
location / {
proxy_pass http://myserver;
proxy_connect_timeout 10;
}
}
}
7.跨域解决
跨域是基于浏览器的同源策略决定的
# 同源的例子
http://example.com/app1/index.html # 只是路径不同
http://example.com/app2/index.html
http://Example.com:80 # 只是大小写差异
http://example.com
# 不同源的例子
http://example.com/app1 # 协议不同
https://example.com/app2
http://example.com # host 不同
http://www.example.com
http://myapp.example.com
http://example.com # 端口不同
http://example.com:8080
使用反向代理解决跨域问题
- 将两个域名都映射到统一IP上面
- 将页面fe.sherlocked93.club的请求全部代理到be.sherlocked93.club,绕过跨域问题
server {
listen 9001;
server_name fe.sherlocked93.club;
location / {
proxy_pass be.sherlocked93.club;
}
}
配置header解决跨域问题
a,b两个页面,请求直接访问b可以,但是通过前端页面a中转b会报跨域错误.
# /etc/nginx/conf.d/be.sherlocked93.club.conf
server {
listen 80;
server_name be.sherlocked93.club;
add_header 'Access-Control-Allow-Origin' $http_origin; # 全局变量获得当前请求origin,带cookie的请求不支持*
add_header 'Access-Control-Allow-Credentials' 'true'; # 为 true 可带上 cookie
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # 允许请求方法
add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers; # 允许请求的 header,可以为 *
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000; # OPTIONS 请求的有效期,在有效期内不用发出另一条预检请求
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204; # 200 也可以
}
location / {
root /usr/share/nginx/html/be;
index index.html;
}
}
8.搭建站点,代理本地文件
# 虚拟主机
server {
listen 8080;
server_name xx_domian; # 浏览器访问域名(若是本地调试,需要在host文件中配置ip,域名映射)
charset utf-8;
access_log logs/xx_domian.access.log access;
# 路由
location / {
root www; # 访问根目录
index index.html index.htm; # 入口文件
}
}
9.根据文件类型设置过期时间
location ~.*\.css$ {
expires 1d;
break;
}
location ~.*\.js$ {
expires 1d;
break;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
access_log off;
expires 15d; #保存15天
break;
}
10.禁止浏览器对文件的缓存
location ~* \.(js|css|png|jpg|gif)$ {
add_header Cache-Control no-store;
}
11.防盗链
location ~* \.(gif|jpg|png)$ {
# 只允许 192.168.0.1 请求资源
valid_referers none blocked 192.168.0.1;
if ($invalid_referer) {
rewrite ^/ http://$host/logo.png;
}
}
12.静态文件压缩
server {
# 开启gzip 压缩
gzip on;
# 设置gzip所需的http协议最低版本 (HTTP/1.1, HTTP/1.0)
gzip_http_version 1.1;
# 设置压缩级别,压缩级别越高压缩时间越长 (1-9)
gzip_comp_level 4;
# 设置压缩的最小字节数, 页面Content-Length获取
gzip_min_length 1000;
# 设置压缩文件的类型 (text/html)
gzip_types text/plain application/javascript text/css;
}
13.指定错误跳转页面
# 根据状态码,返回对于的错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /source/error_page;
}
14.跨域问题,反向代理解决方案
前端server域名: http://xx_domain
后端server域名: https://github.com
## 配置反向代理的参数
server {
listen 8080;
server_name xx_domain
## 1. 用户访问 http://xx_domain,则反向代理到 https://github.com
location / {
proxy_pass https://github.com;
proxy_redirect off;
proxy_set_header Host $host; # 传递域名
proxy_set_header X-Real-IP $remote_addr; # 传递ip
proxy_set_header X-Scheme $scheme; # 传递协议
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
15.禁止指定user_agent访问
#虚拟主机的配置文件里加入:
if ($http_user_agent ~* 'baidu|360|sohu') #禁止useragent为baidu、360和sohu,~*表示不区分大小写匹配
{
return 403;
}
location / 和 location ~ / 优先级是不一样的。
结合这个文章研究一下吧 http://blog.itpub.net/27181165/viewspace-777202/
curl -A "baidu" -x127.0.0.1:80 www.test.com/forum.php -I 该命令指定百度为user_agent,返回403
16.nginx访问控制
# 可以设置一些配置禁止一些ip的访问
deny 127.0.0.1; #全局定义限制,location里的是局部定义的。如果两者冲突,以location这种精确地优先,
location ~ .*admin\.php$ {
#auth_basic "cct auth";
#auth_basic_user_file /usr/local/nginx/conf/.htpasswd;
allow 127.0.0.1; 只允许127.0.0.1的访问,其他均拒绝
deny all;
include fastcgi_params;
fastcgi_pass unix:/tmp/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/www$fastcgi_script_name;
}
17.负载均衡
http {
upstream test.net {
ip_hash;
server 192.168.10.13:80;
server 192.168.10.14:80 down;
server 192.168.10.15:8009 max_fails=3 fail_timeout=20s;
server 192.168.10.16:8080;
}
server {
location / {
proxy_pass http://test.net;
}
}
}
18.gzip常用配置
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;
gzip_disable "MISE [1-6]\.";
gzip_vary on;
底层剖析
Nginx启动后,以daemon多进程⽅式在后台运⾏,包括⼀个Master进程和多个Worker进程,Master 进程是领导,是⽼⼤,Worker进程是⼲活的⼩弟
master进程
- 接收外界信号向各worker进程发送信号(./nginx -s reload)
- 监控worker进程的运行状态,但worker进程异常退出后Master进程会自动重新启动新的worker进程等
worker进程
worker进程具体处理网络请求,各进程互相独立,同等竞争
示例
以./nginx -s reload来说明nginx信号处理部分
- master进程对配置文件进行语法检查
- 尝试配置(比如修改了监听端口,那就尝试新的监听端口)
- 尝试成功则使用新的配置,新建worker进程
- 新建成功,给旧的worker进程发送关闭消息
- 旧的worker进程收到信号会继续服务,直到把当前进程收到的请求处理完毕后关闭
- worker进程处理请求部分的说明
- master进程建立之后,会建立需要监听的socket,然后从master进程在fork出多个work进程,所以,所有worker进程的监听描述符listenfd来新连接到来时都变得可读
- nginx使用互斥锁来保证一个workder进程能够处理请求,拿到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接收该连接,然后解析,处理,返回客户端.
- nginx多进程模型的好处
- 每个worker进程都是独立的,不需要加锁,节省开销
- 每个worker进程都是独立的,互不影响,一个异常结束,其他的照样能提供服务
- 多进程模型为reload热部署机制提供了支撑