介绍
当今的高流量 Web 应用程序由灵活且快速响应的 Web 服务器、可扩展的企业级数据库以及由功能丰富的脚本语言提供的动态内容提供支持。 典型的 Linux Web 应用程序堆栈遵循 LAMP 架构(Linux、Apache、MySQL 和 PHP/Python)。 广泛可用的教程向我们展示了如何在一台服务器中安装和配置这些组件。
现实生活中很少出现这种情况。 在专业的三层设置中,数据库后端将被隔离在自己的服务器中; Web 服务器会将其请求发送到充当数据库和网站之间的中间件的应用层。
尽管 Apache 仍然是迄今为止使用最广泛的 Web 服务器,但 Nginx 因其占用空间小和响应时间快而迅速普及。 MySQL 的社区版仍然是数据库的流行选择,但许多站点还使用另一个名为 PostgreSQL 的开源数据库平台。
目标
在本教程中,我们将在两层架构中创建一个简单的 Web 应用程序。 我们两个节点的基本操作系统都是 CentOS 7。 该站点将由运行与 PostgreSQL 数据库对话的 PHP 代码的 Nginx Web 服务器提供支持。
我们不会采用其他 LAMP 或 LEMP 教程中看到的“自上而下”的方法,而是使用“自上而下”的方法:我们将首先创建一个数据库层,然后是 Web 服务器,然后查看 Web 服务器如何连接到数据库。
我们将此配置称为 LEPP(Linux、Nginx、PHP、PostgreSQL)堆栈。
先决条件
要学习本教程,您将需要以下内容:
- 两个 CentOS 7 Droplet,至少有 2GB 的 RAM 和 2 个 CPU 内核,一个用于数据库服务器和 Web 服务器。
我们将这些机器的IP地址分别称为your_db_server_ip
和your_web_server_ip
; 您可以在 DigitalOcean 控制面板上找到这些机器的实际 IP 地址。
- 两个 Droplet 上的 Sudo 非 root 用户。 要进行此设置,请按照 本教程 。
第一步——安装 PostgreSQL
在这一步中,我们将在数据库服务器上安装 PostgreSQL。
连接到要安装 PostgreSQL 的空的、新安装的 CentOS 7 框。 CentOS 7 默认不附带它的存储库,因此我们需要先下载 yum 存储库 RPM。
sudo wget http://yum.postgresql.org/9.4/redhat/rhel-7Server-x86_64/pgdg-centos94-9.4-1.noarch.rpm
保存 RPM 后,安装存储库。
sudo yum install pgdg-centos94-9.4-1.noarch.rpm -y
最后,安装 PostgreSQL 9.4 服务器及其 contrib 模块。
sudo yum install postgresql94-server postgresql94-contrib -y
第二步——配置 PostgreSQL
在这一步中,我们将为 PostgreSQL 定制一些安装后的配置。
在 CentOS 7 中,PostgreSQL 9.4 数据和配置文件的默认位置是 /var/lib/pgsql/9.4/data/
,程序二进制文件的位置是 /usr/pgsql-9.4/bin/
。 数据目录一开始是空的。 我们需要运行 initdb
程序来初始化数据库集群并在其中创建必要的文件:
sudo /usr/pgsql-9.4/bin/postgresql94-setup initdb
数据库集群初始化完成后,data文件夹下会有一个名为postgresql.conf
的文件,是PostgreSQL的主要配置文件。 我们将更改此文件中的两个参数。 使用 vi
或您喜欢的文本编辑器,打开文件进行编辑。
sudo vi /var/lib/pgsql/9.4/data/postgresql.conf
并更改以下几行:
- 将
#listen_addresses = 'localhost'
更改为listen_addresses = '*'
- 将
#port = 5432
更改为port = 5432
第一个参数指定数据库服务器将侦听的 IP 地址。 作为一种安全措施,开箱即用的 Postgres 安装只允许本地主机连接。 将此更改为 '*' 意味着 Postgres 将侦听来自任何来源的流量。 第二个参数已通过取消注释标记 (#) 启用; 它指定 Postgres 的默认端口。
保存并退出文件。
接下来,我们将编辑 pg_hba.conf
,这是 PostgreSQL 的基于主机的访问 (HBA) 配置文件。 它指定哪些主机和 IP 范围可以连接到数据库服务器。 每个条目都指定了可以在本地还是远程(主机)建立连接,可以连接到哪个数据库,可以连接到哪个用户,请求可以来自哪个 IP 块,以及应该使用哪种身份验证模式。 任何与这些条目不匹配的连接请求都将被拒绝。
打开pg_hba.conf
进行编辑。
sudo vi /var/lib/pgsql/9.4/data/pg_hba.conf
滚动到文件底部,并添加以下行:
host all all your_web_server_ip/32 md5
此行告诉 PostgreSQL 接受仅来自 IP 地址 your_web_server_ip
的数据库连接,使用标准 md5 校验和进行密码验证。 可以以任何用户身份对任何数据库进行连接。
保存并退出文件。
接下来,启动 Postgres 服务:
sudo systemctl start postgresql-9.4.service
然后启用它:
sudo systemctl enable postgresql-9.4.service
要检查数据库服务器是否正在接受连接,我们可以查看最新 Postgres 日志文件的最后几行。 数据库错误日志保存在/var/lib/pgsql/9.4/data/pg_log
目录中。 运行以下命令以查看此目录中的文件。
sudo ls -l /var/lib/pgsql/9.4/data/pg_log
日志文件名的格式为 postgresql-day_of_week.log
(例如,postgresql-Wed.log
)。 找到当天对应的日志文件,查看最新日志文件的最后几行。
sudo tail -f -n 20 /var/lib/pgsql/9.4/data/pg_log/postgresql-day_of_week.log
输出应显示类似于以下内容:
... < 2015-02-26 21:32:24.159 EST >LOG: database system is ready to accept connections < 2015-02-26 21:32:24.159 EST >LOG: autovacuum launcher started
按 CTRL+C 停止 tail
命令的输出。
第三步——更新数据库服务器防火墙
我们还需要允许 Postgres 数据库流量通过防火墙。 CentOS 7 通过 firewalld
守护进程实现动态防火墙; 该服务不需要重新启动以使更改生效。 firewalld
服务应该在系统启动时自动启动,但检查一下总是好的。
sudo firewall-cmd --state
默认状态应该是 running
,但如果是 not running
则以:
sudo systemctl start firewalld
接下来,添加端口 5432 的规则。 这是 PostgreSQL 数据库流量的端口。
sudo firewall-cmd --permanent --zone=public --add-port=5432/tcp
然后重新加载防火墙。
sudo firewall-cmd --reload
第四步——创建和填充数据库
在这一步中,我们将创建一个数据库并向其中添加一些数据。 这是我们的 Web 应用程序将动态获取和显示的数据。
第一步是更改 Postgres 超级用户的密码,称为 postgres,它是在首次安装 PostgreSQL 时创建的。 最好从 Postgres 中更改用户密码,而不是在操作系统提示符下更改。 为此,请切换到 postgres 用户:
sudo su - postgres
这会将命令提示符更改为 -bash-4.2$
。 接下来,启动内置的客户端工具。
psql
默认情况下,这会将 postgres 用户记录到 Postgres 数据库。 您的提示将更改为 postgres=#
,即 psql 提示,而不是操作系统提示。 现在发出 \password
命令将导致提示要求更改密码。
\password
为 Postgres 用户提供安全密码。
接下来,创建一个名为 product 的数据库:
CREATE DATABASE product;
然后连接到 product 数据库:
\connect product;
接下来,在数据库中创建一个名为 product_list 的表:
CREATE TABLE product_list (id int, product_name varchar(50));
一次运行以下每个命令。 每个命令都会将一条记录添加到 product_list
表中。
INSERT INTO product_list VALUES (1, 'Book'); INSERT INTO product_list VALUES (2, 'Computer'); INSERT INTO product_list VALUES (3, 'Desk');
最后,检查数据是否已正确添加。
SELECT * FROM product_list;
输出应如下所示:
id | product_name ----+-------------- 1 | Book 2 | Computer 3 | Desk (3 rows)
这就是我们需要在数据库服务器上做的所有事情; 您现在可以断开连接。
第五步——安装 Nginx
接下来,我们将在另一个 Droplet 中安装和配置 Nginx Web 服务器。 连接到另一个空的、新安装的 CentOS 7 盒子。
与 PosgreSQL 一样,CentOS 7 默认不附带 Nginx 存储库。 我们需要先下载 yum 存储库 RPM。
sudo wget http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
保存 RPM 后,安装存储库。
sudo yum install nginx-release-centos-7-0.el7.ngx.noarch.rpm -y
最后,安装 Nginx Web 服务器。
sudo yum install nginx -y
第六步 — 更新 Web 服务器防火墙
在这一步中,我们将配置防火墙以允许 Nginx 流量,并自定义一些 Nginx 配置。
我们需要允许 HTTP/HTTPS 流量通过防火墙。 像以前一样,检查 firewalld
服务是否正在运行。
sudo firewall-cmd --state
默认状态应该是running
,但是如果是not running
,启动它:
sudo systemctl start firewalld
现在为端口 80 (HTTP) 添加防火墙规则:
sudo firewall-cmd --permanent --zone=public --add-port=80/tcp
为端口 443 (HTTPS) 添加另一个:
sudo firewall-cmd --permanent --zone=public --add-port=443/tcp
然后,重新加载防火墙。
sudo firewall-cmd --reload
接下来,启动 Nginx。
sudo systemctl start nginx.service
并启用它。
sudo systemctl enable nginx.service
将我们的浏览器指向服务器的 IP 地址应该会显示默认网页:
第七步——配置 Nginx
这一步有两个相关的 Nginx 配置文件。 第一个是主配置文件,第二个是特定于站点的配置文件。
通用配置文件控制整个服务器特性。 Nginx 可以为许多网站提供服务,每个网站都称为一个服务器块(Apache 称它们为虚拟主机或虚拟主机)。 每个站点的配置由服务器块配置文件控制。
让我们编辑主服务器配置文件。
sudo vi /etc/nginx/nginx.conf
在文件的第二行,将 worker_processes
参数从 1 更改为 2。 这告诉 Nginx 的工作线程使用所有可用的 CPU 内核。 保存并退出文件。
我们不会在这里创建 serve 块。 相反,我们将在默认服务器块中创建我们的 Web 应用程序,所以让我们编辑默认服务器块配置文件。
sudo vi /etc/nginx/conf.d/default.conf
内容看起来像这样。 您将编辑的部分将突出显示。
server { listen 80; server_name localhost; ... location / { root /usr/share/nginx/html; index index.html index.htm; } #error_page 404 /404.html; ... # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} ... }
进行以下编辑:
- 将
server_name
从localhost
设置为your_web_server_ip
。 - 将
index.php
添加到index
指令,使其读取index.php index.html index.htm
。 - 删除包含
root
和index
指令的location / {
和}
行。 如果没有此更改,您可能会发现您的网页没有显示在浏览器中,并且 Nginx 错误日志记录了"Unable to open primary script: /etc/nginx/html/index.php (No such file or directory)"
等消息 - 取消注释 pass the PHP scripts to FastCGI server 注释下的
location ~ \.php$
块(包括最后一个大括号)。 - 删除同一
location ~ \.php$
块下的根指令。 - 将 fastcgi_pass 指令值从
127.0.0.1:9000
更改为unix:/var/run/php-fpm/php5-fpm.sock
。 这是为了确保 PHP FastCGI 进程管理器(我们将在下一步安装)将监听 Unix 套接字。 - 将 te
fastcgi_param
指令值更改为SCRIPT_FILENAME $document_root$fastcgi_script_name
。 这告诉 Web 服务器 PHP 脚本文件将保存在文档根目录下。
完成编辑后,文件应如下所示:
server { listen 80; server_name your_web_server_ip; ... root /usr/share/nginx/html; index index.php index.html index.htm; ... # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm/php5-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } ...
保存并退出文件,然后启动 Web 服务器。
sudo systemctl restart nginx.service
第八步——安装 PHP
我们现在将在 Web 服务器中安装 PHP 的三个组件:PHP 引擎本身、FastCGI 进程管理器 (FPM) 和 PostgreSQL 的 PHP 模块。
首先,安装 PHP。
sudo yum install php -y
接下来我们将安装 FastCGI Process Manager (FPM),它是 PHP 自己的 FastCGI 实现。 FastCGI 就像您的 Web 服务器之上的附加组件。 它独立运行,通过将用户请求整合到一个进程中来帮助加快用户请求,从而加快响应时间。
sudo yum install php-fpm -y
最后,安装 PHP Postgres 模块:
sudo yum install php-pgsql -y
第九步——配置 PHP
在这一步中,我们将配置 PHP。
打开 PHP 配置文件。
sudo vi /etc/php.ini
进行以下更改:
- 将
expose_php = On
更改为expose_php = Off
。 将此参数设置为Off
只是意味着 PHP 不会将其签名添加到 Web 服务器的标头中,并且不会暴露服务器正在运行 PHP 的事实。 - 将
;cgi.fix_pathinfo=0
更改为;cgi.fix_pathinfo=1
。
保存并退出文件。 接下来,编辑 FPM 配置文件。
sudo vi /etc/php-fpm.d/www.conf
进行以下更改:
- 将
user = apache
更改为user = nginx
。 - 同样,将
group = apache
更改为group = nginx
。 - 将
listen = 127.0.0.1:9000
更改为listen = /var/run/php-fpm/php5-fpm.sock
。 我们在 Nginx 默认服务器块的配置文件中设置了相同的值。
保存并退出 vi。 接下来启动 PHP-FPM。
sudo systemctl start php-fpm.service
然后启用它。
sudo systemctl enable php-fpm.service
第十步——创建 Web 应用程序
我们在两个节点中都准备好了所有服务器组件。 现在是我们创建 PHP 应用程序的时候了。 在 /usr/share/nginx/html
中创建一个名为 index.php
的文件。
sudo vi /usr/share/nginx/html/index.php
粘贴以下内容。 确保将突出显示的变量分别替换为您的数据库服务器 IP 地址和 Postgres 密码。
<html> <head> <title>LEPP Stack Example</title> </head> <body> <h4>LEPP (Linux, Nginx, PHP, PostgreSQL) Sample Page</h4> <hr/> <p>Hello and welcome. This web page is dynamically showing a product list from a PostgreSQL database</p> <?php $host = "your_db_server_ip"; $user = "postgres"; $password = "your_postgres_password"; $dbname = "product"; $con = pg_connect("host=$host dbname=$dbname user=$user password=$password") or die ("Could not connect to server\n"); $query = "SELECT * FROM product_list"; $resultset = pg_query($con, $query) or die("Cannot execute query: $query\n"); $rowcount = pg_numrows($resultset); for($index = 0; $index < $rowcount; $index++) { $row = pg_fetch_array($resultset, $index); echo $row["id"], "-", $row["product_name"]; echo "<br>"; } ?> </body> </html>
这是一个带有嵌入式 PHP 代码的简单网页。 首先,它为数据库连接字符串定义了一些参数。 接下来,对数据库服务器建立一个连接(由 $con
指定)。 指定一个查询,然后针对 product_list 表执行它。 它遍历返回的结果并在新行中打印每一行的内容。
写入并保存文件后,打开浏览器窗口并将其指向 your_web_server_ip
。 内容应如下所示:
结论
我们从头开始构建了两个盒子,安装并配置了所有必要的软件,然后在其中部署了我们的 Web 应用程序。 生产堆栈将具有额外的复杂性,例如添加外部防火墙和负载平衡器,但这是您可以开始使用的可靠基本配置。 享受!