- 传统上基于进程或线程模型架构的 Web 服务通过每进程或每线程处理并发连接请求,这势必会在网络和 I/O 操作时产生阻塞,其另一个必然结果则是对内存或 CPU 的利用率低下。生成一个新的进程/线程需要事先备好其运行时环境,这包括为其分配堆内存和栈内存,以及为其创建新的执行上下文等。这些操作都需要占用 CPU,而且过多的进程/线程还会带来线程抖动或频繁的上下文切换,系统性能也会由此进一步下降。
- 在设计的最初阶段,Nginx 的主要着眼点就是其高性能以及对物理计算资源的高密度利用,因此其采用了不同的架构模型。受启发于多种操作系统设计中基于“事件”的高级处理机制,nginx采用了模块化、事件驱动、异步、单线程及非阻塞的架构,并大量采用了多路复用及事件通知机制。在 Nginx 中,连接请求由为数不多的几个仅包含一个线程的进程 Worker 以高效的回环(run-loop)机制进行处理,而每个 Worker 可以并行处理数千个的并发连接及请求。
- 如果负载以 CPU 密集型应用为主,如 SSL 或压缩应用,则 Worker 数应与 CPU 数相同;如果负载以 IO 密集型为主,如响应大量内容给客户端,则 Worker 数应该为 CPU 个数的 1.5 或 2 倍。
- Nginx会按需同时运行多个进程:一个主进程(Master)和几个工作进程(Worker),配置了缓存时还会有缓存加载器进程(Cache Loader)和缓存管理器进程(Cache Manager)等。所有进程均是仅含有一个线程,并主要通过“共享内存”的机制实现进程间通信。主进程以root用户身份运行,而 Worker、Cache Loader 和 Cache manager 均应以非特权用户身份运行。
- 主进程主要完成如下工作:
- 1.读取并验正配置信息;
- 2.创建、绑定及关闭套接字;
- 3.启动、终止及维护worker进程的个数;
- 4.无须中止服务而重新配置工作特性;
- 5.控制非中断式程序升级,启用新的二进制程序并在需要时回滚至老版本;
- 6.重新打开日志文件,实现日志滚动;
- 7.编译嵌入式perl脚本;
- Worker 进程主要完成的任务包括:
- 1.接收、传入并处理来自客户端的连接;
- 2.提供反向代理及过滤功能;
- 3.nginx任何能完成的其它任务;
- Cache Loader 进程主要完成的任务包括:
- 1.检查缓存存储中的缓存对象;
- 2.使用缓存元数据建立内存数据库;
- Cache Manager 进程的主要任务:
- 1.缓存的失效及过期检验;
mkdir -p /data/docker/nginx/logs /data/docker/nginx/conf
vim /data/docker/nginx/conf/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 127.0.0.1 193.112.221.203 youmeek.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
}
docker pull nginx:1.12.2
docker run --name youmeek-nginx -p 80:80 -v /data/docker/nginx/logs:/var/log/nginx -v /data/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx:1.12.2
docker exec -it youmeek-nginx nginx -s reload
docker exec -it youmeek-nginx nginx -s stop
或者:docker stop youmeek-nginx
docker restart youmeek-nginx
yum install -y nginx
,同时增加了一个 nginx 用户组和用户vim /etc/nginx/nginx.conf
cd /etc/nginx/conf.d/
cd /usr/share/nginx/modules/
cd /usr/share/nginx/html
cd /var/log/nginx/
systemctl status nginx
systemctl start nginx
systemctl stop nginx
nginx -s reload
nginx -V
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/local/nginx/nginx.pid \
--lock-path=/var/lock/nginx/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--with-http_ssl_module \
--with-http_stub_status_module \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/usr/local/nginx-module-vts
yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel
mkdir -p /usr/local/nginx /var/log/nginx /var/temp/nginx /var/lock/nginx
wget http://nginx.org/download/nginx-1.8.1.tar.gz
tar zxvf nginx-1.8.1.tar.gz
cd nginx-1.8.1/
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/local/nginx/nginx.pid \
--lock-path=/var/lock/nginx/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--with-http_ssl_module \
--with-http_stub_status_module \
--http-scgi-temp-path=/var/temp/nginx/scgi
make
make install
cd /usr/local/nginx;ll
,正常的效果应该是显示这样的:drwxr-xr-x. 2 root root 4096 3月 22 16:21 conf
drwxr-xr-x. 2 root root 4096 3月 22 16:21 html
drwxr-xr-x. 2 root root 4096 3月 22 16:21 sbin
nginx -V
nginx version: nginx/1.8.0
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/usr/local/nginx --pid-path=/usr/local/nginx/run/nginx.pid --lock-path=/usr/local/nginx/lock/nginx.lock --with-http_ssl_module --with-http_dav_module --with-http_flv_module --with-http_gzip_static_module --with-http_stub_status_module
service iptables stop
sudo iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
sudo service iptables save
sudo service iptables restart
/usr/local/nginx/sbin/nginx
,启动完成 shell 是不会有输出的ps aux | grep nginx
,正常是显示 3 个结果出来 netstat -ntulp | grep 80
192.168.1.114
,如果能看到:Welcome to nginx!
,即可表示安装成功/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx -s reload
/usr/local/nginx/sbin/nginx -s stop
vim /var/log/nginx/error.log
vim /etc/init.d/nginx
#!/bin/bash
#nginx执行程序路径需要修改
nginxd=/usr/local/nginx/sbin/nginx
# nginx配置文件路径需要修改
nginx_config=/usr/local/nginx/conf/nginx.conf
# pid 地址需要修改
nginx_pid=/var/local/nginx/nginx.pid
RETVAL=0
prog="nginx"
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -x $nginxd ] || exit 0
# Start nginx daemons functions.
start() {
if [ -e $nginx_pid ];then
echo "nginx already running...."
exit 1
fi
echo -n $"Starting $prog: "
daemon $nginxd -c ${nginx_config}
RETVAL=$?
echo
[ $RETVAL = 0 ] && touch /var/lock/subsys/nginx
return $RETVAL
}
# Stop nginx daemons functions.
# pid 地址需要修改
stop() {
echo -n $"Stopping $prog: "
killproc $nginxd
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f /var/lock/subsys/nginx /var/local/nginx/nginx.pid
}
# reload nginx service functions.
reload() {
echo -n $"Reloading $prog: "
#kill -HUP `cat ${nginx_pid}`
killproc $nginxd -HUP
RETVAL=$?
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
reload)
reload
;;
restart)
stop
start
;;
status)
status $prog
RETVAL=$?
;;
*)
echo $"Usage: $prog {start|stop|restart|reload|status|help}"
exit 1
esac
exit $RETVAL
chmod 755 /etc/init.d/nginx
service nginx start
service nginx stop
service nginx restart
使用新的参数configure
后执行make
重新编译,注意之后不要执行make install
.新构建的Nginx会在objs
目录下
备份旧的Nginx cp 老的nginx目录/sbin/nginx 老的nginx目录/sbin/nginx.old
复制新的Nginx cp ./objs/nginx 老的nginx目录/sbin/
,可能提示Nginx被占用,如果是则强制覆盖即可.
检查下Makefile的更新指令 cat Makefile
,检查下路径是否匹配,一般没什么问题毕竟是根据你的参数生成的文件.
upgrade:
/usr/local/nginx/sbin/nginx -t
kill -USR2 `cat /var/local/nginx/nginx.pid`
sleep 1
test -f /var/local/nginx/nginx.pid.oldbin
kill -QUIT `cat /var/local/nginx/nginx.pid.oldbin`
更新 make upgrade
yum install httpd-tools
htpasswd -c /opt/nginx-auth/passwd.db myusername,回车之后输入两次密码
server {
...
location / {
auth_basic "please input you user name and password";
auth_basic_user_file /opt/nginx-auth/passwd.db;
....
}
}
vim /usr/local/nginx/conf/nginx.conf
user root;#我这里习惯使用 root,所以这里需要这样设置。如果你有为你的 nginx 专门配置一个用户,这里需要改为你的用户
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;
}
}
}
service iptables stop
,防止出现特别干扰vim /usr/local/nginx/conf/nginx.conf
user root;#我这里习惯使用 root,所以这里需要这样设置。如果你有为你的 nginx 专门配置一个用户,这里需要改为你的用户
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 一个 server 代表一个虚拟主机
server {
listen 80;
server_name localhost;
location / {
# 虚拟机根目录是 /usr/local/nginx/html 目录
root html;
# 虚拟机首页是 /usr/local/nginx/html 目录下这两个文件
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
# 第二个虚拟机的端口是 90,服务地址还是本地
listen 90;
server_name localhost;
location / {
root html90;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
user root;#我这里习惯使用 root,所以这里需要这样设置。如果你有为你的 nginx 专门配置一个用户,这里需要改为你的用户
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 一个 server 代表一个虚拟主机
server {
listen 80;
# 两个虚拟主机都使用 80 端口,设置不同域名
server_name code.youmeek.com;
location / {
# 虚拟机根目录是 /usr/local/nginx/html 目录
root html;
# 虚拟机首页是 /usr/local/nginx/html 目录下这两个文件
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
# 两个虚拟主机都使用 80 端口,设置不同域名
server_name i.youmeek.com;
location / {
root html-i;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
最精简的环境:一台虚拟机
Nginx 配置:
user root;#我这里习惯使用 root,所以这里需要这样设置。如果你有为你的 nginx 专门配置一个用户,这里需要改为你的用户
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 自己定义的两个 tomcat 请求地址和端口
# 也就是当浏览器请求:tomcat.youmeek.com 的时候从下面这两个 tomcat 中去找一个进行转发
upstream tomcatCluster {
server 192.168.1.114:8080;
server 192.168.1.114:8081;
# 添加 weight 字段可以表示权重,值越高权重越大,默认值是 1,最大值官网没说,一般如果设置也就设置 3,5,7 这样的数
# 官网:https://www.nginx.com/resources/admin-guide/load-balancer/#weight
# server 192.168.1.114:8080 weight=2;
# server 192.168.1.114:8081 weight=1;
}
server {
listen 80;
server_name tomcat.youmeek.com;
location / {
proxy_pass http://tomcatCluster;
index index.html index.htm;
}
}
}
certificate.crt
,private.key
openssl pkcs12 -export -in certificate.crt -inkey private.key -out youmeek.p12 -name youmeek -CAfile certificate.crt -caname -chain
keytool -importkeystore -v -srckeystore youmeek.p12 -srcstoretype pkcs12 -srcstorepass 123456 -destkeystore youmeek.keystore -deststoretype jks -deststorepass 123456
vim /usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 如果访问 http 也直接跳转到 https
server {
listen 80;
server_name sso.youmeek.com;
return 301 https://$server_name$request_uri;
}
# crt 和 key 文件的存放位置根据你自己存放位置进行修改
server {
listen 443;
server_name sso.youmeek.com;
ssl on;
ssl_certificate /opt/ssl/certificate.crt;
ssl_certificate_key /opt/ssl/private.key;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
listen 443 ssl;
ssl_certificate /opt/jar/ssl/server.crt;
ssl_certificate_key /opt/jar/ssl/server.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
yum install -y httpd-tools
ab -n 1000 -c 100 http://www.baidu.com/
-n 总的请求数
-c 单个时刻并发数
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking juejin.im (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx
Server Hostname: juejin.im
Server Port: 443
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256
Document Path: /
Document Length: 271405 bytes
Concurrency Level: 100(并发数:100)
Time taken for tests: 120.042 seconds(一共用了 120 秒)
Complete requests: 1000(总的请求数:1000)
Failed requests: 0(失败的请求次数)
Write errors: 0
Total transferred: 271948000 bytes
HTML transferred: 271405000 bytes
Requests per second: 8.33 [#/sec] (mean)(QPS 系统吞吐量,平均每秒请求数,计算公式 = 总请求数 / 总时间数)
Time per request: 12004.215 [ms] (mean)(毫秒,平均每次并发 100 个请求的处理时间)
Time per request: 120.042 [ms] (mean, across all concurrent requests)(毫秒,并发 100 下,平均每个请求处理时间)
Transfer rate: 2212.34 [Kbytes/sec] received(平均每秒网络流量)
Connection Times (ms)
min mean[+/-sd] median max
Connect: 57 159 253.6 77 1002
Processing: 1139 11570 2348.2 11199 36198
Waiting: 156 1398 959.4 1279 22698
Total: 1232 11730 2374.1 11300 36274
Percentage of the requests served within a certain time (ms)
50% 11300
66% 11562
75% 11863
80% 12159
90% 13148
95% 15814
98% 18882
99% 22255
100% 36274 (longest request)
worker_processes 1;
events {
# 每一个进程可以打开的最大连接数(这个参数是受限制于系统参数的,默认是 1024)(进程数是上面 worker_processes 决定的)
worker_connections 1024;
# 可以一次建立多个连接
multi_accept on;
# epoll 模式效率最高
use epoll;
}
http {
sendfile on; # 减少文件在应用和内核之间的拷贝
tcp_nopush on; # 当数据包达到一定大小再发送
keepalive_timeout 65;
upstream tomcatCluster {
server 192.168.1.114:8080;
server 192.168.1.114:8081;
keepalive 300; # 300 个长连接
}
}
http {
gzip on;
gzip_buffers 8 16k; # 这个限制了nginx不能压缩大于128k的文件
gzip_min_length 512; # 单位byte
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
gzip_http_version 1.1; # 1.0 的版本可能会有问题
gzip_types text/plain text/css application/javascript application/x-javascript application/json application/xml;
}
vim /etc/sysctl.conf
net.ipv4.tcp_fin_timeout = 10 #保持在FIN-WAIT-2状态的时间,使系统可以处理更多的连接。此参数值为整数,单位为秒。
net.ipv4.tcp_tw_reuse = 1 #开启重用,允许将TIME_WAIT socket用于新的TCP连接。默认为0,表示关闭。
net.ipv4.tcp_tw_recycle = 0 #开启TCP连接中TIME_WAIT socket的快速回收。默认值为0,表示关闭。
net.ipv4.tcp_syncookies = 1 #开启SYN cookie,出现SYN等待队列溢出时启用cookie处理,防范少量的SYN攻击。默认为0,表示关闭。
net.core.somaxconn = 1024 #定义了系统中每一个端口最大的监听队列的长度, 对于一个经常处理新连接的高负载 web服务环境来说,默认值为128,偏小。
sysctl -p
vim /etc/security/limits.conf
* soft nofile 262144
* hard nofile 262144
* soft core unlimited
* soft stack 262144
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/local/nginx/nginx.pid \
--lock-path=/var/lock/nginx/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--with-http_ssl_module \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--with-http_stub_status_module
location /nginx_status {
allow 127.0.0.1;
deny all;
stub_status on;
access_log off;
}
allow 127.0.0.1;
表示只允许本机访问:http://127.0.0.1/nginx_status 才能看到deny all;
除了被允许的,其他所有人都不可以访问Active connections: 1
server accepts handled requests
3 6 9
Reading: 0 Writing: 5 Waiting: 0
= 开头表示精确匹配
^~ 开头表示uri以某个常规字符串开头,不是正则匹配
~ 开头表示区分大小写的正则匹配;
~* 开头表示不区分大小写的正则匹配
/ 通用匹配, 如果没有其它匹配,任何请求都会匹配到
location / {
}
location /user {
}
location = /user {
}
location /user/ {
}
location ^~ /user/ {
}
location /user/youmeek {
}
location ~ /user/youmeek {
}
location ~ ^(/cas/|/casclient1/|/casclient2/|/casclient3/) {
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico|woff|woff2|ttf|eot|txt)$ {
}
location ~ .*$ {
}
location /aa/ {
if ( $args ~* '(.*bb.*)' ) {
return 601;
}
}
location /aa/ {
if ($args ~ tag=bb){
return 601;
}
}
mkdir -p /data/nginx/log/logs
mkfifo /data/nginx/log/access_log.log
nohup cat /data/nginx/log/access_log.log | /usr/sbin/cronolog /data/nginx/log/logs/access-%Y-%m-%d.log &
nohup cat /data/nginx/log/access_log.log | /usr/sbin/cronolog /data/nginx/log/logs/access-%Y-%m.log &
access_log /data/nginx/log/access_log.log;
在配置文件中设置自定义缓存以限制缓冲区溢出攻击的可能性 client_body_buffer_size 1K; client_header_buffer_size 1k; client_max_body_size 1k; large_client_header_buffers 2 1k;
将timeout设低来防止DOS攻击 所有这些声明都可以放到主配置文件中。 client_body_timeout 10; client_header_timeout 10; keepalive_timeout 5 5; send_timeout 10;
限制用户连接数来预防DOS攻击 limit_zone slimits $binary_remote_addr 5m; limit_conn slimits 5;
前提:
一般情况 CentOS 是装有:logrotate,你可以检查下:rpm -ql logrotate
,如果有相应结果,则表示你也装了。
logrotate 配置文件一般在:
针对 nginx 创建自定义的配置文件:vim /etc/logrotate.d/nginx
文件内容如下:
/var/log/nginx/access.log /var/log/nginx/error.log {
create 644 root root
notifempty
daily
rotate 15
missingok
dateext
sharedscripts
postrotate
if [ -f /var/local/nginx/nginx.pid ]; then
kill -USR1 `cat /var/local/nginx/nginx.pid`
fi
endscript
}
/var/log/nginx/access.log /var/log/nginx/error.log:多个文件用空格隔开,也可以用匹配符:/var/log/nginx/*.log
notifempty:如果是空文件的话,不转储
create 644 root root:create mode owner group 转储文件,使用指定的文件模式创建新的日志文件
调用频率,有:daily,weekly,monthly可选
rotate 15:一次将存储15个归档日志。对于第16个归档,时间最久的归档将被删除。
sharedscripts:所有的日志文件都轮转完毕后统一执行一次脚本
missingok:如果日志文件丢失,不报错继续执行下一个
dateext:文件后缀是日期格式,也就是切割后文件是:xxx.log-20131216.gz 这样,如果注释掉,切割出来是按数字递增,即前面说的 xxx.log-1 这种格式
postrotate:执行命令的开始标志
endscripthttp:执行命令的结束标志
if 判断的意思不是中止Nginx的进程,而是传递给它信号重新生成日志,如果nginx没启动不做操作
手动执行测试:/usr/sbin/logrotate -vf /etc/logrotate.d/nginx
参数:‘-f’选项来强制logrotate轮循日志文件,‘-v’参数提供了详细的输出。
验证是否手动执行成功,查看 cron 的日志即可:grep logrotate /var/log/cron
设置 crontab 定时任务:vim /etc/crontab
,添加下面内容:
//每天02点10分执行一次
10 02 * * * /usr/sbin/logrotate -f /etc/logrotate.d/nginx