本文及资源最后更新时间 2020-12-20 by sky995
就是记录一下而已
思路大概是这样:
当然你源站 IP 没有暴露的话,用不到备用备用服务器.只需要切换到抗 D 抗 C 的 CDN 上就行.比如Cloudflare
代码
- <?php
- date_default_timezone_set(‘UTC’);
- define(“ACCESSKEYID”, ‘*************’);
- define(“ACCESSKEYSECRET”, ‘********************’);
- define(“RID”, ‘***************’);
- $s = init();
- $h = ‘blog’;//主机记录值 根据自己的填写
- $domain1 = ‘https://blog.kieng.cn/’; //源站 IP/cname
- $domain2 = ‘http://http-status-123456.kieng.cn/’; //跟源站一个 IP 的域名用于判断服务器是否正常运转/A 记录
- $ip1 = ‘blog.kieng.cn.alicdn.com’; //源站 IP/cname
- $ip2 = ‘blog.kieng.cn.tengxun.com’; //备用 IP/cname
- // 当 status.txt 为 0 为正常 访问源站
- if (!$s) {
- $http_status = getHeaders($domain1);
- // 源站正常
- if ($http_status) {
- // 写入日志
- goLog(‘log’, 1, $ip1);
- die(jsonm([‘code’ => 0, ‘msg’ => ‘执行成功!源站正常!’]));
- } else {
- // 超时或状态码不为 200/404
- goLog(‘log’, 2, $ip2);
- // 改 status.txt 为 1
- file_put_contents(__DIR__ . ‘/status.txt’, ‘1’);
- // 切换到备用 IP
- UpdateDomainRecord(RID, $ip2, ‘CNAME’, $h);
- die(jsonm([‘code’ => 0, ‘msg’ => ‘执行成功!以切换为备用站 IP’]));
- }
- } else {
- //反之 status.txt 为 1 已经切换为备用站
- $http_status = getHeaders($domain2);
- // 源站 IP 恢复正常
- if ($http_status) {
- // 写入日志
- goLog(‘log’, 3, $ip1);
- // 改回 status.txt 为 0
- file_put_contents(__DIR__ . ‘/status.txt’, ‘0’);
- // 切回到正常 IP
- UpdateDomainRecord(RID, $ip1, ‘CNAME’, $h);
- die(jsonm([‘code’ => 0, ‘msg’ => ‘执行成功!源站以恢复,以切换为源站’]));
- } else {
- //继续使用备用站 IP
- goLog(‘log’, 4, $ip2);
- die(jsonm([‘code’ => 0, ‘msg’ => ‘执行成功!源站未恢复,正在使用备用站’]));
- }
- }
- /**
- * 更新 ip/cname
- */
- function UpdateDomainRecord($rid, $ip, $type = ‘A’, $rr = ‘cloudflare’) {
- $requestParams = array(
- “Action” => “UpdateDomainRecord”,
- “RecordId” => $rid,
- “RR” => $rr, //主机记录(我用这个用别的自己修改一下)
- “Type” => $type,
- “Value” => $ip, //记录值
- );
- $val = requestAli($requestParams);
- return $val;
- }
- /*
- 写日志
- $msg 1 正常 2.切换为热备 IP 3.切换回源站 IP 4.使用备用站 IP
- */
- function goLog($status = ‘log’, $msg = 1, $ip) {
- $log_path = __DIR__ . ‘/’ . $status . ‘/’ . date(‘Y-m-d’);
- // 写出日志
- // 创建目录
- mkFolder($log_path);
- $filename = $log_path . “/http.log”;
- $handle = fopen($filename, “a+”);
- switch ($msg) {
- case 1:
- fwrite($handle, date(‘Y-m-d H:i:s’) . ‘—-status:访问成功,无异常—-ip:’ . $ip . “\n”);
- break;
- case 2:
- fwrite($handle, date(‘Y-m-d H:i:s’) . ‘—-status:异常已切换—-ip:’ . $ip . “\n”);
- break;
- case 3:
- fwrite($handle, date(‘Y-m-d H:i:s’) . ‘—-status:以切回源站—-ip:’ . $ip . “\n”);
- break;
- case 4:
- fwrite($handle, date(‘Y-m-d H:i:s’) . ‘—-status:现为备用站—-ip:’ . $ip . “\n”);
- break;
- default:
- fwrite($handle, date(‘Y-m-d H:i:s’) . ‘—-status:访问成功,无异常—-ip:’ . $ip . “\n”);
- break;
- }
- fclose($handle);
- return;
- }
- /*
- 初始化 建立所需数据文本
- */
- function init() {
- $path = __DIR__ . ‘/’;
- // status.txt 为 0 是源站 为 1 则以切换到热备站
- if (!file_exists($path . ‘status.txt’)) {
- file_put_contents($path . ‘status.txt’, 0);
- return false;
- } else {
- if (file_get_contents($path . ‘status.txt’) == 0) {
- return false;
- } else {
- return true;
- }
- }
- }
- /*
- 创建目录
- */
- function mkFolder($path) {
- if (!is_readable($path)) {
- is_file($path) or mkdir($path, 0700, true);
- }
- }
- /*
- 判断 http code
- */
- function getHeaders($url) {
- $curl = curl_init();
- curl_setopt($curl, CURLOPT_URL, $url);
- curl_setopt($curl, CURLOPT_HEADER, 1);
- curl_setopt($curl, CURLOPT_NOBODY, 1);
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($curl, CURLOPT_TIMEOUT, 10); //超时 10s
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
- curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
- curl_exec($curl);
- $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
- curl_close($curl);
- if ($http_code == 200 || $http_code == 404) {
- return true;
- } else {
- return false;
- }
- }
- /*
- 执行操作
- */
- function requestAli($requestParams, $accessKeyId = ACCESSKEYID, $accessSecrec = ACCESSKEYSECRET) {
- $publicParams = array(
- “Format” => “JSON”,
- “Version” => “2015-01-09”,
- “AccessKeyId” => $accessKeyId,
- “Timestamp” => date(“Y-m-d\TH:i:s\Z”),
- “SignatureMethod” => “HMAC-SHA1”,
- “SignatureVersion” => “1.0”,
- “SignatureNonce” => substr(md5(rand(1, 99999999)), rand(1, 9), 14),
- );
- $params = array_merge($publicParams, $requestParams);
- $params[‘Signature’] = sign($params, $accessSecrec);
- $uri = http_build_query($params);
- $url = ‘http://alidns.aliyuncs.com/?’ . $uri;
- return curl($url);
- }
- /*
- 计算密匙
- */
- function sign($params, $accessSecrec = ACCESSKEYSECRET, $method = “GET”) {
- ksort($params);
- $stringToSign = strtoupper($method) . ‘&’ . percentEncode(‘/’) . ‘&’;
- $tmp = “”;
- foreach ($params as $key => $val) {
- $tmp .= ‘&’ . percentEncode($key) . ‘=’ . percentEncode($val);
- }
- $tmp = trim($tmp, ‘&’);
- $stringToSign = $stringToSign . percentEncode($tmp);
- $key = $accessSecrec . ‘&’;
- $hmac = hash_hmac(“sha1”, $stringToSign, $key, true);
- return base64_encode($hmac);
- }
- /*
- 格式
- */
- function percentEncode($value = null) {
- $en = urlencode($value);
- $en = str_replace(“+”, “%20”, $en);
- $en = str_replace(“*”, “%2A”, $en);
- $en = str_replace(“%7E”, “~”, $en);
- return $en;
- }
- /*
- 发送请求
- */
- function curl($url) {
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- $result = curl_exec($ch);
- return $result;
- }
- function jsonm($data) {
- header(‘content-type:application/json;charset=utf-8’);
- return stripslashes(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
- }
RID 这个值,其实可以通过 API 去获取,但是没写.其实只需要在DNS解析管理那修改一下记录就能看见,如图:
按 F12,随便修改一下记录 比如修改一下 TTL 时间
这个字符串就是 RID,填写一下就可以.
阿里云有DNS的 SDK.但是不想用.随便写写大概就是这么个意思.
然后把代码存为 xxx.php 放在随便一个服务器里,然后在计划任务里定时执行一下.多久检查一次就看自己了.用腾讯云函数也可以,无所谓.
最后
腾讯云有 D 监控就可以实现.我用的阿里云DNS没找到在哪.估计得花钱..大概思路就是这样.其实写日志什么也可以用别人写好的库,但是在腾讯云函数上没法执行.就这样就好了.