SDB:搭建LNMP服务器
目录
Apache 和 Nginx 的区别
Apache 占据了 HTTP 服务器市场的半壁江山,而 Nginx 则是近年来飞速发展的 HTTP 服务器。
相比老牌的 Apache,新贵 Nginx 有如下特点:
- 抗并发。Nginx 最早是俄罗斯人为了 Ramber.ru 这个本国访问量第二的搜索引擎专门开发的服务器软件,承受超大访问量是必然的设计要求。因此采用了异步非阻塞的设计,而 Apache 则是阻塞性的,因此在高并发的环境下面,Nginx 消耗的资源很小。Apache 在 200 个连接的时候,响应速度和资源占用就很可观了;而 Nginx 在 10000 个连接的时候,内存占用只有 2.5 M。因此如果有抗 DDOS 的需求,建议选用 Nginx。
- 高性能。Nginx 采用的是 Linux 内核中的 epoll 网络 IO 模型(freebsd 上是 kqueue),同时使用 C 语言编写,因此在这两个平台上,Nginx 使用的进程数非常少(Apache 是一个外部连接开一个进程处理,Nginx 是异步的所以一个进程可以处理多个外部连接),运行速度有行云流水之感。但是需要注意,如果你的主机内核未开启 epoll 或 kqueue 模块,那么你使用 Nginx 的性能是非常低的。而且高性能是相对的,Apache 使用的 select 模型对付少数静态文件的效率远高于 epoll 模型。
- 热部署。Nginx 改配置/升级不需要重启服务,Apache 需要,因此如果你的服务器有 High Availability 需求,建议选用 Nginx。
- 负载平衡与反向代理。所谓负载平衡,就是多台服务器来跑同一个站,把请求在它们之间平均分配,防止一个爆掉另一个没访问。反向代理就是,我只接收请求而不处理请求,而是将请求转发给有闲置资源的服务器来处理,我起到中间人的作用。Nginx 是为搜索引擎设计的,这方面要优越得多。
而缺点在于:
- 动态文件是鸡肋。Nginx 善于处理静态网页,而动态文件比如 PHP 则非常鸡肋,它甚至不支持直接处理 PHP,而要通过 FastCGI 来做,这点让很多新从 Apache 转到 Nginx 来的用户无法理解,安装的时候也总漏东西。
- 配置复杂。设计上,Nginx 拥有比 Apache 更简单的配置方式,甚至支持 Linux 内部非常普及的 perl/lua 语言。但现实上,Apache 装了就能用,你完全可以忘掉它,而 Nginx 要去编辑配置文件,容易并不代表不复杂,Nginx 的配置文件对于新人来说还是有点难度的。
- 模块少。两者都是模块化设计的,甚至 Nginx 的模块开发比 Apache 要简单,支持 C/Perl/Lua 等语言的开发。但问题是 Nginx 是新贵,模块比较少,在一些需求量很大的模块上面,性能不如 Apache,比如 rewrite 模块,Apache 的就要强大得多。
- buggy。Nginx 仍处在高速发展之中,因此稳定性要差一些(不是运行的稳定性,而是设计的稳定性,Nginx 跑得比 Apache 稳,但自身有 bug 有时会产生一些非预期行为)。
- 支持少。Apache 有比较成熟的社区,而 Nginx 表面看起来配置教学很多,但是写教学的那些人大部分根本不懂怎么回事。除了官方文档你很难找到能够帮助你的人。
选 Apache 还是 Nginx
如果你有钱,Nginx 做前台接收请求,Apache 集群做后台处理请求。如果你没钱:
- VPS 的内存都是很贵的。Nginx 带 Mysql 空跑的内存 35 MB 左右。用 Nginx 的个人站点内存占用很少上 100 MB。
- 你会不会配置,愿不愿意去学。Nginx 是要配置的。如果死活不会那么没办法。
而其它的抗并发、负载平衡、高性能甚至高在线率几乎都不在个人网站甚至不在小站的考虑之内。那些都是大门户要考虑的问题。
如果你更加没钱,那么抱歉,共享空间默认都是跑 Apache 的。你没得选。
安装
- 安装 nginx:
sudo zypper in nginx
- 安装 php5-fpm:
sudo zypper in php5-fpm
- 安装 Mysql:
openSUSE 12.3+:
sudo zypper in mariadb mariadb-tools php5-mysql
openSUSE 通用:
sudo zypper in mysql-community-server mysql-community-server-tools php5-mysql
开启防火墙端口
共性内容,见搭建LAMP服务器#开启防火墙端口。
配置 Nginx
nginx.conf
编辑 /etc/nginx/nginx.conf
sudo vi /etc/nginx/nginx.conf
里面已经给了一些 example,用注释形式关闭着。我们相应打开即可:
#user nginx;
改成:
user nginx nginx;
其中前面的是名为 nginx 的用户,后面是名为 nginx 的组,它们在安装 nginx 软件包的时候就加好了。
worker_processes 1;
这个改成你的 CPU 数量:
cat /proc/cpuinfo
看里面的"cpu cores",我这里是 4,于是改成:
worker_processes 4;
前面介绍 nginx 的时候说过 nginx 的一个进程可以处理多个连接,这里每个进程就是一个 worker,自然一个 cpu 带一个进程会比较好。
下面的 log 一般选择默认的,也就是取消注释第一项,而 PID 最好也打开,因为 systemd 可能会用。
下面的 events
events { worker_connections 1024; use epoll; }
worker_connections 定义一个进程最多处理多少请求,个人站的话不用管,别的站比如论坛可以开大一些比如 4096。能否 use epoll 那就看你有没有了:
$ zcat config.gz | grep EPOLL CONFIG_EPOLL=y
要是 ”n“ 的话,要改成 use poll 或者 use select。各种方法的比较见 Optimizations。
然后把 gzip on 打开。
接着把 include conf.d/*.conf; 往下都注释掉,直到最后:
include vhosts.d/*.conf;
的前面,vhosts.d 本身这行不注释。
注释的原因很简单,你看到 vhosts.d 也能够明白,nginx 为我们提供了一个可以单独配置某个域名 (vhost) 的机制,所以我们不用把所有东西都丢到主配置文件里。
vhosts
在 /etc/nginx 下新建一个 vhosts.d 文件夹
sudo mkdir -p /etc/nginx/vhosts.d cd /etc/nginx/vhosts.d
然后就可以分站点的配置了,比如我们可以建一个 wordpress.com.conf 并编辑:
sudo vi wordpress.com.conf
配置如下:
server { #建立一个服务器块 server_name wordpress.com www.wordpress.com; # 这里改成你的域名 listen 80; #listen [::]:80; # 有 IPv6 的话 location / { # 建立一个位置块 root /srv/www/htdocs/wordpress.com/; index index.html # 首页 } # 位置块 access_log /var/log/nginx/wordpress.com.access.log # 访问日志 error_log /var/log/nginx/wordpress.com.error.log # 错误日志 } #服务器块
如果这是一个纯 html 静态文件的页面,那这样就做好了。但大部分都是 php,于是我们还要继续配置 php 处理的部分:
server { #建立一个服务器块 server_name wordpress.com www.wordpress.com; # 这里改成你的域名 listen 80; #listen [::]:80; # 有 IPv6 的话 location / { # 建立一个位置块 root /srv/www/htdocs/wordpress.com/; index index.html index.php # 首页 } # 位置块 location ~ \.php$ { # 把 php 后缀都重定向给 php5-fpm 处理 fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /srv/www/htdocs/wordpress.com/$fastcgi_script_name; include fastcgi_params; } access_log /var/log/nginx/wordpress.com.access.log # 访问日志 error_log /var/log/nginx/wordpress.com.error.log # 错误日志 } #服务器块
Wordpress
wordpress 需要一些特殊的 rewrite 规则,可以在 http://codex.wordpress.org/Nginx 找到。一般用 Global restrictions file 和 General WordPress rules 即可。
建立 /etc/nginx/rewrite_rules 文件夹,把那两个规则保存为 restrictions.conf 和 wordpress.conf,然后在 vhosts.d 的分站点配置里分别引入规则,比如上面那个 php 的 hillwood.info 的配置就可以加上两行:
[...] error_log /var/log/wordpress.com.error.log include /etc/nginx/rewrite_rules/restrictions.conf include /etc/nginx/rewrite_rules/wordpress.conf } # 服务器块
SSL
配置 SSL 要对 server 块和配置 php 的地方做一些调整。server 块要对 listen 做一些变动:
listen 443 ssl; listen [::]:443 ssl;
并在它的后面加入如下内容:
ssl on; ssl_certificate ssl/margueritesu/www_marguerite_su.crt; ssl_certificate_key ssl/margueritesu/www_marguerite_su.key; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_ciphers ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM;
证书是放在 /etc/nginx/ssl 文件夹下面的。免费证书申请的话题可以看这个帖子。
配置 php 的地方要加入这两行:
fastcgi_param HTTPS on; fastcgi_param HTTP_SCHEME https;
更多 ssl 配置见 nginx.org 的 配置 HTTPS 服务器一文。
配置 php5-fpm
到 /etc/php5/fpm/ 文件夹下,把 php-fpm.conf.default 复制为 php-fpm.conf
sudo cp -r /etc/php5/fpm/php-fpm.conf.default /etc/php5/fpm/php-fpm.conf
然后打开 php-fpm.conf,配置以下几个地方:
pid=/var/run/php5-fpm.pid error_log=/var/log/php5-fpm.log listen = /var/run/php5-fpm.sock pm.max_requests = 500
注意它们不在同一行,需要你去找的,这里给出的是应该配置为的值。
启动
- 启动 nginx
sudo systemctl enable nginx.service sudo systemctl start nginx.service
- 启动 php5-fpm
sudo systemctl enable php-fpm.service sudo systemctl start php-fpm.service
- 启动 mysql
sudo systemctl enable mysql.service sudo systemctl start mysql.service
初始化 Mysql
共性部分,见 SDB:搭建LAMP服务器。
常见问题
gzip 优化
gzip on; gzip_static on; gzip_vary on; gzip_http_version 1.1; gzip_min_length 700; gzip_comp_level 6; gzip_disable "msie6"; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/xml application/x-javascript application/x-php image/jpeg image/png image/gif image/svg+xml image/svg+xml-compressed;
最好写在 /etc/nginx/nginx.conf 的 gzip on; 部分。
php5-fpm.sock failed (No such file or directory)
这是因为你的 /etc/php/fpm/php-fpm.conf 里的 listen 没有配置或配置有误,那里默认监听的是 127.0.0.1:9000,需要你手动去改成 unix socket
php5-fpm.sock failed (Permission denied)
/var/run/php5-fpm.sock 的权限是这样的:
srw-rw---- 1 root root 0 7月 24 14:22 php5-fpm.sock
而你跑 nginx 的用户和组是:
user nginx nginx;
所以 nginx 无法访问 php5-fpm.sock。
解决方案:编辑 /etc/php/fpm/php-fpm.conf
listen.owner = nginx listen.group = nginx listen.mode = 0660
之后 sudo systemctl restart php-fpm.service 即可。
安全连接失败
连接 127.0.0.1:80 时发生错误。 SSL 接收到一个超出最大准许长度的记录。 (错误码: ssl_error_rx_record_too_long)
这里注意到你的端口是 80, 这是一个 http 而不是 https 端口,所以有可能是 php 转发配置有误:
fastcgi_param HTTPS on; fastcgi_param HTTP_SCHEME https;
在没有配置 ssl 证书和 443 端口的情况下使用这两行配置就会出现上面的情况。
另外,配置了 ssl 却使用了 80 端口也会出现这样的问题。
具体如何区分上面两种情况:如果地址栏里出现的是 https://127.0.0.1:80 这样的,你又确定你没有配置过 ssl,那基本上就是 php 转发配置有误; 而地址栏是 http://127.0.0.1:80 你又配置了 ssl 就是后者。
当然更加复杂的情况也有,比如你使用条件判断(适应百度爬虫)却把条件搞错,本应该走 https 的访问被你手工重定向到了 http 等。这就需要有经验的判断和对 nginx 更加系统的学习了。