{"componentChunkName":"component---src-templates-blog-detail-tsx","path":"/blog/2020-04-10-website-alarm","result":{"data":{"currentBlog":{"id":"44ad21a9-00a3-592c-83c1-696af478c55f","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020414/1586850670017-%E5%B0%81%E9%9D%A2%E5%9B%BE%20%283%29.png","authors":["Anycodes"],"categories":["guides-and-tutorials","operations-and-observability"],"date":"2020-04-10T00:00:00.000Z","title":"Serverless 实战：通过 Serverless 架构实现监控告警","description":"Serverless 的一个重要应用场景就是运维、监控与告警，本文将会通过现有的 Serverless 平台，部署一个网站状态监控脚本，对网站的可用性进行监控告警","authorslink":["https://www.zhihu.com/people/liuyu-43-97"],"translators":null,"translatorslink":null,"tags":["Serverless","监控告警"],"keywords":"Serverless 全局变量组件,Serverless 单独部署组件,Serverless Component","outdated":true},"wordCount":{"words":368,"sentences":65,"paragraphs":65},"fileAbsolutePath":"/opt/build/repo/content/blog/2020-04-10-website-alarm.md","fields":{"slug":"/blog/2020-04-10-website-alarm/","keywords":["php","python","serverless","监控","告警","Serverless","耗时","网站"]},"html":"<p>在实际生产中，我们经常需要做一些监控脚本来监控网站服务或者 API 服务是否可用。传统的方法是使用网站监控平台（例如 DNSPod 监控、360 网站服务监控，以及阿里云监控等），它们的原理是通过用户自己设置要监控的服务地址和监测的时间阈值，由监控平台定期发起请求对网站或服务的可用性进行判断。</p>\n<p>这些方法很大众化，通用性很强，但也不是所有场景都适合。例如，如果我们的需求是监控网站状态码，不同区域的延时，并且通过监控得到的数据，设定一个阈值，一旦超过阈值就通过邮件等进行统治告警，目前大部分的监控平台是很难满足这些需求的，这时就需要定制开发一个监控工具。</p>\n<p>Serverless 服务的一个重要应用场景就是运维、监控与告警，所以本文将会通过现有的 Serverless 平台，部署一个网站状态监控脚本，对目标网站的可用性进行监控告警。</p>\n<h2 id=\"web-服务监控告警\"><a href=\"#web-%E6%9C%8D%E5%8A%A1%E7%9B%91%E6%8E%A7%E5%91%8A%E8%AD%A6\" aria-label=\"web 服务监控告警 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Web 服务监控告警</h2>\n<p>针对 Web 服务，我们先设计一个简单的监控告警功能的流程：</p>\n<p><img src=\"https://img.serverlesscloud.cn/tmp/04b46b3c01bb58ee12b3a1a903a8955c-20200414224657802.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<p>在这个流程中，我们仅对网站的状态码进行监控，即返回的状态为 200，则判定网站可正常使用，否则进行告警：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"78715192399632320000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# -*- coding: utf8 -*-\nimport ssl\nimport json\nimport smtplib\nimport urllib.request\nfrom email.mime.text import MIMEText\nfrom email.header import Header\n\nssl._create_default_https_context = ssl._create_unverified_context\n\n\ndef sendEmail(content, to_user):\n    sender = 'service@anycodes.cn'\n    receivers = [to_user]\n\n    mail_msg = content\n    message = MIMEText(mail_msg, 'html', 'utf-8')\n    message['From'] = Header(&quot; 网站监控 &quot;, 'utf-8')\n    message['To'] = Header(&quot; 站长 &quot;, 'utf-8')\n\n    subject = &quot; 网站监控告警 &quot;\n    message['Subject'] = Header(subject, 'utf-8')\n\n    try:\n        smtpObj = smtplib.SMTP_SSL(&quot;smtp.exmail.qq.com&quot;, 465)\n        smtpObj.login('发送邮件的邮箱地址', '密码')\n        smtpObj.sendmail(sender, receivers, message.as_string())\n    except smtplib.SMTPException as e:\n        print(e)\n\n\ndef getStatusCode(url):\n    return urllib.request.urlopen(url).getcode()\n\n\ndef main_handler(event, context):\n    url = &quot;http://www.anycodes.cn&quot;\n    if getStatusCode(url) == 200:\n        print(&quot; 您的网站 %s 可以访问！&quot; % (url))\n    else:\n        sendEmail(&quot; 您的网站 %s 不可以访问！&quot; % (url), &quot; 接受人邮箱地址 &quot;)\n    return None`, `78715192399632320000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token comment\"># -*- coding: utf8 -*-</span>\n<span class=\"token keyword\">import</span> ssl\n<span class=\"token keyword\">import</span> json\n<span class=\"token keyword\">import</span> smtplib\n<span class=\"token keyword\">import</span> urllib<span class=\"token punctuation\">.</span>request\n<span class=\"token keyword\">from</span> email<span class=\"token punctuation\">.</span>mime<span class=\"token punctuation\">.</span>text <span class=\"token keyword\">import</span> MIMEText\n<span class=\"token keyword\">from</span> email<span class=\"token punctuation\">.</span>header <span class=\"token keyword\">import</span> Header\n\nssl<span class=\"token punctuation\">.</span>_create_default_https_context <span class=\"token operator\">=</span> ssl<span class=\"token punctuation\">.</span>_create_unverified_context\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">sendEmail</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">,</span> to_user<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    sender <span class=\"token operator\">=</span> <span class=\"token string\">'service@anycodes.cn'</span>\n    receivers <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>to_user<span class=\"token punctuation\">]</span>\n\n    mail_msg <span class=\"token operator\">=</span> content\n    message <span class=\"token operator\">=</span> MIMEText<span class=\"token punctuation\">(</span>mail_msg<span class=\"token punctuation\">,</span> <span class=\"token string\">'html'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    message<span class=\"token punctuation\">[</span><span class=\"token string\">'From'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Header<span class=\"token punctuation\">(</span><span class=\"token string\">\" 网站监控 \"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    message<span class=\"token punctuation\">[</span><span class=\"token string\">'To'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Header<span class=\"token punctuation\">(</span><span class=\"token string\">\" 站长 \"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n\n    subject <span class=\"token operator\">=</span> <span class=\"token string\">\" 网站监控告警 \"</span>\n    message<span class=\"token punctuation\">[</span><span class=\"token string\">'Subject'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Header<span class=\"token punctuation\">(</span>subject<span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        smtpObj <span class=\"token operator\">=</span> smtplib<span class=\"token punctuation\">.</span>SMTP_SSL<span class=\"token punctuation\">(</span><span class=\"token string\">\"smtp.exmail.qq.com\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">465</span><span class=\"token punctuation\">)</span>\n        smtpObj<span class=\"token punctuation\">.</span>login<span class=\"token punctuation\">(</span><span class=\"token string\">'发送邮件的邮箱地址'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'密码'</span><span class=\"token punctuation\">)</span>\n        smtpObj<span class=\"token punctuation\">.</span>sendmail<span class=\"token punctuation\">(</span>sender<span class=\"token punctuation\">,</span> receivers<span class=\"token punctuation\">,</span> message<span class=\"token punctuation\">.</span>as_string<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">except</span> smtplib<span class=\"token punctuation\">.</span>SMTPException <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">getStatusCode</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">return</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>getcode<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"http://www.anycodes.cn\"</span>\n    <span class=\"token keyword\">if</span> getStatusCode<span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">200</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">\" 您的网站 %s 可以访问！\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n        sendEmail<span class=\"token punctuation\">(</span><span class=\"token string\">\" 您的网站 %s 不可以访问！\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\" 接受人邮箱地址 \"</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> <span class=\"token boolean\">None</span></code></pre></div>\n<p>通过 ServerlessFramework 可以部署，在部署的时候可以增加时间触发器：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"19346343297182610000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`MyWebMonitor:\n  component: &quot;@serverless/tencent-scf&quot;\n  inputs:\n    name: MyWebMonitor\n    codeUri: ./code\n    handler: index.main_handler\n    runtime: Python3.6\n    region: ap-guangzhou\n    description: 网站监控\n    memorySize: 64\n    timeout: 20\n    events:\n      - timer:\n          name: timer\n          parameters:\n            cronExpression: '*/5 * * * *'\n            enable: true`, `19346343297182610000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">MyWebMonitor</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">component</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"@serverless/tencent-scf\"</span>\n  <span class=\"token key atrule\">inputs</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> MyWebMonitor\n    <span class=\"token key atrule\">codeUri</span><span class=\"token punctuation\">:</span> ./code\n    <span class=\"token key atrule\">handler</span><span class=\"token punctuation\">:</span> index.main_handler\n    <span class=\"token key atrule\">runtime</span><span class=\"token punctuation\">:</span> Python3.6\n    <span class=\"token key atrule\">region</span><span class=\"token punctuation\">:</span> ap<span class=\"token punctuation\">-</span>guangzhou\n    <span class=\"token key atrule\">description</span><span class=\"token punctuation\">:</span> 网站监控\n    <span class=\"token key atrule\">memorySize</span><span class=\"token punctuation\">:</span> <span class=\"token number\">64</span>\n    <span class=\"token key atrule\">timeout</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span>\n    <span class=\"token key atrule\">events</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">timer</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> timer\n          <span class=\"token key atrule\">parameters</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">cronExpression</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'*/5 * * * *'</span>\n            <span class=\"token key atrule\">enable</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span></code></pre></div>\n<p>在这里，timer 表示时间触发器，<code class=\"language-text\">cronExpression</code>是表达式：</p>\n<p>创建定时触发器时，用户能够使用标准的 Cron 表达式的形式自定义何时触发。定时触发器现已推出秒级触发功能，为了兼容老的定时触发器，因此 Cron 表达式有两种写法。</p>\n<h4 id=\"cron-表达式语法一（推荐）\"><a href=\"#cron-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E6%B3%95%E4%B8%80%EF%BC%88%E6%8E%A8%E8%8D%90%EF%BC%89\" aria-label=\"cron 表达式语法一（推荐） permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cron 表达式语法一（推荐）</h4>\n<p>Cron 表达式有七个必需字段，按空格分隔。\n<img src=\"https://img.serverlesscloud.cn/tmp/3d2012b3e31f0ef92694e60870d4d213-20200414224748091.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\">\n其中，每个字段都有相应的取值范围：</p>\n<p><img src=\"https://img.serverlesscloud.cn/tmp/f615f5ee168e2330c26ece95e047e57b-20200414224752288.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<h4 id=\"cron-表达式语法二（不推荐）\"><a href=\"#cron-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E6%B3%95%E4%BA%8C%EF%BC%88%E4%B8%8D%E6%8E%A8%E8%8D%90%EF%BC%89\" aria-label=\"cron 表达式语法二（不推荐） permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cron 表达式语法二（不推荐）</h4>\n<p>Cron 表达式有五个必需字段，按空格分隔。\n<img src=\"https://img.serverlesscloud.cn/tmp/a708facdd3ebb1064a3004876c7867fa-20200414224759391.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\">\n其中，每个字段都有相应的取值范围：\n<img src=\"https://img.serverlesscloud.cn/tmp/906d03b9aa5873296cf484b1082e3028-20200414224804297.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<h4 id=\"通配符\"><a href=\"#%E9%80%9A%E9%85%8D%E7%AC%A6\" aria-label=\"通配符 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>通配符</h4>\n<p><img src=\"https://img.serverlesscloud.cn/tmp/0c89cf5d5d9f23d1ab9ffefe34442d7f-20200414224811024.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<h4 id=\"注意事项\"><a href=\"#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9\" aria-label=\"注意事项 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>注意事项</h4>\n<p>在 Cron 表达式中的“日”和“星期”字段同时指定值时，两者为“或”关系，即两者的条件分别均生效。</p>\n<h4 id=\"示例\"><a href=\"#%E7%A4%BA%E4%BE%8B\" aria-label=\"示例 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>示例</h4>\n<p><code class=\"language-text\">*/5 * * * * * *</code> 表示每 5 秒触发一次\n<code class=\"language-text\">0 0 2 1 * * *</code> 表示在每月的 1 日的凌晨 2 点触发\n<code class=\"language-text\">0 15 10 * * MON-FRI *</code> 表示在周一到周五每天上午 10：15 触发\n<code class=\"language-text\">0 0 10,14,16 * * * *</code> 表示在每天上午 10 点，下午 2 点，4 点触发\n<code class=\"language-text\">0 */30 9-17 * * * *</code> 表示在每天上午 9 点到下午 5 点内每半小时触发\n<code class=\"language-text\">0 0 12 * * WED *</code> 表示在每个星期三中午 12 点触发</p>\n<p>因此，我们上面的代码可以认为是每 5 秒触发一次，当然，也可以根据网站监控密度，自定义设置触发的间隔时间。当我们网站服务不可用时，就可以收到告警：</p>\n<p><img src=\"https://img.serverlesscloud.cn/tmp/cd721942167b4dd24203b2b4423e1a7d-20200414224821171.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<p>这种网站监控方法比较简单，准确度可能会有问题，对于网站或服务的监控不能简单的看返回值，还要看链接耗时、下载耗时以及不同区域、不同运营商访问网站或者服务的延时信息等。</p>\n<p>所以，我们需要对这个代码进行额外的更新与优化：</p>\n<ol>\n<li>通过在线网速测试的网站，抓包获取不同地区不同运营商的请求特征；</li>\n<li>编写爬虫程序，进行在线网速测试模块的编写；</li>\n<li>集成到刚刚的项目中；</li>\n</ol>\n<p>下面以站长工具网站中国内网站测速工具 为例，通过网页查阅相关信息。</p>\n<p>对网站测速工具进行封装，例如：</p>\n<p><img src=\"https://img.serverlesscloud.cn/tmp/41b63003462e9b7c6837c6cf45db3a37-20200414224826020.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<p>通过对网页进行分析，获取请求特征，包括 Url，Form data，以及 Headers 等相关信息，其中该网站在使用不同监测点对网站进行请求时，是通过 Form data 中的 guid 的参数实现的，例如部分监测点的 guid：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"19779488122039780000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`广东佛山\t电信\tf403cdf2-27f8-4ccd-8f22-6f5a28a01309\n江苏宿迁\t多线\t74cb6a5c-b044-49d0-abee-bf42beb6ae05\n江苏常州\t移动\t5074fb13-4ab9-4f0a-87d9-f8ae51cb81c5\n浙江嘉兴\t联通\tddfeba9f-a432-4b9a-b0a9-ef76e9499558`, `19779488122039780000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">广东佛山\t电信\tf403cdf2-27f8-4ccd-8f22-6f5a28a01309\n江苏宿迁\t多线\t74cb6a5c-b044-49d0-abee-bf42beb6ae05\n江苏常州\t移动\t5074fb13-4ab9-4f0a-87d9-f8ae51cb81c5\n浙江嘉兴\t联通\tddfeba9f-a432-4b9a-b0a9-ef76e9499558</code></pre></div>\n<p>此时，我们可以编写基本的爬虫代码，来对 Response 进行初步解析，以<code class=\"language-text\">62a55a0e-387e-4d87-bf69-5e0c9dd6b983 江苏宿迁 [电信]</code>为例，编写代码：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"63331611679114270000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`import urllib.request\nimport urllib.parse\n\nurl = &quot;* 某测速网站地址 *&quot;\nform_data = {\n    'guid': '62a55a0e-387e-4d87-bf69-5e0c9dd6b983',\n    'host': 'anycodes.cn',\n    'ishost': '1',\n    'encode': 'ECvBP9vjbuXRi0CVhnXAbufDNPDryYzO',\n    'checktype': '1',\n}\nheaders = {\n    'Host': 'tool.chinaz.com',\n    'Origin': '* 某测速网站地址 *',\n    'Referer': '* 某测速网站地址 *',\n    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36',\n    'X-Requested-With': 'XMLHttpRequest'\n}\n\nprint(urllib.request.urlopen(\n    urllib.request.Request(\n        url=url,\n        data=urllib.parse.urlencode(form_data).encode('utf-8'),\n        headers=headers\n    )\n).read().decode(&quot;utf-8&quot;))`, `63331611679114270000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">import</span> urllib<span class=\"token punctuation\">.</span>request\n<span class=\"token keyword\">import</span> urllib<span class=\"token punctuation\">.</span>parse\n\nurl <span class=\"token operator\">=</span> <span class=\"token string\">\"* 某测速网站地址 *\"</span>\nform_data <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">'guid'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'62a55a0e-387e-4d87-bf69-5e0c9dd6b983'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'host'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'anycodes.cn'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'ishost'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'1'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'encode'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'ECvBP9vjbuXRi0CVhnXAbufDNPDryYzO'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'checktype'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'1'</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span>\nheaders <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">'Host'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'tool.chinaz.com'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'Origin'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'* 某测速网站地址 *'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'Referer'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'* 某测速网站地址 *'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'User-Agent'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">'X-Requested-With'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'XMLHttpRequest'</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>\n    urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">(</span>\n        url<span class=\"token operator\">=</span>url<span class=\"token punctuation\">,</span>\n        data<span class=\"token operator\">=</span>urllib<span class=\"token punctuation\">.</span>parse<span class=\"token punctuation\">.</span>urlencode<span class=\"token punctuation\">(</span>form_data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        headers<span class=\"token operator\">=</span>headers\n    <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>获得结果：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"43901181262950195000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`({\n\tstate: 1,\n\tmsg: '',\n\tresult: {\n\t\tip: '119.28.190.46',\n\t\thttpstate: 200,\n\t\talltime: '212',\n\t\tdnstime: '18',\n\t\tconntime: '116',\n\t\tdowntime: '78',\n\t\tfilesize: '-',\n\t\tdownspeed: '4.72',\n\t\tipaddress: '新加坡新加坡',\n\t\theaders: 'HTTP/1.1 200 OK br>Server: ...',\n\t\tpagehtml: ''\n\t}\n})`, `43901181262950195000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\">(<span class=\"token punctuation\">{</span>\n\tstate<span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n\tmsg<span class=\"token operator\">:</span> ''<span class=\"token punctuation\">,</span>\n\tresult<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n\t\tip<span class=\"token operator\">:</span> '<span class=\"token number\">119.28</span>.<span class=\"token number\">190.46</span>'<span class=\"token punctuation\">,</span>\n\t\thttpstate<span class=\"token operator\">:</span> <span class=\"token number\">200</span><span class=\"token punctuation\">,</span>\n\t\talltime<span class=\"token operator\">:</span> '<span class=\"token number\">212</span>'<span class=\"token punctuation\">,</span>\n\t\tdnstime<span class=\"token operator\">:</span> '<span class=\"token number\">18</span>'<span class=\"token punctuation\">,</span>\n\t\tconntime<span class=\"token operator\">:</span> '<span class=\"token number\">116</span>'<span class=\"token punctuation\">,</span>\n\t\tdowntime<span class=\"token operator\">:</span> '<span class=\"token number\">78</span>'<span class=\"token punctuation\">,</span>\n\t\tfilesize<span class=\"token operator\">:</span> '-'<span class=\"token punctuation\">,</span>\n\t\tdownspeed<span class=\"token operator\">:</span> '<span class=\"token number\">4.72</span>'<span class=\"token punctuation\">,</span>\n\t\tipaddress<span class=\"token operator\">:</span> '新加坡新加坡'<span class=\"token punctuation\">,</span>\n\t\theaders<span class=\"token operator\">:</span> 'HTTP/<span class=\"token number\">1.1</span> <span class=\"token number\">200</span> OK br>Server<span class=\"token operator\">:</span> ...'<span class=\"token punctuation\">,</span>\n\t\tpagehtml<span class=\"token operator\">:</span> ''\n\t<span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>)</code></pre></div>\n<p>在这个结果中，我们可以提取部分数据，例如江苏宿迁 [电信] 访问目标网站的基础数据：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"69960654743066880000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`总耗时：alltime:'212'\n链接耗时：conntime:'116'\n下载耗时：downtime:'78'`, `69960654743066880000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">总耗时：alltime:&#39;212&#39;\n链接耗时：conntime:&#39;116&#39;\n下载耗时：downtime:&#39;78&#39;</code></pre></div>\n<p>此时，我们可以改造代码对更多的节点，进行测试：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"58078855816370510000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`江苏宿迁 [电信]\t总耗时:223\t链接耗时:121\t下载耗时:81\n广东佛山 [电信]\t总耗时:44\t链接耗时:27\t下载耗时:17\n广东惠州 [电信]\t总耗时:56\t链接耗时:34\t下载耗时:22\n广东深圳 [电信]\t总耗时:149\t链接耗时:36\t下载耗时:25\n浙江湖州 [电信]\t总耗时:3190\t链接耗时:3115\t下载耗时:75\n辽宁大连 [电信]\t总耗时:468\t链接耗时:255\t下载耗时:170\n江苏泰州 [电信]\t总耗时:180\t链接耗时:104\t下载耗时:69\n安徽合肥 [电信]\t总耗时:196\t链接耗时:110\t下载耗时:73\n...`, `58078855816370510000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">江苏宿迁 [电信]\t总耗时:223\t链接耗时:121\t下载耗时:81\n广东佛山 [电信]\t总耗时:44\t链接耗时:27\t下载耗时:17\n广东惠州 [电信]\t总耗时:56\t链接耗时:34\t下载耗时:22\n广东深圳 [电信]\t总耗时:149\t链接耗时:36\t下载耗时:25\n浙江湖州 [电信]\t总耗时:3190\t链接耗时:3115\t下载耗时:75\n辽宁大连 [电信]\t总耗时:468\t链接耗时:255\t下载耗时:170\n江苏泰州 [电信]\t总耗时:180\t链接耗时:104\t下载耗时:69\n安徽合肥 [电信]\t总耗时:196\t链接耗时:110\t下载耗时:73\n...</code></pre></div>\n<p>并对项目中的 index.py 进行代码修改：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"49924309495725970000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# -*- coding: utf8 -*-\nimport ssl\nimport json\nimport re\nimport socket\nimport smtplib\nimport urllib.request\nfrom email.mime.text import MIMEText\nfrom email.header import Header\n\nsocket.setdefaulttimeout(2.5)\nssl._create_default_https_context = ssl._create_unverified_context\n\ndef getWebTime():\n\n    final_list = []\n    final_status = True\n\n    total_list = '''62a55a0e-387e-4d87-bf69-5e0c9dd6b983 江苏宿迁 [电信]\n    f403cdf2-27f8-4ccd-8f22-6f5a28a01309 广东佛山 [电信]\n    5bea1430-f7c2-4146-88f4-17a7dc73a953 河南新乡 [多线]\n    1f430ff0-eae9-413a-af2a-1c2a8986cff0 河南新乡 [多线]\n    ea551b59-2609-4ab4-89bc-14b2080f501a 河南新乡 [多线]\n    2805fa9f-05ea-46bc-8ac0-1769b782bf52 黑龙江哈尔滨 [联通]\n    722e28ca-dd02-4ccd-a134-f9d4218505a5 广东深圳 [移动]\n8e7a403c-d998-4efa-b3d1-b67c0dfabc41 广东深圳 [移动]'''\n\n    url = &quot;* 某测速网站地址 *&quot;\n    for eve in total_list.split('\\n'):\n        id_data, node_name = eve.strip().split(&quot; &quot;)\n        form_data = {\n            'guid': id_data,\n            'host': 'anycodes.cn',\n            'ishost': '1',\n            'encode': 'ECvBP9vjbuXRi0CVhnXAbufDNPDryYzO',\n            'checktype': '1',\n        }\n        headers = {\n            'Host': '* 某测速网站地址 *',\n            'Origin': '* 某测速网站地址 *',\n            'Referer': '* 某测速网站地址 *',\n            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36',\n            'X-Requested-With': 'XMLHttpRequest'\n        }\n        try:\n            result_data = urllib.request.urlopen(\n                urllib.request.Request(\n                    url=url,\n                    data=urllib.parse.urlencode(form_data).encode('utf-8'),\n                    headers=headers\n                )\n            ).read().decode(&quot;utf-8&quot;)\n            try:\n                alltime = re.findall(&quot;alltime:'(.*?)'&quot;, result_data)[0]\n                conntime = re.findall(&quot;conntime:'(.*?)'&quot;, result_data)[0]\n                downtime = re.findall(&quot;downtime:'(.*?)'&quot;, result_data)[0]\n                final_string = &quot;%s\\t 总耗时:%s\\t 链接耗时:%s\\t 下载耗时:%s&quot; % (node_name, alltime, conntime, downtime)\n            except:\n                final_string = &quot;%s 链接异常！&quot; % (node_name)\n                final_status = False\n        except:\n            final_string = &quot;%s 链接超时！&quot; % (node_name)\n            final_status = False\n        final_list.append(final_string)\n        print(final_string)\n    return (final_status,final_list)\ndef sendEmail(content, to_user):\n    sender = 'service@anycodes.cn'\n    receivers = [to_user]\n    mail_msg = content\n    message = MIMEText(mail_msg, 'html', 'utf-8')\n    message['From'] = Header(&quot; 网站监控 &quot;, 'utf-8')\n    message['To'] = Header(&quot; 站长 &quot;, 'utf-8')\n    subject = &quot; 网站监控告警 &quot;\n    message['Subject'] = Header(subject, 'utf-8')\n    try:\n        smtpObj = smtplib.SMTP_SSL(&quot;smtp.exmail.qq.com&quot;, 465)\n        smtpObj.login('service@anycodes.cn', '密码')\n        smtpObj.sendmail(sender, receivers, message.as_string())\n    except smtplib.SMTPException:\n        pass\n\ndef getStatusCode(url):\n    return urllib.request.urlopen(url).getcode()\n\ndef main_handler(event, context):\n    url = &quot;http://www.anycodes.cn&quot;\n    final_status,final_list = getWebTime()\n    if not final_status:\n        sendEmail(&quot; 您的网站 %s 的状态：<br>%s&quot; % (url, &quot;<br>&quot;.join(final_list)), &quot;service@52exe.cn&quot;)`, `49924309495725970000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token comment\"># -*- coding: utf8 -*-</span>\n<span class=\"token keyword\">import</span> ssl\n<span class=\"token keyword\">import</span> json\n<span class=\"token keyword\">import</span> re\n<span class=\"token keyword\">import</span> socket\n<span class=\"token keyword\">import</span> smtplib\n<span class=\"token keyword\">import</span> urllib<span class=\"token punctuation\">.</span>request\n<span class=\"token keyword\">from</span> email<span class=\"token punctuation\">.</span>mime<span class=\"token punctuation\">.</span>text <span class=\"token keyword\">import</span> MIMEText\n<span class=\"token keyword\">from</span> email<span class=\"token punctuation\">.</span>header <span class=\"token keyword\">import</span> Header\n\nsocket<span class=\"token punctuation\">.</span>setdefaulttimeout<span class=\"token punctuation\">(</span><span class=\"token number\">2.5</span><span class=\"token punctuation\">)</span>\nssl<span class=\"token punctuation\">.</span>_create_default_https_context <span class=\"token operator\">=</span> ssl<span class=\"token punctuation\">.</span>_create_unverified_context\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">getWebTime</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n\n    final_list <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n    final_status <span class=\"token operator\">=</span> <span class=\"token boolean\">True</span>\n\n    total_list <span class=\"token operator\">=</span> <span class=\"token triple-quoted-string string\">'''62a55a0e-387e-4d87-bf69-5e0c9dd6b983 江苏宿迁 [电信]\n    f403cdf2-27f8-4ccd-8f22-6f5a28a01309 广东佛山 [电信]\n    5bea1430-f7c2-4146-88f4-17a7dc73a953 河南新乡 [多线]\n    1f430ff0-eae9-413a-af2a-1c2a8986cff0 河南新乡 [多线]\n    ea551b59-2609-4ab4-89bc-14b2080f501a 河南新乡 [多线]\n    2805fa9f-05ea-46bc-8ac0-1769b782bf52 黑龙江哈尔滨 [联通]\n    722e28ca-dd02-4ccd-a134-f9d4218505a5 广东深圳 [移动]\n8e7a403c-d998-4efa-b3d1-b67c0dfabc41 广东深圳 [移动]'''</span>\n\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"* 某测速网站地址 *\"</span>\n    <span class=\"token keyword\">for</span> eve <span class=\"token keyword\">in</span> total_list<span class=\"token punctuation\">.</span>split<span class=\"token punctuation\">(</span><span class=\"token string\">'\\n'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        id_data<span class=\"token punctuation\">,</span> node_name <span class=\"token operator\">=</span> eve<span class=\"token punctuation\">.</span>strip<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>split<span class=\"token punctuation\">(</span><span class=\"token string\">\" \"</span><span class=\"token punctuation\">)</span>\n        form_data <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token string\">'guid'</span><span class=\"token punctuation\">:</span> id_data<span class=\"token punctuation\">,</span>\n            <span class=\"token string\">'host'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'anycodes.cn'</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">'ishost'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'1'</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">'encode'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'ECvBP9vjbuXRi0CVhnXAbufDNPDryYzO'</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">'checktype'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'1'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span>\n        headers <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token string\">'Host'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'* 某测速网站地址 *'</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">'Origin'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'* 某测速网站地址 *'</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">'Referer'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'* 某测速网站地址 *'</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">'User-Agent'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">'X-Requested-With'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'XMLHttpRequest'</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n            result_data <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>\n                urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">(</span>\n                    url<span class=\"token operator\">=</span>url<span class=\"token punctuation\">,</span>\n                    data<span class=\"token operator\">=</span>urllib<span class=\"token punctuation\">.</span>parse<span class=\"token punctuation\">.</span>urlencode<span class=\"token punctuation\">(</span>form_data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                    headers<span class=\"token operator\">=</span>headers\n                <span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span>\n            <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n                alltime <span class=\"token operator\">=</span> re<span class=\"token punctuation\">.</span>findall<span class=\"token punctuation\">(</span><span class=\"token string\">\"alltime:'(.*?)'\"</span><span class=\"token punctuation\">,</span> result_data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span>\n                conntime <span class=\"token operator\">=</span> re<span class=\"token punctuation\">.</span>findall<span class=\"token punctuation\">(</span><span class=\"token string\">\"conntime:'(.*?)'\"</span><span class=\"token punctuation\">,</span> result_data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span>\n                downtime <span class=\"token operator\">=</span> re<span class=\"token punctuation\">.</span>findall<span class=\"token punctuation\">(</span><span class=\"token string\">\"downtime:'(.*?)'\"</span><span class=\"token punctuation\">,</span> result_data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span>\n                final_string <span class=\"token operator\">=</span> <span class=\"token string\">\"%s\\t 总耗时:%s\\t 链接耗时:%s\\t 下载耗时:%s\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>node_name<span class=\"token punctuation\">,</span> alltime<span class=\"token punctuation\">,</span> conntime<span class=\"token punctuation\">,</span> downtime<span class=\"token punctuation\">)</span>\n            <span class=\"token keyword\">except</span><span class=\"token punctuation\">:</span>\n                final_string <span class=\"token operator\">=</span> <span class=\"token string\">\"%s 链接异常！\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>node_name<span class=\"token punctuation\">)</span>\n                final_status <span class=\"token operator\">=</span> <span class=\"token boolean\">False</span>\n        <span class=\"token keyword\">except</span><span class=\"token punctuation\">:</span>\n            final_string <span class=\"token operator\">=</span> <span class=\"token string\">\"%s 链接超时！\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>node_name<span class=\"token punctuation\">)</span>\n            final_status <span class=\"token operator\">=</span> <span class=\"token boolean\">False</span>\n        final_list<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span>final_string<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>final_string<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>final_status<span class=\"token punctuation\">,</span>final_list<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">def</span> <span class=\"token function\">sendEmail</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">,</span> to_user<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    sender <span class=\"token operator\">=</span> <span class=\"token string\">'service@anycodes.cn'</span>\n    receivers <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>to_user<span class=\"token punctuation\">]</span>\n    mail_msg <span class=\"token operator\">=</span> content\n    message <span class=\"token operator\">=</span> MIMEText<span class=\"token punctuation\">(</span>mail_msg<span class=\"token punctuation\">,</span> <span class=\"token string\">'html'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    message<span class=\"token punctuation\">[</span><span class=\"token string\">'From'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Header<span class=\"token punctuation\">(</span><span class=\"token string\">\" 网站监控 \"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    message<span class=\"token punctuation\">[</span><span class=\"token string\">'To'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Header<span class=\"token punctuation\">(</span><span class=\"token string\">\" 站长 \"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    subject <span class=\"token operator\">=</span> <span class=\"token string\">\" 网站监控告警 \"</span>\n    message<span class=\"token punctuation\">[</span><span class=\"token string\">'Subject'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Header<span class=\"token punctuation\">(</span>subject<span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        smtpObj <span class=\"token operator\">=</span> smtplib<span class=\"token punctuation\">.</span>SMTP_SSL<span class=\"token punctuation\">(</span><span class=\"token string\">\"smtp.exmail.qq.com\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">465</span><span class=\"token punctuation\">)</span>\n        smtpObj<span class=\"token punctuation\">.</span>login<span class=\"token punctuation\">(</span><span class=\"token string\">'service@anycodes.cn'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'密码'</span><span class=\"token punctuation\">)</span>\n        smtpObj<span class=\"token punctuation\">.</span>sendmail<span class=\"token punctuation\">(</span>sender<span class=\"token punctuation\">,</span> receivers<span class=\"token punctuation\">,</span> message<span class=\"token punctuation\">.</span>as_string<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">except</span> smtplib<span class=\"token punctuation\">.</span>SMTPException<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">pass</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">getStatusCode</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">return</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>getcode<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">main_handler</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"http://www.anycodes.cn\"</span>\n    final_status<span class=\"token punctuation\">,</span>final_list <span class=\"token operator\">=</span> getWebTime<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token keyword\">not</span> final_status<span class=\"token punctuation\">:</span>\n        sendEmail<span class=\"token punctuation\">(</span><span class=\"token string\">\" 您的网站 %s 的状态：&lt;br>%s\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">,</span> <span class=\"token string\">\"&lt;br>\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span>final_list<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"service@52exe.cn\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>由于本文是以学习为主，所以我们将节点列表进行缩减，只保留几个。通过部署，可得到结果：</p>\n<p><img src=\"https://img.serverlesscloud.cn/tmp/eae0f89c3cb3c61b87841d62424e1322-20200414224848415.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<p>告警的灵敏度和监控的频率，在实际生产过程中可以根据自己的需求进行调整。</p>\n<h2 id=\"云服务监控告警\"><a href=\"#%E4%BA%91%E6%9C%8D%E5%8A%A1%E7%9B%91%E6%8E%A7%E5%91%8A%E8%AD%A6\" aria-label=\"云服务监控告警 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>云服务监控告警</h2>\n<p>前文，我们对网站状态以及健康等信息进行了监控与告警，在实际的生产运维中，还需要对服务进行监控，例如在使用 Hadoop、Spark 的时候对节点的健康进行监控，在使用 K8S 的时候对 API 网关、ETCD 等多维度的指标进行监控，在使用 Kafka 的时候，对数据积压量，以及 Topic、Consumer 等进行监控…</p>\n<p>而这些服务的监控，往往不能通过简单的 URL 以及某些状态来进行判断。传统运维的做法是在额外的机器上设置一个定时任务，对相关的服务进行旁路监控。而在本文中，我们则通过 Serverless 技术，对云产品进行相关的监控与告警。</p>\n<p>在使用云上的 Kafka 时，我们通常要看数据积压量，因为如果 Consumer 集群挂掉了，或者消费能力突然降低导致数据积压，很可能会对服务产生不可预估的影响，这个时候对 Kafka 的数据积压量进行监控告警，就显得额外重要。</p>\n<p>本文以监控腾讯云的 Ckafka 为例进行实践，并通过多个云产品进行组合（包括云监控、Ckafka、云 API 以及云短信等）来实现短信告警、邮件告警以及企业微信告警功能。</p>\n<p>首先，可以设计简单的流程图：</p>\n<p><img src=\"https://img.serverlesscloud.cn/tmp/a62c48d5aae15c7ab86cafe972024b25-20200414224854871.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<p>在开始项目之前，我们要准备一些基础的模块：</p>\n<ul>\n<li>Kafka 数据积压量获取模块：</li>\n</ul>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"73928739371721200000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def GetSignature(param):\n    # 公共参数\n    param[&quot;SecretId&quot;] = &quot;&quot;\n    param[&quot;Timestamp&quot;] = int(time.time())\n    param[&quot;Nonce&quot;] = random.randint(1, sys.maxsize)\n    param[&quot;Region&quot;] = &quot;ap-guangzhou&quot;\n    # param[&quot;SignatureMethod&quot;] = &quot;HmacSHA256&quot;\n    # 生成待签名字符串\n    sign_str = &quot;GETckafka.api.qcloud.com/v2/index.php?&quot;\n    sign_str += &quot;&&quot;.join(&quot;%s=%s&quot; % (k, param[k]) for k in sorted(param))\n    # 生成签名\n    secret_key = &quot;&quot;\n    if sys.version_info[0] > 2:\n        sign_str = bytes(sign_str, &quot;utf-8&quot;)\n        secret_key = bytes(secret_key, &quot;utf-8&quot;)\n    hashed = hmac.new(secret_key, sign_str, hashlib.sha1)\n    signature = binascii.b2a_base64(hashed.digest())[:-1]\n    if sys.version_info[0] > 2:\n        signature = signature.decode()\n    # 签名串编码\n    signature = urllib.parse.quote(signature)\n    return signature\n\ndef GetGroupOffsets(max_lag, phoneList):\n    param = {}\n    param[&quot;Action&quot;] = &quot;GetGroupOffsets&quot;\n    param[&quot;instanceId&quot;] = &quot;&quot;\n    param[&quot;group&quot;] = &quot;&quot;\n    signature = GetSignature(param)\n    # 生成请求地址\n    param[&quot;Signature&quot;] = signature\n    url = &quot;https://ckafka.api.qcloud.com/v2/index.php?Action=GetGroupOffsets&&quot;\n    url += &quot;&&quot;.join(&quot;%s=%s&quot; % (k, param[k]) for k in sorted(param))\n    req_attr = urllib.request.urlopen(url)\n    res_data = req_attr.read().decode(&quot;utf-8&quot;)\n    json_data = json.loads(res_data)\n    for eve_topic in json_data['data']['topicList']:\n        temp_lag = 0\n        result_list = []\n        for eve_partition in eve_topic[&quot;partitions&quot;]:\n            lag = eve_partition[&quot;lag&quot;]\n            temp_lag = temp_lag + lag\n        if temp_lag > max_lag:\n            result_list.append(\n                {\n                    &quot;topic&quot;: eve_topic[&quot;topic&quot;],\n                    &quot;lag&quot;: lag\n                }\n            )\n        print(result_list)\n        if len(result_list)>0:\n            KafkaLagRobot(result_list)\n            KafkaLagSMS(result_list,phoneList)`, `73928739371721200000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">GetSignature</span><span class=\"token punctuation\">(</span>param<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token comment\"># 公共参数</span>\n    param<span class=\"token punctuation\">[</span><span class=\"token string\">\"SecretId\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span>\n    param<span class=\"token punctuation\">[</span><span class=\"token string\">\"Timestamp\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    param<span class=\"token punctuation\">[</span><span class=\"token string\">\"Nonce\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> random<span class=\"token punctuation\">.</span>randint<span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> sys<span class=\"token punctuation\">.</span>maxsize<span class=\"token punctuation\">)</span>\n    param<span class=\"token punctuation\">[</span><span class=\"token string\">\"Region\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"ap-guangzhou\"</span>\n    <span class=\"token comment\"># param[\"SignatureMethod\"] = \"HmacSHA256\"</span>\n    <span class=\"token comment\"># 生成待签名字符串</span>\n    sign_str <span class=\"token operator\">=</span> <span class=\"token string\">\"GETckafka.api.qcloud.com/v2/index.php?\"</span>\n    sign_str <span class=\"token operator\">+=</span> <span class=\"token string\">\"&amp;\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span><span class=\"token string\">\"%s=%s\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>k<span class=\"token punctuation\">,</span> param<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">for</span> k <span class=\"token keyword\">in</span> <span class=\"token builtin\">sorted</span><span class=\"token punctuation\">(</span>param<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token comment\"># 生成签名</span>\n    secret_key <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span>\n    <span class=\"token keyword\">if</span> sys<span class=\"token punctuation\">.</span>version_info<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">></span> <span class=\"token number\">2</span><span class=\"token punctuation\">:</span>\n        sign_str <span class=\"token operator\">=</span> <span class=\"token builtin\">bytes</span><span class=\"token punctuation\">(</span>sign_str<span class=\"token punctuation\">,</span> <span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span>\n        secret_key <span class=\"token operator\">=</span> <span class=\"token builtin\">bytes</span><span class=\"token punctuation\">(</span>secret_key<span class=\"token punctuation\">,</span> <span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span>\n    hashed <span class=\"token operator\">=</span> hmac<span class=\"token punctuation\">.</span>new<span class=\"token punctuation\">(</span>secret_key<span class=\"token punctuation\">,</span> sign_str<span class=\"token punctuation\">,</span> hashlib<span class=\"token punctuation\">.</span>sha1<span class=\"token punctuation\">)</span>\n    signature <span class=\"token operator\">=</span> binascii<span class=\"token punctuation\">.</span>b2a_base64<span class=\"token punctuation\">(</span>hashed<span class=\"token punctuation\">.</span>digest<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">:</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">if</span> sys<span class=\"token punctuation\">.</span>version_info<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">></span> <span class=\"token number\">2</span><span class=\"token punctuation\">:</span>\n        signature <span class=\"token operator\">=</span> signature<span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token comment\"># 签名串编码</span>\n    signature <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>parse<span class=\"token punctuation\">.</span>quote<span class=\"token punctuation\">(</span>signature<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> signature\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">GetGroupOffsets</span><span class=\"token punctuation\">(</span>max_lag<span class=\"token punctuation\">,</span> phoneList<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    param <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n    param<span class=\"token punctuation\">[</span><span class=\"token string\">\"Action\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"GetGroupOffsets\"</span>\n    param<span class=\"token punctuation\">[</span><span class=\"token string\">\"instanceId\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span>\n    param<span class=\"token punctuation\">[</span><span class=\"token string\">\"group\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span>\n    signature <span class=\"token operator\">=</span> GetSignature<span class=\"token punctuation\">(</span>param<span class=\"token punctuation\">)</span>\n    <span class=\"token comment\"># 生成请求地址</span>\n    param<span class=\"token punctuation\">[</span><span class=\"token string\">\"Signature\"</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> signature\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"https://ckafka.api.qcloud.com/v2/index.php?Action=GetGroupOffsets&amp;\"</span>\n    url <span class=\"token operator\">+=</span> <span class=\"token string\">\"&amp;\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span><span class=\"token string\">\"%s=%s\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>k<span class=\"token punctuation\">,</span> param<span class=\"token punctuation\">[</span>k<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">for</span> k <span class=\"token keyword\">in</span> <span class=\"token builtin\">sorted</span><span class=\"token punctuation\">(</span>param<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    req_attr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span>\n    res_data <span class=\"token operator\">=</span> req_attr<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span>\n    json_data <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>loads<span class=\"token punctuation\">(</span>res_data<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">for</span> eve_topic <span class=\"token keyword\">in</span> json_data<span class=\"token punctuation\">[</span><span class=\"token string\">'data'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token string\">'topicList'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span>\n        temp_lag <span class=\"token operator\">=</span> <span class=\"token number\">0</span>\n        result_list <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n        <span class=\"token keyword\">for</span> eve_partition <span class=\"token keyword\">in</span> eve_topic<span class=\"token punctuation\">[</span><span class=\"token string\">\"partitions\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span>\n            lag <span class=\"token operator\">=</span> eve_partition<span class=\"token punctuation\">[</span><span class=\"token string\">\"lag\"</span><span class=\"token punctuation\">]</span>\n            temp_lag <span class=\"token operator\">=</span> temp_lag <span class=\"token operator\">+</span> lag\n        <span class=\"token keyword\">if</span> temp_lag <span class=\"token operator\">></span> max_lag<span class=\"token punctuation\">:</span>\n            result_list<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span>\n                <span class=\"token punctuation\">{</span>\n                    <span class=\"token string\">\"topic\"</span><span class=\"token punctuation\">:</span> eve_topic<span class=\"token punctuation\">[</span><span class=\"token string\">\"topic\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n                    <span class=\"token string\">\"lag\"</span><span class=\"token punctuation\">:</span> lag\n                <span class=\"token punctuation\">}</span>\n            <span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>result_list<span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">if</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>result_list<span class=\"token punctuation\">)</span><span class=\"token operator\">></span><span class=\"token number\">0</span><span class=\"token punctuation\">:</span>\n            KafkaLagRobot<span class=\"token punctuation\">(</span>result_list<span class=\"token punctuation\">)</span>\n            KafkaLagSMS<span class=\"token punctuation\">(</span>result_list<span class=\"token punctuation\">,</span>phoneList<span class=\"token punctuation\">)</span></code></pre></div>\n<ul>\n<li>接入企业微信机器人模块：</li>\n</ul>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"76584499436882480000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def KafkaLagRobot(content):\n    url = &quot;&quot;\n    data = {\n        &quot;msgtype&quot;: &quot;markdown&quot;,\n        &quot;markdown&quot;: {\n            &quot;content&quot;: content,\n        }\n    }\n    data = json.dumps(data).encode(&quot;utf-8&quot;)\n    req_attr = urllib.request.Request(url, data)\n    resp_attr = urllib.request.urlopen(req_attr)\n    return_msg = resp_attr.read().decode(&quot;utf-8&quot;)`, `76584499436882480000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">KafkaLagRobot</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span>\n    data <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string\">\"msgtype\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"markdown\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"markdown\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token string\">\"content\"</span><span class=\"token punctuation\">:</span> content<span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n    data <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span>\n    req_attr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">,</span> data<span class=\"token punctuation\">)</span>\n    resp_attr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>req_attr<span class=\"token punctuation\">)</span>\n    return_msg <span class=\"token operator\">=</span> resp_attr<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<ul>\n<li>接入腾讯云短信服务模块：</li>\n</ul>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"17260763405631097000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def KafkaLagSMS(infor, phone_list):\n    url = &quot;&quot;\n    strMobile = phone_list\n    strAppKey = &quot;&quot;\n    strRand = str(random.randint(1, sys.maxsize))\n    strTime = int(time.time())\n    strSign = &quot;appkey=%s&random=%s&time=%s&mobile=%s&quot; % (strAppKey, strRand, strTime, &quot;,&quot;.join(strMobile))\n    sig = hashlib.sha256()\n    sig.update(strSign.encode(&quot;utf-8&quot;))\n\n    phone_dict = []\n    for eve_phone in phone_list:\n        phone_dict.append(\n            {\n                &quot;mobile&quot;: eve_phone,\n                &quot;nationcode&quot;: &quot;86&quot;\n            }\n        )\n    data = {\n        &quot;ext&quot;: &quot;&quot;,\n        &quot;extend&quot;: &quot;&quot;,\n        &quot;params&quot;: [\n            infor,\n        ],\n        &quot;sig&quot;: sig.hexdigest(),\n        &quot;sign&quot;: &quot; 你的 sign&quot;,\n        &quot;tel&quot;: phone_dict,\n        &quot;time&quot;: strTime,\n        &quot;tpl_id&quot;: 你的模板 id\n    }\n    data = json.dumps(data).encode(&quot;utf-8&quot;)\n    req_attr = urllib.request.Request(url=url, data=data)\n    resp_attr = urllib.request.urlopen(req_attr)\n    return_msg = resp_attr.read().decode(&quot;utf-8&quot;)`, `17260763405631097000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">KafkaLagSMS</span><span class=\"token punctuation\">(</span>infor<span class=\"token punctuation\">,</span> phone_list<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    url <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span>\n    strMobile <span class=\"token operator\">=</span> phone_list\n    strAppKey <span class=\"token operator\">=</span> <span class=\"token string\">\"\"</span>\n    strRand <span class=\"token operator\">=</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">(</span>random<span class=\"token punctuation\">.</span>randint<span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> sys<span class=\"token punctuation\">.</span>maxsize<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    strTime <span class=\"token operator\">=</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">(</span>time<span class=\"token punctuation\">.</span>time<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    strSign <span class=\"token operator\">=</span> <span class=\"token string\">\"appkey=%s&amp;random=%s&amp;time=%s&amp;mobile=%s\"</span> <span class=\"token operator\">%</span> <span class=\"token punctuation\">(</span>strAppKey<span class=\"token punctuation\">,</span> strRand<span class=\"token punctuation\">,</span> strTime<span class=\"token punctuation\">,</span> <span class=\"token string\">\",\"</span><span class=\"token punctuation\">.</span>join<span class=\"token punctuation\">(</span>strMobile<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    sig <span class=\"token operator\">=</span> hashlib<span class=\"token punctuation\">.</span>sha256<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    sig<span class=\"token punctuation\">.</span>update<span class=\"token punctuation\">(</span>strSign<span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\n    phone_dict <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">for</span> eve_phone <span class=\"token keyword\">in</span> phone_list<span class=\"token punctuation\">:</span>\n        phone_dict<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span>\n            <span class=\"token punctuation\">{</span>\n                <span class=\"token string\">\"mobile\"</span><span class=\"token punctuation\">:</span> eve_phone<span class=\"token punctuation\">,</span>\n                <span class=\"token string\">\"nationcode\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"86\"</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">)</span>\n    data <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string\">\"ext\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"extend\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"params\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>\n            infor<span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"sig\"</span><span class=\"token punctuation\">:</span> sig<span class=\"token punctuation\">.</span>hexdigest<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"sign\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\" 你的 sign\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"tel\"</span><span class=\"token punctuation\">:</span> phone_dict<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"time\"</span><span class=\"token punctuation\">:</span> strTime<span class=\"token punctuation\">,</span>\n        <span class=\"token string\">\"tpl_id\"</span><span class=\"token punctuation\">:</span> 你的模板 <span class=\"token builtin\">id</span>\n    <span class=\"token punctuation\">}</span>\n    data <span class=\"token operator\">=</span> json<span class=\"token punctuation\">.</span>dumps<span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>encode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span>\n    req_attr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>Request<span class=\"token punctuation\">(</span>url<span class=\"token operator\">=</span>url<span class=\"token punctuation\">,</span> data<span class=\"token operator\">=</span>data<span class=\"token punctuation\">)</span>\n    resp_attr <span class=\"token operator\">=</span> urllib<span class=\"token punctuation\">.</span>request<span class=\"token punctuation\">.</span>urlopen<span class=\"token punctuation\">(</span>req_attr<span class=\"token punctuation\">)</span>\n    return_msg <span class=\"token operator\">=</span> resp_attr<span class=\"token punctuation\">.</span>read<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>decode<span class=\"token punctuation\">(</span><span class=\"token string\">\"utf-8\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<ul>\n<li>发送邮件告警模块：</li>\n</ul>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"23825797980235497000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`def sendEmail(content, to_user):\n    sender = 'service@anycodes.cn'\n    message = MIMEText(content, 'html', 'utf-8')\n    message['From'] = Header(&quot; 监控 &quot;, 'utf-8')\n    message['To'] = Header(&quot; 站长 &quot;, 'utf-8')\n    message['Subject'] = Header(&quot; 告警 &quot;, 'utf-8')\n    try:\n        smtpObj = smtplib.SMTP_SSL(&quot;smtp.exmail.qq.com&quot;, 465)\n        smtpObj.login('service@anycodes.cn', '密码')\n        smtpObj.sendmail(sender, [to_user], message.as_string())\n    except smtplib.SMTPException as e:\n        logging.debug(e)`, `23825797980235497000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">sendEmail</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">,</span> to_user<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    sender <span class=\"token operator\">=</span> <span class=\"token string\">'service@anycodes.cn'</span>\n    message <span class=\"token operator\">=</span> MIMEText<span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">,</span> <span class=\"token string\">'html'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    message<span class=\"token punctuation\">[</span><span class=\"token string\">'From'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Header<span class=\"token punctuation\">(</span><span class=\"token string\">\" 监控 \"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    message<span class=\"token punctuation\">[</span><span class=\"token string\">'To'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Header<span class=\"token punctuation\">(</span><span class=\"token string\">\" 站长 \"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    message<span class=\"token punctuation\">[</span><span class=\"token string\">'Subject'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> Header<span class=\"token punctuation\">(</span><span class=\"token string\">\" 告警 \"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">try</span><span class=\"token punctuation\">:</span>\n        smtpObj <span class=\"token operator\">=</span> smtplib<span class=\"token punctuation\">.</span>SMTP_SSL<span class=\"token punctuation\">(</span><span class=\"token string\">\"smtp.exmail.qq.com\"</span><span class=\"token punctuation\">,</span> <span class=\"token number\">465</span><span class=\"token punctuation\">)</span>\n        smtpObj<span class=\"token punctuation\">.</span>login<span class=\"token punctuation\">(</span><span class=\"token string\">'service@anycodes.cn'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'密码'</span><span class=\"token punctuation\">)</span>\n        smtpObj<span class=\"token punctuation\">.</span>sendmail<span class=\"token punctuation\">(</span>sender<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>to_user<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> message<span class=\"token punctuation\">.</span>as_string<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">except</span> smtplib<span class=\"token punctuation\">.</span>SMTPException <span class=\"token keyword\">as</span> e<span class=\"token punctuation\">:</span>\n        logging<span class=\"token punctuation\">.</span>debug<span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span></code></pre></div>\n<p>完成模块编写，和上面的方法一样，进行项目部署。部署成功之后进行测试，测试可看到功能可用：</p>\n<ul>\n<li>短信告警样式：</li>\n</ul>\n<p><img src=\"https://img.serverlesscloud.cn/tmp/1dc5a98c27e4144a40ad6fdd0c4c32ea-20200414224913619.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<ul>\n<li>企业微信告警样式：</li>\n</ul>\n<p><img src=\"https://img.serverlesscloud.cn/tmp/24e1181cc5015f96cf9f6cce437fccf6-20200414224916951.png\" alt=\"Serverless 实战：通过 Serverless 架构实现监控告警\"></p>\n<h2 id=\"总结\"><a href=\"#%E6%80%BB%E7%BB%93\" aria-label=\"总结 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>总结</h2>\n<p>通过本文的实践，希望读者可以了解到 Serverless 相关产品在运维行业中的基本应用，尤其是监控告警的基本使用方法和初步灵感。设计一个网站监控程序实际上是一个很初级的入门场景，希望大家可以将更多的监控告警功与 Serverless 技术进行结合，例如监控自己的 MySQL 压力情况、监控已有服务器的数据指标等，通过对这些指标的监控告警，不仅仅可以让管理者及时发现服务的潜在风险，也可以通过一些自动化流程实现项目的自动化运维。</p>\n<p>通过本场景实践，我们也可以对项目进行额外的优化或者应用在不同的领域以及场景中。例如，我们可以通过增加短信告警、微信告警、企业微信告警等多个维度，来确保相关人员可以及时收到告警信息；我们也可以通过监控某个小说网站、视频网站等，看到我们关注的小说或者视频的更新情况，便于追更等。</p>\n<hr>\n<div id='scf-deploy-iframe-or-md'></div>\n<hr>\n<blockquote>\n<p><strong>传送门：</strong></p>\n<ul>\n<li>GitHub: <a href=\"https://github.com/serverless/serverless/blob/master/README_CN.md\">github.com/serverless</a></li>\n<li>官网：<a href=\"https://serverless.com/\">serverless.com</a></li>\n</ul>\n</blockquote>\n<p>欢迎访问：<a href=\"https://serverlesscloud.cn/\">Serverless 中文网</a>，您可以在 <a href=\"https://serverlesscloud.cn/best-practice\">最佳实践</a> 里体验更多关于 Serverless 应用的开发！</p>","tableOfContents":"<ul>\n<li>\n<p><a href=\"/blog/2020-04-10-website-alarm/#web-%E6%9C%8D%E5%8A%A1%E7%9B%91%E6%8E%A7%E5%91%8A%E8%AD%A6\">Web 服务监控告警</a></p>\n<ul>\n<li>\n<ul>\n<li><a href=\"/blog/2020-04-10-website-alarm/#cron-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E6%B3%95%E4%B8%80%EF%BC%88%E6%8E%A8%E8%8D%90%EF%BC%89\">Cron 表达式语法一（推荐）</a></li>\n<li><a href=\"/blog/2020-04-10-website-alarm/#cron-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E6%B3%95%E4%BA%8C%EF%BC%88%E4%B8%8D%E6%8E%A8%E8%8D%90%EF%BC%89\">Cron 表达式语法二（不推荐）</a></li>\n<li><a href=\"/blog/2020-04-10-website-alarm/#%E9%80%9A%E9%85%8D%E7%AC%A6\">通配符</a></li>\n<li><a href=\"/blog/2020-04-10-website-alarm/#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9\">注意事项</a></li>\n<li><a href=\"/blog/2020-04-10-website-alarm/#%E7%A4%BA%E4%BE%8B\">示例</a></li>\n</ul>\n</li>\n</ul>\n</li>\n<li><a href=\"/blog/2020-04-10-website-alarm/#%E4%BA%91%E6%9C%8D%E5%8A%A1%E7%9B%91%E6%8E%A7%E5%91%8A%E8%AD%A6\">云服务监控告警</a></li>\n<li><a href=\"/blog/2020-04-10-website-alarm/#%E6%80%BB%E7%BB%93\">总结</a></li>\n</ul>"},"previousBlog":{"id":"162777c7-987a-5278-92ac-9887c8dc30a7","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/202049/1586443473383-1586438917%281%29_%E5%89%AF%E6%9C%AC.jpg","authors":["serverless 社区"],"categories":["meetup"],"date":"2020-04-11T00:00:00.000Z","title":"前端基于 Serverless 的开发探索 | 直播课","description":"本次直播将深入讲解 Serverless 给前端带来的变革、前端 Serverless 的发展方向，以及开发者如何基于 Serverless 获得成长，创造收益！","authorslink":["https://serverlesscloud.cn"],"translators":null,"translatorslink":null,"tags":["Serverless","Meetup"],"keywords":"Serverless;Front-end;","outdated":null},"wordCount":{"words":78,"sentences":16,"paragraphs":16},"fileAbsolutePath":"/opt/build/repo/content/blog/2020-04-11-serverless-front-end-development.md","fields":{"slug":"/blog/2020-04-11-serverless-front-end-development/","keywords":["serverless","云函数","Serverless","serverless","腾讯","serverlesscloud"]}},"nextBlog":{"id":"66fbf753-e21e-50af-9fb0-8d6ff3611176","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020522/1590170625843-%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_15901706165494.png","authors":["galenye"],"categories":["user-stories"],"date":"2020-04-09T00:00:00.000Z","title":"利用 Serverless，实现 COS & CDN Combo Handler","description":"小 S 维护的一个前端系统，单个页面中有数个没有依赖关系的 js, css 需要加载，此时浏览器会分别去请求对应的文件。此时小 S 收到 Leader 给的一个任务：优化前端的静态资源请求，尽量做合并。","authorslink":["https://cloud.tencent.com/developer/article/1610316"],"translators":null,"translatorslink":null,"tags":["Serverless","对象存储"],"keywords":"Serverless,COS,CDN","outdated":true},"wordCount":{"words":367,"sentences":52,"paragraphs":49},"fileAbsolutePath":"/opt/build/repo/content/blog/2020-04-09-serverless-combo-handler.md","fields":{"slug":"/blog/2020-04-09-serverless-combo-handler/","keywords":["java","serverless","combo","cdn","Serverless"]}},"recommendBlogs":{"edges":[{"node":{"id":"665f9ce2-4451-59fd-bf98-1861789d3b3b","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/Serverless_logo.png","authors":["AndreaPasswater"],"categories":["guides-and-tutorials","engineering-culture"],"date":"2018-03-19T00:00:00.000Z","title":"如何为无服务器开放源代码项目做贡献","description":"想要为无服务器开放源代码项目做贡献？您可以遵循下面的指南。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":96,"sentences":36,"paragraphs":36},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-03-19-how-contribute-to-serverless-open-source.md","fields":{"slug":"/blog/2018-03-19-how-contribute-to-serverless-open-source/","keywords":["serverless","无服务器","serverless","github","插件","服务器","贡献","示例","blog","contribute"]}}},{"node":{"id":"a3e92579-65c3-5159-937c-32d18c5df7d7","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/why-not/why-not-header.png","authors":["AndreaPasswater"],"categories":["guides-and-tutorials","operations-and-observability","engineering-culture"],"date":"2018-03-21T00:00:00.000Z","title":"不适合选择无服务器的情境及原因","description":"无服务器既有优点也有缺点。那么，哪些情境下不适合选择无服务器？原因又是什么呢？","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":163,"sentences":43,"paragraphs":43},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-03-21-when-why-not-use-serverless.md","fields":{"slug":"/blog/2018-03-21-when-why-not-use-serverless/","keywords":["faas","react","serverless","spa","无服务器","无服务器函数","无服务器架构","无服务器开发","服务器","twitter","serverless","blockquote","lang","script","en"]}}},{"node":{"id":"6a16520b-7886-582e-9182-64e50712d486","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/vendor+choice/serverless-data-portability.jpg","authors":["NickGottlieb"],"categories":["engineering-culture","guides-and-tutorials"],"date":"2018-06-20T00:00:00.000Z","title":"浅谈无服务器、数据锁定和供应商选择","description":"供应商选择是如今 IT 领导者需要考虑的最重要事项，而这一点可利用数据可移植性来实现。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":205,"sentences":33,"paragraphs":33},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-06-20-data-lockin-vendor-choice-portability.md","fields":{"slug":"/blog/2018-06-20-data-lockin-vendor-choice-portability/","keywords":["go","serverless","无服务器","无服务器架构","供应商","serverless","开发人员","数据","锁定","选择","服务"]}}},{"node":{"id":"94741abb-10ba-5db1-9756-cd1d573473fa","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/webstorm-ide/streamline-webstorm-serverless2.jpg","authors":["EslamHefnawy"],"categories":["guides-and-tutorials","engineering-culture"],"date":"2018-08-15T00:00:00.000Z","title":"如何使用 WebStorm 简化无服务器工作流程","description":"在本文中，我将和您分享如何使用 WebStorm 进行无服务器特定的 IDE 设置以及如何利用它来极大地加快无服务器工作流程。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":234,"sentences":54,"paragraphs":54},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-08-15-streamline-serverless-workflow-webstorm.md","fields":{"slug":"/blog/2018-08-15-streamline-serverless-workflow-webstorm/","keywords":["nodejs","serverless","无服务器","无服务器开发","serverless","WebStorm","webstorm","服务器","blog","assets"]}}},{"node":{"id":"713a0563-4bf9-5721-bacb-3b4ef609fe4a","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/camp-fire/camp-fire-housing-thumb.jpg","authors":["EricWyne"],"categories":["guides-and-tutorials","user-stories"],"date":"2018-12-05T00:00:00.000Z","title":"Serverless Twitter 机器人帮助为坎普山火受灾者安置住房","description":"加利福尼亚州的坎普山火致使数千人流离失所，为此，我构建了一个简单的 Serverless Twitter 机器人来帮助将受灾者安置在临时住房！","authorslink":["https://serverless.com/author/ericwyne/"],"translators":["Aceyclee"],"translatorslink":["zhihu.com/people/Aceyclee"],"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":157,"sentences":26,"paragraphs":26},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-12-05-serverless-twitter-camp-fire.md","fields":{"slug":"/blog/2018-12-05-serverless-twitter-camp-fire/","keywords":["serverless","无服务器","云函数","Serverless","org","住房","Twitter","函数","受灾","机器人","山火"]}}},{"node":{"id":"17c972d9-0583-51f6-9d5d-c2ba5f21b6a3","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/20191227/1577409288454-v2-577c2b21d600e3ea07f156f3e9d2d6b8_1200x500.jpg","authors":["Alfred Huang"],"categories":["guides-and-tutorials"],"date":"2019-08-21T00:00:00.000Z","title":"Serverless 的运行原理与组件架构","description":"本文重点探讨下开发者使用 Serverless 时经常遇到的一些问题，以及如何解决","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["运行原理","serverless"],"keywords":"Serverless 运行原理,Serverless 组件架构","outdated":null},"wordCount":{"words":236,"sentences":33,"paragraphs":33},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-08-21-serverless-operation-architecture.md","fields":{"slug":"/blog/2019-08-21-serverless-operation-architecture/","keywords":["koa","serverless","云函数","Serverless","用户","函数","请求","实例","形态","业务","serverlesscloud"]}}},{"node":{"id":"ae4fd2f8-515c-5aec-b584-38427ef33f7e","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020114/1578989800047-part-00492-780.jpg","authors":["Anycodes"],"categories":["guides-and-tutorials","user-stories"],"date":"2019-09-16T00:00:00.000Z","title":"突破传统 OJ 瓶颈，「判题姬」接入云函数","description":"通过 Serverless 实现在线编程","authorslink":["https://www.zhihu.com/people/liuyu-43-97"],"translators":null,"translatorslink":null,"tags":["在线编程","云函数"],"keywords":"Serverless 在线编程,Serverless OJ","outdated":null},"wordCount":{"words":169,"sentences":30,"paragraphs":30},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-09-16-online-Judge.md","fields":{"slug":"/blog/2019-09-16-online-Judge/","keywords":["python","serverless","云函数","代码","函数","serverless"]}}},{"node":{"id":"545ab3d2-e14e-5cc2-8548-0e863eac942b","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/2019-10-deployment-best-practices/safeguard-header.png","authors":["FernandoMedinaCorey"],"categories":["guides-and-tutorials"],"date":"2019-10-14T00:00:00.000Z","title":"无服务器部署最佳实践","description":"了解部署无服务器应用时的一些最佳实践。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":221,"sentences":46,"paragraphs":46},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-10-14-serverless-deployment-best-practices.md","fields":{"slug":"/blog/2019-10-14-serverless-deployment-best-practices/","keywords":["serverless","无服务器","serverless","部署","服务器","开发人员","应用","安全措施","使用","函数"]}}}],"totalCount":31}},"pageContext":{"isCreatedByStatefulCreatePages":false,"blogId":"44ad21a9-00a3-592c-83c1-696af478c55f","previousBlogId":"162777c7-987a-5278-92ac-9887c8dc30a7","nextBlogId":"66fbf753-e21e-50af-9fb0-8d6ff3611176","categories":["guides-and-tutorials","operations-and-observability"]}}}