命令行控制:
1. 默认启动方式:
/usr/local/nginx/sbin/nginx
这里的路径是 ./configure 的默认路径, 如果有指定新的路径, 则在新路径的相应文档下. 默认启动时, 会读取默认路径下的默认配置文件 /usr/local/nginx/conf/nginx.conf
2. 另一种指定配置文件的启动方式:
使用 –c 参数指定.
/usr/local/nginx/sbin/nginx –c /tmp/nginx.conf
3. 另一种指定安装目录的启动方式:
使用 –p 参数
/usr/local/nginx/sbin/nginx -p /usr/local/nginx
4. 另一种指定全局配置的启动方式:
使用 –g 参数
/usr/local/nginx/sbin/nginx -g “pid /var/nginx/test.pid”
上面意味着会把pid文件写到 /var/nginx/test.pid中
-g 参数的约束条件是, 以-g方式启动的Nginx服务执行其他命令时, 需要把–g 参数也带上, 否则可能出现配置项不匹配的情形.
例如, 在关闭Nginx服务时候, 需要这样:
/usr/local/nginx/sbin/nginx -g “pid /var/nginx/test.pid” –s stop
如果不带上全局变量, 那么就找不到Nginx服务master进程的pid了
5. 测试配置信息是否正确
在不启动Nginx情况下, 测试配置文件是否有错误
/usr/local/nginx/sbin/nginx -t
6. 在测试配置阶段不输出信息
/usr/local/nginx/sbin/nginx -q
可以不把errer级别以下的信息输出到屏幕
7. 显示版本信息
/usr/local/nginx/sbin/nginx –v
8. 显示编译阶段的信息
/usr/local/nginx/sbin/nginx –V
9. 快速停止服务
/usr/local/nginx/sbin/nginx -s stop
相当于向服务master进程发送SIGINT或是SIGTERM信号
kill -s SIGINT pid
kill -s SIGTERM pid
服务会立刻终止, 不管是否当前正在处理连接
10. 优雅的停止服务
/usr/local/nginx/sbin/nginx -s quit
或发送信号给master进程:
kill –s SIGQUIT masterpid
如果想要优雅的停止某个工作进程, 可以发送WINCH信号
Kill -s SIGWINCH workerpid
11. 使运行中的Nginx重新读取配置并生效
/usr/local/nginx/sbin/nginx -s reload
或发送信号
kill –s SIGHUP pid
12. 日志文件回滚
/usr/local/nginx/sbin/nginx -s reopen
或发生信号:
Kill -s SIGUSR1 pid
这样可以重新打开日志文件. 具体就是先把当前日志文件改名或者移动到别的地方去, 在以O_CREAT的方式重新打开这个文件名. 这样就能使日志文件不过于大
13. 平滑升级Nginx
当Nginx版本需要升级时, 通常需要将旧的二进制可执行文件替换掉, 通常需要重启, 但Nginx支持不重启的版本平滑升级
具体步骤为:
A、 通知正在运行的Nginx版本准备升级. 向master进程发送USR2信号
kill -s SIGUSR2 pid
这样, 运行中的Nginx就会将pid重命名, 比如将 /usr/local/nginx/logs/nginx.pid重命名为/usr/local/nginx/logs/nginx.pid.oldbin,这样新的Nginx才有可能成功启动
B、 启动新版Nginx. 此时通过ps可以观察到同时又两个Nginx在运行
C、 通过kill向旧版发送SIGQUIT信号, 优雅的停止旧的版本. 这样就平滑升级完毕
Nginx模型初探
下面, 一段伪代码来总结Nginx的事件处理模型:
while (true) {
for t inrun_tasks: //将当前可以处理的事件处理掉
t.handler();
update_time(&now); //得到当前时间
timeout =ETERNITY; //先将超时设置为无穷大, 下面会在定时器红黑树中找出最小的timeout来替代无穷大, 找不到说明当前没有定时器需要处理, 也就不需要超时了
for t inwait_tasks: /* sorted already */ //在已经排序好的红黑树中寻找超时事件, 找到就处理
if(t.time <= now) {
t.timeout_handler();
} else{ //发现要在未来某时刻处理的事件, 那么设置好定时器, 给epoll去定时(前提说过了, 是排序好的)
timeout = t.time - now;
break;
}
nevents =poll_function(events, timeout);
for i innevents:
task t;
//有事件发生了, 设置好事件属性
if(events[i].type == READ) {
t.handler = read_handler;
} else{ /* events[i].type == WRITE */
t.handler = write_handler;
}
//加入事件处理队列, 过会儿统一处理
run_tasks_add(t);
}
为什么Nginx要按照master-worker方式同时启动多个进程呢?
1、 master进程不会对用户请求提供服务, 只用于管理真正提供服务的worker进程, 所以master进程可以是唯一的, 它仅专注于自己的纯管理工作, 为管理员提供命令行服务, 诸如启动, 停止, 重载配置文件, 平滑升级程序等. Master进程需要拥有较大的权限, worker进程的权限要小于或等于master进程. 比如当某worker进程发生错误导致coredump, master进程可以立即启动新的worker继续工作
2、 多个worker进程处理互联网请求, 不但提供服务的健壮性, 还能从微观上实现真正的多核并发处理. 这正是Apache与Nginx的不同之处, 在Apache上每个进程在一个时刻只处理一个请求, 如果希望Web服务器拥有更多的并发处理, 对于Apache来说, 需要把进程数或线程数设置更多, 一台机器几百上千个, 这样讲带来很多无意义的上下文切换开销. Nginx则不然, 一个worker进程可以同时处理的请求数只受限于内存大小
那么worker进程的数量多少个才是好呢?
每个worker进程都是单线程进程, 如果进程过程中不会出现阻塞式的调用, 那么有多少个CPU内核就应该配置多少个进程; 反之, 如果有阻塞式的出现, 那么要配置多些的进程
用HTTP proxy module配置一个反向代理服务器
反向代理是指用代理服务器来接收网络上的请求, 然后将请求转发给内部网络中的上游服务器, 并将从上游服务器得到的结果返回给网络上请求的客户端.
因为Nginx的强悍高并发高负载, 一般作为前端的服务器直接向客户提供静态文件服务. 但也有一些复杂多变的业务不适合放到Nginx上, 那么Nginx就会将请求转发到上游服务器处理, 如Apache, Tomcat等服务器
与其他反向代理服务器相比较,Nginx有其自己的特点
当客户端发来HTTP请求, Nginx不会立即转发到上游服务器,而是把用户的请求(包括HTTP包体)完整的接收到Nginx所在服务器的硬盘或内存中, 然后再向上游服务器发起连接, 把缓存的客户端请求转发到上游服务器. 而Squid等代理服务器会采用一边接收客户端请求一边发送到上游服务器的方式.
Nginx这种工作方式缺点是延长了一个请求的处理时间, 并增加了用于缓存处理请求的内存, 磁盘空间. 优点则是降低了上游服务器的负载, 尽量将压力放在Nginx上
之所以降低了上游服务器负载,是因为客户端与代理服务器走的是广域网, 错综复杂, 一个连接可能很久才完成. 而代理服务器与上游服务器则是走内网, 如果是Squid的方式, 上游服务器始终要维持这个连接, 对于上游服务器的并发能力提出了挑战. Nginx则是在完整接收后才提交给上游服务器, 这样一个客户与上游服务器的连接时间会被缩短很多, 这样就明显降低了上游服务器的并发压力
参考资料:
1. http://tengine.taobao.org/book
2. <<深入理解nginx模块开发与架构解析>>