1:何为Nginx?
几个基本的概念
- Web服务器 :
顾名思义,Web的功能就是提供Web化服务。那什么又叫Web服务呢,
简单点理解比如:网站页面服务、邮件服务、网络下载服务等等,都可以称作Web化服务。
总而言之,Web服务器从广义上来说,就是响应用户的需求并提供响应和服务。
所以从这个角度来讲,当下几乎所有服务器软件都可以称之为Web服务器。
- HTTP服务器:(Ngxin,Apache,IIS)
由于当今Web服务器应用层通信协议主要就是HTTP协议,
所以我们 “基本”上可以将HTTP服务器理解为和Web服务器对等,
因此在下文的阐述时这两个概念不会作过多的纠结区分。
HTTP服务器只是把服务器上的资源通过HTTP协议传输给了客户端,
所以这地方我们 侧重于 它对于静态资源传输的支持。因此一般也理解为静态服务器。
当然它的功能一般不止这些,实际企业里也常做反向代理、负载均衡等用途。
- 应用服务器(Tomcat,Jetty,Undertow,JBoss/WildFly,WebLogic)
应用服务器,则可以理解为一个特定应用的承载容器。一般来说它需要有运行时环境的支持。
比如在Java领域比较常用的应用服务器Tomcat,它就必须要Java运行时环境的支持。
因此,应用服务器也常常被称为:动态服务器、动态容器、应用容器、Web容器等等,
这些概念基本都是对等的。
既然属于动态服务器,很明显它就能支持动态响应,
比如可以根据不同用户的请求,能够动态的生成资源并返回。
这样一来,在客户端,不同用户拿到的返回内容也不一样,不像静态服务器,大家拿到的资源都一样。
当然一般来说,在流量不大的场景下,应用服务器肯定也是可以做HTTP服务器来用,只不过很少有这么去干的。
所以接下来我们就以目前市场上常用的服务器软件为例,逐个对号入座,来审视一遍,大致有十几款软件。
Nginx:Nginx 是一款轻量级的 Web 服务器 / 反向代理服务器 / 电子邮件(IMAP/POP3)代理服务器。
Nginx能做什么?
- 静态资源服务,通过本地文件系统提供服务;
- 反向代理服务,延伸出包括缓存、负载均衡等;
- API 服务,OpenResty ;
正向代理和反向代理
正向代理(Forward Proxy)
在这个过程中,Google 并不知道真正访问它的客户端是谁,它只知道这个中间服务器在访问它。因此,这里的代理,实际上是中间服务器代理了客户端,这种代理叫做正向代理。
反向代理(Reverse Proxy)
在这个过程中,10086 这个号码相当于是一个代理,真正提供服务的,是话务员,但是对于客户来说,他不关心到底是哪一个话务员提供的服务,他只需要记得 10086 这个号码就行了。
所有的请求打到 10086 上,再由 10086 将请求转发给某一个话务员去处理。因此,在这里,10086 就相当于是一个代理,只不过它代理的是话务员而不是客户端,这种代理称之为反向代理。
共同点
- 都是做为服务器和客户端的中间层
- 都可以加强内网的安全性,阻止 web 攻击
- 都可以做缓存机制,提高访问速度
Nginx 的优势
在 Java 开发中,Nginx 有着非常广泛的使用,随便举几点:
使用 Nginx 做静态资源服务器:Java 中的资源可以分为动态和静态,动态需要经过 Tomcat 解析之后,才能返回给浏览器,例如 JSP 页面、Freemarker 页面、控制器返回的 JSON 数据等,都算作动态资源,动态资源经过了 Tomcat 处理,速度必然降低。对于静态资源,例如图片、HTML、JS、CSS 等资源,这种资源可以不必经过 Tomcat 解析,当客户端请求这些资源时,之间将资源返回给客户端就行了。此时,可以使用 Nginx 搭建静态资源服务器,将静态资源直接返回给客户端。
使用 Nginx 做负载均衡服务器,无论是使用 Dubbo 还是 Spirng Cloud ,除了使用各自自带的负载均衡策略之外,也都可以使用 Nginx 做负载均衡服务器。
支持高并发、内存消耗少、成本低廉、配置简单、运行稳定等。
2.Nginx的安装
下载nginx
wget http://nginx.org/download/nginx-1.17.0.tar.gz
然后解压下载的目录,进入解压目录中,在编译安装之前,需要安装两个依赖:
yum -y install pcre-devel
yum -y install openssl openssl-devel
然后开始编译安装:
./configure
make
make install
装好之后,默认安装位置在 :
/usr/local/nginx/sbin/nginx
进入到该目录的 sbin 目录下,执行 nginx 即可启动 Nginx :
如果修改了 Nginx 配置,则可以通过如下命令重新加载 Nginx 配置文件:
nginx -s reload
3.Nginx.conf配置文件说明
- 基本命令win
# 启动
# 建议使用第一种,第二种会使窗口一直处于执行中,不能进行其他命令操作
C:\server\nginx-1.19.2> start nginx
C:\server\nginx-1.19.2> nginx.exe
# 停止
# stop是快速停止nginx,可能并不保存相关信息;quit是完整有序的停止nginx,并保存相关信息
C:\server\nginx-1.19.2> nginx.exe -s stop
C:\server\nginx-1.19.2> nginx.exe -s quit
# 重载Nginx
# 当配置信息修改,需要重新载入这些配置时使用此命令
C:\server\nginx-1.19.2> nginx.exe -s reload
# 重新打开日志文件
C:\server\nginx-1.19.2> nginx.exe -s reopen
# 查看Nginx版本
C:\server\nginx-1.19.2> nginx -v
# 查看配置文件是否正确
C:\server\nginx-1.19.2> nginx -t
-
虚拟主机
虚拟主机的定义:虚拟主机是一种特殊的软硬件技术,它可以将网络上的每一台计算机分成多个虚拟主机,每个虚拟主机可以独立对外提供 www 服务,这样就可以实现一台主机对外提供多个 web 服务,每个虚拟主机之间是独立的,互不影响的。
通过 Nginx 可以实现虚拟主机的配置,Nginx 支持三种类型的虚拟主机配置
- 基于 IP 的虚拟主机
- 基于域名的虚拟主机
- 基于端口的虚拟主机
# 每个 server 就是一个虚拟主机
http {
# ...
server{
# ...
}
# ...
server{
# ...
}
}
-
路由
在Nginx的配置文件中,我们经常可以看到这样的配置:
location / {
#....
}
-
静态服务器
静态服务器是Nginx的强项,使用非常容易,在默认配置下本身就是指向了静态的 HTML 界面,如:
location / {
root html;
index index.html index.htm;
}
-
负载均衡
负载均衡功能是Nginx另一大杀手锏,一共有 5 种方式,着重介绍一下。
upstream tomcatserver {
server 192.168.0.1;
server 192.168.0.2;
}
轮询策略是默认的负载均衡策略
指定权重
即在轮询的基础之上,增加权重的概念,weight和访问比率成正比,用于后端服务器性能不均的情况,配置如下:
upstream tomcatserver {
server 192.168.0.1 weight=1;
server 192.168.0.2 weight=10;
}
IP Hash
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题,配置如下:
upstream tomcatserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
fair
第三方提供的负载均衡策略,按后端服务器的响应时间来分配请求,响应时间短的优先分配,生产环境中有各种情况可能导致响应时间波动,需要慎用
upstream tomcatserver {
server server1;
server server2;
fair;
}
url_hash
第三方提供的负载均衡策略,按访问 url 的 hash 结果来分配请求,使每个 url 定向到同一个后端服务器
upstream tomcatserver {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
Nginx 配置的最佳实践
在生产环境或者开发环境中 Nginx 一般会代理多个虚拟主机,如果把所有的配置文件写在默认的nginx.conf中,看起来会非常臃肿,因此建议将每一个虚拟文件单独放置一个文件夹,Nginx 支持这样的配置,如下:
http {
# 省略中间配置
# 引用该目录下以 .conf 文件结尾的配置
include /etc/nginx/conf.d/*.conf;
}
具体文件配置如:
# Demo
upstream web_pro_testin {
server 10.42.46.70:6003 max_fails=3 fail_timeout=20s;
ip_hash;
}
server {
listen 80;
server_name web.pro.testin.cn;
location / {
proxy_pass http://web_pro_testin;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ~ ^/(WEB-INF)/ {
deny all;
}
}
Nginx 全量配置参数说明
# 运行用户
user www-data;
# 启动进程,通常设置成和cpu的数量相等
worker_processes 6;
# 全局错误日志定义类型,[debug | info | notice | warn | error | crit]
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
# 进程pid文件
pid /var/run/nginx.pid;
# 工作模式及连接数上限
events {
# 仅用于linux2.6以上内核,可以大大提高nginx的性能
use epoll;
# 单个后台worker process进程的最大并发链接数
worker_connections 1024;
# 客户端请求头部的缓冲区大小
client_header_buffer_size 4k;
# keepalive 超时时间
keepalive_timeout 60;
# 告诉nginx收到一个新连接通知后接受尽可能多的连接
# multi_accept on;
}
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
# 文件扩展名与文件类型映射表义
include /etc/nginx/mime.types;
# 默认文件类型
default_type application/octet-stream;
# 默认编码
charset utf-8;
# 服务器名字的hash表大小
server_names_hash_bucket_size 128;
# 客户端请求头部的缓冲区大小
client_header_buffer_size 32k;
# 客户请求头缓冲大小
large_client_header_buffers 4 64k;
# 设定通过nginx上传文件的大小
client_max_body_size 8m;
# 开启目录列表访问,合适下载服务器,默认关闭。
autoindex on;
# sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
# 必须设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度
sendfile on;
# 此选项允许或禁止使用socke的TCP_CORK的选项,此选项仅在使用sendfile的时候使用
#tcp_nopush on;
# 连接超时时间(单秒为秒)
keepalive_timeout 65;
# gzip模块设置
gzip on; #开启gzip压缩输出
gzip_min_length 1k; #最小压缩文件大小
gzip_buffers 4 16k; #压缩缓冲区
gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_comp_level 2; #压缩等级
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
# 开启限制IP连接数的时候需要使用
#limit_zone crawler $binary_remote_addr 10m;
# 指定虚拟主机的配置文件,方便管理
include /etc/nginx/conf.d/*.conf;
# 负载均衡配置
upstream mysvr {
# 请见上文中的五种配置
}
# 虚拟主机的配置
server {
# 监听端口
listen 80;
# 域名可以有多个,用空格隔开
server_name www.jd.com jd.com;
# 默认入口文件名称
index index.html index.htm index.php;
root /data/www/jd;
# 图片缓存时间设置
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)${
expires 10d;
}
#JS和CSS缓存时间设置
location ~ .*.(js|css)?${
expires 1h;
}
# 日志格式设定
#$remote_addr与 $http_x_forwarded_for用以记录客户端的ip地址;
#$remote_user:用来记录客户端用户名称;
#$time_local:用来记录访问时间与时区;
#$request:用来记录请求的url与http协议;
#$status:用来记录请求状态;成功是200,
#$body_bytes_sent :记录发送给客户端文件主体内容大小;
#$http_referer:用来记录从那个页面链接访问过来的;
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';
# 定义本虚拟主机的访问日志
access_log /usr/local/nginx/logs/host.access.log main;
access_log /usr/local/nginx/logs/host.access.404.log log404;
# 对具体路由进行反向代理
location /connect-controller {
proxy_pass http://127.0.0.1:88;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
# 后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
# 允许客户端请求的最大单文件字节数
client_max_body_size 10m;
# 缓冲区代理缓冲用户端请求的最大字节数,
client_body_buffer_size 128k;
# 表示使nginx阻止HTTP应答代码为400或者更高的应答。
proxy_intercept_errors on;
# nginx跟后端服务器连接超时时间(代理连接超时)
proxy_connect_timeout 90;
# 后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据
proxy_send_timeout 90;
# 连接成功后,后端服务器响应的超时时间
proxy_read_timeout 90;
# 设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffer_size 4k;
# 设置用于读取应答的缓冲区数目和大小,默认情况也为分页大小,根据操作系统的不同可能是4k或者8k
proxy_buffers 4 32k;
# 高负荷下缓冲大小(proxy_buffers*2)
proxy_busy_buffers_size 64k;
# 设置在写入proxy_temp_path时数据的大小,预防一个工作进程在传递文件时阻塞太长
# 设定缓存文件夹大小,大于这个值,将从upstream服务器传
proxy_temp_file_write_size 64k;
}
# 动静分离反向代理配置(多路由指向不同的服务端或界面)
location ~ .(jsp|jspx|do)?$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
}
}
}
Nginx 还能做什么
解决 CORS 跨域问题
思路有两个:
基于多路由,把跨域的两个请求发到各自的服务器,然后统一访问入口即可避免该问题
利用 Nginx 配置 Headerd 的功能,为其附上相应的请求头
适配 PC 或移动设备
根据用户设备不同返回不同样式的站点,以前经常使用的是纯前端的自适应布局,但无论是复杂性和易用性上面还是不如分开编写的好,比如我们常见的淘宝、京东......这些大型网站就都没有采用自适应,而是用分开制作的方式,根据用户请求的 user-agent 来判断是返回 PC 还是 H5 站点
请求限流
Nginx 按请求速率限速模块使用的是漏桶算法,即能够强行保证请求的实时处理速度不会超过设置的阈值,如:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
location /search/ {
limit_req zone=one burst=5 nodelay;
}
}
}