LINUX -nginx服务安装

了解Nginx

nginx会以daemon的方式在后台运行。后台进程包含一个master进程和多个worker进程。

master进程:
主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程

worker进程:
处理基本的网络事件,各进程互相之间是独立的。worker进程的个数,一般与机器cpu核数一致.

Nginx 的进程模型

从进程模型图可以看出,我们想要操作nginx,只需要与master通信即可。

master进程在接受信号是怎么做的呢?
输入如下命令行

1
kill -HUP pid

这个命令是优雅地重启nginx。当master进程收到信号后,因为是优雅地重启,所以服务器不会中断。而是重新加载配置文件,然后新开worker进程,再向旧的worker进程发送关闭指令。这种直接发送信号给master进程的操作方式已经显得有些老了,在0.8版本后,引入了一系列命令行参数。

1
nginx -s reload

这是一个重新加载配置的命令。在执行命令时,它会向master进程发送信号,同样也是启动一个新的worker进程,再关闭掉旧的worker进程。

worker 进程又是怎么做的??

首先,在master进程里,比方说一个80端口的http服务,会建立好需要listen的sokcet(listenfd),然后再fork出多个worker进程。在新的请求到来时,所有worker进程的listenfd变为可读,然后开始抢锁,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接,开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端。一个请求,完全由worker进程来处理,而且只在一个worker进程中处理。

好处:独立进程,不需要加锁,所以省掉了锁带来的开销。其次,worker进程间互相之间不会影响。

nginx事件模型

对于一个基本的web服务器来说,事件通常有三种类型,网络事件、信号、定时器

网络事件

nginx采用了异步非阻塞的方式来处理请求,可以同时处理成千上万个请求。

请求的完整过程:请求过来,建立连接,然后再接收数据,接收数据后,再发送数据。具体到系统底层,就是读写事件,而当读写事件没有准备好时,必然不可操作。

网络事件模型 说明
阻塞式 事件没准备好,等。在等待中,cpu会让出去。 那么,会造成,网络事件一多,大家都在等,cpu都让出去了但是没人用,cpu使用率都不高,还谈高并发??? 尤其是单线程的worker了,更不合适。
非阻塞式 事件没准备好,马上返回EAGAIN,然后间断性再次访问,直到事件准备完成。 好处是确实可以做更多其他的事情,但开销也增加了。
异步非阻塞 对于事件,它是阻塞的。但是,它不是盲目的等待,而是设定了一段超时时间。 在超时时间内事件准备好了,就返回

epoll(一个异步非阻塞机制的函数)为例:

1 当事件没准备好时,放到epoll里面;
2 事件准备好了,就去读写;
3 当读写返回EAGAIN时,将它再次加入到epoll里面;
4 线程只有一个,所以只能处理一个请求。但可以在请求里切换,再多的并发数,zhi会占用更多的内存而已;

所以说,worker数等于cpu数的原因。就是因为如此,反而事更多的worker数,只会导致cpu资源的竞争,从而带来不必要的上下文切换。

信号

信号会中断掉程序当前的运行,在改变状态后,继续执行。如果是系统调用,则可能会导致系统调用的失败,需要重入。关于信号的处理,大家可以学习一些专业书籍,这里不多说。对于nginx来说,如果nginx正在等待事件(epoll_wait时),如果程序收到信号,在信号处理函数处理完后,epoll_wait会返回错误,然后程序可再次进入epoll_wait调用。

Nginx定时器

由于epoll_wait等函数在调用的时候是可以设置一个超时时间的,所以nginx借助这个超时时间来实现定时器。nginx里面的定时器事件是放在一颗维护定时器的红黑树里面,每次在进入epoll_wait前,先从该红黑树里面拿到所有定时器事件的最小时间,在计算出epoll_wait的超时时间后进入epoll_wait。所以,当没有事件产生,也没有中断信号时,epoll_wait会超时,也就是说,定时器事件到了。这时,nginx会检查所有的超时事件,将他们的状态设置为超时,然后再去处理网络事件。由此可以看出,当我们写nginx代码时,在处理网络事件的回调函数时,通常做的第一个事情就是判断超时,然后再去处理网络事件。

Nginx事件处理伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
while (true) {
for t in run_tasks:
t.handler();
update_time(&now);
timeout = ETERNITY;
for t in wait_tasks: /* sorted already */
if (t.time <= now) {
t.timeout_handler();
} else {
timeout = t.time - now;
break;
}
nevents = poll_function(events, timeout);
for i in nevents:
task t;
if (events[i].type == READ) {
t.handler = read_handler;
} else { /* events[i].type == WRITE */
t.handler = write_handler;
}
run_tasks_add(t);
}

Connection

在nginx中connection就是对tcp连接的封装,其中包括连接的socket,读事件,写事件

安装

一、安装编译工具及库文件

1
yum -y install make zlib zlib-devel gcc-c++ libtool  openssl openssl-devel

二、首先要安装 PCRE

PCRE 作用是让 Nginx 支持 Rewrite 功能。

1、下载 PCRE 安装包,下载地址: http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz

1
2
[root@bogon src]# cd /usr/local/src/
[root@bogon src]# wget http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz

2、解压安装包:

1
[root@bogon src]# tar zxvf pcre-8.35.tar.gz

3、进入安装包目录

1
[root@bogon src]# cd pcre-8.35

4、编译安装

1
2
[root@bogon pcre-8.35]# ./configure
[root@bogon pcre-8.35]# make && make install

5、查看pcre版本

1
[root@bogon pcre-8.35]# pcre-config --version

三、安装 Nginx

1、下载 Nginx,下载地址:http://nginx.org/download/nginx-1.6.2.tar.gz

1
2
[root@bogon src]# cd /usr/local/src/
[root@bogon src]# wget http://nginx.org/download/nginx-1.6.2.tar.gz

2、解压安装包

1
[root@bogon src]# tar zxvf nginx-1.6.2.tar.gz

3、进入安装包目录

1
[root@bogon src]# cd nginx-1.6.2

4、编译安装

1
2
3
[root@bogon nginx-1.6.2]# ./configure --prefix=/usr/local/webserver/nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre=/usr/local/src/pcre-8.35
[root@bogon nginx-1.6.2]# make
[root@bogon nginx-1.6.2]# make install

5、查看nginx版本

1
[root@bogon nginx-1.6.2]# /usr/local/webserver/nginx/sbin/nginx -v

到此,nginx安装完成。

Nginx 配置

创建 Nginx 运行使用的用户 www:

1
2
[root@bogon conf]# /usr/sbin/groupadd www 
[root@bogon conf]# /usr/sbin/useradd -g www www

配置nginx.conf ,将/usr/local/webserver/nginx/conf/nginx.conf替换为以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
[root@bogon conf]#  cat /usr/local/webserver/nginx/conf/nginx.conf

user www www;
worker_processes 2; #设置值和CPU核心数一致
error_log /usr/local/webserver/nginx/logs/nginx_error.log crit; #日志位置和日志级别
pid /usr/local/webserver/nginx/nginx.pid;
#Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile 65535;
events
{
use epoll;
worker_connections 65535;
}
http
{
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';

#charset gb2312;

server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 8m;

sendfile on;
tcp_nopush on;
keepalive_timeout 60;
tcp_nodelay on;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;

#limit_zone crawler $binary_remote_addr 10m;
#下面是server虚拟主机的配置
server
{
listen 80;#监听端口
server_name localhost;#域名
index index.html index.htm index.php;
root /usr/local/webserver/nginx/html;#站点目录
location ~ .*\.(php|php5)?$
{
#fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico)$
{
expires 30d;
# access_log off;
}
location ~ .*\.(js|css)?$
{
expires 15d;
# access_log off;
}
access_log off;
}

}

配置文件详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
########### 每个指令必须有分号结束。#################
#user administrator administrators; #配置用户或者组,默认为nobody nobody。
#worker_processes 2; #允许生成的进程数,默认为1
#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; #最大连接数,默认为512
}
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型,默认为text/plain
#access_log off; #取消服务日志
log_format myFormat '$remote_addr$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式
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 mysvr {
server 127.0.0.1:7878;
server 192.168.10.121:3333 backup; #热备
}
error_page 404 https://www.baidu.com; #错误页
server {
keepalive_requests 120; #单连接请求上限次数。
listen 4545; #监听端口
server_name 127.0.0.1; #监听地址
location ~*^.+$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
#root path; #根目录
#index vv.txt; #设置默认页
proxy_pass http://mysvr; #请求转向mysvr 定义的服务器列表
deny 127.0.0.1; #拒绝的ip
allow 172.18.5.54; #允许的ip
}
}
}

检查配置文件nginx.conf的正确性命令:

1
[root@bogon conf]# /usr/local/webserver/nginx/sbin/nginx -t

修改完conf文件,则应重启nginx软件(不推荐)

systemctl restart nginx

一般重新加载nginx软件

systemctl reload nginx

然后关闭防火墙

systemctl stop firewalld

开机启动nginx

systemctl enable nginx

关闭开机启动nginx

systemctl disable nginx

防火墙同理