Nginx
Nginx简介
什么是Nginx
Nginx(engine x)是一个高性能的http和反向代理的服务器, 占用内存少 |并发能力强, 在国内很多大的互联网企业都在使用.
Nginx 可以作为静态页面的 web 服务器,同时还支持 CGI 协议的动态语言,比如 perl、php 等。但是不支持 java。Java 程序只能通过与 tomcat 配合完成。Nginx 专为性能优化而开发, 性能是其最重要的考量,实现上非常注重效率 ,能经受高负载的考验,有报告表明能支持高 达 50,000 个并发连接数。
Nginx可以做什么
反向代理
Nginx 不仅可以做反向代理,实现负载均衡。还能用作正向代理来进行上网等功能。
正向代理和反向代理的区别
-
正向代理(代理客户端,代理客户端发送请求,发送给服务器)
在服务端如浏览器配置代理服务器, 通过代理服务器去访问这个网址,接受返回内容.
-
反向代理(代理服务器,接收用户的请求,分发给服务器)
反向代理对客户端是无感知的(即对客户端么有影响,不需要任何配置),反向代理代理的是服务器,暴露的是代理服务器的地址,隐藏了真实的服务器ip地址.
负载均衡
当服务器压力越来越大时, 单一服务器无法满足需求, 需要配置多台服务器处理业务, 此时当用户发送请求时,可以通过Nginx来进行任务分发,保证每台服务器都有请求可以处理,即将负载分发到不同的服务器,就是所谓的负载均衡.
动静分离
为了加快网站的解析速度,将动态网页和静态网页分开解析
Nginx 安装
这里使用 docker 安装 Nginx
-
拉取镜像
docker pull nginx:tag -
创建 Nginx 容器
docker run -d --name blogNginx -p 81:80 nginx -
修改配置文件
-
方法一:进入容器内部修改(适用于配置文件修改较少的情况)
-
进入容器内部
docker exec -it 容器id /bin/bash -
执行
cd /etc/nginxls可看见 nginx.conf,进而可进行修改
-
-
方式二:将配置文件挂载到主机(适用于修改较为频繁的情况)
-
在主机
/mnt目录下执行mkdir -p ./nginx/{conf,html,logs}创建挂载目录 -
将容器内的
nginx.conf与default.conf文件分别拷贝到主机/mnt/nginx和/mnt/nginx/conf下,分别执行docker cp ef:/etc/nginx/nginx.conf ./ docker cp ef:/etc/nginx/conf.d/default.conf ./conf/cp 命令代表复制 ef是我们nginx容器的ID,/etc/nginx/nginx.conf 是容器内部nginx.conf 路径
-
执行
docker stop b3命令停止刚刚创建的nginx容器,b3是容器Id,然后执行docker rm b3移除容器 -
重新创建容器
docker run -d --name mynginx -p 80:80 -v /mnt/nginx/nginx.conf:/etc/nginx/nginx.conf -v /mnt/nginx/logs:/var/log/nginx -v /mnt/nginx/html:/usr/share/nginx/html -v /mnt/nginx/conf:/etc/nginx/conf.d --privileged=true 0839-v 挂载目录,格式 -v: 表示将主机目录与容器目录之间进行共享, --privileged=true 容器内部对挂载的目录拥有读写等特权
-
这时候,会出现403,不要惊慌。我们的主机挂载 /mnt/nginx/html目录还为空
这时我们在容器的挂载
/mnt/nginx/html目录下创建index.html,内容随便写上hello docker nginx,再次访问主机IP到这里就大功告成了! 需要注意的:我们在挂载目录的操作,都实际会映射到容器内部,写配置文件的时候一定要注意路径问题!!
-
-
Nginx配置文件解析
docker 默认配置文件
user nginx;
worker_processes auto; # work中的进程数量
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
# 事件块
events {
worker_connections 1024; 每个worker进程支持的最大连接数
}
# http块
http {
include /etc/nginx/mime.types; #Nginx支持的媒体类型库文件
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;
sendfile on; #开启高效传输模式
#tcp_nopush on;
keepalive_timeout 65; #连接超时时间
#gzip on;
include /etc/nginx/conf.d/*.conf;
# 第一个server块开始,表示一个独立的虚拟主机站点
server {
listen 80; # 提供服务的端口
server_name 112.74.186.85; 提供服务的域名|主机名
#location块
location / {
proxy_pass http://112.74.186.85:8066; # 跳转的路径
}
}
}
Nginx 配置由 3 部分组成
-
全局块
从配置文件开始到 events 块之间的内容,主要会设置一些影响 nginx 服务器整体运行的配置指令,主要包括配 置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以 及配置文件的引入等
如上面的
worker_processes auto;这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是 会受到硬件、软件等设备的制约.
-
events 块
events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。
这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。
如events 配置中的
worker_connections 1024;就表示每个 work process 支持的最大连接数为 1024 -
http 块
Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在 需要注意的是:http 块也可以包括 http 全局块、server 块。
-
http 全局块
http 全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
-
server 块
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了 节省互联网服务器硬件成本。
每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。
而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。
-
全局 server 块
最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或 IP 配置。
-
location 块
一个 server 块可以配置多个 location 块。 这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称 (也可以是 IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓 存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
-
-
Nginx 配置实例
docker
配置反向代理
- 实例一
server {
listen 80;
listen [::]:80;
server_name 112.74.186.85;
#access_log /var/log/nginx/host.access.log main;
location / {
proxy_pass http://112.74.186.85:8066;
#proxy_redirect default;
}
}
当直接输入 ip 地址访问时,默认端口号为 80端口,如上配置的反向代理,会监听 80 端口,监听到 80 端口会自动跳转到http://112.74.186.85:8066
- 实例二(未测试成功)
server {
listen 80;
server_name rongwei.tech;
location / {
proxy_pass http://112.74.186.85:8066;
}
location ~/blog/ {
proxy_pass http://112.74.186.85:8066;
}
}
根据路径跳转到不同的服务中
配置负载均衡
负载均衡即是将负载分摊到不同的服务单元,既保证服务的可用性,又保证响应 足够快,给用户很好的体验。快速增长的访问量和数据流量催生了各式各样的负载均衡产品, 很多专业的负载均衡硬件提供了很好的功能,但却价格不菲,这使得负载均衡软件大受欢迎, nginx 就是其中的一个,在 linux 下有 Nginx、LVS、Haproxy 等等服务可以提供负载均衡服 务,而且 Nginx 提供了几种分配方式(策略):
配置文件添加在 http 块中(与 server 同级)
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。
2、weight
weight 代表权,重默认为 1,权重越高被分配的客户端越多
upstream server_pool{
server 192.168.5.21 weight=10;
server 192.168.5.22 weight=10;
}
3、ip_hash
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。 例如:
upstream server_pool{
ip_hash;
server 192.168.5.21:80;
server 192.168.5.22:80;
}
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream server_pool{
server 192.168.5.21:80;
server 192.168.5.22:80;
fair;
}
配置动静分离
Nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和 静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用 Nginx 处理静态页面,Tomcat 处理动态页面。动静分离从目前实现角度来讲大致分为两种,
一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;
另外一种方法就是动态跟静态文件混合在一起发布,通过 nginx 来分开。
通过 location 指定不同的后缀名实现不同的请求转发。通过 expires 参数设置,可以使 浏览器缓存过期时间,减少与服务器之前的请求和流量。具体 Expires 定义:是给一个资 源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可, 所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件, 不建议使用 Expires 来缓存),我这里设置 3d,表示在这 3 天之内访问这个 URL,发送 一个请求,比对服务器该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码 304,如果有修改,则直接从服务器重新下载,返回状态码 200。
server {
listen 80;
server_name rongwei.tech;
#配置访问静态资源(html|img)
location /www/ {
root /data/;
index index.html index.htm
}
location /image/ {
root /data/
autoindex on;
}
}
nginx 原理分析
Nginx 启动后有两种进程:master | worker
maser 相当于老板,负责接收请求,但具体的处理请求工作交由 worker 来做.
具体处理流程:
client 发送请求到达 Master,Master 告知所有的 worker,worker 共同争抢这个 client,争抢到的 worker 去处理这个请求.
master-workers 的机制的好处:
- nginx -s reload 热部署,利于 nginx 进行热部署操作
- 对于每个 worker 进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销
- 在编程以及问题查找时,也会方便很多
- 采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master 进程则很快启动新的 worker 进程。当然,worker 进程的异常退出,肯定是程序有 bug 了,异常退出,会导致当 前 worker 上的所有请求失败,不过不会影响到所有请求,所以降低了风险。
Nginx 需要设置多少个 worker
worker 数和服务器的 cpu 数相等是最为适宜的
Nginx 同 redis 类似都采用了 io 多路复用机制,每个 worker 都是一个独立的进程,但每个进 程里只有一个主线程,通过异步非阻塞的方式来处理请求, 即使是千上万个请求也不在话 下。每个 worker 的线程可以把一个 cpu 的性能发挥到极致。所以 worker 数和服务器的 cpu 数相等是最为适宜的。设少了会浪费 cpu,设多了会造成 cpu 频繁切换上下文带来的损耗。
设置 worker 数量。
worker_processes 4
work 绑定 cpu(4 work 绑定 4cpu)。
worker_cpu_affinity 0001 0010 0100 1000
#work 绑定 cpu (4 work 绑定 8cpu 中的 4 个) 。
worker_cpu_affinity 0000001 00000010 00000100 00001000
连接数 worker_connection
第一个:发送请求,占用了 woker 的几个连接数?
答案:2 或者 4 个
第二个:nginx 有一个 master,有四个 woker,每个 woker 支持最大的连接数 1024,支持的
最大并发数是多少?
-
普通的静态访问最大并发数是: worker_connections * worker_processes /2,
-
而如果是 HTTP 作 为反向代理来说,最大并发数量应该是 worker_connections *
worker_processes/4。
这个值是表示每个 worker 进程所能建立连接的最大值,所以,一个 nginx 能建立的最大连接 数,应该是 worker_connections * worker_processes。当然,这里说的是最大连接数,对于 HTTP 请 求 本 地 资 源 来 说 , 能 够 支 持 的 最 大 并 发 数 量 是 worker_connections * worker_processes,如果是支持 http1.1 的浏览器每次访问要占两个连接,所以普通的静态访 问最大并发数是: worker_connections * worker_processes /2,而如果是 HTTP 作 为反向代 理来说,最大并发数量应该是 worker_connections * worker_processes/4。因为作为反向代理服务器,每个并发会建立与客户端的连接和与后端服 务的连接,会占用两个连接。