nginScript系列:通过TCP负载均衡和Galera集群来扩展MySQL

这是nginScript系列文章的第三篇,将介绍如何使用nginScript将客户端循序渐进地重定向到新的服务器。查看第一篇“nginScript简介”,第二篇“使用nginScript将客户端重定向到新服务器”。

\\

NGINX Plus在R5版本里就引入了TCP的负载均衡,在随后的版本里不断地添加新特性,包括支持UDP的负载均衡。在这篇文章里,我们将探讨NGINX Plus是如何实现TCP负载均衡的。

\\

为了了解NGINX Plus的特性,我们使用了一个简单的测试环境,这个环境包含了应用程序所必需的组件,包括一个可伸缩的数据库。

\\

(点击放大图像)

\\

5b5d051a71681303ed3d7101b227dd23.png

\\

MySQL负载均衡测试环境

\\

在这个环境里,NGINX Plus作为数据库服务器的反向代理,监听MySQL的3306端口。反向代理为客户端提供了一个简单的接口,后端的MySQL节点可以自由伸缩(甚至离线),不会对客户端有任何影响。我们使用MySQL命令行工具作为客户端,在测试环境里充当前端应用。

\\

本文所描述的很多特性在开源的NGINX和NGINX Plus里都有提供。不过,为了简单起见,我们通篇使用NGINX Plus,有些在NGINX里没有的特性我们会明确指明。

\\

我们将探讨如下几个应用场景。

\\
  • TCP负载均衡\\t
  • 高可用和健康检查\\t
  • 日志和诊断\\t
  • 并发写入\

TCP负载均衡

\\

在为应用程序配置负载均衡之前,需要了解应用程序是如何连接到数据库的。我们使用MySQL命令行工具mysql连接到Galera集群,运行查询,然后关闭连接。不过,在实际当中,很多应用框架使用连接池来减小延迟,有效利用数据库的资源。

\\

TCP的负载均衡是在stream context里配置的,所以我们在nginx.conf文件里增加了一个stream配置块来配置我们的MySQL负载均衡。

\\
\stream { include stream.conf; }
\\

我们的TCP负载均衡配置与主配置文件是分开的。我们在相同的目录创建stream.conf文件。要注意,在默认情况下,conf.d目录被保留用于http context配置,如果在这里添加stream配置是不会生效的。

\\
\upstream galera_cluster {\    server 127.0.0.1:33061; # node1\    server 127.0.0.1:33062; # node2\    server 127.0.0.1:33063; # node3\    zone tcp_mem 64k;\}\\server {\    listen 3306; # MySQL默认端口\    proxy_pass galera_cluster;\}
\\

首先,我们定义了一个upstream组,名字叫作galera_cluster,包含了Galera集群里的三个MySQL节点。在我们的测试环境里,可以分别通过本地的不同端口访问它们。

\\

zone指令指定了一些内存,NGINX Plus的工作线程用它来维护负载均衡的状态。server{}配置块定义了NGINX Plus是如何处理客户端的。NGINX Plus监听MySQL的默认端口3306,并将流量转向到Galera集群。

\\

为了验证配置的正确性,我们可以使用MySQL客户端来获取它所连接的MySQL节点的机器名。

\\
\$ echo \"SHOW VARIABLES WHERE Variable_name = 'hostname'\" | mysql --protocol=tcp --user=nginx --password=plus -N 2\u0026gt; /dev/null\hostname    node1
\\

我们可以重复同样的命令,来验证负载均衡是否正常。

\\
\$ !!;!!;!!\hostname    node2\hostname    node3\hostname    node1
\\

这足以说明轮询负载均衡算法是正常的。不过,如果我们的应用程序使用连接池来访问数据库,那么就有可能导致每个节点的连接数不均衡。另外,我们无法保证每一个连接的负载是均等的,因为处理查询的连接有可能很空闲也有可能很忙。另一种负载均衡算法叫作最少连接数(Least Connections),可以使用least_conn指令来配置。

\\
\upstream galera_cluster {\    server 127.0.0.1:33061; # node1\    server 127.0.0.1:33062; # node2\    server 127.0.0.1:33063; # node3\    zone tcp_mem 64k;\    least_conn;\}
\\

现在,如果有客户端连接到数据库,NGINX Plus会选择集群里具有最少连接数的节点。

\\

高可用和健康检查

\\

在集群里进行负载均衡的最大好处是它可以提供高可用性。基于上述的配置,如果一个新的TCP连接建立失败,NGINX Plus就把这台服务器标记为“down”,并停止向它发送TCP数据包。

\\

除了能够探测到宕机的服务器,NGINX Plus还能自动进行自发的健康检查。因此,在客户端发送请求到那些不可用的服务器之前,NGINX Plus能够提前检测到它们(这个特性只在NGINX Plus里提供)。另外,我们可以通过应用程序级别的健康检测来测试服务器的可用性。我们向每一台服务器发送请求,如果服务器返回响应,说明它运行正常。我们在配置里添加了一些内容。

\\
\upstream galera_cluster {\    server 127.0.0.1:33061; # node1\    server 127.0.0.1:33062; # node2\    server 127.0.0.1:33063; # node3\    zone tcp_mem 64k;\    least_conn;\}\\match mysql_handshake {\    send \\x00;\    expect ~* \\x00\\x00; # 用于过滤握手响应数据包中的空值\}\\server {\    listen 3306; # MySQL默认端口\    proxy_pass galera_cluster;\    proxy_timeout 2s;\    health_check match=mysql_handshake interval=20 fails=1 passes=2;\}
\\

在这个例子里,match配置块定义了初始化一个MySQL握手协议需要的请求和响应数据。server配置块里的health_check指令使用了由match配置块定义的模式,并确保NGINX Plus只会向可用的服务器发起MySQL连接。我们每20秒执行一次健康检查,如果连接服务器失败一次,就把这个服务器从TCP负载均衡池里移除,如果连续两次健康检查成功,那么就重新把服务器放回负载均衡池。

\\

日志和诊断

\\

NGINX Plus提供了灵活的日志,所有的TCP和UDP处理过程都可以被记录下来,用于调试和离线分析。对于使用了TCP协议的系统,比如MySQL,NGINX Plus会在每次连接关闭之后记录一条日志。log_format指令指定哪些值可以出现在日志里。我们可以选择出现在Stream模块里的任意可用变量值。我们在stream.conf文件最上面的stream context里定义日志格式。

\\
\log_format mysql '$remote_addr [$time_local] $protocol $status $bytes_received '\                 '$bytes_sent $upstream_addr $upstream_connect_time '\                 '$upstream_first_byte_time $upstream_session_time $session_time';
\\

在server配置块里使用access_log指令来启用日志,并指定日志文件的路径和之前配置过的日志格式的名字。

\\
\server {\    ...\    access_log /var/log/nginx/galera_access.log mysql;\}
\\

这样的配置将生成如下格式的日志。

\\
\$ tail -3 /var/log/nginx/galera_access.log\192.168.91.1 [16/Nov/2016:17:42:18 +0100] TCP 200 369 1611 127.0.0.1:33063 0.000 0.003 12.614 12.614\192.168.91.1 [16/Nov/2016:17:42:18 +0100] TCP 200 369 8337 127.0.0.1:33061 0.001 0.001 11.181 11.181\192.168.91.1 [16/Nov/2016:17:42:19 +0100] TCP 200 369 1611 127.0.0.1:33062 0.001 0.001 10.460 10.460
\\

通过nginScript使用高级日志

\\

nginScript是NGINX的\"原生\"可编程配置语言。它是为NGINX和NGINX Plus专门实现的JavaScript,也是专门为服务器端的使用场景而设计的。

\\

在Stream模块里,可以通过nginScript访问请求和响应消息里的数据包。也就是说,我们可以查看从客户端发出的SQL查询请求,并从中抽取有用的元素,比如SQL的SELECT或UPDATE方法。nginScript可以把这些值变成普通的NGINX变量。在这个例子里,我们的JavaScript代码被放在/etc/nginx/sql_method.js文件里。

\\
\var method = \"-\"; // 全局变量\var client_messages = 0;\\function getSqlMethod(s) {\    if ( !s.fromUpstream ) {\        client_messages++;\        if ( client_messages == 3 ) { // SQL语句出现在第3个数据包里\            var query_text = s.buffer.substr(1,10).toUpperCase();\            var methods = [\"SELECT\
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值