Nginx常用功能及应用场景
前言
这篇文章是大部分是通过学习哔哩哔哩中的视频“Nginx教程”,也添加了一些我个人工作中比较常用的功能,哔哩哔哩的视频连接是https://www.bilibili.com/video/BV1zJ411w7SV?p=1
本人水平有限,如有误导,欢迎斧正,一起学习,共同进步!
一、Nginx是什么?
nginx是一款使用c语言开发的高性能的HTTP和反向代理web服务器。Nginx是异步框架的网页服务器,能用作反向代理、负载平衡器和 HTTP 缓存。其特点是占有内存少,并发能力强,Nginx专为性能优化而开发,性能是其最重要的考量,实现上非常注重效率,能够受高负载的考验,有报告表明能支持高达 50,000 个并发连接数。
二、Nginx的优势?
nginx是基于epoll and kqueue作为开发模型的,而epoll是基于NIO的同步非阻塞开发,在高并发情况下能支持更多的连接,从而保证了更好的性能。
IO、NIO、AIO、BIO的区别:
IO:阻塞IO。
NIO:同步非阻塞IO。服务器实现模式为:一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时才启动一个线程进行处理。用户进程也需要时不时的询问IO操作是否就绪,这需要用户进行不停的去询问。NIO的包括三个核心概念:缓冲区(Buffer)、通道(Channel)、选择器(Selector)。适用于连接数目多且连接比较短(轻操作)的架构,比如聊推荐服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
AIO:Asynchronous IO,异步非阻塞AIO。最大的特性时具有异步能力,这种能力对socket与文件I/O都起作用。AIO其实是一种在读写操作结束之前允许进行其他操作的I/O处理。适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK1.7开始支持。
BIO:同步阻塞IO。服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器需要启动一个线程进行处理,如果这个链接不做任何事情会造成不必要的线程开销。适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4之前的唯一选择, 但是程序简单直观容易理解。
三、整体介绍一下Nginx
1、下载安装
进入Nginx的官网http://nginx.org/en/download.html,选择某一版本(建议选择稳定版),下载。我此次的环境为win10,我选择的是
2、初览Nginx.conf文件
进入到Nginx的安装目录下,找到 /nginx/conf/nginx.conf文件,咱们配置的一切都在这个文件中进行的。
默认文件内容为:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include 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 logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
看着蛮多的,去掉注释以后也没多少,缩水了一大半啊有木有😂:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
3、详解Nginx.conf文件(核心)
Nginx整体分为三大部分,全局块、events块、http块。
3.1 全局块
全局块是指从配置文件开始到 events 块之间的内容,主要会设置一些影响 nginx 服务器整体运行的配置指令,主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以及配置文件的引入等。比如默认配置文件中的
worker_processes 1;
这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约。
3.2 events块
events 块涉及的指令主要影响Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个work process 可以同时支持的最大连接数等。
worker_connections 1024;
表示每个work 进程支持的最大连接数为1024.
3.3 http块
这算是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。需要注意的是:http 块也可以包括 http全局块、server块
3.3.1 http全局块
http 全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
3.3.2 server块
这块和虚拟主机有密切关系,一个server块从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。
3.3.2.1 全局 server块
最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或 IP 配置。
3.3.2.1 location块
一个 server 块可以配置多个 location 块。这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称(也可以是 IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。
这些理论知识看着比较晦涩,但是配置起来相当简单哦~
四、Nginx能做什么?
1、反向代理
a.我们先来介绍一下什么是反向代理,有什么作用?
正向代理:给客户端做代理,服务端不知道实际发请求的客户端。意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。应用场景是:比如你在国内想访问某些国外的地址(或者内网IP),但是你直接通过你自己的IP连接某些国外的地址(或者内网IP)的话,你是连接不到的(被限制了),不过你可以连接VPN,通过VPN代理后的IP,来访问国外的地址。
反向代理(核心功能之一):给服务端做代理,客户端不知道提供服务的是具体哪台服务器。是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端。应用场景是:就是咱们常说的“横向扩展”,压力大,压力大就加服务器呗😉。比如你希望访问com.zheng.cn的时候,通过某种负载均衡策略来实现服务器端的分流。(假设一个服务器能在1秒内同时响应5个请求,那同时来了10个请求,一个服务器的话,就会被宕机了,但是如果你用三台服务器做轮询处理,就可以正常的使用)。
b.产品需求(期望效果)
需求1:打开浏览器,在浏览器地址栏输入地址 www.123.com 跳转到Linux系统中的tomcat主页面中。
需求2:使用 nginx 反向代理,根据访问的路径跳转到不同端口的服务中。
nginx 监听端口为 9001,
访问 http://127.0.0.1:9001/edu/ 直接跳转到 127.0.0.1:8081
访问 http://127.0.0.1:9001/vod/ 直接跳转到 127.0.0.1:8082
c.过程分析
正常情况下,输入域名(比如说的www.123.com),他会首先进入本地的hosts文件中去查看,看看有没有配置域名映射的ip地址;若有,直接根据host文件中的配置去执行;若没有,则去网络上找dns域名解读器,找网络中的ip,从而去访问这个ip地址。
d.具体实现
需求1的具体实现:
①修改本机的hosts文件
进入 C:\Windows\System32\drivers\etc 定位到hosts文件,
在其中加入
192.168.17.129 www.123.com
前者是你Linux系统的IP,后者是域名。中间空格不可省略。
②修改nginx.conf文件(在nginx进行请求转发的配置(反向代理配置))
进入到Nginx的安装目录下,找到 /nginx/conf/nginx.conf文件(下图是在Linux系统中的配置,windows下也是一样)
修改后:
需求2的具体实现:
①前置准备
准备两个 tomcat,一个 8001 端口,一个 8002 端口,并准备好测试的页面
②修改 nginx 的配置文件
一个server从用户的角度来看,就相当于一个物理主机,所以我们直接在配置一下监听的端口、服务名,以及要转发的地址即可。
2、负载均衡
2.1 负载均衡
2.1.1 产品需求(期望效果)
浏览器地址栏输入地址 http://192.168.17.129/edu/a.html,负载均衡效果,平均 8080和 8081 端口中(简单的说,访问同一个路径,服务器端由两台服务器来提供服务)。
2.1.2 准备工作
(1)准备两台 tomcat 服务器,一台 8080,一台 8081
(2)在两台 tomcat 里面 webapps 目录中,创建名称是 edu 文件夹,在 edu 文件夹中创建页面 a.html,用于测试
2.1.3 具体实现
先在http块中添加一个负载均衡配置
upstream myserver{
server 192.168.17.129:8080;
server 192.168.17.129:8081;
}
这是配置负载均衡的,其中“upstream”是固定格式,后面的“myserver”是自己起的名字,跟下面能对应起来就行
修改前的nginx.conf文件
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
修改后的文件:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream myserver{
server 192.168.17.129:8080;
server 192.168.17.129:8081;
}
server {
listen 80;
server_name 192.168.17.129;
location / {
proxy_pass http://myserver;
proxy_connect_timeout 10;
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
2.1.4 Nginx分流策略
(1)轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。
(2) 权重(weight)
weight 代表权重默认为 1,权重越高被分配的客户端越多
(3) 相同Hash(ip_hash)
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器
(4) fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
2.2 Session共享
Session共享也就是分布式的登录问题,即SSO单点登录问题。若我们的项目是单体架构还好,session中存储着当前登录人的信息。但是若是微服务项目的话,我在A服务项目中登录了,难道我还要在B服务项目也登录一下吗?那用户体验度就太差了,太容易流失客户。分布式系统的登录问题,常用的解决方案有redis存用户信息、JWT登录等等,我们这次介绍的是用Nginx的Session绑定。原理:将某个ip的请求固定到多个后端服务器中的同一台后端应用服务器,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,每次登录都访问同一个服务器,也就相当于解决了分布式登录的问题了。缺点:使用ip_hash进行session共享,它的原理是为每个访问者提供一个固定的访问ip,让用户只能在当前访问的服务器上进行操作,保持了session同步的,但是也造成了负载不均衡的问题,如果当前用户访问的服务器挂了的话,那就会出现问题(之所以用分布式就是希望高可用,而他局限性太大,不适用)。
2.2.1 具体实现
# 将多个服务器用相同Hash(ip_hash)的算法来负载均衡,相当于固定ip了
upstream backend {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
ip_hash;
}
3、动静分离
目的:为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度。降低原来单个服务器的压力。
原理:Nginx 动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用 Nginx处理静态页面,Tomcat 处理动态页面。动静分离从目前实现角度来讲大致分为两种:一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;另外一种方法就是动态跟静态文件混合在一起发布,通过 nginx 来分开。
需求:访问Nginx的地址,能够访问到具体的资源(比如说我在根目录下的data文件夹下有aaa文件夹和www文件夹。其中aaa文件夹有b.html文件,我能通过Nginx的配置来通过ip/data/aaa/b.html来查看到b.html文件)
3.1、动静分离具体实现:
修改前的nginx.conf文件
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
修改后的配置文件:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name 172.16.109.55;
location /www/ {
root /data/;
index index.html index.htm;
}
location /aaa/ {
root /data/;
autoindex on; # 其中这个autoindex on是显示目录的
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
五、总结
Nginx是目前市面上最流行的反向代理服务器。在我的工作中最常用的是反向代理,负载均衡。这两项掌握就可以解决90%的问题。