阿里云搭建mha高可用架构
弹性网卡介绍
- 阿里云服务器在虚拟交换机中不能随意获取私网ip,也不能像在虚拟机中随意进行ip漂移,只能利用api接口切换弹性网卡的绑定与解绑来达到ip漂移的目的
服务器系统选择
- 注意服务器最好选择以下版本,这样不需要配置就可以切换,其他版本的系统绑定网卡后需要手动进行配置官方文档地址
- CentOS 7.3 64位
- CentOS 6.8 64位
- Window Server 2008 R2及更高版本
阿里云实现mha高可用应用透明
阿里云的虚拟交换机不能像在虚拟机中随意切换ip,所以需要另外通过api控制弹性网卡,所以之前在虚拟机中应用透明部分的脚本在绑定和解绑ip的部分需要替换为调用api接口脚本
#调用示例
#注意事项
#以下只是调用脚本方法,真实阿里云网络环境中数据库一般没有外网,所以需要在配置nat或者其他方式访问外网才可以调用脚本
#可以将以下命令写入shell脚本,分发到每个mysql服务器然后将php脚本放置在拥有公网ip的主机中,所有mysql服务器调用该公网ip主机的php脚本即可
#以下两个脚本需要当前主机安装php环境,如果没有安装php,就使用 yum install -y php 安装
/usr/bin/php ./aliclould_up_ip.php -h ecs实例id
/usr/bin/php ./aliclould_down_ip.php -h i-*********
- 原虚拟机中使用使用的ip漂移脚本
- 原文地址
vi /usr/local/bin/master_ip_failover
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
$command, $ssh_user, $orig_master_host, $orig_master_ip,
$orig_master_port, $new_master_host, $new_master_ip, $new_master_port
);
#虚拟机中使用
#my $vip = '10.0.0.55/24';
#my $key = '1';
#my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
#my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
#阿里云中使用
my $vip = '172.16.128.1/20';
my $ssh_start_vip = "/usr/bin/php ./aliclould_down_ip.php -h i-*********";
my $ssh_stop_vip = "/usr/bin/php ./aliclould_down_ip.php -h i-*********";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
);
exit &main();
sub main {
print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
my $exit_code = 1;
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
exit 0;
}
else {
&usage();
exit 1;
}
}
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
return 0 unless ($ssh_user);
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
- 实例绑定弹性网卡
aliclould_up_ip.php
<?php
/**
* 阿里云绑定弹性网卡
* AttachNetworkInterface
* https://help.aliyun.com/document_detail/58515.html
*/
//oss账号密码
$accessKeyId = "填入参数";
$accessKeySecret = "填入参数";
// 实例ID
$host = getopt('h:');
if(empty($host['h']))
{
exit;
}
else
{
$InstanceId = $host['h'];
}
// 弹性网卡ID
$NetworkInterfaceId = '填入网卡id';
// 实例所在地域的ID
$RegionId = 'cn-hangzhou';
date_default_timezone_set("UTC");
// 阿里云 调用AttachNetworkInterface附加一个弹性网卡(ENI)到一台专有网络VPC类型ECS实例上
$input = [
'Action' => 'AttachNetworkInterface', // 系统规定参数。取值:AttachNetworkInterface
'InstanceId' => $InstanceId, // 实例ID
'NetworkInterfaceId' => $NetworkInterfaceId, // 弹性网卡ID
'RegionId' => $RegionId, // 实例所在地域的ID
];
// 请求类型
$method = 'GET';
// 请求地址
$url = 'ecs.aliyuncs.com?';
// 请求参数
$common = [
// 'Action' => 'AttachNetworkInterface', // API 的名称。取值参阅 API 概览。
'AccessKeyId' => $accessKeyId, // 访问密钥 ID
'SignatureMethod' => 'HMAC-SHA1', // 签名方式。取值范围:HMAC-SHA1。
'SignatureVersion' => '1.0', // 签名算法版本。取值范围:1.0。
'SignatureNonce' => rand(1000000,9999999), // 签名唯一随机数。用于防止网络重放攻击,建议您每一次请求都使用不同的随机数。
'Timestamp' => date('Y-m-d',time()).'T'.date('H:i:s',time()).'Z', // 请求的时间戳。按照ISO8601标准表示,并需要使用UTC时间,格式为yyyy-MM-ddTHH:mm:ssZ。示例:2018-01-01T12:00:00Z 表示北京时间 2018 年 01 月 01 日 20 点 00 分 00 秒。
'Version' => '2014-05-26', // API 的版本号,格式为 YYYY-MM-DD。取值范围:2014-05-26。
'Format' => 'json', // 返回参数的语言类型。取值范围:json | xml。默认值:xml。
// 'Signature' => '', // 您的签名
];
// 合并参数
$key = array_merge($input,$common);
// 进行键排序
ksort($key);
// 创建变量
$keystr = '';
// 循环拼接字符串
foreach ($key as $k => $v)
{
if($k == 'Timestamp')
{
$keystr .= $k.'='.urlencode($v).'&';
}
else
{
$keystr .= $k.'='.$v.'&';
}
}
// 拼接签字字符串
$srcStr = $method.'&%2F&'.urlencode(rtrim($keystr,'&'));
$srcStr1 = $method.'&%2F&'.rtrim($keystr,'&');
// 生成签名字符串 请求签名,用来验证此次请求的合法性,需要用户根据实际的输入参数计算得出。
// 验证时,如果有中文 需要验证中文字符串 发送请求时改为中文的url编码
$signStr = base64_encode(hash_hmac('sha1', $srcStr, $accessKeySecret.'&', true));
// 拼接请求地址
$str = 'https://'.$url.http_build_query($key).'&Signature='.urlencode($signStr);
// 发送请求
$res = json_decode(curl($str,$method),true)['body']; echo $res;
/**
* CURL发送请求
* @param type $url 地址
* @param type $method 请求方式
* @param type $data 请求参数
* @param type $header 请求头
* @return 返回参数
*/
function curl($url,$method='GET',$data=null,$header=null)
{
// 启动一个CURL会话
$curl = curl_init();
// 要访问的地址
curl_setopt($curl,CURLOPT_URL,$url);
//返回数据不直接输出
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
curl_setopt($curl, CURLOPT_HEADER, true); // 显示返回的Header区域内容
// curl 请求头设置
if(!empty($header))
{
curl_setopt($curl, CURLOPT_HTTPHEADER, $header); // 模拟参数传递
}
else
{
// curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
}
// https
// https请求 不验证证书和hosts php版本过低需要开启此项 否则会无法访问https的地址
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
// 从证书中检查SSL加密算法是否存在(默认不需要验证 php版本过低需要开启此项 否则会无法访问https的地址
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
//如果是post请求
if($method === 'POST' || $method === 'post')
{
//开启发送post请求选项
curl_setopt($curl,CURLOPT_POST,true);
//发送post的数据
curl_setopt($curl,CURLOPT_POSTFIELDS,$data);
}
//发送请求
$res = curl_exec($curl);
// 返回参数包含请求头 则此条无效
// $data = json_decode($res,JSON_UNESCAPED_UNICODE);
// 获取响应头大小
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
// 根据头大小去获取头信息内容
$header = substr($res, 0, $headerSize);
// 根据头大小去获取响应信息内容
$body = substr($res, $headerSize);
// 获取http状态码
$return_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if(substr($body,0,1) != '{')
{
$body = htmlspecialchars($body);
}
//关闭连接
curl_close($curl);
$arr = [
'header' => $header,
'body' => $body,
'return_code' => $return_code,
];
$res = json_encode($arr);
return $res;
}
- 实例解绑弹性网卡
aliclould_down_ip.php
<?php
/**
* 阿里云解绑弹性网卡
* DetachNetworkInterface
* https://help.aliyun.com/document_detail/58514.html
*/
//oss账号密码
$accessKeyId = "填入参数";
$accessKeySecret = "填入参数";
// 实例ID
$host = getopt('h:');
if(empty($host['h']))
{
exit;
}
else
{
$InstanceId = $host['h'];
}
// 弹性网卡ID
$NetworkInterfaceId = '填入网卡id';
// 实例所在地域的ID
$RegionId = 'cn-hangzhou';
date_default_timezone_set("UTC");
// 阿里云 调用DetachNetworkInterface从一台ECS实例上分离一个弹性网卡(ENI)
$input = [
'Action' => 'DetachNetworkInterface', // 系统规定参数。取值:DetachNetworkInterface
'InstanceId' => $InstanceId, // 实例ID
'NetworkInterfaceId' => $NetworkInterfaceId, // 弹性网卡ID
'RegionId' => $RegionId, // 实例所在地域的ID
];
// 请求类型
$method = 'GET';
// 请求地址
$url = 'ecs.aliyuncs.com?';
// 请求参数
$common = [
// 'Action' => 'DetachNetworkInterface', // API 的名称。取值参阅 API 概览。
'AccessKeyId' => $accessKeyId, // 访问密钥 ID
'SignatureMethod' => 'HMAC-SHA1', // 签名方式。取值范围:HMAC-SHA1。
'SignatureVersion' => '1.0', // 签名算法版本。取值范围:1.0。
'SignatureNonce' => rand(1000000,9999999), // 签名唯一随机数。用于防止网络重放攻击,建议您每一次请求都使用不同的随机数。
'Timestamp' => date('Y-m-d',time()).'T'.date('H:i:s',time()).'Z', // 请求的时间戳。按照ISO8601标准表示,并需要使用UTC时间,格式为yyyy-MM-ddTHH:mm:ssZ。示例:2018-01-01T12:00:00Z 表示北京时间 2018 年 01 月 01 日 20 点 00 分 00 秒。
'Version' => '2014-05-26', // API 的版本号,格式为 YYYY-MM-DD。取值范围:2014-05-26。
'Format' => 'json', // 返回参数的语言类型。取值范围:json | xml。默认值:xml。
// 'Signature' => '', // 您的签名
];
// 合并参数
$key = array_merge($input,$common);
// 进行键排序
ksort($key);
// 创建变量
$keystr = '';
// 循环拼接字符串
foreach ($key as $k => $v)
{
if($k == 'Timestamp')
{
$keystr .= $k.'='.urlencode($v).'&';
}
else
{
$keystr .= $k.'='.$v.'&';
}
}
// 拼接签字字符串
$srcStr = $method.'&%2F&'.urlencode(rtrim($keystr,'&'));
$srcStr1 = $method.'&%2F&'.rtrim($keystr,'&');
// 生成签名字符串 请求签名,用来验证此次请求的合法性,需要用户根据实际的输入参数计算得出。
// 验证时,如果有中文 需要验证中文字符串 发送请求时改为中文的url编码
$signStr = base64_encode(hash_hmac('sha1', $srcStr, $accessKeySecret.'&', true));
// 拼接请求地址
$str = 'https://'.$url.http_build_query($key).'&Signature='.urlencode($signStr);
// 发送请求
$res = json_decode(curl($str,$method),true)['body']; echo $res;
sleep(3);
/**
* CURL发送请求
* @param type $url 地址
* @param type $method 请求方式
* @param type $data 请求参数
* @param type $header 请求头
* @return 返回参数
*/
function curl($url,$method='GET',$data=null,$header=null)
{
// 启动一个CURL会话
$curl = curl_init();
// 要访问的地址
curl_setopt($curl,CURLOPT_URL,$url);
//返回数据不直接输出
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
curl_setopt($curl, CURLOPT_HEADER, true); // 显示返回的Header区域内容
// curl 请求头设置
if(!empty($header))
{
curl_setopt($curl, CURLOPT_HTTPHEADER, $header); // 模拟参数传递
}
else
{
// curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
}
// https
// https请求 不验证证书和hosts php版本过低需要开启此项 否则会无法访问https的地址
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
// 从证书中检查SSL加密算法是否存在(默认不需要验证 php版本过低需要开启此项 否则会无法访问https的地址
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
//如果是post请求
if($method === 'POST' || $method === 'post')
{
//开启发送post请求选项
curl_setopt($curl,CURLOPT_POST,true);
//发送post的数据
curl_setopt($curl,CURLOPT_POSTFIELDS,$data);
}
//发送请求
$res = curl_exec($curl);
// 返回参数包含请求头 则此条无效
// $data = json_decode($res,JSON_UNESCAPED_UNICODE);
// 获取响应头大小
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
// 根据头大小去获取头信息内容
$header = substr($res, 0, $headerSize);
// 根据头大小去获取响应信息内容
$body = substr($res, $headerSize);
// 获取http状态码
$return_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if(substr($body,0,1) != '{')
{
$body = htmlspecialchars($body);
}
//关闭连接
curl_close($curl);
$arr = [
'header' => $header,
'body' => $body,
'return_code' => $return_code,
];
$res = json_encode($arr);
return $res;
}
最后一次更新于2020-07-14 16:37
0 条评论