Moodle是一个流行的开源在线学习平台。特别是自2019冠状病毒疾病大流行开始以来,Moodle对学校和大学的重要性进一步增加。在德国的一些州,所有的学校在几天的时间里都不得不切换到Moodle和其他平台,比如BigBlueButton。如果数万名学生突然需要访问Moodle,这会导致可扩展性问题。
除了扩展Moodle应用程序本身之外,还需要考虑数据库。Moodle的数据库选项之一是PostgreSQL。在这篇博文中,我们使用PostgreSQL为Moodle提供了负载平衡选项。
通过Patroni实现高可用性
从教育系统的角度来看,在线学习平台可以被视为关键的基础设施,应该高度可用,尤其是数据库。PostgreSQL的一个好解决方案是Patenti,我们过去曾报道过它的Debian集成。
简而言之,Patenti使用分布式共识存储(DCS)从典型的3节点集群中选择领导者,或者在领导者失败的情况下启动故障转移并选择新的领导者,而不进入分裂大脑场景。此外,Patenti提供了一个REST API,用于节点之间的通信以及来自Patenticl程序的通信,例如在线更改所有节点上的Postgres配置或启动切换。
高可用性客户端解决方案
然而,从Moodle的角度来看,还必须确保它连接到leader,否则就不可能进行写事务。传统的高可用性解决方案(如Pacemaker)在这里使用虚拟IP(VIP),在发生故障转移时,这些IP将被旋转到新的主节点。对于Patroni,有一个vip manager项目,它监视DCS中的leader密钥,并在本地设置或删除集群vip。这也被集成到Debian中。
另一种方法是使用基于PostgreSQL的libpq库的客户端故障切换。为此,所有集群成员都列在连接字符串中,并添加了连接选项target_session_attrs=read-write。通过这种方式配置,如果连接断开,客户端将尝试访问其他节点,直到找到新的主节点。
另一种选择是HAProxy,一种高度可扩展的TCP/HTTP负载平衡器。通过对每个节点的Patenti REST API执行定期健康检查,它可以确定当前的领导者并将客户端查询转发给它。
Moodle数据库配置
Moodle与PostgreSQL数据库的连接在配置中配置。php,例如,对于简单的独立数据库:
$CFG->dbtype = 'pgsql';
$CFG->dblibrary = 'native';
$CFG->dbhost = '192.168.1.1';
$CFG->dbname = 'moodle';
$CFG->dbuser = 'moodle';
$CFG->dbpass = 'moodle';
$CFG->prefix = 'mdl_';
$CFG->dboptions = array (
'dbport' => '',
'dbsocket' => ''
);
此处使用默认端口5432。
如果使用流复制,备用项还可以定义为只读,并分配给自己的数据库用户(只需要读取权限):
$CFG->dboptions = array (
[...]
'readonly' => [
'instance' => [
[
'dbhost' => '192.168.1.2',
'dbport' => '',
'dbuser' => 'moodle_safereads',
'dbpass' => 'moodle'
],
[
'dbhost' => '192.168.1.3',
'dbport' => '',
'dbuser' => 'moodle_safereads',
'dbpass' => 'moodle'
]
]
]
);
使用libpq进行故障切换/负载平衡
如果高可用的Postgres群集与Patroni一起使用,则可以如上所述切换主群集,以防止在发生故障转移或切换事件时丢失数据或关闭系统。Moodle没有提供在这里设置通用数据库选项的方法,target_session_attrs=read-write 因此无法直接设置因此,我们为此开发了一个补丁,并在Moodle跟踪器中实现了它。这允许在$CFG->dboptions数组中添加额外的选项“dbfailover”=>1,该选项添加了必要的连接选项 target_session_attrs=read-write.。自定义配置。php如下所示:
$CFG->dbtype = 'pgsql';
$CFG->dblibrary = 'native';
$CFG->dbhost = '192.168.1.1,192.168.1.2,192.168.1.3';
$CFG->dbname = 'moodle';
$CFG->dbuser = 'moodle';
$CFG->dbpass = 'moodle';
$CFG->prefix = 'mdl_';
$CFG->dboptions = array (
'dbfailover' => 1,
'dbport' => '',
'dbsocket' => '',
'readonly' => [
'instance' => [
[
'dbhost' => '192.168.1.1',
'dbport' => '',
'dbuser' => 'moodle_safereads',
'dbpass' => 'moodle'
],
[
'dbhost' => '192.168.1.2',
'dbport' => '',
'dbuser' => 'moodle_safereads',
'dbpass' => 'moodle'
],
[
'dbhost' => '192.168.1.3',
'dbport' => '',
'dbuser' => 'moodle_safereads',
'dbpass' => 'moodle'
]
]
]
);
使用HAProxy进行故障切换/负载平衡
如果使用HAProxy,则必须将CFG->dbhost设置为HAProxy主机,例如127.0.0.1,以防HAProxy在Moodle服务器上本地运行。此外,可以为读取查询定义第二个端口(例如65432),该端口在CFG->dboptions中配置为只读,与上面的流复制备用端口相同。配置。php将如下所示:
$CFG->dbtype = 'pgsql';
$CFG->dblibrary = 'native';
$CFG->dbhost = '127.0.0.1';
$CFG->dbname = 'moodle';
$CFG->dbuser = 'moodle';
$CFG->dbpass = 'moodle';
$CFG->prefix = 'mdl_';
$CFG->dboptions = array (
'dbport' => '',
'dbsocket' => '',
'readonly' => [
'instance' => [
'dbhost' => '127.0.0.1',
'dbport' => '65432',
'dbuser' => 'moodle_safereads',
'dbpass' => 'moodle'
]
]
);
HAProxy配置文件HAProxy。
cfg可以类似于以下示例:
global
maxconn 100
defaults
log global
mode tcp
retries 2
timeout client 30m
timeout connect 4s
timeout server 30m
timeout check 5s
listen stats
mode http
bind *:7000
stats enable
stats uri /
listen postgres_write
bind *:5432
mode tcp
option httpchk
http-check expect status 200
default-server inter 3s fall 3 rise 3 on-marked-down shutdown-sessions
server pg1 192.168.1.1:5432 maxconn 100 check port 8008
server pg2 192.168.1.2:5432 maxconn 100 check port 8008
server pg3 192.168.1.3:5432 maxconn 100 check port 8008
HAProxy期望在端口5432上输入写入连接(postgres_write),并将其转发到集群成员的端口5432。主端口由端口8008(默认的用户REST API端口)上的HTTP检查确定;Patroni在此返回状态200作为主要,状态503作为备用。
对于读取查询(postgres\u read),必须确定主查询是否也应提供只读查询。如果是这种情况,可以使用简单的Postgres检查(pgsql检查);然而,这可能会导致PostgreSQL日志中出现关于不正确或不完整登录的条目:
listen postgres_read
bind *:65432
mode tcp
balance leastconn
option pgsql-check user haproxy
default-server inter 3s fall 3 rise 3 on-marked-down shutdown-sessions
server pg1 192.168.1.1:5432 check
server pg2 192.168.1.2:5432 check
server pg3 192.168.1.3:5432 check
如果您不想让主服务器参与读扩展,您可以简单地使用与postgres\u write部分相同的HTTP检查,这一次需要HTTP状态503:
listen postgres_read
bind *:65432
mode tcp
balance leastconn
option httpchk
http-check expect status 503
default-server inter 3s fall 3 rise 3 on-marked-down shutdown-sessions
server pg1 192.168.1.1:5432 check port 8008
server pg2 192.168.1.2:5432 check port 8008
server pg3 192.168.1.3:5432 check port 8008
修订版Ansible剧本
我们的Ansible Playbook版本0.3中也实现了HAProxy支持,用于在Debian上自动设置三节点PostgreSQL用户集群。新变量haproxy\u primary\u read\u scale可用于决定haproxy是否也应在只读端口上向主节点或仅向跟随者发出请求。
我们很乐意帮忙!
无论是PostgreSQL、Patroni、HAProxy、Moodle还是任何其他开源软件;凭借在开源领域超过22年的开发和服务经验,credativ GmbH可以为您提供无与伦比的个性化支持。我们将帮助您满足所有开源基础设施的需求——如果需要的话,一年365天,一天24小时!
我们期待着您的来信。
原文标题:Moodle PostgreSQL load balancing with HAProxy and Patroni
原文作者:Michael Banck
原文链接:https://www.credativ.de/en/blog/postgresql/moodle-postgresql-load-balancing-with-haproxy-and-patroni/




