Nginx是俄罗斯人编写的十分轻量级的、高性能的HTTP服务器和反向代理服务器,同时也是一个IMAP/POP3/SMTP代理服务器。
Nginx的特点
支持5万高并发、内存消耗少。
Nginx在架构中的作用
1) 网关 — 面向客户的总入口
2) 虚拟主机 — 为不同域名(IP)、端口提供服务
3) 路由 — 使用反向代理,整合后续服务为一个完整业务
4) 静态服务器 — 发布前端html/css/js/image等
5) 负载均衡服务器 — 使用upstream,负载多个tomcat
正向代理和反向代理
正向代理:客户端发送一个请求,并指定目标,然后代理服务器向目标服务器转交请求并将获得的内容返回给客户端。
用途:
1) 访问无法访问到的资源,如google。
2) 做缓存,加速资源访问。
3 )客户端访问授权、认证。
4) 记录用户访问行为
反向代理:代理服务器接收客户端请求,将请求转发给内部网络上的服务器,并将得到的结果返回给客户端。
用途:
1) 保证内网安全,阻止web攻击。
2) 负载均衡
正向代理,服务端不知道实际发起请求的客户端。
反向代理,客户端不知道实际提供的服务端。
高度模块化设计是nginx架构的基础,nginx服务器被分解为多个模块,每个模块负责一个功能,模块之间严格遵守“高内聚、低耦合”的原则。
核心模块
是nginx服务器正常运行必不可少的模块,提供错误日志记录、配置文件解析、事件驱动机制、进程管理等核心功能。
标准HTTP模块
提供HTTP协议解析相关的功能,如:端口配置、网页编码配置、HTTP响应头信息等。
可选HTTP模块
主要用于扩展标准HTTP的功能,让nginx能处理一些特殊的服务,如:flash多媒体传输、解析GeoIP请求、SSL支持等。
邮件服务模块
主要用于支持nginx的邮件服务,包括POP3协议、IMAP协议和SMTP协议。
第三方模块
为了扩展nginx服务器应用,完成开发者自定义的功能,如json支持、lua脚本的支持。
master是worker进程的管理者,主要功能包括:
1) 接收来自外界的信号
2) 向各个worker进程发送信号
3) 监控worker进程的运行状态
服务器的主进程(master)每收到一个客户端请求时,都会生成一个子进程(worker)来和客户端建立连接并进行交互,直到连接断开。
使用进程的好处是各个进程之间相互独立,不需要加锁,减少了加锁对性能造成的影响,同时降低了编程的复杂度,降低开发成本。
缺点是操作系统生成子进程需要内存复制等操作,在资源和时间上会产生一定的开销。当有大量请求时,会导致系统性能下降。
为了更高效,Nginx利用了LINUX的epoll模型。
epoll模型,提供一种事件驱动机制,它可以监控多个事件是否准备好了,如果准备好了,那么就放入epoll队列中,这种机制是异步的。通过这样,WORKER进程只需要循环处理epoll队列中的请求,我们只需要在请求间不断切换,而这种切换是不需要付出什么代价的,通过这种循环处理已经准备好的请求,从而Nginx可以高效的处理高并发的问题。
epoll的优点
1) epoll是线程安全的。
2) 内部使用了mmap共享用户和内核的部分数据,避免了数据来回拷贝。
3) epoll基于事件驱动,epoll_ctl 注册事件并注册 callback 回调函数,epoll_wait 只返回发生的事件避免了像 select 和 poll 对事件的整个轮询操作。
配置文件结构
main
全局配置
events
设置nginx工作模式和连接数上限。
Nginx日志分为access_log(访问日志)和error_log(错误日志两种)。
访问日志主要记录客户端的请求。客户端向Nginx服务器发起的每一次请求都记录在这里。客户端 IP,浏览器信息,referer,请求处理时间,请求 URL 等都可以在访问日志中得到。
要记录哪些信息,可以通过 log_format 指令定义。
语法
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]]。
path:日志存放目录。
format:日志格式。
buffer:日志缓冲区大小。
flush:将缓冲区日志刷到磁盘的时间间隔。
gzip:日志压缩级别,取值: 1-9,默认为1。
if:如果指定的条件计算结果为0或空字符串,该请求不会记录日志。
示例:
access_log /var/logs/nginx-access.log buffer=32k gzip flush=1m;
作用域
access_log作用域分别为:http、server、loaction。
日志格式
log_format main '$remote_addr - $remote_user[$time_local] "request"'
'$status $body_bytes_sent "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"';
参数 | 含义 |
---|---|
$remote_addr | 客户端的地址 |
$remote_user | 远程客户端的用户名(一般为“-”) |
$time_loacal | 访问时间和时区 |
$request | 请求的url和请求方法 |
$status | 响应状态码 |
$body_bytes_send | 给客户端发送的文件内容字节数 |
$http_user_agent | 用户所使用的代理(一般为浏览器) |
$http_x_forwarded_for | 通过代理服务器来记录客户端ip |
$http_referer | 记录用户是通过哪个链接访问的 |
语法
error_log path [level]
path:日志存放目录。
Level:日志级别(默认全部级别)。级别有:debug、info、notice、warn、error、crit、alter、emerg。
示例(可以将不同级别分开存储):
error_log logs/error.log;
error_log logs/error_notice.log notice;
error_log logs/error_info.log info;
语法
location [=|~|~*|^~] /uri/ {… }
匹配规则优先级
精准匹配(=)命中时,停止匹配。
普通匹配(指定非正则)命中时,取最长,停止匹配。
普通匹配(未指定非正则)命中时,取最长,继续走正则匹配。
按配置顺序匹配正则,命中即停止匹配。
语法
rewrite regex replacement [flag];
regex:正则。
replacement:替换成的新值。
flag:后续处理标志。
flag取值说明:
1) break发生nginx内部重定向,path值更新,rewrite停止,原流程逻辑继续往下走。
2) last发生nginx内部重定向,path值更新,rewrite层面中断。控制流程刷新,重新进入location匹配。
3) redirect/permanent发生页面重定向(302 临时重定向/ 301 永久重定向),nginx 流程结束,返回响应给浏览器。
4) 为空时,发生nginx内部重定向,rewrite继续,最后一个rewrite完毕,控制流程刷新,重新进入location匹配。
语法
upstream 负载名称 {
[ip_hash];
server ip:port [weight] [down];
}
ip_hash:同一客户端请求发往同一服务器。
weight:指负载权重,用于后端服务器性能不均的情况。标记为down的server不参数负载。
使用
location / {
proxy_pass http://负载名称;
}
server {
listen 80;
server_name jdiy.xyz;
#是否允许请求带有验证信息
add_header Access-Control-Allow-Credentials true;
#允许跨域访问的域名,可以是一个域的列表,也可以是通配符 *
add_header Access-Control-Allow-Origin http://static.enjoy.com;
#多个域名配置(条件匹配多个)
#if ($http_origin ~* "\.enjoy\.com$") {
# set $origin $http_origin;
#}
#add_header Access-Control-Allow-Origin $origin;
#允许脚本访问的返回头
add_header Access-Control-Allow-Headers 'x-requested-with,content-type,Cache-Control,Pragma,Date,x-timestamp';
#允许使用的请求方法,以逗号隔开
add_header Access-Control-Allow-Methods 'POST,GET,OPTIONS,PUT,DELETE';
#允许自定义的头部,以逗号隔开,大小写不敏感
add_header Access-Control-Expose-Headers 'WWW-Authenticate,Server-Authorization';
#P3P支持跨域cookie操作
add_header P3P 'policyref="/w3c/p3p.xml", CP="NOI DSP PSAa OUR BUS IND ONL UNI COM NAV INT LOC"';
if ($request_method = 'OPTIONS') {##OPTIONS类的请求,是跨域先验请求
return 204;##204代表ok
}
location / {
proxy_pass http://192.168.114.1:8080
}
}
server {
listen 80;
server_name static.jdiy.xyz;
location /static {
valid_referers *.jdiy.xyz;
if ($invalid_referer) {return 404;}
root static/images;
}
}
server {
listen 80;
server_name static.jdiy.xyz;
location ~ /(.*)\.(html|js|css|png)$ {
gzip on; # 启用gzip压缩,默认是off,不启用
# 对js、css、jpg、png、gif格式的文件启用gzip压缩功能
gzip_types application/javascript text/css image/jpeg image/png image/gif;
gzip_min_length 1024; # 所压缩文件的最小值,小于这个的不会压缩
gzip_buffers 4 1k; # 设置压缩响应的缓冲块的大小和个数,默认是内存一个页的大小
gzip_comp_level 1; # 压缩水平,默认1。取值范围1-9,取值越大压缩比率越大,但越耗cpu时间
root /etc/nginx/html/gzip;
}
}
server {
listen 80;
server_name static.jdiy.xyz;
location ^~ /chrome.png {
expires 2m; #缓存2分钟
root /etc/nginx/html/gzip;
}
}
server {
listen 443 ssl;
server_name jdiy.xyz;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server_nopass.key;
location / {
root html;
index a.html;
}
}