SDB:搭建LNMP服务器

跳转至: 导航, 搜索
本教学指导您在 openSUSE 12.3+ 上搭建 LNMP 环境。顾名思义,LNMP 和 LAMP 一样,只是把 Apache 替换为 Nginx,因此一些共性的地方还请参阅 LAMP。

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 更加系统的学习了。

参考链接