创作不易,如果觉得这篇文章对你有帮助,欢迎各位老铁点个赞呗,您的支持是我创作的最大动力!
上一篇 高性能web服务器之Nginx使用详解 中,介绍了Nginx的环境搭建,以及一些基础的使用,本文将介绍一些Nginx使用时的高级应用。
下面简单介绍下Nginx的核心配置文件/usr/local/nginx/conf/nginx.conf
,更详细的配置,可以参考我的另一篇博文:https://blog.csdn.net/smilehappiness/article/details/106676066
nginx文件结构如下:
... #全局块
events { #events块
...
}
http { #http块
... #http全局块
server { #server块
... #server全局块
location [PATTERN] { #location块
...
}
location [PATTERN]{
...
}
}
server{
...
}
... #http全局块
}
全局块
该全局块配置影响nginx全局的指令。全局配置,一般包含运行nginx服务器的用户组
,nginx进程pid存放路径
,日志存放路径
,配置文件引入
,允许生成worker process数
等。
events块
配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数
,选取哪种事件驱动模型处理连接请求
,是否允许同时接受多个网路连接
,开启多个网络连接序列化
等。
http块
可以嵌套多个server
,配置代理
,缓存
,日志定义
等绝大多数功能和第三方模块
的配置。
比如: 文件引入
,mime-type定义
,日志自定义
,是否使用sendfile传输文件
,连接超时时间
,单连接请求数
等。
server块
配置虚拟主机的相关参数,一个http中可以有多个server。
location块
配置请求的路由,以及页面资源的映射路径等。
注:
块配置项一定会用大括号把一系列所属的配置项全包含进来,块配置项可以嵌套,内层块直接继承外层块,当内外层块中的配置发生冲突时,以内层块为准。
下面给大家上一个配置文件,方便老铁们理解
########### 每个指令必须有分号结束。#################
#user administrator administrators; #配置用户或者组,默认为nobody nobody
#worker_processes 2; #允许生成的进程数,默认为1,这里一般设置为cpu核心数相等
#pid /nginx/pid/nginx.pid; #指定nginx进程运行文件存放地址
error_log log/error.log debug; #指定日志路径,级别。这个设置可以放入全局块,http块,server块,级别依次为:debug|info|notice|warn|error|crit|alert|emerg
events {
accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on
multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off
#use epoll; #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
worker_connections 1024; #最大连接数(指定同一时间最多可开启的文件数,对于linux来说,一个进程就会开启一个文件去处理),默认为1024,可以设置为65535(ulimit -h 65535)
}
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型
#access_log off; #取消服务日志
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"'; #自定义配置 If the format is not specified then the predefined “combined” format is used.
access_log log/access.log myFormat; #combined为日志格式的默认值
sendfile on; #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块
sendfile_max_chunk 100k; #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限
keepalive_timeout 65; #连接超时时间,默认为75s,可以在http,server,location块中进行配置
upstream app{
server 127.0.0.1:9091;
server 127.0.0.1:9092 backup; #热备
}
server {
keepalive_requests 120; #单连接请求上限次数。
listen 80; #监听端口
server_name 127.0.0.1; #监听地址(ip或者域名)
error_page 404 500 https://www.baidu.com; #错误页
location ~*^.+$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
#root path; #根目录
#index index.html index.htm; #设置默认页
proxy_pass http://app; #请求转向app定义的服务器列表
deny 127.0.0.1; #拒绝的ip
allow 172.18.5.54; #允许的ip
}
}
}
上面是nginx的基本配置,需要注意的有以下几点:
惊群现象
:一个网路连接到来,多个睡眠的进程被同时叫醒,但只有一个进程能获得链接,这样会影响系统性能
每个指令必须有分号结束。
Nginx动静分离,指的是静态资源请求由Nginx 处理,动态资源请求由tomcat或其他web服务器处理。
Nginx主要用于部署静态资源,比如部署静态网站,如果我们是一个动态网站,比如Java开发的动态网站,那么动态网站里面肯定有一些静态资源,像图片、css、html、js、视频、音频、文档等等,这些静态资源如果使用tomcat等服务器部署,效率并不高,而采用nginx部署则大大提高性能。
在负载均衡服务器的服务器上, Nginx根据客户端请求的URI判断请求的是否为静态资源,如果请求的 URI包含了jpg、png、.js、.html等信息,则由处理静态请求的服务器处理(部署 Nginx)。如果请求的URI包含了 .php、.jsp等字段,则由处理动态请求的服务器处理(部署 Tomcat)。
动静分离是实际应用中常见的一种场景,动态资源,由tomcat或其他web服务器完成,静态资源,如图片、css、js等由nginx服务器完成。
动静分离充分发挥它们各自的优势,从而达到更高效合理的架构,如下图所示:
nginx中配置静态资源,有以下两种方式:
第一种方式
通过在nginx.conf
配置文件中添加静态资源的location
进行匹配,比如:
当访问静态资源的时候,从linux服务器的静态资源目录/opt/static
目录下获取(静态资源目录可以根据个人习惯设置)
location ~ .*\.(js|css|htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ {
root /opt/static;
}
location后面的参数说明:
~
表示正则匹配,也就是说后面的内容可以是正则表达式匹配
第一个点 .
表示匹配任意字符
*
表示匹配一个或多个字符
\
是转义字符,是后面这个点的转义字符
|
表示或者
$
表示结尾
整个配置表示以 .
后面括号里面的这些后缀结尾的文件都由nginx服务器处理
以上localtion匹配的最终效果:
访问资源的时候,如:http://域名/umi.js
、http://域名/app.css
、http://域名/index.html
、http://域名/hello.pdf
、http://域名/test.png
等,都可以通过Nginx服务器,映射到静态资源目录/opt/static
下,去获取资源。
第二种方式
通过在nginx.conf配置文件中配置静态资源所在目录实现,比如:
location ~ .*/(css|js|img|image) {
root /opt/static;
}
Localtion匹配的最终效果: hello/css、hello/js、hello/picture/img、*/image等
如,访问以下请求时,可以访问到目录下的资源
http://域名/css/index.css
、http://域名/admin/js/index.css
注意: nginx是把ip:80端口映射成你的root路径(比如笔者这里是 /opt/static
),假设你需要这样http://域名/css/index.css
访问资源,则需要配置资源的位置为: /opt/static/css/index.css
放置静态资源的目录,要注意一下目录权限问题,如果权限不足,可能会出现403错误,使用以下命令,给目录赋予权限 chmod 744 filename
Nginx动静分离,结合负载均衡一起使用,进行如下配置即可:
upstream app1 {
server ip:91 weight=3;
server 域名 weight=2;
}
location /admin{
proxy_pass http://app1;
}
location ~ .*/(css|js|img|image) {
root /opt/static;
}
以上配置中,请求http://ip/admin
,会分发到请求服务器,加载动态的数据,而请求http://ip/static/js/index.js
,就会直接访问nginx服务器下的静态资源
nginx服务,日志也是必不可少的,下面使用自定义日志配置:
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
与 $http_x_forwarded_for
用以记录客户端的ip地址
$remote_user
用来记录客户端用户名称
$time_local
用来记录访问时间与时区
$request
用来记录请求的url与http协议
$status
用来记录请求状态;成功是200
$body_bytes_sent
记录发送给客户端文件主体内容大小
$http_referer
用来记录从那个页面链接访问过来的
$http_user_agent
记录客户端浏览器的相关信息
官网日志配置: http://nginx.org/en/docs/http/ngx_http_log_module.html
当nginx服务器运行一段时间之后,日志文件特别的大,不方便查看日志,这时候,可以按照实际的情况,进行日志文件的切分。
使用以下命令:
/usr/local/nginx/sbin/nginx -s reopen
使用-s reopen
参数可以重新打开日志文件,这样可以先把当前日志文件改名或转移到其他目录中进行备份,再重新打开时就会生成新的日志文件,这个功能使得日志文件不至于过大 ,进行日志切分后,方便查找日志。
Linux下我们可以直接把日志文件mv走,但是当你mv移走后新的日志文件没有重新生成,一般linux下用的文件句柄
,文件被打开情况下你mv走文件,但是原来操作这个文件的进程还是有这个文件的inode等信息
,原进程还是读写原来的文件,而此时我们只需要执行一下reopen
,则会生成新的日志文件。
操作步骤:
/usr/local/nginx/sbin/nginx -s reopen
用来打开新日志文件,这样nginx会把新日志信息写入到这个新的日志文件中,这样就完成了日志的切割工作, 同时切割过程中没有日志的丢失。一般来说,不会手动进行日志的切割,通常会使用Linux的定时任务,去定周期的进行日志的切割,可以根据公司实际情况,根据日志产生的数据量,来合理的设置定时任务的周期。
(不会使用Linux定时任务的童鞋们,可以参考我的另一篇博文https://blog.csdn.net/smilehappiness/article/details/105180845脑补一下)
为了更高效地完成此工作,可以采用定时任务+脚本实现
脚本配置如下:
#!/bin/bash
date=`date +%Y%m%d%`
logpath1=/usr/local/nginx/logs/
logpath2=/opt/logs/nginx/
mv $logpath1/access.log $logpath2/access-$date.log
mv $logpath1/error.log $logpath2/error-$date.log
/usr/local/nginx/sbin/nginx -s reopen
日志的路径可以根据个人习惯指定,博主这里,把日志移动到/opt/logs/nginx/
路径下,所以需要创建
这个用来存放日志的目录/opt/logs/nginx/
,以后,我可以去这个路径下查看nginx的运行日志情况。
使用以下命令创建目录:
mkdir -pv /opt/logs/nginx/
-p表示递归创建 -v表示显示目录创建信息
如果没有Linux操作基础的童鞋们,可以参考博主的文章 Linux使用详解,10分钟带你玩转Linux基础操作 进行入门。
配置定时任务
首先,把上面的这个shell脚本,放到一个文件logCrontab.sh
中,并放到目录/usr/local/nginx/logs
下,接着,然后创建定时任务
使用命令:
crontab -e
添加如下内容,每日23点进行日志切割:
* 23 * * * /usr/local/nginx/logs/logCrontab.sh
然后就可以根据实际情况,完成日志的切割啦。
注意:
有可能没有执行权限:-bash: /usr/local/nginx/logs/logCrontab.sh: Permission denied
进入/usr/local/nginx/logs/
目录,使用以下命令,设置可执行权限:
chmod 777 logCrontab.sh
或者 chmod +x logCrontab.sh
可以使用以下命令,查看定时任务执行情况:
tail -f /var/log/cron
HTTPS (全称:Hyper Text Transfer Protocol over SecureSocket Layer),是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性 [1] 。HTTPS 在HTTP 的基础下加入SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。 HTTPS 存在不同于 HTTP 的默认端口及一个加密/身份验证层(在 HTTP与 TCP 之间)。这个系统提供了身份验证与加密通讯方法。它被广泛用于万维网上安全敏感的通讯,例如交易支付等方面 [2] 。(百度百科)
HTTPS 是以安全为目标的 HTTP 通道,即 HTTP 下加入 SSL 加密层,HTTPS 不同于 HTTP 的端口,HTTP默认端口为80,HTTPS默认端口为443,现在大部分网站都实现了https。
比如访问京东和百度:https:
//www.baidu.com/、https:
//www.jd.com/。
HTTP 协议虽然使用极为广泛, 但是却存在不小的安全缺陷, 主要是其数据的明文传送和消息完整性检测的缺乏, 而这两点恰好是网络支付, 网络交易等新兴应用中安全方面最需要关注的。
使用http容易被攻击,同事攻击者也可以从网络中获取普通用户的隐秘信息,包括手机号码,身份证号码,信用卡号等重要资料,导致严重的安全事故。
Nginx中配置HTTPS
比较简单,主要有以下两个步骤:
SSL证书
是一种数字证书,它使用Secure Socket Layer
协议在浏览器和Web服务器之间建立一条安全通道,从而实现:
1、数据信息在客户端和服务器之间的加密传输,保证双方传递信息的安全性,不可被第三方窃听;
2、用户可以通过服务器证书验证他所访问的网站是否真实可靠;
SSL证书主要有两个功能: 加密
和身份证明
,证书需要购买,比如:https://www.wosign.com
笔者这里,自己签发一个证书,用来演示。实际开发中,为了保证数据交互的安全性,在企业里面都会够买一个https的SSL证书,一般都是在阿里云或者腾讯云购买SSL证书,整个配置步骤都是完全一样的。
颁发不受浏览器信任的SSL证书:
通过openssl
来生成,如果Linux中没有安装openssl,需要安装一下
执行以下命令:
yum install openssl openssl-devel -y
具体步骤如下:
生成一个RSA密钥(私钥)
执行以下命令:
openssl genrsa -out nginx-private.key 2048
生成一个证书请求
执行以下命令:
openssl req -new -key nginx-private.key -out nginx-private.csr -subj "/C=CN/ST=ShangHai/L=ShangHai/O=smilehappiness Inc./OU=Web Security/CN=smilehappiness .cn"
参数说明:
C
字段:Country
,单位所在国家,为两位数的国家缩写,如:CN表示中国
ST
字段:State/Province
,单位所在州或省;
L
字段:Locality
,单位所在城市/或县区;
O
字段:Organization
,此网站的单位名称;
OU
字段:Organization Unit
,下属部门名称,也常常用于显示其他证书相关信息,如证书类型,证书产品名称或身份验证类型或验证内容等
CN
字段:Common Name
,网站的域名
自己签发SSL证书
执行以下命令:
openssl x509 -req -days 365 -in nginx-private.csr -signkey nginx-private.key -out nginx-private.crt
添加Nginx的ssl模块
支持,最终是要重新编译出一个新的nginx可执行程序
如果之前安装时没有加入ssl模块,则需要到解压的nginx
目录下执行
./configure --with-http_ssl_module
当执行上面语句,出现./configure: error: SSL modules require the OpenSSL library.
则需要安装openssl
执行以下命令:
yum -y install openssl openssl-devel
依赖错误解决后再执行./configure --with-http_ssl_module
然后执行make
命令,(得到一个新的nginx可执行程序)
注意:
不要make install
,否则会覆盖掉之前的nginx配置
备份原来的nginx(如果不需要原来的也可以不备份)
执行以下命令:
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.back
把新编译出来的nginx覆盖旧的
执行以下命令:
先停止nginx服务,然后再进行nginx可执行程序覆盖
/usr/local/nginx/sbin/nginx -s quit
cp ./objs/nginx /usr/local/nginx/sbin/nginx
当然啦,如果在第一次安装nginx时,都依赖了这个ssl模块,就不用这么麻烦了。
配置HTTPS server:
使用以下命令,编辑nginx.conf
vim /usr/local/nginx/conf/nginx.conf
server {
# Nginx 版本为 nginx/1.15.0 以上请使用 listen 443 ssl 代替 listen 443 和 ssl on
#listen 443 ssl;
# 禁止ip访问
listen 443 ssl default_server;
# 填写绑定证书的域名
server_name www.domain.cn;
# 禁止ip访问
server_name _;
# 证书文件名称
ssl_certificate /usr/local/nginx/nginx-private.crt;
# 私钥文件名称
ssl_certificate_key /usr/local/nginx/nginx-private.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
#请按照以下协议配置
#ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
#ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
大致配置都差不多,如果有问题,参照腾讯云或者阿里云配置即可。
配置参数说明:
ssl_session_cache shared:SSL:1m;
所有工作进程之间共享缓存,缓存大小以字节为单位指定,一兆字节可以存储大约4000个session,每个共享缓存都应该有一个任意名称,具有相同名称的缓存可以用于多个虚拟服务器,Nginx官方提示使用shared,性能会更高。
ssl_session_timeout 5m;
指定客户端可以重用会话参数的时间
ssl_ciphers HIGH:!aNULL:!MD5;
指定启用的密码,密码以OpenSSL库可以理解的格式指定
ssl_prefer_server_ciphers on
设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件
至此,SSL证书就配置完成了。
第一次访问,由于博主是自己生成的证书,浏览器不信任,会弹出红色警告,点继续访问就行了。如果是实际项目中,使用公司购买的SSL证书,SSL证书都是有效的,就会显示绿色,如:
官方文档: http://nginx.org/en/docs/http/configuring_https_servers.html
如果考虑安全性,可以设置禁止ip访问,这样黑客或者其他有心者,就不能通过ip或者他们的域名访问你的ip服务资源了。
具体配置也比较简单,如果是http访问,新添加如下server即可:
# http禁止IP直接访问网站
server {
listen 80 default;
server_name _;
return 403;
}
如果是https禁止ip访问,需要在ssl配置那里设置:
# https禁止IP直接访问网站(这种方式如果不好用,可以使用下面5.5中,域名的判断方式处理)
server {
# 禁止ip访问
listen 443 ssl default_server;
# 填写绑定证书的域名
server_name www.domain.cn;
# 禁止ip访问
server_name _;
return 403;
# 证书文件名称
ssl_certificate /usr/local/nginx/nginx-private.crt;
# 私钥文件名称
ssl_certificate_key /usr/local/nginx/nginx-private.key;
}
禁止访问如下所示:
一般来说,可以设置一些禁止访问的友好界面,看起来更好看。
worker_processes 4;
events {
worker_connections 65535;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
# 监听80端口
listen 80;
#填写绑定证书的域名
server_name www.domain.cn;
#把http的域名请求转成https,这个是HTTP自动跳转HTTPS的安全配置(可选)让其自动将HTTP的请求重定向到HTTPS
return 301 https://$host$request_uri;
# location / {
# root html;
# index index.html index.htm;
# }
}
server {
# Nginx 版本为 nginx/1.15.0 以上请使用 listen 443 ssl 代替 listen 443 和 ssl on
listen 443 ssl;
# 填写绑定证书的域名
server_name www.domain.cn;
# https禁止ip访问
if ($host != 'www.domain.cn') {
return 500;
}
# 证书文件名称
ssl_certificate /usr/local/nginx/nginx-private.crt;
# 私钥文件名称
ssl_certificate_key /usr/local/nginx/nginx-private.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
#请按照以下协议配置
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
#ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
# http禁止IP直接访问网站
server {
listen 80 default;
server_name _;
return 403;
}
}
更新中,敬请期待…
更新中,敬请期待…
本文参考资料:
Nginx官方文档: http://nginx.org/en/docs/
nginx配置:https://www.runoob.com/w3cnote/nginx-setup-intro.html
写博客是为了记住自己容易忘记的东西,另外也是对自己工作的总结,希望尽自己的努力,做到更好,大家一起努力进步!
如果有什么问题,欢迎大家评论,一起探讨,代码如有问题,欢迎各位大神指正!
给自己的梦想添加一双翅膀,让它可以在天空中自由自在的飞翔!