概述
高可用架构是 Keepalived + HAproxy,用 HAproxy 来做 RabbitMQ 负载均衡和高可用,用 Keepalived 来保证 HAproxy 的高可用。
组件 | IP地址 | 端口 |
RabbitMQ磁盘节点-01 | 192.168.0.101 | 5672 |
RabbitMQ磁盘节点-02 | 192.168.0.102 | 5672 |
RabbitMQ磁盘节点-03 | 192.168.0.103 | 5672 |
HAproxy-01 | 192.168.0.104 | |
HAproxy-02 | 192.168.0.105 | |
Keepalived-Master | 192.168.0.104 | |
Keepalived-Backup | 192.168.0.105 |
虚拟IP:192.168.0.100
之前安装过RabbitMQ。
也安装过单节点的HAProxy,IP地址为:192.168.0.104。
现在,需要把单节点的HAProxy克隆一份,形成两个HAProxy,新克隆出来的HAProxy节点的IP地址为:192.168.0.105。
安装KeepAlived
在两个节点使用yum安装keepalived:
yum install -y keepalived
在两个节点的/etc/keepalived/文件夹下编写检测haproxy的shell脚本:
#!/bin/bash
case "$1" in master) notify master service haproxy start exit 0 ;; backup) notify backup service haproxy stop exit 0 ;; fault) notify fault service haproxy stop exit 0 ;; *) echo 'Usage: `basename $0` {master|backup|fault}' exit 1 ;; esac
编辑keepalived.cfg文件:
vi /etc/keepalived/keepalived.conf
修改192.168.0.104节点的配置文件:
vrrp_script chk_haproxy {
script "service haproxy status" # 服务探测,返回0说明服务是正常的
interval 1 # 每隔1秒探测一次
weight -2 # 不正常时,权重-1,即haproxy上线,权重加2;下线,权重减2
}
vrrp_instance haproxy {
state MASTER # 主机为MASTER,备机为BACKUP interface ens33 # 监测网络端口,用ipconfig查看 virtual_router_id 108 # 主备机必须相同 priority 100 # 主备机取不同的优先级,主机要大。 advert_int 1 # VRRP Multicast广播周期秒数 authentication { auth_type PASS # VRRP认证方式 auth_pass 1234 # VRRP口令 主备机密码必须相同 } track_script { # 调用haproxy进程检测脚本,备节点不配置 chk_haproxy } track_interface { bond0 } virtual_ipaddress { # VIP 漂移地址 即集群IP地址 192.168.0.100/25 dev ens33 } }
修改192.168.0.105节点的配置文件:
vrrp_instance haproxy {
state BACKUP
interface ens33
virtual_router_id 108
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
track_interface {
ens33
}
virtual_ipaddress {
192.168.0.100
}
notify_master "/etc/keepalived/notify.sh master" # 当前节点成为master时,通知脚本执行任务,一般用于启动某服务
notify_backup "/etc/keepalived/notify.sh backup" # 当前节点成为backup时,通知脚本执行任务,一般用于关闭某服务
JsonConvert.DefaultSettings =
() => new JsonSerializerSettings() {
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Converters = {new StringEnumConverter(www.tianscpt.com)}
};
// Serialized as: {"day":"Saturday"}
await PostSomeStuff(new { Day = DayOfWeek.Saturday });
因为默认设置是全局设置,它会影响你的整个应用。所以这里我们最好使用针对特定API使用独立的配置。当使用Refit生成一个接口对象的时候,你可以传入一个RefitSettings参数,这个参数可以指定你使用的JSON序列化配置。
Copy
var gitHubApi = RestService.For<IGitHubApi>("https://api.github.com",
new RefitSettings {
ContentSerializer = new JsonContentSerializer(
new JsonSerializerSettings {
ContractResolver = new SnakeCasePropertyNamesContractResolver()
}
)});
var otherApi = RestService.For<IOtherApi>www.hnxinhe.cn("https://www.chenhaiyulp.cn api.example.com",
new RefitSettings {
ContentSerializer = new JsonContentSerializer(
new JsonSerializerSettings {
ContractResolver = new CamelCasePropertyNamesContractResolver()
}
)});
针对自定义属性的序列化和反序列化,我们同样可以使用Json.NET的JsonProperty属性。
Copy
public class Foo
{
// Works like [AliasAs("b")] would in form posts (see below)
[JsonProperty(PropertyName="b"www.yunyouuyL.com )]
public string Bar { get; set; }
}
Xml内容#
针对XML请求和响应的序列化和反序列化,Refit使用了System.Xml.Serialization.XmlSerializer。默认情况下, Refit会使用JSON内容序列化器,如果想要使用XML内容序列化器,你需要将RefitSetting的ContentSerializer属性指定为XmlContentSerializer。
Copy
var gitHubApi = RestService.For<IXmlApi>("https://www.baihuiyulegw.com /XML",
new RefitSettings {
ContentSerializer = new XmlContentSerializer()
});
我们同样可以使用System.Xml.Serialization命名空间下的特性,自定义属性的序列化和反序列化。
Copy
public class Foo
{
[XmlElement(Namespace = "https://www.yunsengyule.com /XML")]
public string Bar { get; set; }
}
System.Xml.Serialization.XmlSerializer提供了多种序列化方式,你可以通过在XmlContentSerialier对象的构造函数中指定一个XmlContentSerializerSettings 对象类进行配置。
Copy
var gitHubApi = RestService.For<IXmlApi>("https://www.chenghgongs.com /XML",
new RefitSettings {
ContentSerializer = new XmlContentSerializer(
new XmlContentSerializerSettings
{
XmlReaderWriterSettings = new XmlReaderWriterSettings()
{
ReaderSettings = new XmlReaderSettings
{
IgnoreWhitespace = true
在两个节点分别启动keepalived:
systemctl stop NetworkManager
systemctl start keepalived
systemctl enable keepalived
通过虚拟IP访问控制台
通过程序测试
修改RabbitMQ的连接地址为虚拟IP:
spring:
#消息队列配置
rabbitmq:
#addresses: 192.168.0.101:5672,192.168.0.102:5672,192.168.0.103:5672
host: 192.168.0.100 # 虚拟IP
port: 5672
username: guest
password: guest
virtual-host: /
publisher-returns: true
publisher-confirms: true connection-timeout: 5000ms listener: simple: acknowledge-mode: manual prefetch: 1000
执行发送消息和接收消息,结果为:
2019-05-05 23:04:15.508 INFO 77132 --- [.168.0.100:5672] cc.xuepeng.config.RabbitMQConfig : ConfirmCallback -> 消息发布到交换器成功,id:CorrelationData [id=581660c3-e3f9-40a4-8905-50dd3681fd50]
2019-05-05 23:04:15.518 INFO 68844 --- [cTaskExecutor-1] cc.yesway.service.DirectQueueListener : 消费消息成功: ack