使用 Nginx 来反向代理远程 MariaDB/MySQL 服务

  Armstrong 的服务器除了托管网站,还托管了像是 KMS、新干线、TeamTalk 等服务,在当年,Armstrong 只有一台服务器,因此,过大的负载经常引起服务器宕机,而服务器宕机的表现则是系统强制关闭了数据库服务,这必然会引起数据错误甚至丢失。Armstrong 决定扩容服务器,这得到了同学们的支持,服务器扩容后,首要任务就是把数据库与网页服务器分离,这会带来一些挑战。<!–more..>
  为了性能的考量,Armstrong 设定本机的 PHP 与 MariaDB 连接时,通过 Unix 套接字完成,而不是通过 TCP,因为后者需要使用系统的网络堆栈,这会降低系统的性能,显然,我们无法通过 Unix 套接字直接连接到远程的 MariaDB 服务器。另外,通过网络连接到远程的 MariaDB 还需要加密,否则网络上的其它系统可以查看甚至修改数据,获取数据库服务器的密码,引发安全问题。
  有人建议通过 SSH 来将远程系统上的目录挂接到网站服务器,从而通过 Unix 套接字连接到远程的 MariaDB 数据库服务。这种方法确实不错,既可以达到使用 Unix 套接字的目的,又可以起到加密的作用,更关键的是,这不需要安装额外的软件。然而,这需要改动目录结构,另外,SSH 也不适合进行大量数据的传递,前几年,我介绍过使用 Nginx 的 Stream 模块来映射端口,现在,我又一次使用这个模块,因为它可以满足我的需要:在套接字与 TCP 间进行转换,通过 TLS 加密传输的内容,限制来源 IP,建立不会经常断开的长连接。
  配置的思路是这样的:在数据库服务器上,配置 MariaDB,关闭 TCP 网络,只监听 Unix 套接字,默认位于 /var/lib/mysql/mysql.sock,然后配置 Nginx,通过 Stream 模块,把指定端口传来的请求,转发给 mysql.sock,并且设定 TLS,以及 ACL(当然我们还要再防火墙中设置)。在网站服务器上,停止 MariaDB,停止之前我猜你已经转移数据了,然后配置 nginx,让 Stream 模块使用套接字监听,套接字文件放在原先 MariaDB 服务器的 Unix 套接字文件的位置,把套接字收到的请求转发给数据库服务器上 Nginx 监听的端口。对,就这么简单。
  由于 Armstrong 的服务器运行 CentOS 8 系统,这里就按照 CentOS 8 仓库中自带的 MariaDB 来介绍。首先,从网站服务器把数据导出,然后导入到专门的数据库服务器,导入成功后,修改数据库服务器的配置,首先来修改 /etc/my.cnf.d/mariadb-server.cnf,在 [mysqld] 单元加上或修改原有配置成如下配置:

————— 分割线 —————
socket=/var/lib/mysql/mysql.sock
; 如有上述项,不要修改,如无请加
skip-networking
; 如无请加
————— 分割线 —————
保存后,我们来重启 MariaDB,确认没错误,我们来修改 Nginx 的配置,由于需要加入其它模块,因此我手动编译了 Nginx,请你找到正在调用的 nginx.conf 文件,在文件最末尾加上:

————— 分割线 —————
请不要全文复制,否则会因编码问题导致 Nginx 配置文件错误,切记!
stream {
upstream mysql {

上游服务器组配置,便于配置多个上游服务器进行负载均衡,名称为 mysql

server unix:/var/lib/mysql/mysql.sock;

上游服务器地址,可以是 IP 地址,也可以是 Unix 套接字文件路径

}

server {
listen 1735 ssl reuseport so_keepalive=30m::10;

监听端口,要求 SSL

ssl_certificate /etc/letsencrypt/live/shinkansen.viyf.org/fullchain.pem;

TLS 证书文件路径,开启 TLS 时必须,可通过 OpenSSL 生成

ssl_certificate_key /etc/letsencrypt/live/shinkansen.viyf.org/privkey.pem;

对应于 TLS 证书文件的 TLS 私钥文件路径,开启 TLS 时必须,可通过 OpenSSL 生成

ssl_protocols TLSv1.2;

规定使用的 TLS 版本,防止使用不安全的 SSLv3 及 TLS 1.0

ssl_session_cache builtin:512 shared:viyf_mysql_ssl:4m;

配置内存中的 TLS 会话缓存

ssl_session_timeout 1d;

配置 TLS 会话超时时间,可选单位有 s(秒)、m(分)、h(小时)和d(天)

proxy_pass mysql;

上游服务器组名称,upstream 设置的上游组名称

proxy_buffer_size 16k;

代理服务器的缓冲区大小

allow 127.0.0.1;

允许连接到该端口的服务器,可配置多项 allow,格式如 8.8.8.8、192.168.0.0/16 等

deny all;

拒绝 allow 之外的所有 IP 的连接

}
}

————— 分割线 —————

  修改配置文件后,使用 nginx -t 确认配置文件没有错误,否则,请不要重启 Nginx,OK,你现在可以重启 Nginx 了。

  在网站服务器上,请修改 Nginx 配置文件:

————— 分割线 —————

stream {
proxy_socket_keepalive on;

upstream mysql {
server 8.8.8.8:1735;
}

server {
listen /var/lib/mysql/mysql.sock;
proxy_pass mysql;
proxy_ssl on;
proxy_ssl_protocols TLSv1.2;
}
}

————— 分割线 —————

  相信大家都能看懂上一段配置的含义,同样的,我们在重新启动 Nginx 之前,一定要检查配置文件是否正确。好了,我们来停止 MariaDB,然后马上重启 Nginx。重启后,访问托管在这台服务器上,并且需要 MariaDB/MySQL 的站点,在不会缓存的页面上,如果能正常显示,搜索功能工作正常,我们的迁移操作就算完成了。
  大家需要注意的问题是,通过 Nginx 连接到 MariaDB 数据库,当你停止 nginx 后,/var/lib/mysql/mysql.sock 可能不会被删除,如遇这种情况,请手动删除,否则 Nginx 将无法启动。
  我们通过 Nginx 反向代理 MariaDB,巧妙地实现了偷梁换柱地更换 MariaDB 服务器,而不需要修改网站程序,换句话说,网站程序会误以为我们的 MariaDB 就安装在本机,因为访问地址依然还是熟悉的 localhost。

留下评论

电子邮件地址不会被公开。 必填项已用*标注