{"@attributes":{"version":"2.0"},"channel":{"title":"Shining Moon","link":"https:\/\/blog.monsterxx03.com\/","description":"Recent content on Shining Moon","generator":"Hugo","language":"zh-cn","copyright":"monsterxx03","lastBuildDate":"Sat, 23 May 2026 17:34:10 +0800","item":[{"title":"Tachi: \u4ece 0 \u5f00\u59cb\u505a agent","link":"https:\/\/blog.monsterxx03.com\/2026\/05\/23\/tachi-%E4%BB%8E-0-%E5%BC%80%E5%A7%8B%E5%81%9A-agent\/","pubDate":"Sat, 23 May 2026 17:34:10 +0800","guid":"https:\/\/blog.monsterxx03.com\/2026\/05\/23\/tachi-%E4%BB%8E-0-%E5%BC%80%E5%A7%8B%E5%81%9A-agent\/","description":"<p>\u5e02\u9762\u4e0a\u5404\u79cd agent \u7528\u8fc7\u4e0d\u5c11\uff0ccursor\u3001claudecode\u3001codex\u3001opencode\u3001trae\u3001openclaw\u3001pi\u2026\u2026\u5176\u5b9e\u4e5f\u6ca1\u611f\u89c9\u54ea\u4e2a\u5bf9\u5176\u4ed6\u6709\u964d\u7ef4\u6253\u51fb\uff0c\u53cd\u800c\u5404\u6709\u5404\u7684\u4e0d\u723d\uff1a\n\u8981\u4e48\u6709\u6a21\u578b\u9650\u5236\uff0c\u6362\u522b\u7684\u517c\u5bb9\u63a5\u53e3\u8981\u5404\u79cd\u8f6c\u63a5\uff0c\u8fd0\u884c\u8fc7\u7a0b\u4e0d\u900f\u660e\u2014\u2014\u4e4b\u524d\u505a\u4e86 <a href=\"https:\/\/github.com\/monsterxx03\/linko\">linko<\/a>\uff0c\u521d\u8877\u4e5f\u662f\u4e3a\u4e86\u641e\u6e05\u695a\u5404\u79cd agent \u90fd\u5728\u5e72\u561b\u3002\n\u8981\u4e48\u5929\u5929\u5347\u7ea7\u5f04\u51fa\u5404\u79cd\u5947\u602a bug\uff0c\u8981\u4e48\u8fc7\u5ea6\u81c3\u80bf\uff0c\u8981\u914d\u5404\u79cd\u770b\u7740\u6709\u7528\u5b9e\u9645\u7528\u8d77\u6765\u53c8\u6ca1\u4ec0\u4e48\u5375\u7528\u7684\u63d2\u4ef6\u3002<\/p>\n<p>\u6240\u4ee5\uff0c\u5728 2026 \u5e74\u8fd9\u4e2a\u65f6\u95f4\u70b9\uff0c\u81ea\u5df1\u4ece 0 \u5f00\u59cb\u505a\u4e00\u4e2a agent \u5230\u5e95\u6709\u95e8\u69db\u5417\uff08\u4e0d\u9650\u4e8e coding\uff09\uff1f\u4e8e\u662f 4 \u6708\u7684\u65f6\u5019\u5f00\u59cb\u505a\u4e86 <a href=\"https:\/\/github.com\/monsterxx03\/tachi\">tachi<\/a>\u3002\n\u7ed3\u8bba\u662f\uff1a\u505a\u4e00\u4e2a\u5339\u914d\u4e2a\u4eba\u9700\u6c42\u548c\u5de5\u4f5c\u6d41\u7684 agent\uff0c\u6beb\u65e0\u95e8\u69db\uff0c\u6709\u624b\u5c31\u80fd\u5e72\uff0c\u6548\u679c\u4e0d\u4f1a\u6bd4\u4efb\u4f55\u73b0\u6709\u5de5\u5177\u5dee\u3002\u8981\u505a\u6ee1\u8db3\u901a\u7528\u9700\u6c42\u7684 agent\uff0c\u6709\u95e8\u69db\uff0c\u95e8\u69db\u4e3b\u8981\u5728\u4ea7\u54c1\u7ec6\u8282\u7684\u6253\u78e8\u548c\u5404\u79cd\u9002\u914d\u2014\u2014\u8fd9\u4e9b\u5bf9\u4e2a\u4eba\u4f7f\u7528\u5176\u5b9e\u6beb\u65e0\u4ef7\u503c\uff0c\u504f\u504f\u53c8\u662f\u901a\u7528\u5de5\u5177\u91cc\u5de5\u7a0b\u91cf\u6700\u5927\u7684\u90e8\u5206\u3002<\/p>"},{"title":"Hacking Claude Code in Realtime","link":"https:\/\/blog.monsterxx03.com\/2026\/02\/15\/hacking-claude-code-in-realtime\/","pubDate":"Sun, 15 Feb 2026 19:25:07 +0800","guid":"https:\/\/blog.monsterxx03.com\/2026\/02\/15\/hacking-claude-code-in-realtime\/","description":"<p>\u505a\u4e86\u4e2a\u65b0\u73a9\u5177 <a href=\"https:\/\/github.com\/monsterxx03\/linko\">linko<\/a>, \u672c\u8d28\u4e0a\u662f\u4e2a\u900f\u660e mitm proxy, \u4f46\u7ed9\u4ed6\u52a0\u4e0a\u4e86\u53ef\u89c6\u5316 ai agent \u548c llm api \u4e4b\u95f4\u5bf9\u8bdd\u7684\u80fd\u529b.<\/p>\n<p>\u9650\u5236:<\/p>\n<ul>\n<li>\u76ee\u524d\u53ea\u652f\u6301 MacOS (\u900f\u660e\u4ee3\u7406\u7684\u5b9e\u73b0\u7528\u4e86MacOS \u4e0a\u7684pfctl, linux \u7684\u652f\u6301\u5f88\u7b80\u5355, \u6709\u7a7a\u53ef\u4ee5\u52a0\u4e0b)<\/li>\n<li>\u652f\u6301\u7684 llm api \u53ea\u6709 anthropic \u7684\u63a5\u53e3\u683c\u5f0f, \u4efb\u610f\u517c\u5bb9\u7684\u7b2c\u4e09\u65b9\u63a5\u53e3\u5e94\u8be5\u90fd\u53ef\u4ee5(\u6d4b\u8bd5\u8fc7minimax \u548c deepseek)<\/li>\n<\/ul>\n<p>\u539f\u7406\u4e0a\u548c charles \u4e4b\u7c7b\u7684\u5de5\u5177\u7684\u4e3b\u8981\u533a\u522b\u5728&quot;\u900f\u660e&quot;, \u4e0d\u9700\u8981\u5ba2\u6237\u7aef\u6307\u5b9a<code>http_proxy<\/code>(\u6709\u4e9b\u5de5\u5177\u4e0d\u652f\u6301), \u901a\u8fc7\u9632\u706b\u5899\u5f3a\u884c\u52ab\u6301https\u6d41\u91cf, \u6765\u505a\u6d41\u91cf\u89e3\u5bc6.<\/p>"},{"title":"gospy dev note2 (rewrite with aider)","link":"https:\/\/blog.monsterxx03.com\/2025\/03\/30\/gospy-dev-note2-rewrite-with-aider\/","pubDate":"Sun, 30 Mar 2025 19:05:11 +0800","guid":"https:\/\/blog.monsterxx03.com\/2025\/03\/30\/gospy-dev-note2-rewrite-with-aider\/","description":"<p>\u51e0\u5e74\u524d\u5199\u8fc7\u4e2a\u5de5\u5177 <a href=\"https:\/\/github.com\/monsterxx03\/gospy\">gospy<\/a>, \u7528\u4e8e\u4ece\u65c1\u8def dump \u4e00\u4e2a golang \u8fdb\u7a0b\u7684 runtime \u4fe1\u606f(\u5305\u62ec goroutine, memory \u7b49), \u5927\u81f4\u539f\u7406\u89c1\u4ee5\u524d\u7684<a href=\"https:\/\/blog.monsterxx03.com\/tags\/gospy\/\">\u6587\u7ae0<\/a>.<\/p>\n<p>\u57fa\u672c\u529f\u80fd\u80fd\u7528, \u4f46\u6ca1\u7ee7\u7eed\u505a\u4e0b\u53bb, \u9664\u4e86\u6ca1\u65f6\u95f4\u5916, \u5176\u4ed6\u8fd8\u6709\u51e0\u4e2a\u95ee\u9898:<\/p>\n<ul>\n<li>\u4e0d\u652f\u6301 MacOS (\u4e3b\u8981\u662f\u6ca1\u641e\u61c2 MacOS \u4e0b\u600e\u4e48\u8bfb\u53d6\u8fdb\u7a0b\u5185\u5b58).<\/li>\n<li>DWARF \u89e3\u6790\u5199\u7684\u8fc7\u4e8e\u7e41\u7410, golang \u7248\u672c\u66f4\u65b0\u65f6, \u89e3\u6790\u903b\u8f91\u5f88\u96be\u8c03\u6574.<\/li>\n<li>\u5bf9\u5199 UI (\u5305\u62ec terminal UI \u548c\u524d\u7aef) \u5b9e\u5728\u6ca1\u5174\u8da3, \u4e0d\u5199\u53c8\u6ca1\u6cd5\u66b4\u9732\u529f\u80fd, \u4e5f\u61d2\u5f97\u53bb\u505a\u901a\u8fc7 http \u63a5\u53e3\u66b4\u9732\u6570\u636e.<\/li>\n<\/ul>\n<p>\u524d\u9635\u5b50\u8bd5\u4e86\u4e0b\u901a\u8fc7 <a href=\"https:\/\/aider.chat\/\">aider<\/a> \u6765\u5199\u4ee3\u7801, \u6548\u679c\u975e\u5e38\u60ca\u8273, \u5bf9\u6211\u6765\u8bf4, \u6bd4 curosr \u8fd8\u987a\u624b. \u4e8e\u662f\u82b1\u4e86\u4e24\u4e2a\u5468\u672b\u7684\u65f6\u95f4, \u628a gospy \u6574\u4e2a\u91cd\u5199\u4e86.<\/p>"},{"title":"\u6574\u7406\u51e0\u4e2a\u78b0\u5230\u7684 etcd bug","link":"https:\/\/blog.monsterxx03.com\/2023\/04\/12\/%E6%95%B4%E7%90%86%E5%87%A0%E4%B8%AA%E7%A2%B0%E5%88%B0%E7%9A%84-etcd-bug\/","pubDate":"Wed, 12 Apr 2023 09:25:34 +0800","guid":"https:\/\/blog.monsterxx03.com\/2023\/04\/12\/%E6%95%B4%E7%90%86%E5%87%A0%E4%B8%AA%E7%A2%B0%E5%88%B0%E7%9A%84-etcd-bug\/","description":"<p>\u4ea7\u54c1\u91cc\u7528\u4e86\u4e00\u5e74\u591a\u7684 etcd, \u78b0\u5230\u8fc7\u4e00\u4e9b bug, \u6574\u7406\u4e0b\uff0c\u5176\u4e2d\u7528\u4e9b\u5728\u6700\u65b0\u7248\u672c\u91cc\u5df2\u7ecf\u4fee\u590d\u4e86, \u4f1a\u6807\u6ce8\u4e0b.<\/p>\n<h2 id=\"\u6dfb\u52a0-etcd-\u8282\u70b9\u76f8\u5173-bug\">\u6dfb\u52a0 etcd \u8282\u70b9\u76f8\u5173 bug<\/h2>\n<p>\u6dfb\u52a0 etcd \u8282\u70b9\u7684\u8fc7\u7a0b\u4e00\u822c\u662f\u5148 member add, \u7136\u540e\u542f\u52a8\u65b0\u8282\u70b9\u4e0a\u7684 etcd\uff0c\u8fd9\u6837\u7684\u95ee\u9898\u662f\u5728 member add \u548c\u65b0 etcd \u542f\u52a8\n\u4e4b\u95f4\u6574\u4e2a etcd \u96c6\u7fa4\u5904\u4e8e quorum - 1 \u7684\u72b6\u6001, \u6b64\u8fc7\u7a0b\u589e\u52a0\u4e86\u96c6\u7fa4\u7684\u4e0d\u7a33\u5b9a\u6027\uff0c\u5982\u679c\u65b0\u8282\u70b9\u7531\u4e8e\u914d\u7f6e\u9519\u8bef\u8d77\u4e0d\u6765\uff0c\u73b0\u5b58\u8282\u70b9\u518d\u6302\u4e00\u4e2a\n\u5c31\u53ef\u80fd\u5bfc\u81f4\u6574\u4e2a\u96c6\u7fa4\u4e0d\u53ef\u7528.<\/p>\n<p>\u4ece 3.4 \u5f00\u59cb etcd \u5f15\u5165\u4e86 learner \u7684\u6982\u5ff5, member add &ndash;learner, \u53ef\u4ee5\u5c06\u65b0\u8282\u70b9\u6dfb\u52a0\u6210 leaner \u89d2\u8272\uff0c\u53ea\u540c\u6b65 raft log, \u4e0d\u53c2\u4e0e quorum vote,\n\u5373\u73b0\u6709\u96c6\u7fa4\u7684 quorum size \u4e0d\u4f1a\u53d8\u5316. \u7b49\u65b0\u8282\u70b9\u8d77\u6765\u540e\u518d\u901a\u8fc7 member promote \u5c06\u65b0\u8282\u70b9\u63d0\u5347\u4e3a\u6b63\u5e38\u8282\u70b9\uff0c\u53c2\u4e0e quorum vote.<\/p>"},{"title":"\u7528 Patroni \u6765\u505a PostgreSQL \u7684 HA","link":"https:\/\/blog.monsterxx03.com\/2022\/01\/26\/%E7%94%A8-patroni-%E6%9D%A5%E5%81%9A-postgresql-%E7%9A%84-ha\/","pubDate":"Wed, 26 Jan 2022 14:06:09 +0800","guid":"https:\/\/blog.monsterxx03.com\/2022\/01\/26\/%E7%94%A8-patroni-%E6%9D%A5%E5%81%9A-postgresql-%E7%9A%84-ha\/","description":"<p>patroni \u7684\u5b89\u88c5\u8df3\u8fc7, \u5b83\u53ea\u662f\u4e2a python \u5305, \u628a\u4f9d\u8d56\u88c5\u597d\u5c31\u884c, \u540c\u65f6\u8981\u6c42\u88c5\u597d postgres-server, patroni \u8fd0\u884c\u8fc7\u7a0b\u4e2d\u4f1a\u8c03\u7528 pg_ctl \u7b49\u547d\u4ee4: <a href=\"https:\/\/patroni.readthedocs.io\/en\/latest\/README.html\">https:\/\/patroni.readthedocs.io\/en\/latest\/README.html<\/a>\n\u6bcf\u4e2a patroni \u7ba1\u7406\u4e00\u4e2a pg \u5b9e\u4f8b, \u4e24\u8005\u5fc5\u987b\u90e8\u7f72\u5728\u540c\u4e00\u8282\u70b9\u4e0a, patroni \u9700\u8981\u80fd:<\/p>\n<ul>\n<li>\u8bbf\u95ee pg \u7684\u76d1\u542c\u7aef\u53e3<\/li>\n<li>\u8bfb\u5199 pg data dir (patroni \u4f1a\u91cd\u5199 postgres.conf, pg_hba.conf \u7b49\u6587\u4ef6)<\/li>\n<\/ul>\n<p><img src=\"https:\/\/blog.monsterxx03.com\/posts\/images\/patroni-ha.png\" alt=\"\"><\/p>\n<h2 id=\"\u914d\u7f6e\u6587\u4ef6\">\u914d\u7f6e\u6587\u4ef6<\/h2>\n<p>\u914d\u7f6e\u6587\u4ef6\u662fyaml \u683c\u5f0f, \u5177\u4f53\u89c1 <a href=\"https:\/\/patroni.readthedocs.io\/en\/latest\/SETTINGS.html\">https:\/\/patroni.readthedocs.io\/en\/latest\/SETTINGS.html<\/a><br>\n\u4f7f\u7528 patroni postgres.yaml \u547d\u4ee4\u542f\u52a8\u4e00\u4e2a patroni \u5b9e\u4f8b<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#586e75;background-color:#eee8d5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-yaml\" data-lang=\"yaml\"><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># \u96c6\u7fa4\u540d\u5b57, \u540c\u4e00\u96c6\u7fa4\u5185\u7684 patroni \u5fc5\u987b\u8bbe\u7f6e\u4e00\u6837, \u4f1a\u6210\u4e3a postgres.conf \u5185\u7684 cluster_name\u53c2\u6570<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">scope<\/span>: <span style=\"color:#2aa198\">xsky-test<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># patroni \u4f1a\u5c06\u4e00\u4e9b\u52a8\u6001\u914d\u7f6e\u5b58\u5728 DCS \u5185, namespace \u662f\u5728 DCS \u5185\u7684\u5b58\u50a8\u8def\u5f84, eg: \u4f7f\u7528 etcdv3 \u4f5c\u4e3a DCS, \u53ef\u4ee5\u901a\u8fc7 etdctl get \/service --prefix \u770b\u5230 patroni \u5728 DCS \u5185\u5b58\u4e86\u4ec0\u4e48<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">namespace<\/span>: <span style=\"color:#2aa198\">\/service  <\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># \u7ba1\u7406\u7684 pg \u7684\u5b9e\u4f8b\u540d, \u540c\u4e00\u96c6\u7fa4\u5185\u6bcf\u4e2a\u5b9e\u4f8b\u5fc5\u987b\u90fd\u4e0d\u540c, eg: pg0, pg1, pg2<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">name<\/span>: <span style=\"color:#2aa198\">pg0<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\">#  \u65e5\u5fd7\u76f8\u5173\u914d\u7f6e<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">log<\/span>:  \n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#268bd2;font-weight:bold\">level<\/span>: <span style=\"color:#2aa198\">INFO <\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># patroni restapi \u76f8\u5173\u914d\u7f6e<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">restapi<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#268bd2;font-weight:bold\">listen<\/span>: <span style=\"color:#2aa198;font-weight:bold\">0.0.0.0<\/span>:<span style=\"color:#2aa198;font-weight:bold\">8008<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># \u7528\u521b\u5efa pg \u5b9e\u4f8b, \u751f\u6210 pg \u7684 data dir, postgres.conf, pg_hba.conf \u7b49\u6587\u4ef6<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">bootstrap<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#93a1a1;font-style:italic\"># dcs \u4e0b\u5185\u5bb9\u4f1a\u5199\u5165 DCS \u7684 {namespace}\/{scope}\/config key \u4e2d,\u53ea\u6709\u5728\u521d\u59cb\u5316\u96c6\u7fa4\u7684\u65f6\u5019\u88ab\u4f7f\u7528\u4e00\u6b21, \u540e\u7eed\u4fee\u6539\u4e0d\u4f1a\u751f\u6548, \u53ef\u4ee5\u901a\u8fc7 patrionctl edit-config \u6216 rest api \u6765\u4fee\u6539\u5b58\u5728 dcs \u4e2d\u7684\u503c<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#268bd2;font-weight:bold\">dcs<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#268bd2;font-weight:bold\">loop_wait<\/span>: <span style=\"color:#2aa198;font-weight:bold\">10<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#268bd2;font-weight:bold\">ttl<\/span>: <span style=\"color:#2aa198;font-weight:bold\">30<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#93a1a1;font-style:italic\"># \u521d\u59cb\u5316\u96c6\u7fa4\u65f6\u751f\u6210 pg_bha.conf, \u540e\u7eed\u6539\u52a8\u4e0d\u4f1a\u751f\u6548<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#268bd2;font-weight:bold\">pg_hba<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>   - <span style=\"color:#2aa198\">host replication replicator 127.0.0.1\/32 md5<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#93a1a1;font-style:italic\"># \u5728\u521d\u59cb\u5316\u96c6\u7fa4\u65f6\u9700\u8981\u521b\u5efa\u7684\u7528\u6237, \u540e\u7eed\u6539\u52a8\u4e0d\u4f1a\u751f\u6548<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#268bd2;font-weight:bold\">users<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># \u4f7f\u7528 etcd v2 api \u4f5c\u4e3a dcs<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">etcd<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># \u4f7f\u7528 etcd v3 api \u4f5c\u4e3a dcs<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">etcd3<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># \u7528\u4e8e patroni \u8fd0\u884c\u65f6\u8fde\u63a5 pg<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">postgresql<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#268bd2;font-weight:bold\">listen<\/span>: <span style=\"color:#2aa198;font-weight:bold\">0.0.0.0<\/span>:<span style=\"color:#2aa198;font-weight:bold\">5432<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># patronictl.py \u8fde\u63a5 restapi \u65f6 http\u53c2\u6570(ssl\u76f8\u5173)<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">ctl<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># \u901a\u8fc7 linux \u7684 softdog \u6a21\u5757, \u5728 patroni \u63a7\u5236\u7684 pg \u6302\u6389\u65f6\u91cd\u542f server<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">watchdog<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>  <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#93a1a1;font-style:italic\"># \u901a\u8fc7nofailover \u7b49 tag \u53ef\u4ee5\u63a7\u5236\u884c\u4e3a(eg: \u4e0d\u5141\u8bb8\u67d0\u4e2a patrion \u5b9e\u4f8b\u6210\u4e3a leader, \u4e5f\u53ef\u4ee5\u6dfb\u52a0\u81ea\u5b9a\u4e49tag\u4f5c\u4e3a\u5143\u6570\u636e<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2;font-weight:bold\">tags<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>   <span style=\"color:#2aa198\">...<\/span>\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"\u7528-patroni-bootstrap-pg-\u96c6\u7fa4\">\u7528 patroni bootstrap pg \u96c6\u7fa4<\/h2>\n<p>\u5047\u8bbe\u6709\u4e09\u8282\u70b9, \u4e0a\u9762\u5df2\u7ecf\u90e8\u7f72\u597d etcd(v3) \u4f5c\u4e3a dcs, \u4e09\u8282\u70b9 ip\u4e3a: 10.252.90.217, 10.252.90.218, 10.252.90.219\n217 \u8282\u70b9\u4e0a patroni \u7684 postgres.yml \u914d\u7f6e, \u5176\u4ed6\u8282\u70b9\u7c7b\u4f3c, \u628a ip \u6539\u4e0b:<\/p>"},{"title":"Rolling Upgrade Worker Nodes in EKS","link":"https:\/\/blog.monsterxx03.com\/2021\/04\/01\/rolling-upgrade-worker-nodes-in-eks\/","pubDate":"Thu, 01 Apr 2021 14:40:30 +0800","guid":"https:\/\/blog.monsterxx03.com\/2021\/04\/01\/rolling-upgrade-worker-nodes-in-eks\/","description":"<p>EKS control plane \u7684\u5347\u7ea7\u662f\u6bd4\u8f83\u7b80\u5355\u7684, \u76f4\u63a5\u5728 aws console \u4e0a\u70b9\u4e0b\u5c31\u53ef\u4ee5\u4e86, \u4f46 worker node \u662f\u81ea\u5df1\u7528 asg(autoscaling group) \u7ba1\u7406\u7684, \u5347\u7ea7 worker node \u53c8\u4e0d\u60f3\u5f71\u54cd\u4e1a\u52a1\u662f\u6709\u8bb2\u7a76\u7684.<\/p>\n<p>\u8dd1\u5728 EKS \u91cc, \u4e14\u5e0c\u671b\u4e0d\u88ab\u4e2d\u65ad traffic \u7684\u6709:<\/p>\n<ul>\n<li>stateless \u7684 api server, queue consumer<\/li>\n<li>\u88ab redis sentinel \u76d1\u63a7\u7740\u7684 redis master\/slave<\/li>\n<li>\u7528\u4e8e cache \u7684 redis cluster<\/li>\n<\/ul>\n<p>\u5199\u4e86\u4e2a\u5185\u90e8\u5de5\u5177, \u628a\u4e0b\u9762\u7684\u6d41\u7a0b\u5168\u90e8\u81ea\u52a8\u5316\u4e86. \u8fd9\u6837\u5347\u7ea7 eks \u7248\u672c, \u9700\u8981\u66f4\u6362 worker node \u65f6\u5019\u5c31\u8f7b\u677e\u591a\u4e86. \u56e0\u4e3a\u8fd9\u4e2a\u5de5\u5177\u5bf9\u90e8\u7f72\u60c5\u51b5\u505a\u4e86\u5f88\u591a\u5047\u8bbe\u548c\u9650\u5236, \u5f00\u6e90\u7684\u4ef7\u503c\u4e0d\u662f\u5f88\u5927.<\/p>\n<h2 id=\"stateless-application\">Stateless application<\/h2>\n<p>stateless \u7684\u5e94\u7528\u5168\u90e8\u7528 deployment \u90e8\u7f72.<\/p>\n<p>\u4e00\u822c\u5efa\u8bae\u7684\u6d41\u7a0b\u662f:<\/p>\n<ul>\n<li>\u4fee\u6539 asg \u7684 launch configuration, \u6307\u5411\u65b0\u7248\u672c\u7684 ami<\/li>\n<li>\u628a\u6240\u6709\u8001\u7684 worker node \u7528 kubectl cordon \u6807\u8bb0\u6210 unschedulable<\/li>\n<li>\u5173\u95ed cluster-autoscaler<\/li>\n<li>\u4fee\u6539 asg \u7684 desired count, \u8ba9 asg \u7528\u65b0 ami \u542f\u52a8\u65b0\u7684 worker node<\/li>\n<li>\u7528 kubectl drain \u628a\u8001 worker node \u4e0a\u7684 pod evict \u6389, \u8ba9\u5b83\u4eec schedule \u5230\u65b0\u7684 worker node \u4e0a.<\/li>\n<li>\u91cd\u65b0\u5f00\u542f cluster autoscaler, \u7b49\u5b83\u628a\u8001\u7684\u95f2\u7f6e worker node \u5173\u95ed.<\/li>\n<\/ul>\n<p>\u8fd9\u91cc\u6709\u4e9b\u95ee\u9898:<\/p>"},{"title":"\u4ecek8s deprecating docker \u8bf4\u8d77","link":"https:\/\/blog.monsterxx03.com\/2020\/12\/04\/%E4%BB%8Ek8s-deprecating-docker-%E8%AF%B4%E8%B5%B7\/","pubDate":"Fri, 04 Dec 2020 10:49:40 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/12\/04\/%E4%BB%8Ek8s-deprecating-docker-%E8%AF%B4%E8%B5%B7\/","description":"<p>k8s 1.20 \u7684 release note \u91cc\u8bf4 deprecated docker: <a href=\"https:\/\/github.com\/kubernetes\/kubernetes\/blob\/master\/CHANGELOG\/CHANGELOG-1.20.md#deprecation\">https:\/\/github.com\/kubernetes\/kubernetes\/blob\/master\/CHANGELOG\/CHANGELOG-1.20.md#deprecation<\/a><\/p>\n<p>\u5bf9 docker \u548c k8s \u5173\u7cfb\u6bd4\u8f83\u4e86\u89e3\u7684\u4eba\u4e00\u770b\u5c31\u77e5\u9053\u662f\u5e9f\u5f03 dockershim, \u6b63\u5e38\u64cd\u4f5c, \u5177\u4f53\u6709\u4ec0\u4e48\u5f71\u54cd, \u5efa\u8bae\u9605\u8bfb:<\/p>\n<ul>\n<li><a href=\"https:\/\/kubernetes.io\/blog\/2020\/12\/02\/dont-panic-kubernetes-and-docker\/\">https:\/\/kubernetes.io\/blog\/2020\/12\/02\/dont-panic-kubernetes-and-docker\/<\/a><\/li>\n<li><a href=\"https:\/\/kubernetes.io\/blog\/2020\/12\/02\/dockershim-faq\/\">https:\/\/kubernetes.io\/blog\/2020\/12\/02\/dockershim-faq\/<\/a><\/li>\n<\/ul>\n<p>\u4f46\u5bb9\u5668\u5708\u91cc\u90a3\u5806\u540d\u8bcd\u7684\u786e\u5f88\u8ba9\u4eba\u56f0\u60d1, docker, dockershim, containerd, containerd-shim, runc, cri, oci, csi, cni, cri-o, \u6216\u8bb8\u66fe\u7ecf\u8fd8\u542c\u8bf4\u8fc7 runv, rkt, clear containers, \u540e\u6765\u53c8\u6765\u4e86 kata containers, firecracker, gvisor. \u8bba\u9020\u540d\u8bcd, \u9020\u9879\u76ee, \u90fd\u5feb\u8d76\u4e0a\u524d\u7aef\u5708\u7684\u811a\u8dbe\u5934\u4e86.<\/p>\n<p>\u8fd9\u7bc7\u6bd4\u8f83\u6c34, \u5c31\u89e3\u91ca\u4e0b\u5b83\u4eec\u5927\u81f4\u7684\u5173\u7cfb, \u524d\u63d0\u662f\u4f60\u5927\u6982\u77e5\u9053 docker, namespace, cgroup, container, k8s pod \u4e4b\u95f4\u7684\u5173\u7cfb, \u4e0d\u505a\u989d\u5916\u89e3\u91ca.<\/p>\n<h2 id=\"\u4ece-docker-\u8bf4\u8d77\">\u4ece docker \u8bf4\u8d77<\/h2>\n<p>\u5728\u6211\u73b0\u5728\u8fd9\u53f0\u673a\u5668\u4e0a\u7684 ubuntu 18.04, \u5b89\u88c5 docker, \u6dfb\u52a0\u5b98\u65b9\u6e90\u4e4b\u540e, \u5b89\u88c5\u7684 deb package(version 19.03) \u662f docker-ce<\/p>\n<p><code>apt show docker-ce<\/code>  \u770b\u4f9d\u8d56:<\/p>"},{"title":"\u4e8c\u4e09\u4e8b","link":"https:\/\/blog.monsterxx03.com\/2020\/12\/02\/%E4%BA%8C%E4%B8%89%E4%BA%8B\/","pubDate":"Wed, 02 Dec 2020 16:00:13 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/12\/02\/%E4%BA%8C%E4%B8%89%E4%BA%8B\/","description":"<p>\u5929\u6c14\u6e10\u51c9, \u65e0\u5948\u5f97\u62ff\u51fa\u4e86\u79cb\u88e4. \u5077\u61d2\u597d\u4e45\u6ca1\u5199\u535a\u5ba2\u4e86, \u56de\u987e\u4e0b\u8fd9\u9635\u5b50\u505a\u4e86\u4ec0\u4e48.<\/p>\n<h2 id=\"\u5de5\u4f5c\">\u5de5\u4f5c<\/h2>\n<p>\u5e74\u5e95\u6253\u7b97\u628a\u4e4b\u524d\u7528\u7684 dedicated ec2 instance \u5168\u90e8\u6362\u6389, \u51e0\u5e74\u524d\u4e3a\u4e86 HIPAA \u5408\u89c4\u505a\u7684, \u4f46 AWS \u7684 BBA \u91cc\u540e\u6765\u4e0d\u8981\u6c42 dedicated instance \u4e86, \u6362\u6210\u666e\u901a\u7684, \u53ef\u4ee5\u7701\u6389\u6bcf\u67081400\u591a\u5200\u7684\u56fa\u5b9a dedicated fee, \u540c\u7c7b\u578b\u7684 ec2 instance \u53ef\u4ee5\u518d\u770110%\u5de6\u53f3. \u4e3a\u4e86\u8fd9\u4e2a, \u6253\u7b97\u628a\u90e8\u5206\u9057\u7559\u5728 vm \u4e0a\u7684\u4e1c\u897f\u8fc1\u79fb\u5230 k8s \u91cc, \u51cf\u5c11\u4e4b\u540e\u66f4\u6362 instance \u7684\u5de5\u4f5c\u91cf.<\/p>\n<h3 id=\"cronjob\">cronjob<\/h3>\n<p>\u5c1d\u8bd5\u7528 <a href=\"https:\/\/github.com\/argoproj\/argo\">argo<\/a> \u6765\u8c03\u5ea6 cronjob.<\/p>\n<p>\u8fd8\u662f\u6709\u4e0d\u5c11\u5751\u7684:<\/p>\n<ul>\n<li>cron workflow \u5230\u70b9\u540e\u6709\u4e00\u5b9a\u51e0\u7387\u4f1a trigger \u91cd\u590d\u7684workflow, \u76ee\u524d\u8fd8\u6ca1\u6709\u4fee\u590d<a href=\"https:\/\/github.com\/argoproj\/argo\/issues\/4558\">#4558<\/a>, \u4e34\u65f6\u5728\u6240\u6709 cronjob \u7684\u4ee3\u7801\u91cc\u52a0\u4e86\u4e2a\u4fdd\u62a4, \u5728 redis \u91cc\u4e0a\u4e2a\u9501, \u6ca1\u62a2\u5230\u9501\u7684 cronjob \u76f4\u63a5\u629b\u5f02\u5e38\u5931\u8d25. \u76ee\u524d\u770b\u6bcf\u5929\u8fd8\u662f\u6709 7,8 \u6b21\u91cd\u590d\u7684 workflow \u4f1a\u89e6\u53d1.<\/li>\n<li>WorkflowTemplate \u53ef\u4ee5\u7528\u6765\u590d\u7528 pod \u7684\u5b9a\u4e49, \u4f46\u5916\u90e8\u5f80\u91cc\u9762\u4f20\u53c2\u7684\u65b9\u5f0f\u5f88\u6413, \u4e0d\u662f\u6240\u6709\u5b57\u6bb5\u90fd\u80fd\u76f4\u63a5\u8986\u76d6, \u6bd4\u5982activeDeadlineSeconds, resources \u7b49, \u5fc5\u987b\u7528 podSpecPatch \u7684\u65b9\u5f0f, \u6587\u6863\u91cc\u53c8\u4e0d\u8bf4\u6e05\u695a, \u53ea\u80fd\u81ea\u5df1\u53bb\u7ffbissue.<\/li>\n<li>exit-handler \u7528\u6765\u5728 workflow \u72b6\u6001\u6539\u53d8\u7684\u65f6\u5019\u89e6\u53d1\u4e00\u4e2a callback, \u4f46\u6ca1\u6cd5\u83b7\u53d6\u89e6\u53d1\u5b83\u7684\u90a3\u4e2a workflow \u7684\u8be6\u7ec6\u4fe1\u606f, \u6bd4\u5982\u4e00\u4e2a workflow \u7531\u5f88\u591a\u4e2a step \u6784\u6210, \u5931\u8d25\u65f6\u6211\u5e0c\u671b\u80fd\u4ece exit-handler \u91cc\u62ff\u5230\u662f\u54ea\u4e2astep \u6302\u4e86, \u73b0\u5728\u505a\u4e0d\u5230. \u4e5f\u6ca1\u6cd5\u5f80 exit-handler \u91cc\u4f20\u53c2(\u53ea\u80fd\u53d6\u4e00\u4e9bglobal paramaters).<\/li>\n<li>\u5982\u679c\u4e00\u4e2a workflow \u7531\u591a\u4e2a step \u6784\u6210, \u5f53\u5176\u4e2d\u4e00\u4e2a step \u6302\u4e86, \u53ef\u4ee5\u8bbe\u7f6e continueOn \u63a7\u5236\u662f\u5426\u7ee7\u7eed\u540e\u9762\u7684step, \u4f46\u5982\u679c\u6211\u9009\u62e9\u4e86\u7ee7\u7eed, \u6574\u4e2a workflow \u7684\u6700\u7ec8\u72b6\u6001\u53c8\u662f success \u7684, \u5bfc\u81f4\u5728 exit-handler \u91cc\u6ca1\u6cd5\u533a\u5206, \u6700\u597d\u6709\u4e2a partial success \u7684\u72b6\u6001.<\/li>\n<\/ul>\n<h3 id=\"\u65e5\u5fd7\">\u65e5\u5fd7<\/h3>\n<p>\u5e94\u7528\u91cc\u7684\u65e5\u5fd7, \u4e4b\u524d\u662f\u6253\u5230\u90e8\u7f72\u5728 vm \u4e0a\u7684\u4e00\u53f0 rsyslog \u4e0a. \u5728 k8s \u73af\u5883\u4e0b\u6211\u7528 fluent-bit \u505a daemonset \u6765\u6536\u96c6 pod \u65e5\u5fd7. fluent-bit \u5728\u6700\u8fd1\u7684\u7248\u672c\u91cc\u652f\u6301\u4e86\u8f6c\u53d1\u5230 loki, \u6211\u5c31\u90e8\u7f72\u4e86 loki \u6765\u6536\u96c6pod \u65e5\u5fd7, \u53ef\u4ee5\u65b9\u4fbf\u5728 grafana \u91cc\u8fdb\u884c\u67e5\u770b. \u95ee\u9898\u4e5f\u5f88\u591a:<\/p>"},{"title":"Linux \u8fdb\u7a0b\u865a\u62df\u5185\u5b58\u5206\u5e03","link":"https:\/\/blog.monsterxx03.com\/2020\/08\/26\/linux-%E8%BF%9B%E7%A8%8B%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98%E5%88%86%E5%B8%83\/","pubDate":"Wed, 26 Aug 2020 23:06:01 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/08\/26\/linux-%E8%BF%9B%E7%A8%8B%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98%E5%88%86%E5%B8%83\/","description":"<p>\u5de9\u56fa\u4e0b\u57fa\u7840\u77e5\u8bc6.<\/p>\n<p>\u73b0\u4ee3\u7cfb\u7edf\u90fd\u8fd0\u884c\u5728\u4fdd\u62a4\u6a21\u5f0f(protected mode)\u4e0b, x86_64 \u4e0b\u7528\u6237\u6001\u7a0b\u5e8f\u542f\u52a8\u65f6\u5019\u90fd\u4f1a\u88ab\u5206\u914d\u4e00\u7247\u865a\u62df\u5185\u5b58, \u5927\u5c0f\u662f 2^47 (128TiB), \u4f46\u76ee\u524d cpu \u53ea\u80fd\u6620\u5c04 2^46 (64TiB), \u901a\u8fc7 page table \u5c06\u865a\u62df\u5185\u5b58\u4e2d\u7684\u5730\u5740(vma)\u548c\u7269\u7406\u5730\u5740\u6620\u5c04\u8d77\u6765.\n\u4ee5\u524d\u7684 BIOS \u8dd1\u5728 \u5b9e\u6a21\u5f0f\u4e0b(real mode), \u76f4\u63a5\u8bbf\u95ee\u7269\u7406\u5185\u5b58, \u4e0d\u8fc7\u53ea\u80fd\u8bbf\u95ee\u524d 2^20(1MiB) \u7684\u7a7a\u95f4.<\/p>\n<p>Linux \u4e0b \/proc\/$pid\/maps \u6587\u4ef6\u5185\u5bb9\u5c31\u662f\u8fdb\u7a0b\u7684\u865a\u62df\u5185\u5b58\u5206\u5e03. \u6bcf\u4e00\u5217\u542b\u4e49\u901a\u8fc7 <code>man 5 proc<\/code> \u770b, \u4e0d\u91cd\u590d\u4e86.<\/p>\n<p>\u7f51\u4e0a\u7684\u4f8b\u5b50\u90fd\u6709\u70b9\u8fc7\u65f6, \u5728\u6bd4\u8f83\u65b0\u7684 linux \u53d1\u884c\u7248\u91cc, \u9ed8\u8ba4\u5f00\u542f\u4e86ASLR(\u5730\u5740\u7a7a\u95f4\u968f\u673a\u5316), \u81ea\u5e26\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\u90fd\u662f PIE(Position Independent Executable) build \u7684. \u8fd9\u4e24\u7ed3\u5408\u8d77\u6765\u8ba9\u8fdb\u7a0b\u5728\u865a\u62df\u5185\u5b58\u4e2d\u7684\u57fa\u5730\u5740\u968f\u673a\u5316, heap \u548c stack \u7684\u5f00\u59cb\u4f4d\u7f6e\u4e5f\u968f\u673a\u5316, \u76ee\u7684\u662f\u4e3a\u4e86\u9632\u6b62\u8fdc\u7a0b\u6ce8\u5165\u6f0f\u6d1e\u731c\u5230\u4e00\u4e9b\u8f6f\u4ef6\u7684vma.<\/p>"},{"title":"Kubectl Plugin for Redis Cluster","link":"https:\/\/blog.monsterxx03.com\/2020\/08\/04\/kubectl-plugin-for-redis-cluster\/","pubDate":"Tue, 04 Aug 2020 22:44:40 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/08\/04\/kubectl-plugin-for-redis-cluster\/","description":"<p>\u5728 k8s \u4e0a\u90e8\u7f72 redis cluster \u540e, \u611f\u89c9 redis-cli \u7ba1\u7406 redis cluster \u975e\u5e38\u522b\u626d, \u5199\u4e86\u4e2a kubectl \u7684\u63d2\u4ef6 <a href=\"https:\/\/github.com\/monsterxx03\/kubectl-rc\">kubectl-rc<\/a> \u6765\u8f85\u52a9\u7ba1\u7406 redis-cluster.<\/p>\n<h2 id=\"redis-cli-\u96be\u7528\u5728\u54ea\">redis-cli \u96be\u7528\u5728\u54ea<\/h2>\n<ol>\n<li>\u4e0d\u76f4\u89c2 &amp; \u4e0d\u7edf\u4e00<\/li>\n<\/ol>\n<p>\u90e8\u5206 cluster \u4fe1\u606f\u662f\u76f4\u63a5\u901a\u8fc7 redis protocol \u83b7\u5f97\u7684, \u6bd4\u5982 <code>cluster nodes<\/code>, <code>cluster slots<\/code>, \u4f46\u90e8\u5206\u7ba1\u7406\u547d\u4ee4\u53c8\u662f\u901a\u8fc7 <code>redis-cli --cluster<\/code> \u6267\u884c\u7684.<\/p>\n<p><code>cluster nodes<\/code>, <code>cluster slots<\/code> \u8fd9\u4e9b\u547d\u4ee4\u8f93\u51fa\u7684\u53c8\u662f ip \u548c node id, k8s \u73af\u5883\u4e0b\u6211\u66f4\u5173\u5fc3\u5b9e\u9645\u7684 pod name.<\/p>\n<p>\u505a failover \u7684\u65f6\u5019\u53c8\u4e0d\u662f\u901a\u8fc7 <code>--cluster<\/code> \u6267\u884c\u7684, \u5fc5\u987b\u8fde\u5230 slave \u4e0a\u901a\u8fc7 <code>cluster failover<\/code> \u6765\u6267\u884c<\/p>\n<ol start=\"2\">\n<li>\u4f20\u53c2\u5728 k8s \u73af\u5883\u4e0b\u7279\u522b\u9ebb\u70e6<\/li>\n<\/ol>\n<p>\u4e3e\u4e2a\u4f8b\u5b50, \u6dfb\u52a0\u8282\u70b9:<\/p>\n<pre><code>redis-cli --cluster add-node new_host:new_port existing_host:existing_port\n    --cluster-slave --cluster-master-id &lt;arg&gt;\n<\/code><\/pre>\n<p>\u9700\u8981\u77e5\u9053\u64cd\u4f5c pod \u7684 ip, \u5982\u679c\u8981\u53d8\u6210\u67d0\u4e2a\u6307\u5b9a pod \u7684 slave, \u53c8\u8981\u4f20 node id.<\/p>\n<p>\u5728 k8s \u73af\u5883\u4e0b\u5b9e\u9645\u64cd\u4f5c\u7684\u65f6\u5019\u6d41\u7a0b\u5c31\u4f1a\u53d8\u6210:<\/p>"},{"title":"\u4ece twemproxy \u8fc1\u79fb\u5230 redis cluster","link":"https:\/\/blog.monsterxx03.com\/2020\/07\/08\/%E4%BB%8E-twemproxy-%E8%BF%81%E7%A7%BB%E5%88%B0-redis-cluster\/","pubDate":"Wed, 08 Jul 2020 17:08:40 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/07\/08\/%E4%BB%8E-twemproxy-%E8%BF%81%E7%A7%BB%E5%88%B0-redis-cluster\/","description":"<p>\u7ebf\u4e0a\u6709\u4e2a redis \u7684\u7f13\u5b58\u96c6\u7fa4, \u8dd1\u7684\u8fd8\u662f 3.0, \u524d\u9762\u5957 twemproxy \u505a sharding. \u8dd1\u4e86\u597d\u51e0\u5e74\u4e86\u90fd\u5f88\u7a33\u5b9a, \u4f46\u4e00\u76f4\u6709\u4e9b\u5f88\u4e0d\u723d\u7684\u5730\u65b9, \u6700\u8fd1\u6709\u70b9\u65f6\u95f4,\u51b3\u5b9a\n\u5347\u7ea7\u5230redis 6, \u5e76\u8fc1\u79fb\u5230 redis cluster \u65b9\u6848.<\/p>\n<h3 id=\"twemproxy-\u7684\u5de5\u4f5c\u6a21\u5f0f\">twemproxy \u7684\u5de5\u4f5c\u6a21\u5f0f<\/h3>\n<p>twemproxy \u7684\u539f\u7406\u5f88\u7b80\u5355, \u540e\u9762\u8fd0\u884c N \u4e2a redis \u5b9e\u4f8b, \u5e94\u7528\u8fde\u5230 twemproxy, twemproxy \u89e3\u6790\u5e94\u7528\u53d1\u8fc7\u6765\u7684 redis protocol, \u6839\u636e key \u505a hash, \u6253\u6563\u5230\u540e\u9762 N \u4e2a redis \u5b9e\u4f8b\u4e0a.<\/p>\n<p>\u5177\u4f53\u6253\u6563\u7684\u65b9\u5f0f\u53ef\u4ee5\u662f\u7b80\u5355\u7684 hash%N, \u4e5f\u53ef\u4ee5\u7528\u4e00\u81f4\u6027 hash \u7b97\u6cd5. hash%N \u7684\u95ee\u9898\u662f, \u589e\u51cf\u8282\u70b9\u7684\u65f6\u5019\u6240\u6709 cache \u5fc5\u7136 miss.<\/p>\n<p>\u4e00\u81f4\u6027 hash, \u5728\u5b9e\u73b0\u7684\u65f6\u5019\u4f1a\u5148\u5f04\u4e00\u4e2a size \u5f88\u5927\u7684 hash ring(eg: 2^32),\u8fd9\u91cc\u6bcf\u4e2a\u8282\u70b9\u88ab\u53eb\u505a\u4e00\u4e2a\u865a\u62df\u8282\u70b9, \u628a\u865a\u62df\u8282\u70b9\u7684\u6570\u76ee\u53eb\u505a X, \u7136\u540e\u5c06 N \u4e2a redis \u5b9e\u4f8b\u5747\u5300\u5206\u5e03\u5230\u8fd9\u4e2a\u73af\u4e0a, \u6bcf\u4e2a redis \u628a\u5b83\u53eb\u505a\u5b9e\u8282\u70b9\u5427, \u5206\u914d key\n\u7684\u65f6\u5019 hash%X, \u5f97\u5230\u865a\u62df\u8282\u70b9, \u7136\u540e\u987a\u65f6\u9488\u627e\u4e0b\u4e00\u4e2a\u6700\u8fd1\u7684\u5b9e\u8282\u70b9, \u5c31\u627e\u5230\u4e86\u76f8\u5e94\u7684 redis. \u56e0\u4e3a\u865a\u62df\u8282\u70b9\u7684\u6570\u76ee\u662f\u4e0d\u53d8\u7684, \u589e\u51cf redis \u5b9e\u4f8b\u7684\u6570\u76ee\u662f\u6539\u53d8\u4e86\u5b9e\u8282\u70b9\u7684\u5206\u5e03, \u987a\u65f6\u9488\u627e\u4e0b\u4e2a\u5b9e\u8282\u70b9\u7684\u65f6\u5019\u8fd8\u662f\u6709\u4e00\u5b9a\u51e0\u7387\u843d\u5728\u4ee5\u524d\u7684\nredis \u5b9e\u4f8b\u4e0a\u7684, \u8fd9\u5728\u4e00\u5b9a\u7a0b\u5ea6\u4e0a\u51cf\u5c11\u4e86 cache \u7684 miss. \u53ef\u4ee5\u770b\u4f5c hash%N \u7684\u4f18\u5316\u7248\u672c,\u4f46\u4e0d\u89e3\u51b3\u672c\u8d28\u95ee\u9898.<\/p>"},{"title":"snet dev note: stats api and terminal UI","link":"https:\/\/blog.monsterxx03.com\/2020\/06\/30\/snet-dev-note-stats-api-and-terminal-ui\/","pubDate":"Tue, 30 Jun 2020 14:40:01 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/06\/30\/snet-dev-note-stats-api-and-terminal-ui\/","description":"<p>\u4ece <a href=\"https:\/\/github.com\/monsterxx03\/snet\/releases\">0.10.0<\/a> \u7248\u672c\u5f00\u59cb\u7ed9 snet \u52a0\u4e86 stats api \u6765\u66b4\u9732\u5185\u90e8\u7684\u4e00\u4e9b\u7edf\u8ba1\u6570\u636e.<\/p>\n<p>\u8bbe\u7f6e <code>&quot;enable-stats&quot;: true<\/code> \u5f00\u542f, \u9ed8\u8ba4\u76d1\u542c 8810 \u7aef\u53e3, <code>curl http:\/\/localhost:8810\/stats<\/code><\/p>\n<pre><code>    {\n        &quot;Uptime&quot;: &quot;26m42s&quot;,\n        &quot;Total&quot;: {\n            &quot;RxSize&quot;: 161539743,\n            &quot;TxSize&quot;: 1960171\n        },\n        &quot;Hosts&quot;: [\n            {\n                &quot;Host&quot;: &quot;112.113.115.113&quot;,\n                &quot;Port&quot;: 443,\n                &quot;RxRate&quot;: 0,\n                &quot;TxRate&quot;: 0,\n                &quot;RxSize&quot;: 840413,\n                &quot;TxSize&quot;: 172528\n            },\n            ...\n        ]\n    }\n<\/code><\/pre>\n<p>\u5206 host, \u7edf\u8ba1\u4ece\u8be5\u5730\u5740\u63a5\u6536\u7684\u5b57\u8282\u6570(RxSize), \u53d1\u9001\u5b57\u8282\u6570(TxSize), \u548c\u76f8\u5e94\u7684 rate\/s (RxRate, TxRate).<\/p>\n<p>\u9ed8\u8ba4\u53ea\u8bb0\u5f55 ip, \u53ef\u4ee5\u8bbe\u7f6e <code>&quot;stats-enable-tls-sni-sniffer&quot;: true<\/code>, \u5f00\u542f\u5bf9\u53bb\u5f80 443 \u7aef\u53e3\u7684\u6d41\u91cf\u8fdb\u884c sni sniffer, \u5c1d\u8bd5\u89e3\u6790\u51fa\u57df\u540d.\n<code>&quot;stats-enable-http-host-sniffer&quot;: true<\/code>, \u5bf9\u53d1\u5f80 80 \u7aef\u53e3\u6d41\u91cf\u5c1d\u8bd5\u89e3\u6790 http host \u5b57\u6bb5, \u4e24\u8005\u90fd\u4f1a\u7ed9\u8fde\u63a5\u5efa\u7acb\u8fc7\u7a0b\u589e\u52a0\u4e00\u4e9b overhead.<\/p>\n<p>server \u5f00\u542f stats api \u540e, \u7528 <code>.\/snet -top<\/code> \u53ef\u4ee5\u663e\u793a\u4e00\u4e2a\u7c7b\u4f3c top \u7684 terminal UI \u4f5c\u6d41\u91cf\u76d1\u63a7.<\/p>"},{"title":"\u89e3\u51b3 k8s 1.16 apiVersion deprecation \u9020\u6210\u7684 helm revision \u51b2\u7a81","link":"https:\/\/blog.monsterxx03.com\/2020\/06\/16\/%E8%A7%A3%E5%86%B3-k8s-1.16-apiversion-deprecation-%E9%80%A0%E6%88%90%E7%9A%84-helm-revision-%E5%86%B2%E7%AA%81\/","pubDate":"Tue, 16 Jun 2020 16:02:58 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/06\/16\/%E8%A7%A3%E5%86%B3-k8s-1.16-apiversion-deprecation-%E9%80%A0%E6%88%90%E7%9A%84-helm-revision-%E5%86%B2%E7%AA%81\/","description":"<p>\u6700\u8fd1\u5f00\u59cb\u628a\u7ebf\u4e0a\u7684 k8s \u4ece 1.15 \u5347\u7ea7\u5230 1.16, 1.16 \u91cc\u6709\u4e00\u4e9b api verison \u88ab\u5f7b\u5e95\u5e9f\u5f03, \u9700\u8981\u8fc1\u79fb\u5230\u65b0\u7684 api version, \u5177\u4f53\u6709: <a href=\"https:\/\/github.com\/kubernetes\/kubernetes\/blob\/master\/CHANGELOG\/CHANGELOG-1.16.md#deprecations-and-removals\">https:\/\/github.com\/kubernetes\/kubernetes\/blob\/master\/CHANGELOG\/CHANGELOG-1.16.md#deprecations-and-removals<\/a><\/p>\n<p>\u6709\u4e24\u4e2a\u95ee\u9898:<\/p>\n<ul>\n<li>\u96c6\u7fa4\u4e2d\u4f7f\u7528\u7684\u4e00\u4e9b\u7b2c\u4e09\u65b9 controller(nginx-ingress, external-dns-controller&hellip;), \u8c03\u7528\u7684 apiVersion \u9700\u8981\u5347\u7ea7.<\/li>\n<li>\u5df2\u5b58\u5728\u96c6\u7fa4\u4e2d\u7684 objects(Deployment\/ReplicaSet&hellip;), \u662f\u5426\u9700\u8981\u5904\u7406, eg: Deployment: extensions\/v1beta1 -&gt; apps\/v1.<\/li>\n<\/ul>\n<p>\u7b2c\u4e00\u4e2a\u95ee\u9898\u597d\u89e3\u51b3, \u5347\u7ea7\u4e00\u4e0b\u5bf9\u5e94\u7684 image \u7248\u672c\u5c31\u884c\u4e86, \u53ea\u8981\u8fd8\u5728\u7ef4\u62a4\u7684 controller, \u90fd\u5df2\u7ecf\u5347\u7ea7\u5230\u652f\u6301 1.16. \u81ea\u5df1\u5199\u7684\u5de5\u5177\u94fe\u4e5f\u6392\u67e5\u4e0b\u662f\u5426\u6709\u8fd8\u5728\u4f7f\u7528\u8001\u7248\u672c api \u7684, \u56e0\u4e3a\u6211\u7528\u7684\u662f aws eks, \u5f00\u4e0b <a href=\"https:\/\/docs.aws.amazon.com\/eks\/latest\/userguide\/control-plane-logs.html\">control-plane-logs<\/a> \u91cc\u7684 audit log, \u53ef\u4ee5\u770b\u8fd8\u6709\u4ec0\u4e48\u5728\u8c03\u7528\u8001\u7684 api.<\/p>\n<p>\u7b2c\u4e8c\u4e2a\u95ee\u9898\u662f\u4e0d\u9700\u8981\u6539, \u5df2\u5b58\u5728\u7684 objects \u65e0\u6cd5\u4fee\u6539 apiVersion, \u96c6\u7fa4\u5347\u7ea7\u5230 1.16 \u540e\uff0c \u4ece\u65b0\u7684 apiVersion \u91cc\u80fd pull \u5230\u4e4b\u524d\u7684\u6570\u636e, apiVersion \u5b57\u6bb5\u81ea\u52a8\u5c31\u5347\u7ea7\u4e86.<\/p>"},{"title":"\u5728 eks \u4e2d\u6b63\u786e\u8bbe\u7f6e IAM \u6743\u9650","link":"https:\/\/blog.monsterxx03.com\/2020\/04\/16\/%E5%9C%A8-eks-%E4%B8%AD%E6%AD%A3%E7%A1%AE%E8%AE%BE%E7%BD%AE-iam-%E6%9D%83%E9%99%90\/","pubDate":"Thu, 16 Apr 2020 11:03:39 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/04\/16\/%E5%9C%A8-eks-%E4%B8%AD%E6%AD%A3%E7%A1%AE%E8%AE%BE%E7%BD%AE-iam-%E6%9D%83%E9%99%90\/","description":"<p>\u5728\u4ee3\u7801\u4e2d\u8c03\u7528 aws api \u7684\u65f6\u5019\u5e38\u7528\u4e24\u79cd\u65b9\u6cd5:<\/p>\n<ul>\n<li>\u76f4\u63a5\u4f20\u5165 aws accessKey\/secretKey<\/li>\n<li>\u4f7f\u7528 instance profile<\/li>\n<\/ul>\n<p>\u524d\u8005\u4e00\u822c\u662f\u521b\u5efa\u4e00\u4e2a IAM \u7528\u6237, \u7ed1\u5b9a\u5bf9\u5e94\u6743\u9650, \u751f\u6210 keypair, \u5728 k8s \u73af\u5883\u91cc, \u628a keypair \u653e\u5728 Secrets \u91cc, \u6216\u901a\u8fc7\u73af\u5883\u53d8\u91cf\u6ce8\u5165. \u597d\u5904\u662f\u53ef\u4ee5\u6bcf\u4e2a\u5e94\u7528\u5355\u72ec\u8bbe\u7f6e,\n\u4f46\u9700\u8981\u81ea\u5df1\u7ba1\u7406 keypair.<\/p>\n<p>\u540e\u8005\u521b\u5efa\u4e00\u4e2a IAM role, \u7ed1\u5b9a\u5bf9\u5e94\u6743\u9650, \u521b\u5efa ec2 \u7684\u65f6\u5019\u9009\u62e9\u5bf9\u5e94\u7684 role. \u8dd1\u5728\u8be5 ec2 instance \u4e0a\u7684\u7a0b\u5e8f\u81ea\u52a8\u80fd\u62ff\u5230\u5bf9\u5e94\u7684 IAM \u6743\u9650. \u597d\u5904\u662f\u4e0d\u5fc5\u81ea\u5df1\u7ba1\u7406 keypair,\n\u7f3a\u70b9\u662f\u8dd1\u5728\u540c\u4e00 server \u4e0a\u7684\u7a0b\u5e8f\u6743\u9650\u90fd\u4e00\u6837.<\/p>\n<p>eks 1.14 \u91cc\u6709\u4e2a\u4e24\u5168\u9f50\u7f8e\u7684\u529e\u6cd5: serviceaccount role: <a href=\"https:\/\/docs.aws.amazon.com\/eks\/latest\/userguide\/iam-roles-for-service-accounts.html\">https:\/\/docs.aws.amazon.com\/eks\/latest\/userguide\/iam-roles-for-service-accounts.html<\/a><\/p>\n<p>\u53ef\u4ee5\u628a IAM role \u7ed1\u5b9a\u5728 pod \u4f7f\u7528\u7684 ServiceAccount \u4e0a, \u65e2\u907f\u514d\u4e86\u7ba1\u7406 keypair \u7684\u9ebb\u70e6, \u4e5f\u53ef\u4ee5 per \u5e94\u7528\u5f97\u8bbe\u7f6e\u6743\u9650.<\/p>"},{"title":"\u91cd\u6784\u63a8\u9001\u670d\u52a1","link":"https:\/\/blog.monsterxx03.com\/2020\/04\/07\/%E9%87%8D%E6%9E%84%E6%8E%A8%E9%80%81%E6%9C%8D%E5%8A%A1\/","pubDate":"Tue, 07 Apr 2020 10:54:12 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/04\/07\/%E9%87%8D%E6%9E%84%E6%8E%A8%E9%80%81%E6%9C%8D%E5%8A%A1\/","description":"<p>\u6700\u8fd1\u5bf9\u4e1a\u52a1\u91cc\u53d1\u9001 apple APNS, google FCM \u90e8\u5206\u7684\u4ee3\u7801\u8fdb\u884c\u4e86\u91cd\u6784, \u62bd\u51fa\u4e86\u4e00\u4e2a\u5355\u72ec\u7684 service, \u672c\u6587\u8bb0\u5f55\u4e0b\u6574\u4e2a\u8fc7\u7a0b.<\/p>\n<h2 id=\"\u5b58\u5728\u7684\u95ee\u9898\">\u5b58\u5728\u7684\u95ee\u9898<\/h2>\n<p>\u6211\u4eec\u6709\u597d\u51e0\u4e2a mobile app, \u6bcf\u4e2a app \u4f1a\u6709\u4e00\u5957\u5bf9\u5e94\u7684 server \u7aef service \u505a\u4e1a\u52a1\u903b\u8f91, \u56e0\u4e3a\u5386\u53f2\u539f\u56e0, \u6bcf\u4e2a service \u91cc\u9762\u5176\u5b9e\u6709\u5f88\u591a\u91cd\u590d\u4ee3\u7801, \u5927\u591a\u53ea\u662f\u4e00\u4e9b\u914d\u7f6e\u548c\u9519\u8bef\u5904\u7406\u4e0a\u6709\u5dee\u5f02.\n\u7ed9 app \u53d1\u63a8\u9001\u662f\u4e2a\u5178\u578b, \u539f\u6765\u7684\u505a\u6cd5\u662f\u5f53\u8981\u53d1\u63a8\u9001\u7684\u65f6\u5019, \u5f80 python \u7684 celery \u961f\u5217\u91cc\u6254\u4e00\u4e2a task, \u7531 celery \u5f02\u6b65\u5f97\u53bb\u53d1.<\/p>\n<p>\u6709\u5982\u4e0b\u95ee\u9898:<\/p>\n<ul>\n<li>celery \u6027\u80fd\u4e0d\u4f73, worker class \u7528\u7684\u662f gevent, \u4f46\u5728\u9ad8\u5cf0\u65f6\u5019\u4efb\u52a1\u961f\u5217\u91cc\u8fd8\u662f\u6709\u5927\u91cf pending, \u4ee3\u7801\u4e0a\u4e4b\u524d\u505a\u8fc7\u591a\u6b21\u4f18\u5316, \u4f46\u6536\u6548\u751a\u5fae.<\/li>\n<li>\u5f53 pending \u4e86\u5927\u91cf\u53d1\u63a8\u9001\u7684 task \u4e4b\u540e, \u4f1a\u5bfc\u81f4\u5176\u4ed6\u5f02\u6b65 task \u8ddf\u7740\u5ef6\u65f6, \u9020\u6210\u7528\u6237\u4f53\u9a8c\u4e0a\u7684\u4e00\u4e9b\u95ee\u9898.<\/li>\n<li>\u5386\u53f2\u4ee3\u7801\u7684\u95ee\u9898, \u6bcf\u4e2a app \u91cc\u5bf9\u63a5 APNS\/FCM \u90fd\u6709\u4e00\u5957\u5355\u72ec\u7684\u4ee3\u7801, \u5728\u90e8\u5206\u9519\u8bef\u5904\u7406\u548c\u7edf\u8ba1 metrics \u4e0a\u6709\u5dee\u5f02.<\/li>\n<\/ul>\n<h2 id=\"\u89e3\u51b3\u65b9\u6848\">\u89e3\u51b3\u65b9\u6848<\/h2>\n<ul>\n<li>\u95ee\u98981, \u76ee\u524d\u5df2\u7ecf\u8fc1\u79fb\u5230 k8s, \u5176\u5b9e\u53ef\u4ee5\u65e0\u8111\u5f00 HPA, \u505a auto scaling, \u6765\u63d0\u9ad8\u53d1\u9001\u6548\u7387. \u95ee\u9898\u662f python \u6027\u80fd\u5b9e\u5728\u592a\u5dee, \u5cf0\u503c\u65f6\u5019\u4f30\u8ba1\u4f1a scale \u5230\u539f\u5148\u7684\u597d\u591a\u500d, \u800c celery \u91cc\n\u9664\u4e86\u53d1\u63a8\u9001\u8fd8\u6709\u5f88\u591a task \u6709 db \u64cd\u4f5c, scale \u8fc7\u591a, \u4f1a\u5e26\u6765\u5176\u4ed6\u95ee\u9898, \u90a3\u662f\u53e6\u4e00\u4e2a\u95ee\u9898, \u4e0d\u60f3\u5728\u5f53\u524d\u8fd9\u4e2a\u95ee\u9898\u91cc\u89e3\u51b3.<\/li>\n<li>\u95ee\u9898\uff12, celery \u91cc\u53ef\u4ee5\u8bbe routing, \u7b80\u5355\u8bf4\u53ef\u4ee5\u7528\u5355\u72ec\u7684 celery instance \u6765\u4e13\u95e8\u5904\u7406\u63a8\u9001\u76f8\u5173 task, \u4e5f\u53ef\u4ee5\u89c4\u907f1\u91cc\u7684 db \u95ee\u9898.<\/li>\n<li>\u95ee\u98983, \u5355\u7eaf\u4ee3\u7801\u95ee\u9898, \u7edf\u4e00\u7528\u4e00\u5957\u4ee3\u7801\u91cd\u6784\u5c31\u884c\u4e86.<\/li>\n<\/ul>\n<p>\u8bb2\u771f, \u78b0\u5230\u7684 celery \u7684 bug \u5b9e\u5728\u592a\u591a\u4e86, \u5b58\u91cf\u4ee3\u7801\u7528\u7528\u5c31\u884c\u4e86, \u65b0\u505a\u4e1a\u52a1\u5b9e\u5728\u4e0d\u60f3\u7528. \u800c\u53d1\u63a8\u9001\u662f\u4e2a\u5f88\u72ec\u7acb\u7684\u4e1a\u52a1, \u6700\u540e\u6253\u7b97\u62ff go \u6765\u5355\u72ec\u8dd1\u63a8\u9001.<\/p>"},{"title":"\u7528 AWS Personalize \u505a\u63a8\u8350\u7cfb\u7edf","link":"https:\/\/blog.monsterxx03.com\/2020\/02\/18\/%E7%94%A8-aws-personalize-%E5%81%9A%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F\/","pubDate":"Tue, 18 Feb 2020 14:38:56 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/02\/18\/%E7%94%A8-aws-personalize-%E5%81%9A%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F\/","description":"<p>\u8fd9\u51e0\u5929\u6d4b\u8bd5\u4e86\u4e0b aws \u7684 personalize service, \u770b\u770b\u80fd\u4e0d\u80fd\u66ff\u6362\u6389\u4ea7\u54c1\u91cc\u73b0\u6709\u7684\u4e00\u4e9b\u63a8\u8350\u903b\u8f91.<\/p>\n<p>\u5927\u81f4\u7684\u6d41\u7a0b:<\/p>\n<ul>\n<li>\u5bfc\u5165\u6570\u636e<\/li>\n<li>\u9009\u62e9 recipe \u8fdb\u884c training, \u5f97\u5230\u4e00\u4e2a solution version<\/li>\n<li>\u9009\u62e9\u6700\u4f73 solution version \u521b\u5efa compaign<\/li>\n<li>\u8c03\u7528 api, \u6839\u636e compaign \u5f97\u5230 recommendations<\/li>\n<\/ul>\n<p>\u4e00\u4e9b iam \u6743\u9650\u76f8\u5173\u7684\u8bbe\u7f6e\u5c31\u4e0d\u5199\u4e86, \u5177\u4f53\u770b\u6587\u6863\u5427, \u8fd9\u91cc\u53ea\u8bb0\u5f55\u4e0b\u4e3b\u8981\u6b65\u9aa4.<\/p>\n<h2 id=\"\u5bfc\u5165\u6570\u636e\">\u5bfc\u5165\u6570\u636e<\/h2>\n<p>\u9996\u5148\u9700\u8981\u51c6\u5907\u7528\u6765 training \u7684\u6570\u636e, \u5206\u6210\u4e09\u79cd\u6570\u636e\u96c6:<\/p>\n<ul>\n<li>User<\/li>\n<li>Item<\/li>\n<li>User-Item interaction<\/li>\n<\/ul>\n<p>\u5176\u4e2d User-Item interaction \u662f\u5fc5\u987b\u7684 dataset, \u6240\u6709 recipe \u90fd\u4f1a\u7528\u5230, User \u548c Item \u88ab\u79f0\u4f5c metadata dataset, \u53ea\u6709\u4e2a\u522b recipe \u4f1a\u7528\u5230.<\/p>\n<p>\u6bcf\u4e2a dataset \u521b\u5efa\u7684\u65f6\u5019\u9700\u8981\u5efa\u7acb\u4e00\u4e2a schema, \u6765\u63cf\u8ff0\u5404\u81ea\u7684\u7ed3\u6784(avro \u683c\u5f0f).<\/p>\n<p>example User schema:<\/p>\n<pre><code>{\n    &quot;type&quot;: &quot;record&quot;,\n    &quot;name&quot;: &quot;Users&quot;,\u4e0e\u4e0e\n    &quot;namespace&quot;: &quot;com.amazonaws.personalize.schema&quot;,\n    &quot;fields&quot;: [\n        {\n            &quot;name&quot;: &quot;user_id&quot;,\n            &quot;type&quot;: &quot;string&quot;\n        },\n        {\n            &quot;name&quot;: &quot;birthday&quot;,\n            &quot;type&quot;: &quot;int\u4e0e\n        },\n        {\n            &quot;name&quot;: &quot;gender&quot;,\n            &quot;type&quot;: &quot;string&quot;,\n            &quot;categorical&quot;: true\n        },\n        {\n            &quot;name&quot;: &quot;location&quot;,\n            &quot;type&quot;: &quot;string&quot;,\n            &quot;categorical&quot;: true\n        }\n    ],\n    &quot;version&quot;: &quot;1.0&quot;\n}\n<\/code><\/pre>\n<p>\u5176\u4e2d <code>user_id<\/code> \u662f\u5fc5\u586b\u5b57\u6bb5, \u5176\u4ed6\u90fd\u662f\u53ef\u9009\u7684\u81ea\u5b9a\u4e49\u5b57\u6bb5, \u5176\u4ed6\u5b57\u6bb5\u5982\u679c\u662f string, \u5fc5\u987b\u52a0\u4e0a<code>&quot;categorical&quot;: true<\/code>, \u8868\u793a\u5b83\u662f\u7528\u6765\u5206\u7c7b\u7684.<\/p>"},{"title":"\u4e8c\u6708","link":"https:\/\/blog.monsterxx03.com\/2020\/02\/09\/%E4%BA%8C%E6%9C%88\/","pubDate":"Sun, 09 Feb 2020 22:22:30 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/02\/09\/%E4%BA%8C%E6%9C%88\/","description":"<p>\u8fc7\u4e86\u4e2a\u77ed\u6682\u7684\u6625\u8282, \u6015\u4e4b\u540e\u9ad8\u94c1\u4e5f\u505c\u4e86, \u65e9\u65e9\u56de\u4e86\u4e0a\u6d77.<\/p>\n<p>\u7b97\u8d77\u6765\u5230\u4eca\u5929\uff0c\u5df2\u7ecf\u6709\u534a\u4e2a\u6708\u6ca1\u548c\u4eba\u5f53\u9762\u8bf4\u4e09\u53e5\u4ee5\u4e0a\u7684\u8bdd\u4e86. \u83ab\u540d\u5f97\u8fd8\u633a\u4eab\u53d7\u7684.<\/p>\n<h2 id=\"\u6700\u8fd1\u600e\u4e48\u8fc7\u7684\">\u6700\u8fd1\u600e\u4e48\u8fc7\u7684<\/h2>\n<p>\u4e00\u89c9\u7761\u5230\u516b\u70b9\u591a\u8d77\u5e8a, \u65e9\u996d\u7092\u4e24\u4e2a\u86cb\u52a0\u4e00\u676f\u725b\u5976\uff0c \u5076\u5c14\u559d\u7ca5. \u76d2\u9a6c\u4e70\u7684\u7c73\u771f\u662f\u5de8\u8d35, \u716e\u996d\u4e5f\u6ca1\u591a\u597d\u5403, \u716e\u7ca5\u5012\u4e0d\u9519.<\/p>\n<p>\u6253\u5f00\u7535\u8111, \u5904\u7406\u70b9\u5de5\u4f5c\u6216\u770b\u770b\u65b0\u95fb, \u6069, \u57fa\u672c\u6ca1\u4ec0\u4e48\u597d\u65b0\u95fb, \u5fae\u535a\u4e0a\u8981\u4e48\u52a0\u6cb9\u4f53, \u8981\u4e48\u6495\u903c, \u90fd\u662f\u4fe1\u606f\u5783\u573e, \u4e0d\u8bc4\u8bba\u4e86.<\/p>\n<p>\u65b0\u4e70\u7684\u684c\u5b50\u4e0d\u592a\u884c,\u4fbf\u5b9c\u6ca1\u597d\u8d27\u54e6, \u6253\u5b57\u7528\u529b\u70b9\u90fd\u4f1a\u6643, \u8003\u8651\u628a\u9910\u684c\u62ff\u6765\u529e\u516c, \u8fd9\u5f20\u684c\u5b50\u5403\u996d\u5427.<\/p>"},{"title":"\u7f16\u5199 postmortem","link":"https:\/\/blog.monsterxx03.com\/2020\/01\/18\/%E7%BC%96%E5%86%99-postmortem\/","pubDate":"Sat, 18 Jan 2020 15:20:47 +0800","guid":"https:\/\/blog.monsterxx03.com\/2020\/01\/18\/%E7%BC%96%E5%86%99-postmortem\/","description":"<p>\u6210\u529f\u7684\u7ecf\u9a8c\u603b\u662f\u5e26\u6709\u70b9\u8fd0\u6c14\u6210\u4efd, \u5931\u8d25\u5219\u662f\u5fc5\u7136\u7684:). \u5de5\u4f5c\u4e2d\uff0c \u7ebf\u4e0a\u73af\u5883\u7684\u95ee\u9898\u5343\u5947\u767e\u602a, \u6709\u7684\u6765\u81ea\u81ea\u5df1\u4ee3\u7801 bug, \u6709\u7684\u662f\u914d\u7f6e\u9519\u8bef, \u6709\u65f6\u5019\u662f\u7b2c\u4e09\u65b9\u7684 vendor \u6210\u4e86\u732a\u961f\u53cb. \u5bf9\u4e8e\u4e00\u4e9b\u6392\u67e5\u8fc7\u7a0b\u6bd4\u8f83\u56f0\u96be\u6216\u5177\u6709\u4ee3\u8868\u6027\u7684\u95ee\u9898, \u9700\u8981\u8bb0\u5f55\u4e0b\u6765, \u4e00\u822c\u628a\u8fd9\u4e2a\u8fc7\u7a0b\u53eb\u505a postmortem(\u9a8c\u5c38).<\/p>\n<p>\u8fd9\u7bc7\u5199\u4e00\u4e0b\u81ea\u5df1\u505a postmortem \u7684\u8fc7\u7a0b, \u5e76\u8bb0\u5f55\u4e00\u4e2a\u6700\u8fd1\u5904\u7406\u7684\u6545\u969c.<\/p>\n<h2 id=\"postmortem-process\">Postmortem process<\/h2>\n<p>\u6211\u5927\u4f53\u5206\u4ee5\u4e0b\u51e0\u4e2a\u90e8\u5206:<\/p>\n<ul>\n<li>\u7528\u5c3d\u91cf\u7b80\u7ec3\u7684\u8bed\u53e5\u63cf\u8ff0\u6e05\u695a\u5728\u4ec0\u4e48\u65f6\u95f4\u53d1\u751f\u4e86\u4ec0\u4e48,\u8c01\u53c2\u4e0e\u4e86\u95ee\u9898\u7684\u5904\u7406(when, what, who)?<\/li>\n<li>\u8be6\u7ec6\u63cf\u8ff0\u89e3\u51b3\u95ee\u9898\u7684\u8fc7\u7a0b, \u5305\u62ec\u4f46\u4e0d\u9650\u4e8e:  debug \u7684\u8fc7\u7a0b, \u4e2d\u95f4\u7684\u63a8\u6d4b, \u7528\u5230\u7684\u5de5\u5177&hellip; (How)<\/li>\n<li>\u5982\u679c\u627e\u5230\u4e86 root case, \u8bb0\u5f55\u4e0b\u6765, \u6ca1\u627e\u5230, \u8bb0\u5f55\u4e0b\u5f53\u65f6\u7684 workaround, \u6709\u4ec0\u4e48\u526f\u4f5c\u7528. (Why)<\/li>\n<\/ul>\n<h2 id=\"postmortem-case\">Postmortem case<\/h2>\n<p>\u5b9e\u9645\u7684 postmorten \u5199\u5f97\u66f4\u7b80\u5355\u4e00\u70b9, \u8fd9\u91cc\u628a\u8fc7\u7a0b\u4e2d\u7684\u4e00\u4e9b\u601d\u8003\u4e5f\u8bb0\u4e0b\u6765.<\/p>"},{"title":"\u804a\u804a AWS \u7684\u8ba1\u8d39\u6a21\u5f0f","link":"https:\/\/blog.monsterxx03.com\/2019\/12\/30\/%E8%81%8A%E8%81%8A-aws-%E7%9A%84%E8%AE%A1%E8%B4%B9%E6%A8%A1%E5%BC%8F\/","pubDate":"Mon, 30 Dec 2019 12:08:47 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/12\/30\/%E8%81%8A%E8%81%8A-aws-%E7%9A%84%E8%AE%A1%E8%B4%B9%E6%A8%A1%E5%BC%8F\/","description":"<p>\u7f51\u4e0a\u7ecf\u5e38\u6709\u4eba\u8bdf\u75c5 AWS \u7684\u8ba1\u8d39\u6a21\u5f0f\u590d\u6742, \u559c\u6b22\u56fd\u5185\u90a3\u79cd\u6253\u5305\u5f0f\u7684\u552e\u5356\u65b9\u5f0f, \u8fd9\u4e2a\u53ef\u80fd\u53d7\u9650\u4e8e\u6bcf\u4e2a\u516c\u53f8\u7684\u8d22\u52a1\u6d41\u7a0b, \u9884\u7b97\u5236\u5b9a\u65b9\u5f0f, \u5408\u4e0d\u5408\u56fd\u60c5,\u672c\u6587\u4e0d\u8ba8\u8bba.\n\u4ec5\u4ece\u5f00\u53d1\u8005\u7684\u89d2\u5ea6\u4ecb\u7ecd\u4e0b AWS \u90e8\u5206\u5e38\u7528 service \u7684\u8ba1\u8d39\u65b9\u5f0f.<\/p>\n<p>PS: \u90a3\u4e9b\u4e3a\u4e86\u8e6d\u4e00\u5e74 free plan \u7136\u540e\u62b1\u6028\u4ec0\u4e48\u5077\u8dd1\u6d41\u91cf, \u5077\u5077\u6263\u8d39\u7684\u5927\u54e5\u5c31\u7701\u7701\u5427, AWS \u6839\u672c\u4e0d\u662f\u7ed9\u4e2a\u4eba\u7528\u7684, \u8001\u8001\u5b9e\u5b9e\u7528 lightsail \u5f97\u4e86.<\/p>\n<h2 id=\"ec2\">EC2<\/h2>\n<p>EC2 \u7684\u4ef7\u683c\u662f\u6700\u590d\u6742\u7684, \u4e00\u53f0 EC2 instance \u7684\u4ef7\u683c\u7ec4\u6210:<\/p>\n<ul>\n<li>instance fee, \u5b9e\u9645\u652f\u4ed8\u7684\u662f CPU+RAM \u7684\u8d39\u7528<\/li>\n<li>EBS fee, server \u7684\u6839\u5206\u533a\u90fd\u662f EBS volume, \u6309 EBS \u8ba1\u8d39(31GB \u7684 volume \u4f7f\u7528 1 \u5c0f\u65f6, \u548c 1GB \u7684volume \u4f7f\u7528 744 \u5c0f\u65f6\u4ef7\u683c\u76f8\u540c).<\/li>\n<li>data transfer fee, \u8fd9\u90e8\u5206\u7ec4\u6210\u6bd4\u8f83\u590d\u6742\uff0c\u7b80\u5355\u8bb2, \u5165\u6d41\u91cf\u514d\u8d39, \u51fa\u6d41\u91cf\u6309 GiB \u8ba1\u8d39, \u5982\u679c\u51fa\u6d41\u91cf\u662f\u5230 AWS \u5176\u4ed6 region, \u4ef7\u683c\u6bd4\u4e00\u822c\u516c\u7f51\u4fbf\u5b9c, \u5728\u5185\u7f51\u4f20\u8f93\u6d41\u91cf, \u540c\u4e00\u4e2a available zone \u662f\u514d\u8d39\u7684,\n\u8de8 az \u6536\u8d39.<\/li>\n<li>EIP fee, \u6bcf\u53f0 instance \u6302\u4e00\u4e2a EIP \u662f\u514d\u8d39\u7684(eip \u4f7f\u7528\u72b6\u6001\u4e0d\u6536\u8d39, \u95f2\u7f6e\u6536\u8d39), \u8d85\u8fc7\u4e00\u4e2a eip, \u6bcf\u4e2a\u6309\u5c0f\u65f6\u518d\u6536\u8d39.<\/li>\n<\/ul>\n<p>instance fee \u53c8\u5206 on-demand\/resersed\/spot instance.<\/p>"},{"title":"snet dev note","link":"https:\/\/blog.monsterxx03.com\/2019\/11\/29\/snet-dev-note\/","pubDate":"Fri, 29 Nov 2019 12:00:01 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/11\/29\/snet-dev-note\/","description":"<p><a href=\"https:\/\/github.com\/monsterxx03\/snet\">snet<\/a>: 0.5 ~ 0.6.1, \u6574\u7406\u4ece<a href=\"https:\/\/blog.monsterxx03.com\/2019\/06\/20\/snet-dev-note-support-macos\/\">\u4e0a\u4e00\u7bc7<\/a>\u4ee5\u6765\u7684\u4e00\u4e9b\u66f4\u65b0.<\/p>\n<h2 id=\"\u65b0\u589e\u9009\u9879\">\u65b0\u589e\u9009\u9879<\/h2>\n<p><code>proxy-scope<\/code>, \u9ed8\u8ba4 <code>bypassCN<\/code>, \u53ef\u9009 <code>global<\/code>. <code>bypassCN<\/code> \u4f1a\u505a\u56fd\u5185\u5916\u5206\u6d41, <code>global<\/code> \u76f4\u63a5\u8ba9\u6240\u6709\u6d41\u91cf\u53bb\u5f80\u56fd\u5916.<\/p>\n<p><code>host-map<\/code>, \u4e3a\u57df\u540d\u6307\u5b9a ip. \u4e4b\u524d\u5728\u6d4b\u8bd5\u4e00\u4e2a\u529f\u80fd\u7684\u65f6\u5019\u9700\u8981\u5728\u5185\u7f51\u8ba9\u624b\u673a\u5bf9\u67d0\u4e2a\u57df\u540d\u7684\u89e3\u6790\u5207\u6362\u5230\u6211\u7684\u6d4b\u8bd5 ip \u4e0a, \u5751\u7239\u7684\u662f\u516c\u53f8\u7684\u8def\u7531\u5668\u7adf\u7136\u6ca1\u8fd9\u529f\u80fd, \u7d22\u6027\u5728 snet \u91cc\u5199\u4e86\u8fd9\u4e2a\u529f\u80fd, \u8ba9\u6211\u7684\u53f0\u5f0f\u673a\u53d1\u5c04 wifi, \u624b\u673a\u8fde\u4e0a\u6765, snet \u7684 <code>mode<\/code> \u5207\u6362\u6210 <code>router<\/code>, <code>listen-host<\/code> \u6539\u4e3a <code>0.0.0.0<\/code> \u5c31\u597d\u4e86.<\/p>\n<p><code>block-hosts<\/code>, \u56e0\u4e3a <code>block-host-file<\/code> \u91cc\u7684\u57df\u540d\u662f\u4ece\u4e00\u4e2a\u73b0\u6210\u7684\u5217\u8868\u751f\u6210\u51fa\u6765\u7684, \u4e0d\u597d\u652f\u6301\u901a\u914d\u7b26, \u6240\u4ee5\u52a0\u4e86\u8fd9\u4e2a, \u6bd4\u5982 <code>[&quot;*.hpplay.cn&quot;]<\/code>, \u5c31\u80fd\u628a\u7535\u89c6\u4e0a\u6240\u6709\u4e50\u64ad\u6295\u5c4f\u7684\u5e7f\u544a\u5e72\u6389.<\/p>\n<p><code>proxy-type<\/code> \u65b0\u589e <code>tls<\/code>, \u4e00\u4e2a\u57fa\u4e8e tls \u7684\u7b80\u5355\u81ea\u5b9a\u4e49\u534f\u8bae, \u4f7f\u7528\u8fd9\u4e2a\u9700\u8981\u90e8\u7f72\u4e00\u4e2a snet \u7684 server \u7aef, \u8be6\u7ec6\u770b README \u5427.<\/p>"},{"title":"11\u6708","link":"https:\/\/blog.monsterxx03.com\/2019\/11\/24\/11%E6%9C%88\/","pubDate":"Sun, 24 Nov 2019 22:31:42 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/11\/24\/11%E6%9C%88\/","description":"<p>\u524d\u4e24\u5929\u843d\u6795\u4e86, \u8d77\u5e8a\u540e\u8116\u5b50\u7279\u522b\u75bc, \u4e45\u5750\u4e0d\u52a8\u7684\u6076\u679c, \u8fd9\u5468\u672b\u53bb\u4e86\u9644\u8fd1\u4e00\u5bb6\u76f2\u4eba\u6309\u6469\u63a8\u62ff\u4e86\u4e00\u4e0b, \u8212\u5766\u4e86\u4e0d\u5c11, \u8fd9\u8fd8\u662f\u7b2c\u4e00\u6b21\u8fd1\u8ddd\u79bb\u63a5\u89e6\u4e00\u4e2a\u76f2\u4eba, \u611f\u89e6\u9887\u6df1.<\/p>\n<p>\u7ed9\u6211\u63a8\u62ff\u7684\u662f\u4e2a\u5927\u59d0, \u5927\u6211\u51e0\u5c81, \u521a\u8fdb\u95e8\u7684\u65f6\u5019\u6211\u8fd8\u6ca1\u610f\u8bc6\u5230\u5979\u662f\u4e2a\u76f2\u4eba, \u52a8\u4f5c\u7279\u522b\u5229\u843d, \u5c4b\u91cc\u4e5f\u6536\u62fe\u5f97\u4e95\u4e95\u6709\u6761(\u60ed\u6127!), \u76f4\u5230\u770b\u5230\u5979\u7528\u624b\u673a\u624d\u786e\u5b9a\u662f\u771f\u7684\u770b\u4e0d\u89c1.\n\u4e00\u822c\u5728\u5916\u9762\u6211\u4e0d\u592a\u559c\u6b22\u548c\u5e97\u5458\u642d\u8bdd, \u6bd4\u5982\u7406\u53d1\u5e08\u8bdd\u591a\u7684\u8bdd\u7edd\u5bf9\u4e0d\u4f1a\u53bb\u7b2c\u4e8c\u6b21, \u8fd9\u6b21\u867d\u7136\u5bf9\u76f2\u4eba\u7684\u751f\u6d3b\u6709\u70b9\u597d\u5947, \u4e5f\u6ca1\u591a\u95ee, \u4e0d\u6e05\u695a\u5979\u662f\u5148\u5929\u8fd8\u662f\u540e\u5929,\n\u662f\u5426\u5168\u76f2\u8fd8\u662f\u6709\u5149\u611f. \u8ffd\u7740\u4eba\u5bb6\u95ee\u8fd9\u4e9b\u4e5f\u4e0d\u592a\u793c\u8c8c.<\/p>"},{"title":"\u96c6\u6210 opentracing","link":"https:\/\/blog.monsterxx03.com\/2019\/11\/15\/%E9%9B%86%E6%88%90-opentracing\/","pubDate":"Fri, 15 Nov 2019 14:05:59 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/11\/15\/%E9%9B%86%E6%88%90-opentracing\/","description":"<p>\u4e4b\u524d\u7528\u8fc7 datadog \u7684 tracing \u529f\u80fd, \u975e\u5e38\u597d\u7528, \u4f46\u662f\u5f88\u8d35(\u5355\u53f030$), \u8fc1\u79fb\u5230 k8s \u540e, \u76d1\u63a7\u8fc1\u79fb\u5230\u4e86 prometheus, \u4e5f\u628a datadog \u7684 tracing \u53bb\u6389\u4e86.datadog \u7684 tracing \u4e5f\u662f opentracing \u7684\u4e00\u79cd\u5b9e\u73b0, \u7d22\u6027\u5c31\u6362\u4e0a\u5f00\u6e90\u5b9e\u73b0.<\/p>\n<p>tracing \u7cfb\u7edf\u662f\u5206\u5e03\u5f0f\u7cfb\u7edf\u4e2d\u5f88\u597d\u7528\u7684 performance tuning \u5de5\u5177, opentracing \u53ea\u662f\u4e00\u4e2a\u6807\u51c6\uff0c\u91cc\u9762\u5b9a\u4e49\u4e86 span, scope, tracer \u7b49\u6982\u5ff5\uff0c\u4f46\u4e0d\u89c4\u5b9a tracing\n\u6570\u636e\u5e94\u8be5\u600e\u4e48 encoding, \u600e\u4e48\u5b58\u50a8, \u8de8\u8fdb\u7a0b\u7684 span \u6570\u636e\u600e\u4e48\u4e32\u8d77\u6765.<\/p>\n<p>\u9996\u5148\u8981\u6311\u9009\u4e00\u4e2a\u5f00\u6e90\u7684 tracer \u5b9e\u73b0\uff0ctracer \u7528\u6765\u63a5\u53d7\u4e1a\u52a1\u7cfb\u7edf\u53d1\u51fa\u7684 encode \u8fc7\u7684 span \u6570\u636e,\u5e76\u5b58\u50a8\uff0c\u63d0\u4f9b\u4e00\u4e2a\u754c\u9762\u4f9b\u67e5\u8be2. \u6211\u9009\u7684\u662f jaeger, go\u5b9e\u73b0\u7684,\u90e8\u7f72\u8d77\u6765\u6bd4\u8f83\u8f7b\u91cf\u7ea7,\n\u4e5f\u662f cncf \u7684\u9879\u76ee, \u8fd8\u6709\u4e2a jaeger-operator \u65b9\u4fbf\u90e8\u7f72.<\/p>"},{"title":"\u8001\u4ee3\u7801\u91cc\u548c MySQL \u7684\u4e8b\u52a1\u9694\u79bb\u76f8\u5173\u7684\u4e00\u4e2abug","link":"https:\/\/blog.monsterxx03.com\/2019\/10\/31\/%E8%80%81%E4%BB%A3%E7%A0%81%E9%87%8C%E5%92%8C-mysql-%E7%9A%84%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%9B%B8%E5%85%B3%E7%9A%84%E4%B8%80%E4%B8%AAbug\/","pubDate":"Thu, 31 Oct 2019 11:45:44 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/10\/31\/%E8%80%81%E4%BB%A3%E7%A0%81%E9%87%8C%E5%92%8C-mysql-%E7%9A%84%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%9B%B8%E5%85%B3%E7%9A%84%E4%B8%80%E4%B8%AAbug\/","description":"<p>\u8fd9\u4e24\u5929\u5728\u8c03\u8bd5\u4ee3\u7801\u7684\u65f6\u5019, \u53d1\u73b0 db \u5c42\u7684\u4ee3\u7801\u5728\u6bcf\u6b21\u628a connection \u653e\u56de db pool \u7684\u65f6\u5019,\u5373\u4f7f\u4e4b\u524d\u6267\u884c\u7684\u662f select \u8bed\u53e5,\u4e5f\u4f1a rollback \u4e00\u4e0b,\n\u8fd9\u4ee3\u7801\u5f88\u53e4\u8001, \u6211\u4e5f\u4e0d\u77e5\u9053\u4e3a\u5565, \u5c1d\u8bd5\u628a rollback \u53bb\u6389, \u7ed3\u679c\u5355\u5143\u6d4b\u8bd5\u6302\u4e86\u4e00\u5806, \u5927\u591a\u90fd\u662f\u6570\u636e\u4e0d\u4e00\u81f4\u7684\u95ee\u9898, debug \u4e86\u4e00\u4e0b, \u6700\u540e\u53d1\u73b0\u8fd9\u5751\u8fd8\u633a\u5927\u7684.<\/p>\n<p>\u4e3a\u4ec0\u4e48\u53bb\u6389 select \u7684 rollback \u540e\u4f1a\u51fa\u73b0\u6570\u636e\u4e0d\u4e00\u81f4?<\/p>\n<p>pymysql \u9ed8\u8ba4\u5173\u95ed\u4e86 autocommit, connection A \u8fdb\u884c select \u4e4b\u540e, \u5176\u5b9e MySQL \u5185\u90e8\u4e3a select \u4e5f\u5f00\u542f\u4e86\u4e00\u4e2a transaction(Repeatable Read),\n\u53ef\u4ee5\u901a\u8fc7 <code>SELECT * FROM information_schema.innodb_trx\\G<\/code>  \u67e5\u770b.<\/p>\n<p>\u6240\u4ee5\u5f53 connection A \u5148 select \u4e00\u6b21, connection B \u5728 transaction \u5185\u66f4\u65b0\u6570\u636e\u5e76 commit, connection A \u518d\u6b21 select (\u4e4b\u524d\u7684 transaction \u5e76\u6ca1 rollback \u6216 commit),\n\u5f97\u5230\u4e86\u8001\u7684\u6570\u636e. MySQL \u5728 repeatable read \u4e0b, \u4e3a\u4e86 consistent read \u4f1a\u4f7f\u7528\u4e00\u4e2a snapshot, \u65f6\u95f4\u662f\u7b2c\u4e00\u6b21 read \u53d1\u751f\u7684\u65f6\u95f4: <a href=\"https:\/\/dev.mysql.com\/doc\/refman\/5.7\/en\/glossary.html#glos_consistent_read\">https:\/\/dev.mysql.com\/doc\/refman\/5.7\/en\/glossary.html#glos_consistent_read<\/a><\/p>"},{"title":"gospy dev note","link":"https:\/\/blog.monsterxx03.com\/2019\/09\/29\/gospy-dev-note\/","pubDate":"Sun, 29 Sep 2019 15:07:11 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/09\/29\/gospy-dev-note\/","description":"<p><a href=\"https:\/\/blog.monsterxx03.com\/2019\/09\/20\/gospy-non-invasive-goroutine-inspector\/\">\u524d\u6587<\/a>\u8bb2\u4e86\u4e0b gospy \u7684\u5927\u81f4\u7528\u6cd5, \u8fd9\u7bc7\u8bb0\u5f55\u5177\u4f53\u5b9e\u73b0\u548c\u8fc7\u7a0b\u4e2d\u78b0\u5230\u7684\u4e00\u4e9b\u95ee\u9898.<\/p>\n<h2 id=\"\u539f\u7406\">\u539f\u7406<\/h2>\n<p>\u8981\u4ece\u5916\u90e8\u83b7\u53d6 golang \u8fdb\u7a0b\u7684 runtime \u4fe1\u606f, \u9700\u8981\u505a\u5f97\u662f\u4ece\u8fdb\u7a0b\u7684 binary \u4e2d\u7684 debug \u4fe1\u606f\u91cc parse \u51fa\u9700\u8981\u7684\u4e00\u4e9b\u53d8\u91cf\u7684\u865a\u62df\u5185\u5b58\u5730\u5740, \u8bfb\u53d6\u76ee\u6807\u8fdb\u7a0b\u7684\u5185\u5b58, \u5f97\u5230\u76f8\u5e94\u7684\u6570\u636e,\n\u5c06\u4e24\u8005\u6620\u5c04\u8d77\u6765\u5c31\u597d\u4e86.\u53ea\u652f\u6301\u4e86 linux \u4e0a\u7684 ELF \u683c\u5f0f binary, debug \u4fe1\u606f\u662f go \u5728\u7f16\u8bd1\u65f6\u5019\u5f04\u8fdb\u53bb\u7684, \u683c\u5f0f\u662f\u901a\u7528\u7684 DWARF.<\/p>\n<p>ELF \u548c DWARF \u683c\u5f0f\u672c\u8eab\u4e0d\u7ec6\u7a76(\u6c57, \u6587\u6863\u51e0\u767e\u9875\u4e5f\u5b9e\u5728\u770b\u4e0d\u52a8), go \u6807\u51c6\u5e93\u91cc\u81ea\u5e26\u76f8\u5e94\u7684 parser: <code>debug\/elf, debug\/dwarf, debug\/gosym<\/code>. \u4e00\u4e2a\u57fa\u672c\u7684\u8bfb\u53d6\u4f8b\u5b50:<\/p>\n<pre><code>f, _ := os.Open(path)\nb, _ := elf.NewFile(f)\nlndata, _ := b.Section(&quot;.gopclntab&quot;).Data()\nln := gosym.NewLineTable(lndata, b.Section(&quot;.text&quot;).Addr)\nsymtab, _ := gosym.NewTable([]byte{}, ln)\n<\/code><\/pre>\n<p>\u5728 go 1.3 \u4e4b\u524d, elf binary \u91cc\u6709\u4e00\u8282 session: <code>.gosymtab<\/code>, 1.3 \u5f00\u59cb\u4e0d\u9700\u8981\u4e86,\u3000\u4e3a\u4e86 api \u517c\u5bb9, <code>gosym.NewTable<\/code> \u8fd8\u9700\u8981\u8fd9\u4e2a\u53c2\u6570,\u4f20\u4e2a\u7a7a\u3000byte slice \u8fdb\u53bb\u5c31\u884c.<\/p>"},{"title":"\u5272\u88c2\u611f","link":"https:\/\/blog.monsterxx03.com\/2019\/09\/26\/%E5%89%B2%E8%A3%82%E6%84%9F\/","pubDate":"Thu, 26 Sep 2019 16:05:05 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/09\/26\/%E5%89%B2%E8%A3%82%E6%84%9F\/","description":"<p>\u9898\u6587\u65e0\u5173.<\/p>\n<h2 id=\"\u697c\u4e0b\u963f\u59e8\">\u697c\u4e0b\u963f\u59e8<\/h2>\n<p>\u4e09\u697c\u4f4f\u4e86\u4e00\u5bf9\u8001\u592b\u59bb, \u4e08\u592b\u8eab\u4f53\u4e0d\u597d, \u4e0d\u600e\u4e48\u51fa\u95e8, \u963f\u59e8\u5012\u662f\u5f88\u7cbe\u795e, \u5929\u5929\u6e9c\u8fbe, \u5076\u5c14\u4f1a\u4e0a\u6765\u95ee\u6211\u4e9b\u7528\u624b\u673a\u7684\u4e8b\u60c5. \u963f\u59e8\u4eba\u633a\u597d, \u5c31\u662f\u603b\u60f3\u7740\u6361\u4e9b\u5c0f\u4fbf\u5b9c, \u90a3\u4e2a\u5e74\u4ee3\u8fc7\u6765\u7684\u4eba\u90fd\u8fd9\u6837, \u65e0\u53ef\u539a\u975e.<\/p>\n<p>\u67d0\u65e5, \u62ff\u7740\u624b\u673a\u7ed9\u6211\u770b\u67d0\u57fa\u91d1\u7684\u516c\u4f17\u53f7, \u8bf4\u662f\u53ef\u4ee5\u9886\u7ea2\u5305, \u610f\u5174\u9611\u73ca\u5f97\u5e2e\u5979\u770b\u4e86\u4e0b, \u5927\u81f4\u610f\u601d\u662f\u5728\u516c\u4f17\u53f7\u4e0b\u7559\u8a00, \u8bb0\u5f55\u81ea\u5df1\u5728\u8fd9\u4e2a\u57fa\u91d1\u7684\u6295\u8d44\u6545\u4e8b,\n\u62bd\u53d6\u5199\u5f97\u597d\u7684\u53d1\u7ea2\u5305&hellip;\u6211\u5c31\u544a\u8bc9\u5979, \u8fd9\u4e2a\u57fa\u672c\u662f\u6ca1\u5565\u53ef\u80fd\u88ab\u62bd\u4e2d\u7684(\u6211\u4e5f\u4e0d\u53ef\u80fd\u5e2e\u4f60\u7f16\u4e00\u7bc7\u5c0f\u4f5c\u6587\u554a), \u963f\u59e8\u8fd8\u662f\u575a\u6301\u8981\u5199, \u8bf4\u5c31\u5199:&ldquo;\u8fd9\u4e2a\u57fa\u91d1\u633a\u597d\u7684, \u867d\u7136\u5230\u73b0\u5728\u8fd8\u662f\u4e8f\u635f\u7684.&rdquo;, \u770b\u7740\u963f\u59e8\u4e00\u8138\u771f\u631a\u7684\u6837\u5b50, \u60a8\u771f\u7684\u4e0d\u662f\u53cd\u4e32\u9ed1\u5417???<\/p>"},{"title":"gospy: Non-invasive goroutine inspector","link":"https:\/\/blog.monsterxx03.com\/2019\/09\/20\/gospy-non-invasive-goroutine-inspector\/","pubDate":"Fri, 20 Sep 2019 14:07:12 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/09\/20\/gospy-non-invasive-goroutine-inspector\/","description":"<p>go \u81ea\u5e26\u7684 profiling \u5de5\u5177\u5f88\u5f3a\u5927(pprof, trace, GODEBUG &hellip;), \u4f46\u6709\u65f6\u6211\u8fd8\u662f\u60f3\u4e0d\u4fee\u6539\u76ee\u6807\u8fdb\u7a0b\u7684\u6e90\u7801\u83b7\u53d6\u5b83\u7684\u4e00\u4e9b\nruntime \u4fe1\u606f, \u6700\u8fd1\u7814\u7a76\u4e86\u4e00\u4e0b py-spy \u548c delve, \u53d1\u73b0\u8fd8\u662f\u53ef\u5b9e\u73b0\u7684, \u5c31\u505a\u4e86\u4e2a\u5c0f\u4e1c\u897f<a href=\"https:\/\/github.com\/monsterxx03\/gospy\">gospy<\/a>.<\/p>\n<h2 id=\"\u7528\u6cd5\">\u7528\u6cd5<\/h2>\n<p>\u76ee\u524d\u5c31\u4e24\u4e2a\u547d\u4ee4: <code>gospy summary<\/code> \u548c <code>gospy top<\/code><\/p>\n<p><code>sudo .\/gospy summary --pid 1234<\/code>, \u53ef\u4ee5 dump \u76ee\u6807\u8fdb\u7a0b\u7684\u4e00\u4e9b\u4fe1\u606f\u548c\u5f53\u524d\u6d3b\u52a8 goroutine \u6b63\u5728\u6267\u884c\u7684\u51fd\u6570\u4fe1\u606f,\n\u6bd4\u5982\u5bf9\u4e00\u4e2a prometheus \u8fdb\u7a0b\u505a\u4e00\u6b21 snapshot:<\/p>\n<pre><code>bin: \/home\/will\/Downloads\/prometheus-2.12.0.linux-amd64\/prometheus, goVer: 1.12.8, gomaxprocs: 6\nP0 idle, schedtick: 642, syscalltick: 81\nP1 idle, schedtick: 959, syscalltick: 67\nP2 idle, schedtick: 992, syscalltick: 32\nP3 idle, schedtick: 581, syscalltick: 17\nP4 idle, schedtick: 89, syscalltick: 8\nP5 idle, schedtick: 231, syscalltick: 5\nThreads: 14 total, 0 running, 14 sleeping, 0 stopped, 0 zombie\nGoroutines: 44 total, 0 idle, 0 running, 5 syscall, 39 waiting\n\ngoroutines:\n\n1 - waiting for chan receive: rt0_go (\/usr\/local\/go\/src\/runtime\/asm_amd64.s:202) \n2 - waiting for force gc (idle): 5 (\/usr\/local\/go\/src\/runtime\/proc.go:240) \n3 - waiting for GC sweep wait: gcenable (\/usr\/local\/go\/src\/runtime\/mgc.go:209) \n8 - syscall: addtimerLocked (\/usr\/local\/go\/src\/runtime\/time.go:169) \n9 - waiting for select: 0 (\/app\/vendor\/go.opencensus.io\/stats\/view\/worker.go:33) \n16 - waiting for GC worker (idle): gcBgMarkStartWorkers (\/usr\/local\/go\/src\/runtime\/mgc.go:1785) \n17 - waiting for finalizer wait: createfing (\/usr\/local\/go\/src\/runtime\/mfinal.go:156) \n19 - syscall: 0 (\/usr\/local\/go\/src\/os\/signal\/signal_unix.go:30) \n22 - waiting for GC worker (idle): gcBgMarkStartWorkers (\/usr\/local\/go\/src\/runtime\/mgc.go:1785) \n23 - waiting for GC worker (idle): gcBgMarkStartWorkers (\/usr\/local\/go\/src\/runtime\/mgc.go:1785) \n38 - waiting for GC worker (idle): gcBgMarkStartWorkers (\/usr\/local\/go\/src\/runtime\/mgc.go:1785) \n49 - waiting for GC worker (idle): gcBgMarkStartWorkers (\/usr\/local\/go\/src\/runtime\/mgc.go:1785) \n50 - waiting for GC worker (idle): gcBgMarkStartWorkers (\/usr\/local\/go\/src\/runtime\/mgc.go:1785) \n74 - waiting for select: sync (\/app\/scrape\/scrape.go:408) \n75 - syscall: addtimerLocked (\/usr\/local\/go\/src\/runtime\/time.go:169) \n84 - syscall: addtimerLocked (\/usr\/local\/go\/src\/runtime\/time.go:169) \n85 - waiting for select: Run (\/app\/vendor\/github.com\/oklog\/run\/group.go:36) \n...\n<\/code><\/pre>\n<p>P0, P1 &hellip;, \u662f go \u7684 GMP schedule \u6a21\u578b\u91cc\u7684 P, \u53ef\u4ee5\u7b80\u5355\u7406\u89e3\u6210\u5bf9\u4e00\u4e2a\u7269\u7406\u6838\u5fc3\u7684\u903b\u8f91\u62bd\u8c61. \u4e2a\u6570\u53ef\u7531\u73af\u5883\u53d8\u91cf GOMAXPROCS \u63a7\u5236,\n\u9ed8\u8ba4\u662f\u673a\u5668\u6838\u5fc3\u6570.<\/p>"},{"title":"\u6742","link":"https:\/\/blog.monsterxx03.com\/2019\/08\/16\/%E6%9D%82\/","pubDate":"Fri, 16 Aug 2019 15:00:02 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/08\/16\/%E6%9D%82\/","description":"<p>\u968f\u8bb0.<\/p>\n<h2 id=\"life\">Life<\/h2>\n<p><code>&lt;\u706b\u7130\u6587\u7ae0-\u98ce\u82b1\u96ea\u6708&gt;<\/code> \u6d41\u7a0b\u8fc7\u534a, \u8fd9\u4e00\u4f5c\u96be\u5ea6\u786e\u5b9e\u4f4e, \u6002\u5982\u6211\u73a9\u7684\u53c8\u662f\u4e0d\u6b7b\u4eba\u6a21\u5f0f, \u5373\u4f7f\u662f\u56f0\u96be\u96be\u5ea6, \u5230\u540e\u9762\u4e5f\u662f\u5207\u83dc. \u6d41\u7a0b\u91cc\u5b66\u751f\u4eec seisei \u5f97\u558a, \u60f3\u5230\u540e\u9762\u8981\u628a\u4ed6\u4eec\u4e00\u4e2a\u4e2a\u5e72\u6389, \u5fc3\u60c5\u633a\u590d\u6742\u5f97&hellip;\n\u98ce\u82b1\u96ea\u6708\u8fd9\u4e2a\u526f\u6807\u9898, \u73a9\u7740\u73a9\u7740\u4e5f\u6709\u70b9\u660e\u767d\u610f\u601d\u4e86, \u7f8e\u7248\u7adf\u7136\u53eb <code>&lt;Three houses&gt;<\/code>, \u8001\u5916\u795e\u7ecf\u679c\u7136\u50bb\u5927\u7c97\u554a&hellip;<\/p>\n<p>\u897f\u6cfd\u4fdd\u5f66\u7684\u9ad8\u5343\u548c\u5343\u6653\u7cfb\u5217\u770b\u5b8c\u4e86\u597d\u51e0\u672c, \u8fd8\u5269\u4e0b<code>&lt;\u4f9d\u5b58&gt;<\/code> \u548c <code>&lt;\u5564\u9152\u4e4b\u5bb6\u7684\u5192\u9669&gt;<\/code>. \u6628\u665a\u8bfb\u5b8c\u4e86 <code>&lt;\u82cf\u683c\u5170\u6e38\u620f&gt;<\/code>, \u5267\u60c5\u9ad8\u5f00\u4f4e\u8d70, \u524d\u534a\u6bb5\u7684\u8ff7\u9898\u548c\u60ac\u5ff5\u8bbe\u7f6e\u582a\u79f0\u7cfb\u5217\u4e4b\u6700, \u6211\u90fd\u60f3\u5927\u5439\u7279\u5439\u8fd9\u672c\u4e86, \u7ed3\u679c\u6700\u540e\u7684\u51f6\u624b\u72af\u7f6a\u52a8\u673a\u7279\u522b\u65e0\u8bed, \u602a\u4e0d\u5f97\u8c46\u74e3\u4e0a\u8bc4\u5206\u4e0d\u9ad8. \u4f46\u4ecd\u65e7\u975e\u5e38\u63a8\u8350, \u6bd5\u7adf\u662f\u9ad8\u5343\u7684\u6545\u4e8b\u561b.<\/p>"},{"title":"kube-scheduler internal","link":"https:\/\/blog.monsterxx03.com\/2019\/08\/02\/kube-scheduler-internal\/","pubDate":"Fri, 02 Aug 2019 16:30:10 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/08\/02\/kube-scheduler-internal\/","description":"<p>\u8ffd\u4e86\u4e00\u4e0b kube-scheduler \u7684\u6e90\u7801, \u8bb0\u5f55\u4e00\u70b9, \u57fa\u4e8e tag <code>v1.16.0-alpha.2<\/code>.<\/p>\n<p>\u4e00\u53e5\u8bdd\u6982\u62ec kube-scheduler \u7684\u804c\u8d23\u662f: \u627e\u5230 pending \u7684 pod, \u6311\u9009\u4e00\u4e2a\u5408\u9002\u7684 node, \u5c06 pod bind \u4e0a\u53bb.<\/p>\n<h2 id=\"get-pending-pod\">Get pending pod<\/h2>\n<p>\u5728 scheduler \u7684\u521d\u59cb\u5316\u8fc7\u7a0b\u4e2d\u7ed9 <code>pod\/node\/pv\/pvc\/service\/storageClassInformer<\/code> \u6dfb\u52a0\u56de\u8c03\u51fd\u6570, \u529f\u80fd\u5927\u81f4\u90fd\u662f\u5728\u8fd9\u4e9b\u8d44\u6e90\u53d1\u751f\u53d8\u5316\u65f6\u66f4\u65b0\u672c\u5730\u7684 cache \u548c ScheduleQueue <a href=\"https:\/\/github.com\/kubernetes\/kubernetes\/blob\/v1.16.0-alpha.2\/pkg\/scheduler\/scheduler.go#L207\">scheduler.go:New<\/a>.<\/p>\n<p>ScheduleQueue \u662f\u5173\u952e, \u5185\u90e8\u5b9e\u73b0\u662f\u4e00\u4e2a PriorityQueue, \u5b83\u6709\u4e09\u4e2a sub queue:<\/p>\n<ul>\n<li>activeQ \u7528\u6765\u5b58\u653e\u7b49\u5f85 schedule \u7684 pods, kube-schedule \u5b9e\u9645\u5de5\u4f5c\u65f6\u5019\u4ece\u8fd9\u4e2a queue \u4e2d\u53d6 pod, \u5b9e\u73b0\u4e0a\u662f\u4e00\u4e2a heap, \u5982\u679c pod \u5b9a\u4e49\u4e86 priority, \u5219\u6309\u7167 priority \u7531\u9ad8\u5230\u4f4e\u6392\u5e8f, \u5426\u5219\u6309 pod \u5230\u8fbe\u7684\u65f6\u95f4\u6392\u5e8f: <a href=\"https:\/\/github.com\/kubernetes\/kubernetes\/blob\/v1.16.0-alpha.2\/pkg\/scheduler\/internal\/queue\/scheduling_queue.go#L154\">activeQComp<\/a><\/li>\n<li>podBackoffQ \u5b58\u653e\u6b63\u5728\u7ecf\u5386 backoff \u7684 pod, \u4e5f\u662f heap, \u6309 pod \u4e0a\u6b21 backoff \u7684\u65f6\u95f4\u6392\u5e8f: <a href=\"https:\/\/github.com\/kubernetes\/kubernetes\/blob\/v1.16.0-alpha.2\/pkg\/scheduler\/internal\/queue\/scheduling_queue.go#L651\">podsCompareBackoffCompleted<\/a><\/li>\n<li>unschedulableQ \u5b58\u653e schedule \u5931\u8d25\u7684 pod, \u53ea\u9700\u8981\u80fd\u6839\u636e pod \u7684 identity (<code>podName_namespace<\/code>) \u627e\u5230 pod \u5c31\u884c, \u4e0d\u9700\u8981\u6392\u5e8f, \u5185\u90e8\u662f\u4e2a map.<\/li>\n<\/ul>\n<p>\u7531 podInformer \u7684 eventHandler \u5c06\u65b0\u7684 pod \u52a0\u5230 activeQ \u4e2d.<\/p>"},{"title":"Pyflame \u7684 kubectl plugin","link":"https:\/\/blog.monsterxx03.com\/2019\/07\/28\/pyflame-%E7%9A%84-kubectl-plugin\/","pubDate":"Sun, 28 Jul 2019 12:47:23 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/07\/28\/pyflame-%E7%9A%84-kubectl-plugin\/","description":"<p><a href=\"https:\/\/github.com\/uber\/pyflame\">pyflame<\/a> \u53ef\u4ee5\u6bd4\u8f83\u65b9\u4fbf\u5f97\u751f\u6210 python \u8fdb\u7a0b\u7684\u8c03\u7528\u51fd\u6570\u6808\u706b\u7130\u56fe, \u6765 debug\n\u4e00\u4e9b\u6027\u80fd\u74f6\u9888, \u505a\u4e86\u4e2a kubectl \u7684\u5c0f\u63d2\u4ef6, \u6765\u65b9\u4fbf\u5f97\u5bf9 k8s pod \u4e2d\u7684 python \u8fdb\u7a0b\u8fdb\u884c debug: <a href=\"https:\/\/github.com\/monsterxx03\/kube-pyflame\">https:\/\/github.com\/monsterxx03\/kube-pyflame<\/a>\n\u76f4\u63a5\u628a svg \u6587\u4ef6\u4e0b\u8f7d\u5230\u672c\u5730.<\/p>\n<p>\u8981\u5bf9 pod \u4e2d\u7684 python \u8fdb\u7a0b\u8fdb\u884c profiling, \u5927\u81f4\u601d\u8def\u6709\u4e24\u79cd:<\/p>\n<ul>\n<li>\u76f4\u63a5\u5728 container \u5185\u4f7f\u7528 pyflame, \u4f46\u8fd9\u6837\u8981\u628a pyflame \u505a\u5230\u6240\u6709\u7684 base \u955c\u50cf\u91cc\u53bb, \u800c\u4e14\u76ee\u6807 container\u8981\u5728 SecurityContext \u52a0\u4e0a <code>SYS_PTRACE<\/code><\/li>\n<li>\u5728 host \u4e0a\u7528 pyflame debug \u5bf9\u5e94\u8fdb\u7a0b, pyflame \u81ea\u8eab\u662f\u80fd\u8bc6\u522b\u8dd1\u5728 container \u91cc\u7684\u8fdb\u7a0b, \u81ea\u52a8\u6267\u884c <code>setns<\/code> \u7684.<\/li>\n<\/ul>\n<p>\u6211\u5e0c\u671b\u4fdd\u6301\u7ebf\u4e0a\u73af\u5883\u5e72\u51c0, \u6700\u540e\u7684\u505a\u6cd5\u662f, \u628a pyflame \u5355\u72ec\u505a\u4e00\u4e2a\u955c\u50cf, \u5148\u7528 kubectl \u627e\u5230\u76ee\u6807 pod \u6240\u5728\u8282\u70b9, \u7136\u540e\u7528 nodeSelector \u5728\u5bf9\u5e94\u8282\u70b9\u4e0a\u8d77\u4e00\u4e2a\npyflame \u7684 pod, \u56e0\u4e3a\u8981\u80fd\u770b\u5230\u5176\u4ed6 namespace \u7684\u8fdb\u7a0b, \u9700\u8981\u8bbe\u7f6e <code>hostPID: true<\/code>, pyflame \u8981\u80fd\u6267\u884c <code>setns<\/code>, \u8fd9\u4e2a debug pod \u8981\u8bbe\u7f6e <code>privileged: true<\/code>.\n\u6267\u884c\u5b8c\u6210\u540e\u628a svg \u4e0b\u8f7d\u4e0b\u6765, \u5e76\u5220\u9664 debug pod.<\/p>"},{"title":"\u6742\u8c08","link":"https:\/\/blog.monsterxx03.com\/2019\/07\/24\/%E6%9D%82%E8%B0%88\/","pubDate":"Wed, 24 Jul 2019 21:58:09 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/07\/24\/%E6%9D%82%E8%B0%88\/","description":"<p>\u56de\u9996\u4e00\u770b, \u5927\u534a\u5e74\u6ca1\u5199\u8fc7\u6742\u8c08\u7cfb\u5217\u4e86, \u4eca\u5e74\u90fd\u6ca1\u4f11\u5047, \u4e5f\u662f\u9189\u4e86. \u968f\u4fbf\u5520\u53e8\u51e0\u53e5.<\/p>\n<p>\u5c0f\u533a\u95e8\u53e3\u7684\u5927\u7237\u517b\u7684\u82b1\u732b\u751f\u4e86\u4e8c\u80ce, \u957f\u7279\u522b\u597d\u770b, \u968f\u5b83\u4eec\u5988, \u989c\u503c\u540a\u6253\u767d\u732b\u5927\u54e5, \u6bcf\u5929\u4e0b\u73ed\u8def\u8fc7\u770b\u5b83\u4eec\u5728\u9a6c\u8def\u53e3\u54ac\u62a5\u7eb8\u4e5f\u662f\u5f88\u6709\u610f\u601d. \u72b9\u8c6b\u4e86\u51e0\u5929\u8981\u4e0d\u8981\u62b1\u53ea\u56de\u6765, \u72b9\u8c6b\u7740\u72b9\u8c6b\u7740\u5c31\u90fd\u88ab\u522b\u4eba\u9886\u8d70\u4e86, \u53f9.<\/p>\n<p>\u6700\u8fd1\u5728\u770b\u897f\u6cfd\u4fdd\u5f66\u7684\u4e66, \u770b\u5b8c\u4e86\u4e00\u672c&lt;\u6b7b\u4e867\u6b21\u7684\u7537\u4eba&gt;, \u6b63\u5728\u8bfb&lt;\u89e3\u4f53\u8bf8\u56e0&gt;. \u7b80\u76f4\u662f\u53d1\u73b0\u4e86\u5b9d\u85cf, \u597d\u4e45\u6ca1\u6709\u770b\u5230\u559c\u6b22\u7684\u63a8\u7406\u5c0f\u8bf4\u4e86, \u771f\u7684\u662f\u770b\u5230\u6700\u540e\u4f1a\u558a\u4e00\u58f0&quot;\u725b\u903c&quot;,\n\u8fd9\u4e66\u8fd8\u662f20\u591a\u5e74\u524d\u5199\u7684, \u884c\u6587\u4e2d\u7684\u9ed1\u8272\u5e7d\u9ed8\u771f\u662f\u975e\u5e38\u559c\u6b22\u4e86. \u89c9\u7740\u8fd9\u4eba\u4f30\u8ba1\u633a\u70e6\u607c\u5bb6\u5ead\u5173\u7cfb\u7684, \u4e66\u91cc\u591a\u5904\u5939\u5e26\u79c1\u8d27.<\/p>"},{"title":" \u8fc1\u79fb\u5230 k8s \u8fc7\u7a0b\u4e2d\u78b0\u5230\u7684\u95ee\u9898","link":"https:\/\/blog.monsterxx03.com\/2019\/07\/23\/%E8%BF%81%E7%A7%BB%E5%88%B0-k8s-%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%A2%B0%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98\/","pubDate":"Tue, 23 Jul 2019 12:32:08 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/07\/23\/%E8%BF%81%E7%A7%BB%E5%88%B0-k8s-%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%A2%B0%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98\/","description":"<p>\u5f00\u59cb\u628a\u7ebf\u4e0a\u6d41\u91cf\u5f80 k8s \u96c6\u7fa4\u91cc\u9762\u5bfc\u4e86, \u4e2d\u95f4\u78b0\u5230\u4e86\u832b\u832b\u591a\u7684\u95ee\u9898 &hellip;&hellip; \u8bb0\u5f55\u4e00\u4e0b(\u5927\u591a\u90fd\u4e0d\u662f k8s \u7684\u95ee\u9898).<\/p>\n<h2 id=\"nginx-ingress-controller-\u7684\u95ee\u9898\">nginx ingress controller \u7684\u95ee\u9898<\/h2>\n<h3 id=\"zero-downtime-pods-upgrade\">zero-downtime pods upgrade<\/h3>\n<p>\u9ed8\u8ba4\u914d\u7f6e\u4e0b, nginx ingress controller \u7684 upstream \u662f service \u7684 endpoints, \u5728 eks \u91cc, \u5c31\u662f vpc cni plugin \u5206\u914d\u7ed9 pod \u7684 vpc ip(\u4e0d\u662f cluster ip),\n\u548c\u76f4\u63a5\u4f7f\u7528 service cluster ip \u6bd4, \u597d\u5904\u662f:<\/p>\n<ul>\n<li>\u53ef\u4ee5\u652f\u6301 sticky session<\/li>\n<li>\u53ef\u4ee5\u7528 round robin \u4e4b\u5916\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5<\/li>\n<\/ul>\n<p>\u5177\u4f53\u5b9e\u73b0\u662f, \u5f53 service \u7684 endpoint \u5217\u8868\u53d1\u751f\u53d8\u5316\u65f6, nginx ingress controller \u6536\u5230\u901a\u77e5, \u5bf9\u5b83\u7ba1\u7406\u7684 nginx \u8fdb\u7a0b\u53d1\u8d77\u4e00\u4e2a http request, \u66f4\u65b0 endpoint ip\nlist(nginx \u5185\u7f6e\u7684 lua \u6765\u4fee\u6539\u5185\u5b58\u4e2d\u7684 ip list)<\/p>\n<p>\u8fd9\u6837\u7684\u95ee\u9898\u662f, \u4ece pod \u88ab\u5e72\u6389\u5230 nginx \u66f4\u65b0\u4e4b\u95f4\u6709\u4e2a\u65f6\u95f4\u5dee, \u90e8\u5206\u8bf7\u6c42\u4f1a\u6302\u6389, \u89e3\u51b3\u65b9\u6cd5\u53ef\u4ee5\u7ed9 pod \u8bbe\u7f6e\u4e00\u4e2a preStop hook, sleep \u51e0\u79d2, \u7b49 nginx ingress controller\n\u66f4\u65b0\u5b8c\u6210.<\/p>"},{"title":"K8S: \u5269\u4e0b\u7684\u95ee\u9898","link":"https:\/\/blog.monsterxx03.com\/2019\/06\/30\/k8s-%E5%89%A9%E4%B8%8B%E7%9A%84%E9%97%AE%E9%A2%98\/","pubDate":"Sun, 30 Jun 2019 16:11:06 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/06\/30\/k8s-%E5%89%A9%E4%B8%8B%E7%9A%84%E9%97%AE%E9%A2%98\/","description":"<p>\u51c6\u5907\u5de5\u4f5c\u90fd\u5dee\u4e0d\u591a\u4e86, \u6ca1\u610f\u5916\u4e0b\u5468\u5c31\u8be5\u5f00\u59cb\u628a\u7ebf\u4e0a\u7684\u670d\u52a1\u5f80 k8s \u4e0a\u8fc1\u79fb\u4e86. \u8bb0\u5f55\u51e0\u4e2a\u95ee\u9898\uff0c\u6682\u65f6\u4e0d block \u6211\u7684\u8fc1\u79fb\u8fdb\u7a0b,\n\u4f46\u9700\u8981\u6301\u7eed\u5173\u6ce8.<\/p>\n<h2 id=\"dns-timeout-and-conntrack\">DNS timeout and conntrack<\/h2>\n<p>\u770b\u5230\u6709\u4e2a\u5173\u4e8e DNS \u7684issue: <a href=\"https:\/\/github.com\/kubernetes\/kubernetes\/issues\/56903\">#56903<\/a><\/p>\n<p>\u73b0\u8c61\u662f k8s cluster \u5185\u90e8 dns \u67e5\u8be2\u95f4\u6b47\u6027\u4f1a 5s \u8d85\u65f6, \u5927\u81f4\u539f\u56e0\u662f coredns \u4f5c\u4e3a\u4e2d\u5fc3 dns \u7684\u65f6\u5019,\n\u8981\u901a\u8fc7 iptables \u628a\u3000coredns \u7684 cluster ip, \u8f6c\u5316\u5230\u5b83\u771f\u5b9e\u7684\u53ef\u8def\u7531 ip, \u4e2d\u95f4\u9700\u8981 SNAT, DNAT, \u5e76\u5728\nconntrack \u5185\u8bb0\u5f55\u6620\u5c04\u5173\u7cfb.<\/p>\n<p>\u8fd9\u53ef\u80fd\u4f1a\u5e26\u6765\u4e24\u4e2a\u95ee\u9898:<\/p>\n<h3 id=\"conntrack-table-\u88ab-udp-\u7684-dns-\u67e5\u8be2\u586b\u6ee1\">conntrack table \u88ab udp \u7684 dns \u67e5\u8be2\u586b\u6ee1<\/h3>\n<p>udp \u662f\u65e0\u8fde\u63a5\u7684, tcp \u5173\u95ed\u94fe\u63a5\u5c31\u4f1a\u6e05\u7406 conntrack \u5185\u8bb0\u5f55, udp \u4e0d\u4f1a\uff0c\u53ea\u80fd\u7b49\u8d85\u65f6, \u9ed8\u8ba4 30s(<code>net.netfilter.nf_conntrack_udp_timeout<\/code>)\n\u77ed\u65f6\u95f4\u5185\u5927\u91cf udp \u67e5\u8be2\u53ef\u80fd\u586b\u6ee1 conntrack, \u5bfc\u81f4\u4e22\u5305.<\/p>"},{"title":"snet dev note: support MacOS","link":"https:\/\/blog.monsterxx03.com\/2019\/06\/20\/snet-dev-note-support-macos\/","pubDate":"Thu, 20 Jun 2019 16:03:56 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/06\/20\/snet-dev-note-support-macos\/","description":"<p>\u8fd9\u4e24\u5929\u5f97\u4e86\u7a7a, \u8ba9 snet \u652f\u6301\u4e86\u4e0b MacOS.<\/p>\n<p>snet \u7684\u5927\u81f4\u539f\u7406\u662f\u901a\u8fc7\u7cfb\u7edf\u9632\u706b\u5899\u7684\u6d41\u91cf\u91cd\u5b9a\u5411\u529f\u80fd,\u5c06\u6240\u6709\u53bb\u5f80\u56fd\u5916\u7684\u6d41\u91cf\u5bfc\u5230 snet \u76d1\u542c\u7684\u7aef\u53e3, \u5728\u7a0b\u5e8f\u5185\u90e8\n\u5c06\u6d41\u91cf\u4f20\u9012\u7ed9\u4e0a\u6e38\u7684 proxy server(ss, http), \u62ff\u5230\u54cd\u5e94\u540e\u518d\u56de\u7ed9\u5ba2\u6237\u7aef.<\/p>\n<p>\u5b9e\u73b0\u5173\u952e\u662f\u8981\u5728 snet \u5185\u90e8\u83b7\u53d6\u5230\u6d41\u91cf\u7684\u539f\u76ee\u6807\u5730\u5740, \u56e0\u4e3a\u91cd\u5b9a\u5411\u4e4b\u540e tcp connnection \u7684\u76ee\u6807\u5730\u5740\u53d8\u6210\u4e86 snet \u76d1\u542c\n\u7684\u5730\u5740.<\/p>\n<p>Linux \u4e0a\u7684\u5b9e\u73b0\uff0c\u4ee5\u524d\u8bb2\u8fc7: <a href=\"https:\/\/blog.monsterxx03.com\/2019\/03\/31\/snet-transparent-ss-proxy-on-linux\/\">https:\/\/blog.monsterxx03.com\/2019\/03\/31\/snet-transparent-ss-proxy-on-linux\/<\/a>\n\u662f\u901a\u8fc7 <code>SO_ORIGINAL_DST<\/code> \u8fd9\u4e2a socket option \u5b9e\u73b0\u7684.<\/p>\n<p>MacOS \u4e0a\u6ca1\u6709 iptables, \u7c7b\u4f3c\u7684\u5de5\u5177\u662f\u7cfb\u7edf\u81ea\u5e26\u7684 pfctl, \u6363\u9f13\u4e86\u4e00\u4e0b\u4e5f\u80fd\u5b9e\u73b0\u4e00\u6837\u7684\u529f\u80fd.<\/p>\n<h2 id=\"\u7528-pfctl-\u505a\u6d41\u91cf\u91cd\u5b9a\u5411\">\u7528 pfctl \u505a\u6d41\u91cf\u91cd\u5b9a\u5411<\/h2>\n<p>pfctl \u7684\u6587\u6863\u53ef\u4ee5\u901a\u8fc7 <code>man pfctl<\/code>, <code>man pf.conf<\/code> \u67e5\u770b. \u6211\u4e5f\u53ea\u662f\u770b\u4e86\u4e2a\u5927\u6982, \u7ec6\u8282\u5e76\u4e0d\u6e05\u695a.<\/p>"},{"title":"Random Talk","link":"https:\/\/blog.monsterxx03.com\/2019\/05\/30\/random-talk\/","pubDate":"Thu, 30 May 2019 18:48:23 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/05\/30\/random-talk\/","description":"<p>Just some random complains and notes about server infra management. I think those are my motivations to move to kubernetes.<\/p>\n<p>Won&rsquo;t explain k8s or docker in detail, and how they solve those problems in this post.<\/p>\n<h2 id=\"infrastructure-levelon-aws\">Infrastructure level(on AWS)<\/h2>\n<p>We use following services provided by AWS.<\/p>\n<ul>\n<li>Compute:\n<ul>\n<li>EC2<\/li>\n<li>AutoScaling Group<\/li>\n<li>Lambda<\/li>\n<\/ul>\n<\/li>\n<li>network:\n<ul>\n<li>VPC (SDN network)<\/li>\n<li>DNS (route53)<\/li>\n<li>CDN (CloudFront)<\/li>\n<\/ul>\n<\/li>\n<li>Loadbalancer:\n<ul>\n<li>ELB (L4)<\/li>\n<li>NLB (L4, ELB successor, support static IP)<\/li>\n<li>ALB (L7)<\/li>\n<\/ul>\n<\/li>\n<li>Storage:\n<ul>\n<li>EBS (block storage)<\/li>\n<li>EFS (hosted NFS)<\/li>\n<li>RDS(MySQl\/PostgreSQL &hellip;)<\/li>\n<li>Redshift (data warehouse)<\/li>\n<li>DynamoDB (KV)<\/li>\n<li>S3 (object storage)<\/li>\n<li>Glacier (cheap archive storage)<\/li>\n<\/ul>\n<\/li>\n<li>Web Firewall (WAF)<\/li>\n<li>Monitor (CloudWatch)<\/li>\n<li>DMS (ETL)\n&hellip;<\/li>\n<\/ul>\n<p>For infra management, in early days, we just click, click, click&hellip; or write some simple scripts to call AWS api.<\/p>\n<p>With infra resources growing, management became complex, a concept called <code>Infrastructure as Code<\/code> rising.<\/p>\n<p>AWS provides CloudFormation as orchestration tool, but we use <a href=\"https:\/\/www.terraform.io\/\">terraform<\/a> (for short: CloudFormation sucks, for long: <a href=\"https:\/\/blog.monsterxx03.com\/2017\/04\/21\/infrastructure-as-code\/\">Infrastructure as Code<\/a>)<\/p>\n<p>So far, not bad.(tweak those services internally is another story&hellip; never belive <code>work out of box<\/code>)<\/p>\n<h2 id=\"application-level\">Application level<\/h2>\n<ul>\n<li>configuration management (setup nginx, jenkins, redis, twemproxy, ElasticSearch or WTF..)<\/li>\n<li>CI\/CD<\/li>\n<li>dependency management<\/li>\n<\/ul>\n<p>They&rsquo;re complicated, people developped bunch of tools to handle: puppet, chef, ansible, saltstack &hellip;<\/p>\n<p>They&rsquo;re great and working, but writing correct code still a challenge when changes involves:<\/p>"},{"title":"Centralized Logging on K8S","link":"https:\/\/blog.monsterxx03.com\/2019\/05\/26\/centralized-logging-on-k8s\/","pubDate":"Sun, 26 May 2019 14:27:38 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/05\/26\/centralized-logging-on-k8s\/","description":"<p>\u641e\u5b9a\u4e86\u76d1\u63a7, \u4e0b\u4e00\u6b65\u5728 k8s \u4e0a\u8981\u505a\u7684\u662f\u4e2d\u5fc3\u5316\u65e5\u5fd7, \u5927\u4f53\u770b\u4e86\u4e0b, \u611f\u5174\u8da3\u7684\u6709\u4e24\u4e2a\u9009\u62e9: ELK \u5957\u4ef6, \u6216fluent-bit + fluentd.<\/p>\n<p>ELK \u90a3\u5957\u597d\u5904\u662f, \u53ef\u4ee5\u628a\u76d1\u63a7\u548c\u65e5\u5fd7\u4e00\u4f53\u5316, filebeat \u6536\u96c6\u65e5\u5fd7, metricbeat \u6536\u96c6 metrics, \u7edf\u4e00\u5b58\u50a8\u5728 ElasticSearch \u91cc, \u901a\u8fc7\u7b2c\u4e09\u65b9\u9879\u76ee<a href=\"https:\/\/github.com\/Yelp\/elastalert\">elastalert<\/a>\n\u53ef\u4ee5\u505a\u62a5\u8b66\uff0c\u4e5f\u80fd\u5728 kibana \u91cc\u96c6\u6210\u754c\u9762. \u574f\u5904\u662f ElasticSearch \u5b58\u50a8\u6210\u672c\u9ad8, \u5403\u8d44\u6e90. \u6211\u4eec\u5bf9\u5b58\u50a8\u7684\u65e5\u5fd7\u4f7f\u7528\u9700\u6c42\u57fa\u672c\u5c31\u662f debug, \u6ca1\u6709\u7279\u522b\u590d\u6742\u7684BI\u9700\u6c42, \u4e0a\u4e00\u6574\u5957 ELK \u8fd8\u662f\u592a\u91cd\u4e86.<\/p>\n<p>\u9009\u62e9 fluent-bit + fluentd \u8fd8\u6709\u4e2a\u597d\u5904\u662f, \u4e4b\u524d\u5185\u90e8\u6709\u5957\u6536\u96c6 metrics(\u7528\u4e8e\u7edf\u8ba1 DAU, retention \u4e4b\u7c7b\u6307\u6807) \u7684\u7cfb\u7edf\u672c\u6765\u5c31\u662f\u57fa\u4e8e fluentd \u7684, \u7528\u8fd9\u5957\u5c31\u4e0d\u7528\u6539 metrics \u90a3\u8fb9\u7684 ETL \u4e86.<\/p>"},{"title":"Prometheus on K8S","link":"https:\/\/blog.monsterxx03.com\/2019\/05\/14\/prometheus-on-k8s\/","pubDate":"Tue, 14 May 2019 13:52:02 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/05\/14\/prometheus-on-k8s\/","description":"<h1 id=\"why-move-to-prometheus\">Why move to prometheus?<\/h1>\n<p>\u628a\u751f\u4ea7\u73af\u5883\u8fc1\u79fb\u5230 k8s \u7684\u7b2c\u4e00\u6b65\u662f\u8981\u641e\u5b9a\u76d1\u63a7, \u76ee\u524d\u7ebf\u4e0a\u76d1\u63a7\u7528\u7684\u662f\u5546\u4e1a\u7684 datadog, \u5728 container \u73af\u5883\u4e0b\ndatadog \u76d1\u63a7\u8fd8\u8981\u6309 container \u6570\u76ee\u6536\u8d39, \u5355 host \u53ea\u6709 10 \u4e2a\u7684\u989d\u5ea6, \u8d85\u8fc7\u8981\u52a0\u94b1, \u9ad8\u5bc6\u5ea6\u90e8\u7f72\u4e0b\u5f88\u4e0d\u5212\u7b97.\n\u4e00\u4e2a server \u8dd1 20 \u4e2a\u4ee5\u4e0a container \u662f\u5f88\u6b63\u5e38\u7684\u4e8b\u60c5, \u5355\u53f0 server \u7684\u76d1\u63a7\u8d39\u7528\u7acb\u9a6c\u7ffb\u500d.<\/p>\n<p>tracing \u8fd9\u5757\u4e4b\u524d\u7528\u7684\u4e5f\u662f datadog, \u4f46\u592a\u8d35\u4e86,\u4e00\u76f4\u4e5f\u60f3\u6362\u5f00\u6e90\u5b9e\u73b0, \u7d22\u6027\u76d1\u63a7\u62a5\u8b66\u4e5f\u6362\u4e86, \u8e29\u4e00\u628a\u5751\u5427.<\/p>\n<p>vendor lock \u603b\u662f\u4e0d\u723d\u7684&hellip;<\/p>\n<h1 id=\"metrics-in-k8s\">Metrics in k8s<\/h1>\n<p>\u5148\u4e0d\u63d0 prometheus, k8s \u4e2d metrics \u6765\u6e90\u6709\u90a3\u4e48\u51e0\u4e2a:<\/p>\n<h2 id=\"metrics-serever\">metrics-serever<\/h2>\n<p><a href=\"https:\/\/github.com\/kubernetes-incubator\/metrics-server\">metrics-server<\/a> (\u53d6\u4ee3 heapster), \u4ece node\n\u4e0a kubelet \u7684 <a href=\"https:\/\/github.com\/kubernetes\/kubernetes\/blob\/master\/pkg\/kubelet\/apis\/stats\/v1alpha1\/types.go\">summary api<\/a> \u6293\u53d6\u6570\u636e(node\/pod \u7684 cpu\/memory \u4fe1\u606f), kubectl top \u548c kube-dashboard \u7684 metrics \u6570\u636e\u6765\u6e90\u5c31\u662f\u5b83, horizontal pod\nautoscaler \u505a scale up\/down \u51b3\u7b56\u7684\u6570\u636e\u6765\u6e90\u4e5f\u662f\u5b83, metrics-server \u53ea\u5728\u5185\u5b58\u91cc\u4fdd\u7559 node \u548c pod \u7684\u6700\u65b0\u503c.<\/p>"},{"title":"kubeconfig \u548c aws named profile \u7ba1\u7406\u7684 tips","link":"https:\/\/blog.monsterxx03.com\/2019\/05\/07\/kubeconfig-%E5%92%8C-aws-named-profile-%E7%AE%A1%E7%90%86%E7%9A%84-tips\/","pubDate":"Tue, 07 May 2019 18:36:38 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/05\/07\/kubeconfig-%E5%92%8C-aws-named-profile-%E7%AE%A1%E7%90%86%E7%9A%84-tips\/","description":"<p>\u6211\u6709\u4e24\u4e2a EKS \u96c6\u7fa4 (sandbox + production), \u8fd9\u4e24\u4e2a\u96c6\u7fa4\u5206\u5904\u4e24\u4e2a aws \u5e10\u53f7\u4e2d.\n\u6240\u4ee5\u7ba1\u7406\u7684\u65f6\u5019\u4e5f\u9700\u8981\u4e24\u5957 aws credential.<\/p>\n<p>\u540c\u65f6\u6211\u7528 <a href=\"https:\/\/github.com\/futuresimple\/helm-secrets\">helm-secrets<\/a> \u6765\u7ba1\u7406 helm charts\n\u4e2d\u9700\u8981\u52a0\u5bc6\u7684\u4e00\u4e9b\u914d\u7f6e. helm-secrets \u53ea\u662f <a href=\"https:\/\/github.com\/mozilla\/sops\">sops<\/a> \u7684\u4e00\u4e2a shell\nwrapper, \u5b9e\u9645\u52a0\u5bc6\u662f\u901a\u8fc7 sops \u8fdb\u884c\u7684.<\/p>\n<p>sops \u652f\u6301 aws KMS, gcp KMS, azure key vault.. \u7b49\u52a0\u5bc6\u670d\u52a1. \u6211\u7528\u7684\u662f aws KMS, \u5728 KMS \u91cc\u521b\u5efa\u4e00\u4e2a key,\n\u6388\u6743\u5141\u8bb8\u6211\u8fd9\u4e2a iam \u5e10\u53f7\u80fd\u7528\u5b83\u6765\u8fdb\u884c\u52a0\u89e3\u5bc6.<\/p>\n<p>\u8fd9\u5e26\u6765\u4e86\u4e00\u4e2a\u95ee\u9898, kubectl \u548c helm-secrets \u90fd\u9700\u8981 aws credential, \u5982\u679c\u4e24\u8fb9\u7528\u7684\u4e0d\u4e00\u6837\u5c31\u4f1a\u6267\u884c\u5931\u8d25.<\/p>\n<p>\u6211\u7edf\u4e00\u4f7f\u7528 aws \u7684 <a href=\"https:\/\/docs.aws.amazon.com\/cli\/latest\/userguide\/cli-configure-profiles.html\">named profiles<\/a>\n\u6765\u7ba1\u7406 credential. \u4e0d\u5728\u73af\u5883\u53d8\u91cf\u91cc\u8bbe aws \u7684 access key\/secret key(\u5982\u679c\u8bbe\u7f6e\u4e86, \u4f18\u5148\u7ea7\u6bd4 named profile \u9ad8)<\/p>\n<p>\u76ee\u5f55\u7ed3\u6784:<\/p>"},{"title":"Jenkins on K8S","link":"https:\/\/blog.monsterxx03.com\/2019\/04\/29\/jenkins-on-k8s\/","pubDate":"Mon, 29 Apr 2019 15:56:12 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/04\/29\/jenkins-on-k8s\/","description":"<p>\u6700\u8fd1\u5728\u628a jenkins \u8fc1\u79fb\u5230 k8s, \u5177\u4f53\u600e\u4e48 setup \u7684\u4e0d\u8d58\u8ff0\u4e86(helm chart, jenkins home \u76ee\u5f55\u6302pvc, jenkins kubernetes-plugin).<\/p>\n<p>jenkins \u8dd1 k8s \u597d\u5904\u662f\u53ef\u4ee5\u65b9\u4fbf\u5f97\u505a\u5206\u5e03\u5f0f build, \u6bcf\u6b21 trigger \u4e00\u4e2a job \u7684\u65f6\u5019\u81ea\u52a8\u8d77\u4e00\u4e2a pod \u4f5c\u4e3a jenkins slave agent, \u7ed3\u675f\u4e86\u81ea\u52a8\u5220\u6389.\n\u5728 aws \u4e0a\u7ed3\u5408 cluster-autoscaler \u53ef\u4ee5\u6781\u5927\u5f97\u6269\u5c55 ci \u7684\u5e76\u884c\u80fd\u529b, \u964d\u4f4e\u6210\u672c.<\/p>\n<p>\u8bb0\u5f55\u4e00\u70b9\u8fc7\u7a0b\u4e2d\u7684\u5751.<\/p>\n<p>\u88c5\u4e0a <a href=\"https:\/\/github.com\/jenkinsci\/kubernetes-plugin\">kubernetes-plugin<\/a> \u540e,\u8981\u60f3\u8ba9 jenkins \u7684 job \u5728 pod \u4e2d\u8dd1, \u5fc5\u987b\u7528 pipeline \u7684\u65b9\u5f0f\u7f16\u5199 job \u5b9a\u4e49. script \u548c declarative\n\u4e24\u79cd\u65b9\u5f0f\u90fd\u652f\u6301\u542f\u52a8 pod. \u5982\u679c\u7528 shell \u7684\u65b9\u5f0f\u7f16\u5199, \u4e0d\u4f1a\u8dd1\u5728 pod \u91cc\uff0c\u4f1a\u76f4\u63a5\u5728\u3000master \u7684\u3000workspace \u91cc build.<\/p>\n<p>declarative \u65b9\u5f0f\u7684\u4f8b\u5b50:<\/p>\n<pre><code>pipeline {\n    agent {\n        kubernetes  {\n            label 'test-deploy'\n            yamlFile 'test-deploy.yaml'\n        }\n    }\n    stages {\n        stage('stage test') {\n            steps('tests') {\n                container('test') {\n                    sh 'ls'\n                }\n            }\n        }\n    }\n}\n<\/code><\/pre>\n<p><code>ls<\/code> \u547d\u4ee4\u5c31\u4f1a\u5728 test container \u91cc\u6267\u884c, \u5982\u679c\u4e0d\u7528 <code>container()<\/code> step \u7684\u8bdd\uff0c\u9ed8\u8ba4\u4f1a\u5728 pod \u7684 default container \u91cc\u6267\u884c.<\/p>"},{"title":"K8s Volume Resize on EKS","link":"https:\/\/blog.monsterxx03.com\/2019\/04\/12\/k8s-volume-resize-on-eks\/","pubDate":"Fri, 12 Apr 2019 13:23:54 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/04\/12\/k8s-volume-resize-on-eks\/","description":"<p>\u4ece k8s 1.8 \u5f00\u59cb\u652f\u6301 <a href=\"https:\/\/kubernetes.io\/blog\/2018\/07\/12\/resizing-persistent-volumes-using-kubernetes\/\">PersistentVolumeClaimResize<\/a>. \u4f46 api \u662f alpha \u72b6\u6001, \u9ed8\u8ba4\u4e0d\u5f00\u542f, eks launch\n\u7684\u65f6\u5019\u7248\u672c\u662f 1.10, \u56e0\u4e3a\u6ca1\u6cd5\u6539 control plane, \u6240\u4ee5\u6ca1\u6cd5\u76f4\u63a5\u5728 k8s \u5185\u505a ebs \u6269\u5bb9. \u540e\u6765\u5347\u7ea7\u5230\u4e86\n1.11, \u8fd9\u4e2a feature \u9ed8\u8ba4\u88ab\u6253\u5f00\u4e86, \u5c1d\u8bd5\u4e86\u4e0b\u76f4\u63a5\u5728 EKS \u5185\u505a ebs \u7684\u6269\u5bb9.<\/p>\n<p>\u6ce8\u610f:<\/p>\n<ul>\n<li>\u8fd9\u4e2a feature \u53ea\u80fd\u5bf9\u901a\u8fc7 pvc \u7ba1\u7406\u7684 volume \u505a\u6269\u5bb9, \u5982\u679c\u76f4\u63a5\u6302\u7684\u662f pv, \u53ea\u80fd\u81ea\u5df1\u6309\u4f20\u7edf\u7684 ebs \u6269\u5bb9\u6d41\u7a0b\u5728 eks \u4e4b\u5916\u505a.<\/li>\n<li>\u7528\u6765\u521b\u5efa pvc \u7684 storageclass \u4e0a\u5fc5\u987b\u8bbe\u7f6e <code>allowVolumeExpansion<\/code> \u4e3a true<\/li>\n<\/ul>\n<p>\u5728 eks \u4e0a\u4f7f\u7528 pv\/pvc,\u3000\u5bf9\u4e8e\u9700\u8981 retain \u7684 volume, \u6211\u4e00\u822c\u7684\u6d41\u7a0b\u662f:<\/p>\n<ul>\n<li>\u5728 eks \u4e4b\u5916\u624b\u5de5\u521b\u5efa ebs volume.<\/li>\n<li>\u5728 eks \u4e2d\u521b\u5efa pv, \u6307\u5411 ebs \u7684 volume id<\/li>\n<li>\u5728 eks \u4e2d\u521b\u5efa pvc, \u6307\u5411 pv<\/li>\n<\/ul>\n<p>\u793a\u4f8b yaml:<\/p>\n<pre><code>---\nkind: PersistentVolume\napiVersion: v1\nmetadata:\n  name: test\nspec:\n  storageClassName: gp2\n  persistentVolumeReclaimPolicy: Retain\n  accessModes:\n    - ReadWriteOnce\n  capacity:\n    storage: 5Gi\n  awsElasticBlockStore:\n    fsType: ext4\n    volumeID: vol-xxxx   # create in aws manually\n---\nkind: PersistentVolumeClaim\napiVersion: v1\nmetadata:\n  name: test-claim\nspec:\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 5Gi\n  volumeName: test\n<\/code><\/pre>\n<p>\u5047\u5982\u73b0\u5728\u8981\u6269\u5bb9\u5230 10Gi, \u6d41\u7a0b\u662f:<\/p>"},{"title":"snet dev note","link":"https:\/\/blog.monsterxx03.com\/2019\/04\/10\/snet-dev-note\/","pubDate":"Wed, 10 Apr 2019 22:33:49 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/04\/10\/snet-dev-note\/","description":"<p>\u5b8c\u6210 <a href=\"https:\/\/github.com\/monsterxx03\/snet\">SNET<\/a> \u521d\u7248\u540e\u53c8\u505a\u4e86\u4e9b\u540e\u7eed\u66f4\u65b0,\u3000\u8bb0\u5f55\u4e00\u70b9.<\/p>\n<h2 id=\"\u652f\u6301-http-tunnel\">\u652f\u6301 http tunnel<\/h2>\n<p>\u914d\u7f6e\u6587\u4ef6\u91cc\u589e\u52a0\u4e00\u4e2a <code>proxy-type<\/code> \u9009\u9879, \u9ed8\u8ba4\u4e3a <code>ss<\/code>, \u53ef\u6539\u6210 <code>http<\/code>, \u8fd9\u6837\u53ef\u4ee5\u5c06\n\u652f\u6301 http tunnel \u7684\u4ee3\u7406\u670d\u52a1\u5668\u4f5c\u4e3a upstream(\u4f8b\u5982 squid). \u586b\u4e0a <code>http-proxy-<\/code> \u5f00\u5934\n\u7684\u9009\u9879\u5c31\u884c.<\/p>\n<p>\u5b9e\u73b0\u4e0a client \u7aef\u8981\u5bf9\u63a5 http tunnel \u975e\u5e38\u7b80\u5355:<\/p>\n<ul>\n<li>client \u53d1\u9001\u8bf7\u6c42: <code>Connect tgt-host:tgt-port HTTP\/1.1<\/code><\/li>\n<li>server response: <code>HTTP\/1.1 200<\/code>, \u5373\u8868\u793a server \u7aef\u652f\u6301 http tunnel<\/li>\n<li>client \u540e\u7eed\u5411\u8be5 tcp connection \u5199\u5165\u7684\u6570\u636e\u90fd\u4f1a\u88ab server \u8f6c\u53d1\u5230 tgt-host:tgt-port<\/li>\n<\/ul>\n<p>\u6539\u52a8\u7684\u65f6\u5019\u628a upstream proxy \u7684\u90e8\u5206\u91cd\u6784\u4e86\u4e00\u4e0b, \u62bd\u4e86\u4e2a <code>Proxy<\/code> interface \u51fa\u6765, \u540e\u7eed\u60f3\u5bf9\u63a5\u5176\u4ed6\u534f\u8bae\u65b9\u4fbf\u6269\u5c55.<\/p>\n<h2 id=\"\u5bf9-udp-\u652f\u6301\u7684\u5c1d\u8bd5\">\u5bf9 udp \u652f\u6301\u7684\u5c1d\u8bd5<\/h2>\n<p>\u5bf9 tcp \u6d41\u91cf\u7684\u8f6c\u53d1\u80fd\u901a\u8fc7 iptables REDIRECT \u5b9e\u73b0\u7684, \u901a\u8fc7 getsockoption \u53ef\u4ee5\u77e5\u9053 tcp connection\n\u7684\u539f\u76ee\u6807, \u4f46\u8fd9\u5bf9 udp \u884c\u4e0d\u901a, REDIRECT \u4e4b\u540e\u62ff\u4e0d\u5230\u539f target.<\/p>"},{"title":"snet: transparent ss proxy on Linux","link":"https:\/\/blog.monsterxx03.com\/2019\/03\/31\/snet-transparent-ss-proxy-on-linux\/","pubDate":"Sun, 31 Mar 2019 22:19:46 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/03\/31\/snet-transparent-ss-proxy-on-linux\/","description":"<p>\u65e5\u5e38\u4f7f\u7528 Linux \u5de5\u4f5c, Linux \u4e0b\u5b9e\u73b0\u5168\u5c40\u900f\u660e\u4ee3\u7406\u53ef\u4ee5\u7528 iptables + ss-redir, \u8981\u6709\u6bd4\u8f83\u597d\u7684\u4e0a\u7f51\u4f53\u9a8c\u8fd8\u9700\u8981 ChinaDNS \u914d\u5408 dnsmasq,\n\u8fd9\u4e00\u6574\u5957\u5728\u8def\u7531\u5668\u4e0a\u641e\u4e00\u904d\u5c31\u7b97\u4e86, \u5728\u672c\u5730\u592a\u9ebb\u70e6\u4e86. \u4ed4\u7ec6\u60f3\u60f3\u8fd9\u51e0\u4e2a\u52a0\u8d77\u6765\u7684\u529f\u80fd\u5b9e\u73b0\u8d77\u6765\u4e5f\u5e76\u4e0d\u590d\u6742, \u524d\u9635\u5b50\u5c31\u5199\u4e86\u4e2a\u5c0f\u4e1c\u897f,\n\u7528\u4e00\u4e2a\u8fdb\u7a0b\u5b8c\u6210\u5168\u5c40\u900f\u660e\u4ee3\u7406 + ChinaDNS + \u56fd\u5185\u5916\u5206\u6d41: <a href=\"https:\/\/github.com\/monsterxx03\/snet\">https:\/\/github.com\/monsterxx03\/snet<\/a><\/p>\n<p>\u76ee\u524d\u7684\u9650\u5236:<\/p>\n<ul>\n<li>\u4e0d\u652f\u6301 ipv6<\/li>\n<li>\u53ea\u652f\u6301 tcp (\u56e0\u4e3a\u6211\u7684\u6d4b\u8bd5\u670d\u52a1\u5668\u4e0d\u652f\u6301 udp, \u4ee5\u540e\u518d\u52a0\u4e0a\u5427)<\/li>\n<li>\u4e0a\u6e38 server \u53ea\u652f\u6301 ss<\/li>\n<\/ul>\n<p>\u76ee\u7684\u662f\u4e00\u4e2a\u8fdb\u7a0b + \u4e00\u4e2a\u914d\u7f6e\u6587\u4ef6\u5b8c\u6210\u6240\u6709\u4e8b\u60c5. \u9700\u8981\u7684 iptable \u89c4\u5219\u4e5f\u5168\u90e8\u5185\u7f6e\u4e86(\u5305\u62ec CN ip \u6bb5), \u7f3a\u5c11\u7075\u6d3b\u4f46\u5bf9\u6211\u591f\u7528\u4e86, \u4ee5\u540e\u6709\u9700\u8981\u518d\u52a0\u4e0a\u9009\u9879\u4e0d\u81ea\u52a8\u914d\u5427.<\/p>"},{"title":"Celery Time Limit \u7684\u5751","link":"https:\/\/blog.monsterxx03.com\/2019\/03\/28\/celery-time-limit-%E7%9A%84%E5%9D%91\/","pubDate":"Thu, 28 Mar 2019 17:37:29 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/03\/28\/celery-time-limit-%E7%9A%84%E5%9D%91\/","description":"<p>\u4e4b\u524d\u7528 celery \u505a\u7684 task \u90fd\u662f\u4e00\u4e9b\u5f88\u7b80\u5355\u8f7b\u91cf\u7ea7\u7684 task, \u4ece\u6765\u6ca1\u89e6\u53d1\u8fc7 timeout, \u6700\u8fd1\u52a0\u5165\u4e86\u4e00\u4e9b\u590d\u6742\u5f88\u8017\u65f6\u7684 task, \u78b0\u5230\u4e00\u4e9b time limit \u7684\u5751.<\/p>\n<p>celery \u4e2d time limit \u6709\u4e24\u79cd, soft_time_limit \u548c hard_time_limit, \u533a\u522b\u662f soft_time_limit \u4f1a\u5728\u5185\u90e8\u629b\u4e00\u4e2a Exception, task \u53ef\u4ee5 catch \u81ea\u884c\u5904\u7406.\nhard time limit \u6ca1\u6cd5\u88ab catch.<\/p>\n<p>\u4f7f\u7528\u5982\u4e0b:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" style=\"color:#586e75;background-color:#eee8d5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"><code class=\"language-python\" data-lang=\"python\"><span style=\"display:flex;\"><span><span style=\"color:#dc322f;font-weight:bold\">from<\/span> <span style=\"color:#268bd2\">myapp<\/span> <span style=\"color:#dc322f;font-weight:bold\">import<\/span> <span style=\"color:#268bd2\">app<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#dc322f;font-weight:bold\">from<\/span> <span style=\"color:#268bd2\">celery.exceptions<\/span> <span style=\"color:#dc322f;font-weight:bold\">import<\/span> <span style=\"color:#268bd2\">SoftTimeLimitExceeded<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#268bd2\">@app.task<\/span>\n<\/span><\/span><span style=\"display:flex;\"><span><span style=\"color:#859900\">def<\/span> <span style=\"color:#268bd2\">mytask<\/span>():\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#859900\">try<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#268bd2\">do_work<\/span>()\n<\/span><\/span><span style=\"display:flex;\"><span>    <span style=\"color:#859900\">except<\/span> <span style=\"color:#268bd2\">SoftTimeLimitExceeded<\/span>:\n<\/span><\/span><span style=\"display:flex;\"><span>        <span style=\"color:#268bd2\">clean_up_in_a_hurry<\/span>()<\/span><\/span><\/code><\/pre><\/div>\n<p>\u6211 celery pool \u7528\u7684\u662f gevent, \u5b9e\u9645\u4e0a\u5728\u73b0\u5728\u7684\u5b9e\u73b0\u91cc gevent \u505a worker pool \u7684\u65f6\u5019\u4f1a\u5ffd\u7565 soft_time_limit, \u53ea\u6709 hard_time_limit \u4f1a\u88ab\u89e6\u53d1(\u901a\u8fc7 gevent.Timeout \u5b9e\u73b0).<\/p>\n<p>\u5751\u7239\u7684\u662f\u6587\u6863\u91cc\u5199\u7684\u662f\u9519\u7684: <a href=\"http:\/\/docs.celeryproject.org\/en\/latest\/userguide\/workers.html#time-limit\">http:\/\/docs.celeryproject.org\/en\/latest\/userguide\/workers.html#time-limit<\/a><\/p>\n<p>soft_time_limit \u53ea\u5728 prefork pool \u91cc\u652f\u6301.<\/p>\n<p>\u6211\u73b0\u5728\u60f3\u8ba9 celery \u628a\u8fd9\u4e2a hard timeout \u7684\u60c5\u51b5 report \u5230 sentry, \u770b\u4e86\u5708\u4ee3\u7801\u5e76\u6ca1\u6cd5\u4ece\u5916\u9762 override timeout \u7684 callback. \u53ea\u80fd\u5f88\u4e11\u5f97\u505a\u4e86\u4e2a monkey patch, \u5728\u521d\u59cb\u5316 celeryapp\n\u7684\u4ee3\u7801\u91cc:<\/p>"},{"title":"\u7ba1\u7406\u8d1f\u8f7d","link":"https:\/\/blog.monsterxx03.com\/2019\/02\/12\/%E7%AE%A1%E7%90%86%E8%B4%9F%E8%BD%BD\/","pubDate":"Tue, 12 Feb 2019 13:08:29 +0800","guid":"https:\/\/blog.monsterxx03.com\/2019\/02\/12\/%E7%AE%A1%E7%90%86%E8%B4%9F%E8%BD%BD\/","description":"<p>\u6700\u8fd1\u5728\u770b google \u7684 <code>&lt;The Site Reliablity Workbook&gt;<\/code>, \u5176\u4e2d\u6709\u4e00\u7ae0\u662f&quot;Manage load&quot;, \u5185\u5bb9\u8fd8\u633a\u8be6\u7ec6\u7684, \u7ed3\u5408\u5728 aws \u4e0a\u7684\u7ecf\u9a8c\u505a\u70b9\u7b14\u8bb0.<\/p>\n<h2 id=\"load-balancing\">Load Balancing<\/h2>\n<p>\u6d41\u91cf\u7684\u5165\u53e3\u662f\u8d1f\u8f7d\u5747\u8861, \u6700\u6700\u7b80\u5355\u7684\u505a\u6cd5\u662f\u5728 DNS \u4e0a\u505a round robin, \u4f46\u8fd9\u6837\u5f88\u4f9d\u8d56 client, \u4e0d\u540c\u7684 client \u53ef\u80fd\u4e0d\u5b8c\u5168\u9075\u5b88 DNS \u7684 TTL, \u5f53\u5730\u7684 ISP \u4e5f\u4f1a\u6709\u7f13\u5b58.<\/p>\n<p>google \u7528 anycast \u6280\u672f\u5728\u81ea\u5df1\u7684\u7f51\u7edc\u4e2d\u901a\u8fc7 BGP \u7ed9\u4e00\u4e2a\u57df\u540d\u53d1\u5e03\u591a\u4e2a endpoint, \u5171\u4eab\u4e00\u4e2a vip(virtual ip), \u901a\u8fc7 BGP routing \u6765\u5c06\u7528\u6237\u7684\u6570\u636e\u5305\u53d1\u9001\u5230\u6700\u8fd1\u7684 frontend server, \u4ee5\u6b64\u6765\u51cf\u5c11 latency.<\/p>\n<p>\u4f46\u53ea\u4f9d\u8d56 BGP \u4f1a\u5e26\u6765\u4e24\u4e2a\u95ee\u9898:<\/p>\n<ul>\n<li>\u67d0\u4e2a\u5730\u533a\u7684\u7528\u6237\u8fc7\u591a\u4f1a\u7ed9\u6700\u8fd1\u7684 frontend server \u5e26\u6765\u8fc7\u9ad8\u7684\u8d1f\u8f7d<\/li>\n<li>ISP \u7684 BGP \u8def\u7531\u4f1a\u91cd\u8ba1\u7b97, \u5f53 BGP routing \u53d8\u5316\u540e, \u8fdb\u884c\u4e2d\u7684 tcp connection \u4f1a\u88ab reset(\u540c\u4e00\u4e2a connection \u4e0a\u7684\u540e\u7eed\u6570\u636e\u5305\u88ab\u53d1\u9001\u5230\u4e0d\u540c\u7684 server, tcp session \u4e0d\u5b58\u5728\u4e8e\u65b0 server \u4e0a)<\/li>\n<\/ul>\n<p>\u4e3a\u4e86\u89e3\u51b3\u539f\u751f BGP anycast \u7684\u95ee\u9898, google \u5f00\u53d1\u4e86 Maglev, \u5373\u4f7f\u8def\u7531\u53d1\u751f\u4e86\u53d8\u5316(routing flap), connection \u4e5f\u4e0d\u65ad\u5f00, \u628a\u8fd9\u79cd\u65b9\u5f0f\u53eb\u505a stablized anycast.<\/p>"},{"title":"\u4ece\u53bb\u5e74\u7684\u4e00\u4e2apatch\u8bf4\u8d77","link":"https:\/\/blog.monsterxx03.com\/2018\/12\/29\/%E4%BB%8E%E5%8E%BB%E5%B9%B4%E7%9A%84%E4%B8%80%E4%B8%AApatch%E8%AF%B4%E8%B5%B7\/","pubDate":"Sat, 29 Dec 2018 15:14:46 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/12\/29\/%E4%BB%8E%E5%8E%BB%E5%B9%B4%E7%9A%84%E4%B8%80%E4%B8%AApatch%E8%AF%B4%E8%B5%B7\/","description":"<p>\u53bb\u5e74\u5bf9\u7ebf\u4e0a\u4e1a\u52a1\u505a\u4e86\u4e00\u4e9b\u6027\u80fd\u4f18\u5316, \u5f53\u65f6\u628a http client \u4ece requests \u6362\u6210\u4e86 geventhttpclient ,\n\u4e0a\u7ebf\u540e\u53d1\u8d77 rpc \u8c03\u7528\u7684 server \u6574\u4f53\u8d1f\u8f7d\u4f4e\u4e86\u5f88\u591a, \u4f46 client \u7aef latency \u5374\u9ad8\u4e86\u5f88\u591a, \u7ecf\u8fc7 debug\n\u89c9\u5f97\u95ee\u9898\u662f geventhttpclient \u628a header \u548c body \u901a\u8fc7\u4e24\u6b21 sock send \u53d1\u51fa\u7684\u989d\u5916\u5f00\u9500\u9020\u6210\u7684, \u5c1d\u8bd5\n\u4fee\u6539\u6210\u4e00\u6b21 send \u540e latency \u5c31\u6062\u590d\u4e86: <a href=\"https:\/\/github.com\/gwik\/geventhttpclient\/pull\/85\">https:\/\/github.com\/gwik\/geventhttpclient\/pull\/85<\/a><\/p>\n<p>\u6700\u8fd1\u5728\u8c03\u8bd5 gunicorn \u7684\u4ee3\u7801\u65f6\u5019, \u770b\u5230\u5b83\u5efa\u7acb socket \u7684\u65f6\u5019\u8bbe\u7f6e\u4e86 TCP_NODELAY, \u5728\u5f88\u591a\u9879\u76ee\u91cc\u770b\u5230\u8fc7\u8fd9\u4e2a\ntcp option, \u4f46\u6ca1\u7ec6\u7a76\u8fc7, <code>man tcp<\/code> \u5f97\u77e5\u662f\u7528\u6765\u5173\u95ed tcp \u91cc\u7684 nagle \u7b97\u6cd5\u7684. nagle \u5728 linux \u7684\n\u9ed8\u8ba4 tcp \u534f\u8bae\u6808\u91cc\u662f\u5f00\u542f\u7684, \u5f53\u53d1\u9001\u7684\u6570\u636e\u5305 size \u5c0f\u4e8e mss \u7684\u65f6\u5019\u4f1a\u5728\u5185\u5b58\u91cc buffer \u8d77\u6765, \u79ef\u7d2f\u8d77\u6765\u540e\u518d\u53d1\u9001,\n\u76ee\u7684\u662f\u63d0\u9ad8\u5e26\u5bbd\u5229\u7528\u7387, \u6bd5\u7adf payload \u53ea\u53d1\u4e00\u6b21\u5b57\u8282\u4e5f\u8981\u5e26\u4e0a 40 \u5b57\u8282\u7684 ip+tcp header.<\/p>"},{"title":"Kubernetes \u4e2d\u7684 pod \u8c03\u5ea6","link":"https:\/\/blog.monsterxx03.com\/2018\/12\/16\/kubernetes-%E4%B8%AD%E7%9A%84-pod-%E8%B0%83%E5%BA%A6\/","pubDate":"Sun, 16 Dec 2018 13:09:20 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/12\/16\/kubernetes-%E4%B8%AD%E7%9A%84-pod-%E8%B0%83%E5%BA%A6\/","description":"<p>\u5b9a\u4e49 pod \u7684\u65f6\u5019\u901a\u8fc7\u6dfb\u52a0 node selector \u53ef\u4ee5\u8ba9 pod \u8c03\u5ea6\u5230\u6709\u7279\u5b9a label \u7684 node \u4e0a\u53bb, \u8fd9\u662f\u6700\u7b80\u5355\u7684\u8c03\u5ea6\u65b9\u5f0f.\n\u5176\u4ed6\u8fd8\u6709\u66f4\u590d\u6742\u7684\u8c03\u5ea6\u65b9\u5f0f: node-taints\/tolerations, node-affinity, pod-affinity, \u6765\u8fbe\u5230\u8ba9\u67d0\u4e9b\u7c7b\u578b\u7684 pod \u8c03\u5ea6\u5230\u4e00\u8d77,\n\u8ba9\u67d0\u4e9b\u7c7b\u578b\u7684 pod \u4e0d\u8dd1\u4e00\u8d77\u7684\u6548\u679c.<\/p>\n<h2 id=\"taints-and-tolerations\">Taints and Tolerations<\/h2>\n<p>\u5982\u679c node \u6709 taints, \u90a3\u53ea\u6709\u80fd tolerate \u8fd9\u4e9b taints \u7684 pod \u624d\u80fd\u8c03\u5ea6\u5230\u4e0a\u9762.<\/p>\n<p>taint \u7684\u57fa\u672c\u683c\u5f0f\u662f: <code>&lt;key&gt;&lt;operator&gt;&lt;value&gt;:&lt;effect&gt;<\/code><\/p>\n<p><code>kubectl describe node xxx<\/code> \u53ef\u4ee5\u770b\u5230\u8282\u70b9\u7684 taints, \u6bd4\u5982 master \u8282\u70b9\u4e0a\u4f1a\u6709:<\/p>\n<pre><code>Taints:       node-role.kubernetes.io\/master:NoSchedule \n<\/code><\/pre>\n<p>\u8fd9\u91cc key \u662f <code>node-role.kubernetes.io\/master<\/code>, \u6ca1\u6709\u7b49\u53f7\u548c value, operator \u5c31\u662f <code>Exists<\/code> , effect \u662f <code>NoSchedule<\/code>.<\/p>\n<p>master \u8282\u70b9\u4e0a\u7684\u8fd9\u6761 taint \u5c31\u5b9a\u4e49\u4e86\u53ea\u6709\u80fd tolerate \u5b83\u7684 pod \u80fd\u8c03\u5ea6\u5230\u4e0a\u9762, \u4e00\u822c\u90fd\u662f\u4e9b\u7cfb\u7edf pod.<\/p>\n<p>\u6bd4\u5982\u770b\u4e0b kube-proxy: <code>kubectl describe pod kube-proxy-efiv -n kube-system<\/code><\/p>"},{"title":"Debug Skills on Linux","link":"https:\/\/blog.monsterxx03.com\/2018\/12\/03\/debug-skills-on-linux\/","pubDate":"Mon, 03 Dec 2018 22:47:51 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/12\/03\/debug-skills-on-linux\/","description":"<p>This post will show several commands used for debugging on linux server, all examples are tested on ubuntu 18.04,\nsome tools are not installed by default, you can installl by <code>sudo apt install xxx<\/code>.\nSome commands must be used via <code>sudo<\/code>.<\/p>\n<p>System resources can be classified in three main categories: compute, storage, and network.\nUsually, when you come to a performance issue, it&rsquo;s always caused by exhaustion of those\nresources.<\/p>\n<h2 id=\"universal-metric-system-load\">Universal metric: System load<\/h2>\n<p>There&rsquo;re several ways to get system load, <code>w<\/code>, <code>uptime<\/code>, <code>top<\/code>, <code>cat \/proc\/loadavg<\/code><\/p>\n<p><code>uptime<\/code> example:<\/p>\n<pre><code>03:34:23 up 20:31,  1 user,  load average: 1.02, 0.65, 0.45\n<\/code><\/pre>\n<p>Top right corner three values named <code>load average<\/code> is system load.<\/p>\n<p>They means: average system load during last minute\/last 5 minutes\/last 15 minutes periods.<\/p>\n<p>If <code>load\/(# of cpu core) &gt; 1<\/code>  means there&rsquo;re tasks pending in cpu queue. Usually, you will feel <strong>slow<\/strong>.<\/p>\n<p>It&rsquo;s different with cpu utilization. CPU utilization is a metrics shows how busy cpu is handling tasks.<\/p>\n<p>If system load is high, means tasks are pending in CPU queue, maybe a result of:<\/p>\n<ul>\n<li>High cpu usage.<\/li>\n<li>Poor disk performance(disk io).<\/li>\n<li>Exhaustion of ram.<\/li>\n<li>&hellip;<\/li>\n<\/ul>\n<h2 id=\"free\">free<\/h2>\n<p><code>free -k\/-m\/-g<\/code> show memory usage in KB\/MB\/GB<\/p>\n<p><code>free -h<\/code>  humanize output (automatically show in KB\/MB\/GB&hellip;)<\/p>"},{"title":"\u6742\u8c08","link":"https:\/\/blog.monsterxx03.com\/2018\/11\/30\/%E6%9D%82%E8%B0%88\/","pubDate":"Fri, 30 Nov 2018 17:39:00 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/11\/30\/%E6%9D%82%E8%B0%88\/","description":"<p>\u5c4b\u91cc\u6709\u4e24\u4e2a\u949f\uff0c\u4e00\u4e2a\u5feb 5 \u5206\u949f\uff0c\u3000\u4e00\u4e2a\u6162 5 \u5206\u949f,\u3000\u4e00\u76f4\u61d2\u5f97\u628a\u5b83\u4eec\u8c03\u6b63, \u6709\u79cd\u83ab\u540d\u7684\u65f6\u95f4\u6495\u88c2\u611f, \u597d\u50cf\u8fd8\u633a\u559c\u6b22.\u8fd8\u6709\u4e00\u4e2a\u6708 2018 \u5c31\u8fc7\u53bb\u4e86,\n\u6211\u60f3\u60f3\u6700\u8fd1\u90fd\u5e72\u561b\u4e86.<\/p>\n<h2 id=\"\u6700\u8fd1\u770b\u7684\u4e66\">\u6700\u8fd1\u770b\u7684\u4e66<\/h2>\n<p>\u8bfb\u5b8c\u4e86 <code>&lt;a philosophy of software design&gt;<\/code>, \u4e66\u662f\u597d\u4e66, \u5c31\u662f\u597d\u8d35(\u82b1\u4e86\u6211260&hellip;). \u672c\u6765\u60f3\u4e13\u95e8\u5199\u4e00\u7bc7\u7684,\u4f46\u5f00\u4e86\u4e2a\u5934\u53d1\u5374\u53d1\u73b0\u6ca1\u592a\u591a\u53ef\u5199\u7684. \u4e66\u91cc\u63d0\u5230\u7684\u95ee\u9898\u90fd\u78b0\u5230\u8fc7, \u89e3\u51b3\u65b9\u6cd5\u548c\u5efa\u8bae\u5176\u5b9e\u4e5f\u4e00\u76f4\u5728\u7528,\n\u6ca1\u6709\u4ec0\u4e48\u94f6\u5f39, \u7b49\u518d\u8df5\u884c\u4e00\u6bb5\u65f6\u95f4\u518d\u8bf4\u5427. PS: \u6536\u76ca\u6700\u5927\u7684\u662f\u8bb2\u6ce8\u91ca\u7684\u7ae0\u8282.<\/p>\n<p>\u6628\u665a\u770b\u5b8c\u4e86 <code>&lt;\u591c\u884c&gt;<\/code>. \u68ee\u89c1\u767b\u7f8e\u5f66\u7684\u4e66, \u6539\u7f16\u7684\u52a8\u753b\u5012\u662f\u770b\u8fc7\u4e0d\u5c11, \u4e66\u4ee5\u524d\u53ea\u770b\u8fc7 <code>&lt;\u6709\u9876\u5929\u5bb6\u65cf&gt;<\/code>. \u8fd9\u672c\u98ce\u683c\u5dee\u5f97\u633a\u8fdc,\u3000\u901a\u7bc7\u4e94\u91cc\u96fe\u4e2d\u7684\u611f\u89c9, \u6709\u70b9\u3000<code>&lt;1Q84&gt;<\/code>\u3000\u7684\u610f\u601d. &ldquo;\u4e16\u754c\u662f\u4e00\u573a\u591c&rdquo;, \u540e\u534a\u90e8\u5206\u770b\u5230\u8fd9\u53e5\u8bdd\u7684\u65f6\u5019, \u8d77\u4e86\u9e21\u76ae\u7599\u7629,\u3000\u591c\u884c\u548c\u66d9\u5149\u4e16\u754c\u91cc\u7684\u5cb8\u7530\u8fc7\u7740\u5b8c\u5168\u4e0d\u540c\u7684\u751f\u6d3b, \u5951\u673a\u53ea\u662f\u978d\u9a6c\u706b\u796d\u4e0a\u7684\u5076\u9047. \u662f\u4e0d\u662f\u771f\u7684\u5b58\u5728\u4e00\u4e2a\u548c\u73b0\u5b9e\u5b8c\u5168\u5bf9\u7acb\u7684\u4e16\u754c, \u8de8\u8d8a\u7684\u5206\u754c\u7ebf\u53ea\u662f\u90a3\u4e00\u70b9\u70b9\u5951\u673a?\u90a3\u4e2a\u4e16\u754c\u7684\u81ea\u5df1\u53c8\u8fc7\u5f97\u5230\u597d\u8fd8\u662f\u5dee\u5462?\u3000<\/p>"},{"title":"\u7528 Bloom filter \u7ed9\u63a8\u8350\u5217\u8868\u53bb\u91cd","link":"https:\/\/blog.monsterxx03.com\/2018\/11\/17\/%E7%94%A8-bloom-filter-%E7%BB%99%E6%8E%A8%E8%8D%90%E5%88%97%E8%A1%A8%E5%8E%BB%E9%87%8D\/","pubDate":"Sat, 17 Nov 2018 13:58:27 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/11\/17\/%E7%94%A8-bloom-filter-%E7%BB%99%E6%8E%A8%E8%8D%90%E5%88%97%E8%A1%A8%E5%8E%BB%E9%87%8D\/","description":"<p>\u4e4b\u524d\u4ea7\u54c1\u91cc\u6709\u4e00\u4e2a\u529f\u80fd\u662f\u6bcf\u5929\u7ed9\u7528\u6237\u63a8\u8350\u4e00\u6279\u6587\u7ae0,\u8981\u4fdd\u8bc1\u6700\u540e\u63a8\u7ed9\u7528\u6237\u7684\u6587\u7ae0\u6bcf\u5929\u4e0d\u91cd\u590d. \u539f\u5148\u7684\u5b9e\u73b0\u5f88\u76f4\u63a5, \u6bcf\u6b21\u63a8\u9001\u65f6\u5019\u8bb0\u5f55\u4e0b\u7528\u6237 id \u548c topic id \u7684\u952e\u503c\u5bf9, \u62ff\u5230\u65b0 topic \u5217\u8868\u540e,\u53d6\u51fa\u66fe\u7ecf\u7ed9\u8be5\u7528\u6237\u63a8\u9001\u8fc7\u7684\u6587\u7ae0\u5217\u8868, \u4e24\u4e2a set \u53bb\u91cd.<\/p>\n<p>\u8fd9\u4e2a\u5b9e\u73b0\u7684\u95ee\u9898\u5f88\u660e\u663e, \u5b58\u50a8\u7a7a\u95f4\u91cf\u592a\u5927(M * N), user id (int64) + topic id (int64) = 16 bytes, 1 million \u7684\u7528\u6237, \u6bcf\u5929\u7ed9\u7528\u6237\u63a8\u900110\u7bc7\u6587\u7ae0, \u4e00\u5e74\u8981\u5b58\u50a8: 16 * 10 * 365 * 1M = 54.4GB. \u67e5\u8be2\u6548\u7387\u4e5f\u5f88\u4f4e,\u8981\u4e48\u4e00\u6b21\u53d6\u6240\u6709\u5df2\u8bfb topic id, \u8981\u4e48\u628a\u8981\u63a8\u9001\u7684 topic id \u90fd\u4e22\u8fdb\u6570\u636e\u5e93\u53bb\u91cd.<\/p>"},{"title":"\u6fd1\u6237\u5185\u6d77\u7684\u98ce\u4e0e\u9633","link":"https:\/\/blog.monsterxx03.com\/2018\/11\/04\/%E6%BF%91%E6%88%B7%E5%86%85%E6%B5%B7%E7%9A%84%E9%A3%8E%E4%B8%8E%E9%98%B3\/","pubDate":"Sun, 04 Nov 2018 23:31:07 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/11\/04\/%E6%BF%91%E6%88%B7%E5%86%85%E6%B5%B7%E7%9A%84%E9%A3%8E%E4%B8%8E%E9%98%B3\/","description":"<p>\u4e0a\u6708\u4f11\u5047\u53bb\u6fd1\u6237\u5185\u6d77\u6e9c\u8fbe\u4e86\u4e00\u5708, \u4e00\u4e2a\u6bd4\u60f3\u8c61\u4e2d\u7f8e\u592a\u591a\u7684\u5730\u65b9.<\/p>\n<p>\u5bf9\u6fd1\u6237\u5185\u6d77\u7684\u5370\u8c61, \u8981\u8ffd\u6eaf\u5230\u9ad8\u4e2d\u65f6\u770b\u7684\u4e00\u90e8\u641e\u7b11\u756a &lt;\u6fd1\u6237\u82b1\u5ac1&gt;, \u633a\u6709\u610f\u601d\u7684\u7247\u5b50, \u7206\u7b11\u4e4b\u4f59, \u5bf9\u6fd1\u6237\u5185\u6d77\u8fd9\u4e2a\u5730\u65b9\u6709\u4e86\u6a21\u6a21\u7cca\u7cca\u7684\u5370\u8c61.<\/p>\n<p>\u53bb\u5e74\u53bb\u4e86\u9752\u68ee\u548c\u4e5d\u5dde, \u5c31\u60f3\u7740\u518d\u53bb\u4e2a\u65e5\u672c\u7284\u89d2\u65ee\u65ef\u7684\u5730\u5427, \u56db\u56fd\u5c31\u88ab\u63d0\u4e0a\u4e86\u65e5\u7a0b, \u7a0d\u505a\u653b\u7565, \u53d1\u73b0\u6fd1\u6237\u5185\u6d77\u5c31\u8fd9\u91cc, \u5174\u8da3\u6765\u4e86.<\/p>\n<p>\u660e\u5e74\u4e09\u6708\u7684\u65f6\u5019\u6fd1\u6237\u5185\u6d77\u6709\u827a\u672f\u796d, \u90a3\u4f1a\u4f30\u8ba1\u5c31\u88ab\u4e16\u754c\u5404\u5730\u7684\u4eba\u7ed9\u6324\u7206\u4e86, \u4e0d\u51d1\u8fd9\u70ed\u95f9, \u8fd8\u662f10\u6708\u53bb\u5427.<\/p>\n<p>\u5927\u81f4\u884c\u7a0b: \u4e0a\u6d77 -&gt; \u9ad8\u677e -&gt; \u5c0f\u8c46\u5c9b -&gt; \u4e30\u5c9b -&gt; \u76f4\u5c9b. \u9664\u4e86\u5728\u5c0f\u8c46\u5c9b\u4e0a\u5446\u4e86\u4e00\u665a\u4e0a\uff0c\u5176\u4ed6\u65f6\u5019\u90fd\u4f4f\u5728\u4e86\u9ad8\u677e.<\/p>"},{"title":"AWS Aurora DB","link":"https:\/\/blog.monsterxx03.com\/2018\/10\/31\/aws-aurora-db\/","pubDate":"Wed, 31 Oct 2018 15:23:45 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/10\/31\/aws-aurora-db\/","description":"<p>\u6700\u8fd1\u5728\u628a\u90e8\u5206\u7528 RDS \u7684 MySQL \u8fc1\u79fb\u5230 aurora \u4e0a\u53bb, \u8bfb\u4e86\u4e0b aurora \u7684 paper, \u987a\u4fbf\u548c RDS \u7684\u67b6\u6784\u505a\u4e9b\u5bf9\u6bd4.<\/p>\n<h2 id=\"paper-notes\">Paper notes<\/h2>\n<ul>\n<li>\u5b58\u50a8\u8ba1\u7b97\u5206\u79bb<\/li>\n<li>redo log \u4e0b\u63a8\u5230\u5b58\u50a8\u5c42<\/li>\n<li>\u526f\u672c: 6 \u526f\u672c 3 AZ(2 per az), \u5931\u53bb\u4e00\u4e2a AZ + 1 additoinal node \u4e0d\u4f1a\u4e22\u6570\u636e(\u53ef\u8bfb\u4e0d\u53ef\u5199). \u5931\u53bb\u4e00\u4e2a AZ (\u6216\u4efb\u610f2 node) \u4e0d\u5f71\u54cd\u6570\u636e\u5199\u5165.<\/li>\n<li>10GB \u4e00\u4e2a segment, \u6bcf\u4e2a segment 6 \u526f\u672c\u4e00\u4e2a PG (protection group), \u4e00 AZ\u3000\u4e24\u526f\u672c.<\/li>\n<li>\u5728 10Gbps \u7684\u7f51\u7edc\u4e0a, \u4fee\u590d\u4e00\u4e2a 10GB \u7684segment \u9700\u8981 10s.<\/li>\n<\/ul>\n<p>MySQL \u4e00\u4e2a\u5e94\u7528\u5c42\u7684\u5199\u4f1a\u5728\u5e95\u5c42\u4ea7\u751f\u5f88\u591a\u989d\u5916\u7684\u5199\u64cd\u4f5c\uff0c\u4f1a\u5e26\u6765\u5199\u653e\u5927\u95ee\u9898:<\/p>\n<p><img src=\"https:\/\/blog.monsterxx03.com\/posts\/images\/aurora-mysql-replication.png\" alt=\"\"><\/p>\n<p>redo log \u7528\u6765 crash recovery, binlog \u4f1a\u4e0a\u4f20 s3\u3000\u7528\u4e8e point in time restore.<\/p>\n<p>\u5728 aurora \u91cc\uff0c\u53ea\u6709 redo log \u4f1a\u901a\u8fc7\u7f51\u7edc\u590d\u5236\u5230\u5404\u4e2a replica, master \u4f1a\u7b49\u5f85 4\/6 replicas \u5b8c\u6210 redo log \u7684\u5199\u5165\u5c31\u8ba4\u4e3a\u5199\u5165\u6210\u529f (\u6240\u4ee5\u5931\u53bb3\u526f\u672c\u5c31\u65e0\u6cd5\u5199\u5165\u6570\u636e\u4e86). \u5176\u4ed6\u526f\u672c\u4f1a\u6839\u636e redo log \u91cd\u5efa\u6570\u636e(\u5355\u72ec\u7684 redo log applicator \u8fdb\u7a0b).<\/p>"},{"title":"\u4e3a service \u5236\u5b9a SLO","link":"https:\/\/blog.monsterxx03.com\/2018\/10\/15\/%E4%B8%BA-service-%E5%88%B6%E5%AE%9A-slo\/","pubDate":"Mon, 15 Oct 2018 11:31:05 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/10\/15\/%E4%B8%BA-service-%E5%88%B6%E5%AE%9A-slo\/","description":"<p>\u901a\u5e38\u6211\u4eec\u4f7f\u7528\u4e91\u670d\u52a1\u7684\u65f6\u5019, \u670d\u52a1\u63d0\u4f9b\u5546\u4f1a\u63d0\u4f9b SLA(Service Level Aggrement),\u4f5c\u4e3a\u4ed6\u4eec\u63d0\u4f9b\u7684\u670d\u52a1\u8d28\u91cf\u7684\u6807\u51c6(\u5e38\u8bf4\u7684\u51e0\u4e2a9),\u8fbe\u4e0d\u5230\u4f1a\u8fdb\u884c\u8d54\u507f.\n\u6bd4\u5982 AWS \u7684\u8ba1\u7b97\u7c7b\u670d\u52a1: <a href=\"https:\/\/aws.amazon.com\/compute\/sla\/\">https:\/\/aws.amazon.com\/compute\/sla\/<\/a> .<\/p>\n<p>\u5bf9\u516c\u53f8\u81ea\u5df1 host \u7684 service, \u6211\u4eec\u5185\u90e8\u4e5f\u9700\u8981\u4e00\u4e9b\u6280\u672f\u6307\u6807\u6765 track \u6211\u4eec\u4e3a\u5ba2\u6237\u63d0\u4f9b\u7684\u670d\u52a1\u8d28\u91cf\u5982\u4f55, \u8fd9\u4e2a\u53eb\u505a\nSLO(Service Level Objective). \u4e5f\u53ef\u4ee5\u628a\u4ed6\u5f53\u6210\u4e00\u4e2a\u5bf9\u5185\u7684,\u6ca1\u6709\u8d54\u507f\u534f\u8bae\u7684SLA.<\/p>\n<h2 id=\"\u5b9a\u4e49\u6307\u6807\">\u5b9a\u4e49\u6307\u6807<\/h2>\n<p>\u6211\u4e3b\u8981 track \u4e24\u4e2a\u6307\u6807:<\/p>\n<ul>\n<li>Availability (\u670d\u52a1\u7684\u53ef\u7528\u6027)<\/li>\n<li>Quality (\u670d\u52a1\u8d28\u91cf)<\/li>\n<\/ul>\n<p>Availability \u7684\u5b9a\u4e49, \u4ee5\u524d\u7528\u7b80\u5355\u7684 service  uptime \u6765\u5b9a\u4e49, \u5728\u96c6\u7fa4\u5916\u90e8\u7528\u4e00\u4e2a service check \u5b9a\u65f6 ping \u6211\u4eec service\u3000\u7684 check endpoint,\n\u5931\u8d25\u5c31\u5b9a\u4e49\u4e3a failure.<\/p>"},{"title":"\u5728 redshift \u4e2d\u8ba1\u7b97 p95 latency","link":"https:\/\/blog.monsterxx03.com\/2018\/10\/12\/%E5%9C%A8-redshift-%E4%B8%AD%E8%AE%A1%E7%AE%97-p95-latency\/","pubDate":"Fri, 12 Oct 2018 14:49:13 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/10\/12\/%E5%9C%A8-redshift-%E4%B8%AD%E8%AE%A1%E7%AE%97-p95-latency\/","description":"<p>p95 latency \u7684\u5b9a\u4e49: \u628a\u4e00\u6bb5\u65f6\u95f4\u7684 latency \u6309\u7167\u4ece\u5c0f\u5230\u5927\u6392\u5e8f, \u780d\u6389\u6700\u9ad8\u7684 %5, \u5269\u4e0b\u6700\u5927\u7684\u503c\u5c31\u662f p95 latency. p99, p90 \u540c\u7406.<\/p>\n<p>p95 latency \u8868\u793a\u8be5\u65f6\u95f4\u6bb5\u5185 95% \u7684 reqeust \u90fd\u6bd4\u8fd9\u4e2a\u503c\u5feb.<\/p>\n<p>\u4e00\u822c\u6211\u76f4\u63a5\u770b CloudWatch, \u548c datadog \u7b97\u597d\u7684 p95 \u503c. \u8fd9\u6b21\u770b\u770b\u600e\u4e48\u4ece access log \u91cc\u76f4\u63a5\u8ba1\u7b97 p95 latency.<\/p>\n<p>\u5047\u8bbe\u5728 redshift \u4e2d\u6709\u4e00\u5f20\u8868\u5b58\u50a8\u4e86\u5e94\u7528\u7684 access log, \u7ed3\u6784\u5982\u4e0b:<\/p>\n<pre><code>CREATE TABLE access_log (\n    url         string,\n    time        string,\n    resp_time   real\n);\n<\/code><\/pre>\n<table>\n  <thead>\n      <tr>\n          <th>url<\/th>\n          <th>time<\/th>\n          <th>resp_time<\/th>\n      <\/tr>\n  <\/thead>\n  <tbody>\n      <tr>\n          <td>\/test1<\/td>\n          <td>2018-10-11T00:10:00.418480Z<\/td>\n          <td>0.123<\/td>\n      <\/tr>\n      <tr>\n          <td>\/test2<\/td>\n          <td>2018-10-11T00:12:00.512340Z<\/td>\n          <td>0.321<\/td>\n      <\/tr>\n  <\/tbody>\n<\/table>\n<p>\u8981\u7b97 p95 \u5f88\u7b80\u5355, \u628a log \u6309\u5206\u949f\u6570\u5206\u7ec4, \u7528 <code>percentile_cont<\/code> \u5728\u7ec4\u5185\u6309 <code>resp_time<\/code> \u6392\u5e8f\u8ba1\u7b97 \u5c31\u80fd\u5f97\u5230:<\/p>\n<pre><code>select date_trunc('minute', time::timestamp) as ts,\n      percentile_cont(0.95) within group(order by resp_time) as p95\nfrom access_log \ngroup by 1\norder by 1;\n<\/code><\/pre>\n<p>\u5f97\u5230:<\/p>\n<pre><code>     ts          |        p95\n---------------------+-------------------\n 2018-10-11 00:00:00 |  0.71904999999995\n 2018-10-11 00:01:00 | 0.555550000000034\n 2018-10-11 00:02:00 | 0.478999999999939\n 2018-10-11 00:03:00 | 0.507250000000081\n 2018-10-11 00:04:00 | 0.456000000000025\n 2018-10-11 00:05:00 | 0.458999999999949\n 2018-10-11 00:06:00 | 0.581000000000054\n 2018-10-11 00:07:00 | 0.585099999999937\n 2018-10-11 00:08:00 | 0.527999999999908\n 2018-10-11 00:09:00 | 0.570999999999936\n 2018-10-11 00:10:00 | 0.587950000000069\n 2018-10-11 00:11:00 | 0.648900000000077\n 2018-10-11 00:12:00 | 0.570000000000024\n 2018-10-11 00:13:00 | 0.592649999999954\n 2018-10-11 00:14:00 | 0.584149999999998\n 2018-10-11 00:15:00 |  3.00854999999952\n 2018-10-11 00:16:00 | 0.832999999999871\n 2018-10-11 00:17:00 |  1.07154999999991\n 2018-10-11 00:18:00 | 0.553600000000092\n 2018-10-11 00:19:00 | 0.605799999999997\n 2018-10-11 00:20:00 | 0.832000000000137\n ...\n<\/code><\/pre>\n<p><code>PERCENTILE_CONT<\/code> \u662f\u9006\u5206\u5e03\u51fd\u6570, \u7ed9\u5b9a\u4e00\u4e2a\u767e\u5206\u6bd4, \u5728\u4e00\u4e2a\u8fde\u7eed\u5206\u5e03\u6a21\u578b\u4e0a\u8ba1\u7b97\u8be5\u767e\u5206\u6bd4\u5904\u7684\u6570\u503c, \u5982\u679c\u5728\u8be5\u70b9\u5904\u6ca1\u6709\u6570\u636e, \u4f1a\u6839\u636e\u6700\u63a5\u8fd1\u7684\u524d\u540e\u503c\u8fdb\u884c\u63d2\u503c\u8ba1\u7b97\u51fa\u5b9e\u9645\u503c.<\/p>"},{"title":"EkS \u8bc4\u6d4b part-3","link":"https:\/\/blog.monsterxx03.com\/2018\/09\/26\/eks-%E8%AF%84%E6%B5%8B-part-3\/","pubDate":"Wed, 26 Sep 2018 10:16:42 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/09\/26\/eks-%E8%AF%84%E6%B5%8B-part-3\/","description":"<p>\u8fd9\u7bc7\u8bb0\u5f55\u5bf9 ingress \u7684\u6d4b\u8bd5.<\/p>\n<p>ingress \u7528\u6765\u5c06\u5916\u90e8\u6d41\u91cf\u5bfc\u5165\u3000k8s \u5185\u7684\u3000service. \u5c06 service \u7684\u7c7b\u578b\u8bbe\u7f6e\u4e3a LoadBalancer \/ NodePort \u4e5f\u53ef\u4ee5\u5c06\u5355\u4e2a service \u66b4\u9732\u5230\u516c\u7f51, \u4f46\u7528 ingress \u53ef\u4ee5\u53ea\u4f7f\u7528\u4e00\u4e2a\u516c\u7f51\u5165\u53e3,\u6839\u636e\u3000host name \u6216\u3000url path \u6765\u5c06\u8bf7\u6c42\u5206\u53d1\u5230\u4e0d\u540c\u7684 service.<\/p>\n<p>\u4e00\u822c\u3000k8s \u5185\u7684\u8d44\u6e90\u90fd\u4f1a\u7531\u4e00\u4e2a controller \u6765\u8d1f\u8d23\u5b83\u7684\u72b6\u6001\u7ba1\u7406, \u90fd\u7531 kube-controller-manager \u8d1f\u8d23\uff0c\u3000\u4f46 ingress controller \u4e0d\u662f\u5b83\u7684\u4e00\u90e8\u5206\uff0c\u9700\u8981\u662f\u89c6\u60c5\u51b5\u81ea\u5df1\u9009\u62e9\u5408\u9002\u7684 ingress controller.<\/p>\n<p>\u5728 eks \u4e0a\u6211\u4e3b\u8981\u9700\u8981 <a href=\"https:\/\/github.com\/kubernetes\/ingress-nginx\">ingress-nginx<\/a> \u548c <a href=\"https:\/\/github.com\/kubernetes-sigs\/aws-alb-ingress-controller\">aws-alb-ingress-controller<\/a>. \u6ce8\u610f, nginx inc \u8fd8\u7ef4\u62a4\u4e00\u4e2a <a href=\"https:\/\/github.com\/nginxinc\/kubernetes-ingress\">kubernetes-ingress<\/a>, \u548c\u5b98\u65b9\u90a3\u4e2a\u4e0d\u662f\u4e00\u4e2a\u4e1c\u897f\uff0c \u6ca1\u6d4b\u8bd5\u8fc7.<\/p>\n<p>\u8fd9\u91cc\u4e3b\u8981\u53ea\u6d4b\u8bd5\u4e86 ingress-nginx, \u770b\u4e86\u4e0b\u5185\u90e8\u5b9e\u73b0, \u6570\u636e\u7684\u8f6c\u53d1\u771f\u626d\u66f2&hellip;.<\/p>"},{"title":"eks \u8bc4\u6d4b part-2","link":"https:\/\/blog.monsterxx03.com\/2018\/09\/21\/eks-%E8%AF%84%E6%B5%8B-part-2\/","pubDate":"Fri, 21 Sep 2018 10:28:17 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/09\/21\/eks-%E8%AF%84%E6%B5%8B-part-2\/","description":"<p>\u4e0a\u6587\u6d4b\u8bd5\u4e86\u4e00\u4e0b EKS \u548c cluster autoscaler, \u672c\u6587\u8bb0\u5f55\u5bf9 persisten volume \u7684\u6d4b\u8bd5.<\/p>\n<h1 id=\"persistentvolume\">PersistentVolume<\/h1>\n<p>\u521b\u5efa gp2 \u7c7b\u578b\u7684 storageclass, \u5e76\u7528 annotations \u8bbe\u7f6e\u4e3a\u9ed8\u8ba4 sc, dynamic volume provision \u4f1a\u7528\u5230:<\/p>\n<pre><code>kind: StorageClass\napiVersion: storage.k8s.io\/v1\nmetadata:\n    name: gp2\n    annotations:\n        storageclass.kubernetes.io\/is-default-class: &quot;true&quot;\nprovisioner: kubernetes.io\/aws-ebs\nreclaimPolicy: Retain\nparameters:\n    type: gp2\n    fsType: ext4\n    encrypted: &quot;true&quot;\n<\/code><\/pre>\n<p>\u56e0\u4e3a eks \u662f\u57fa\u4e8e 1.10.3 \u7684, volume expansion \u8fd8\u662f alpha \u72b6\u6001, \u6ca1\u6cd5\u81ea\u52a8\u5f00\u542f(\u6ca1\u6cd5\u6539 api server \u914d\u7f6e), \u6240\u4ee5 storageclass \u7684 allowVolumeExpansion, \u8bbe\u7f6e\u4e86\u4e5f\u6ca1\u7528.\n\u8fd9\u91cc <code>encrypted<\/code> \u7684\u503c\u5fc5\u987b\u662f\u5b57\u7b26\u4e32, \u5426\u5219\u4f1a\u521b\u5efa\u5931\u8d25, \u800c\u4e14\u62a5\u9519\u83ab\u540d\u5176\u5999.<\/p>\n<h2 id=\"\u521b\u5efa-pod-\u7684\u65f6\u5019\u6307\u5b9a\u4e00\u4e2a\u5df2\u5b58\u5728\u7684-ebs-volume\">\u521b\u5efa pod \u7684\u65f6\u5019\u6307\u5b9a\u4e00\u4e2a\u5df2\u5b58\u5728\u7684 ebs volume<\/h2>\n<pre><code>apiVersion: v1\nkind: Pod\nmetadata:\n    name: test\nspec:\n    volumes:\n        - name: test\n          awsElasticBlockStore:\n              fsType: ext4\n              volumeID: vol-03670d6294ccf29fd\n    containers:\n        - image: nginx\n          name: nginx\n          volumeMounts:\n              - name: test\n                mountPath: \/mnt\n<\/code><\/pre>\n<p><code>kubectl -it test -- \/bin\/bash<\/code>  \u8fdb\u53bb\u770b\u4e00\u4e0b:<\/p>\n<pre><code>root@test:\/# df -h\nFilesystem      Size  Used Avail Use% Mounted on\noverlay          20G  2.2G   18G  11% \/\ntmpfs           3.9G     0  3.9G   0% \/dev\ntmpfs           3.9G     0  3.9G   0% \/sys\/fs\/cgroup\n\/dev\/xvdcz      976M  2.6M  907M   1% \/mnt\n\/dev\/xvda1       20G  2.2G   18G  11% \/etc\/hosts\nshm              64M     0   64M   0% \/dev\/shm\ntmpfs           3.9G   12K  3.9G   1% \/run\/secrets\/kubernetes.io\/serviceaccount\ntmpfs           3.9G     0  3.9G   0% \/sys\/firmware\n<\/code><\/pre>\n<p>\u90a3\u5757 volume \u7684\u786e\u7ed1\u5b9a\u5728 <code>\/mnt<\/code><\/p>"},{"title":"EKS \u8bc4\u6d4b","link":"https:\/\/blog.monsterxx03.com\/2018\/09\/11\/eks-%E8%AF%84%E6%B5%8B\/","pubDate":"Tue, 11 Sep 2018 15:02:22 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/09\/11\/eks-%E8%AF%84%E6%B5%8B\/","description":"<p>EKS \u6b63\u5f0f launch \u8fd8\u6ca1\u6709\u6b63\u7ecf\u7528\u8fc7, \u6700\u8fd1\u603b\u7b97\u8bd5\u4e86\u4e00\u628a, \u8bb0\u5f55\u4e00\u70b9.<\/p>\n<h2 id=\"setup\">Setup<\/h2>\n<p>AWS \u5b98\u65b9\u7684 Guide \u53ea\u63d0\u4f9b\u4e86\u4e00\u4e2a cloudformation template \u6765\u8bbe\u7f6e worker node, \u6211\u559c\u6b22\u7528 terraform, \u53ef\u4ee5\u8ddf\u7740\u8fd9\u4e2a\u6587\u6863\u5c1d\u8bd5:https:\/\/www.terraform.io\/docs\/providers\/aws\/guides\/eks-getting-started.html \u6765\u8bbe\u7f6e\u5b8c\u6574\u7684 eks cluster \u548c\u7ba1\u7406 worker node \u7684 autoscaling  group.<\/p>\n<p>\u8bbe\u7f6e\u5b8c EKS \u540e\u9700\u8981\u6dfb\u52a0\u4e00\u6761 ConfigMap:<\/p>\n<pre><code>apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: aws-auth\n  namespace: kube-system\ndata:\n  mapRoles: |\n    - rolearn: arn:aws:iam::&lt;account-id&gt;:role\/eksNodeRole\n      username: system:node:{{EC2PrivateDNSName}}\n      groups:\n        - system:bootstrappers\n        - system:nodes\n<\/code><\/pre>\n<p>\u8fd9\u6837 worker node \u8282\u70b9\u624d\u80fd\u52a0\u5165\u96c6\u7fa4.<\/p>\n<h2 id=\"\u7f51\u7edc\">\u7f51\u7edc<\/h2>\n<p>\u4e4b\u524d\u4e00\u76f4\u6ca1\u6709\u5728 AWS \u4e0a\u5c1d\u8bd5\u6784\u5efa k8s \u7684\u4e00\u4e2a\u539f\u56e0, \u5c31\u662f\u4e0d\u559c\u6b22 overlay \u7f51\u7edc, \u7ed9\u7cfb\u7edf\u5e26\u6765\u4e86\u989d\u5916\u7684\u590d\u6742\u5ea6\u548c\u7ba1\u7406\u5f00\u9500, VPC flowlog \u770b\u4e0d\u5230 pod \u4e4b\u95f4\u6d41\u91cf, \u5c01\u5305\u540e tcpdump \u4e0d\u597d debug \u5e94\u7528\u5c42\u6d41\u91cf.<\/p>"},{"title":"Kubernetes in Action Notes","link":"https:\/\/blog.monsterxx03.com\/2018\/09\/03\/kubernetes-in-action-notes\/","pubDate":"Mon, 03 Sep 2018 18:20:46 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/09\/03\/kubernetes-in-action-notes\/","description":"<p>Miscellaneous notes when reading <code>&lt;Kubernetes in Action&gt;<\/code>.<\/p>\n<h2 id=\"api-group-and-api-version\">api group and api version<\/h2>\n<p>core api group need&rsquo;t specified in <code>apiVersion<\/code> field.<\/p>\n<p>For example, <code>ReplicationController<\/code> is on core api group, so only:<\/p>\n<pre><code>apiVersion: v1\nkind: ReplicationController\n...\n<\/code><\/pre>\n<p><code>ReplicationSet<\/code> is added later in <code>app<\/code> group, <code>v1beta2<\/code> version (k8s v1.8):<\/p>\n<pre><code>apiVersion: apps\/v1beta2            1\nkind: ReplicaSet           \n<\/code><\/pre>\n<p><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/overview\/kubernetes-api\/\">https:\/\/kubernetes.io\/docs\/concepts\/overview\/kubernetes-api\/<\/a><\/p>\n<h3 id=\"replicationcontroller-vs-replicationset\">ReplicationController VS ReplicationSet<\/h3>\n<p>ReplicationController is replaced by ReplicationSet, which has more expressive pod selectors.<\/p>\n<p>ReplicationController&rsquo;s label selector only allows matching pods that include a certain label, ReplicationSet can\nmeet multi labels at same time.<\/p>\n<p>rs also support operator on key value: <code>In, NotIn, Exists, DoesNotExist<\/code><\/p>\n<p>If migrate from rc to rs, can delete rc with <code>--cascade=false<\/code> option, it will delete\nrc only, but left pods running, then we can create a rs with same selector to make pods under management.<\/p>\n<h3 id=\"daemonset\">DaemonSet<\/h3>\n<p>DaemonSet ensures pod run exact one copy on one node, useful for processes like monitor agent and log collector. Use <code>node-selector<\/code>\nto make ds only run on specific nodes.<\/p>\n<p>If node is made unschedulable, normal pods won&rsquo;t be scheduled to deploy on them, but ds will still be deployed to it, since ds will bypass\nscheduler.<\/p>\n<h3 id=\"job\">Job<\/h3>\n<p>Job is used to run a single completable task.<\/p>"},{"title":"\u6742\u8c08","link":"https:\/\/blog.monsterxx03.com\/2018\/09\/01\/%E6%9D%82%E8%B0%88\/","pubDate":"Sat, 01 Sep 2018 12:03:42 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/09\/01\/%E6%9D%82%E8%B0%88\/","description":"<p>\u5fd9\u4e86\u597d\u4e00\u9635, \u4e24\u4e2a\u6708\u6ca1\u5199\u4e86, \u5de5\u4f5c\u4e0a\u7684\u4e8b\u544a\u4e00\u6bb5\u843d, \u4e5f\u8be5\u8865\u4e0a\u8fd9\u7b14\u5e10\u4e86, \u8001\u89c4\u77e9, \u968f\u4fbf\u5199\u5199 :)<\/p>\n<h2 id=\"\u6700\u8fd1\u5728\u505a\u4ec0\u4e48\">\u6700\u8fd1\u5728\u505a\u4ec0\u4e48?<\/h2>\n<p>\u628a\u516c\u53f8\u7684\u4ee3\u7801\u73af\u5883\u4ece python 2.7 \u5347\u7ea7\u5230 python3.6, \u524d\u540e\u5fd9\u4e86 3 \u4e2a\u6708, 50w \u884c\u4ee3\u7801, \u4e5f\u662f\u591f\u545b, \u597d\u6b79\u7b97\u662f\u987a\u5229\u5b8c\u6210\u4e86, \u5177\u4f53\u7684\u8fc7\u7a0b6\u6708\u96f6\u6563\u5199\u8fc7\n\u51e0\u7bc7\u6587\u7ae0, \u5927\u5dee\u4e0d\u5dee, \u540e\u7eed\u53c8\u78b0\u4e86\u4e0d\u5c11\u5751, \u4f46\u4e5f\u90fd\u80fd\u89e3\u51b3. \u4e0b\u4e00\u6b65\u6253\u7b97\u57fa\u4e8e python3 \u7684\u4e00\u4e9b\u7279\u6027\u5bf9\u4ee3\u7801\u505a\u4e9b\u91cd\u6784, \u4ece\u57fa\u7840\u5e93\u5f00\u59cb\u5427.<\/p>\n<h2 id=\"\u6700\u8fd1\u770b\u4e86\u4ec0\u4e48\u4e66\">\u6700\u8fd1\u770b\u4e86\u4ec0\u4e48\u4e66?<\/h2>\n<p>&lt;\u7279\u522b\u7684\u732b&gt;, \u7279\u522b\u559c\u6b22\u7684\u4e00\u672c\u4e66, \u4e0d\u662f\u90a3\u79cd\u732b\u5974\u4e00\u6627\u8d5e\u7f8e\u732b\u54aa\u591a\u4e48\u591a\u4e48\u53ef\u7231\u7684\u6587\u5b57, \u4f5c\u8005\u548c\u732b\u54aa\u8fc7\u4e86\u4e00\u8f88\u5b50, \u628a\u5b83\u4eec\u5f53\u6210\u81ea\u5df1\u7684\u670b\u53cb, \u5bb6\u4eba\u4e00\u6837\u5bf9\u5f85, \u8feb\u4e8e\u65e0\u5948\u5bf9\u732b\u505a\u8fc7\u6b8b\u9177\u7684\u4e8b\u60c5, \u4e5f\u5c3d\u529b\u7167\u987e\u8fc7\u75c5\u75db\u4e2d\u7684\u732b,\u628a\u5b83\u4ece\u6b7b\u4ea1\u8fb9\u7f18\u62c9\u56de\u6765\u8fc7, \u732b\u7ed9\u5979\u5e26\u6765\u7684\u5feb\u4e50\u548c\u70e6\u607c\u90fd\u5728\u8fd9\u672c\u4e66\u91cc. \u8bfb\u7740\u8bfb\u7740, \u4f1a\u4ea7\u751f\u4e00\u79cd\u9519\u89c9, \u90a3\u4e00\u4e2a\u4e2a\u7cbe\u7075\u53e4\u602a\u7684\u5c0f\u4e1c\u897f\u5c31\u81ea\u5df1\u811a\u8fb9\u8f6c\u60a0. \u4f5c\u8005\u662f\u4e00\u4e2a\u61c2\u751f\u6d3b\u7684\u4eba, \u592a\u7fa1\u6155\u4e86.<\/p>"},{"title":"\u5347\u7ea7celery \u5230 4.2.0 \u78b0\u5230\u7684\u5751","link":"https:\/\/blog.monsterxx03.com\/2018\/06\/22\/%E5%8D%87%E7%BA%A7celery-%E5%88%B0-4.2.0-%E7%A2%B0%E5%88%B0%E7%9A%84%E5%9D%91\/","pubDate":"Fri, 22 Jun 2018 16:10:41 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/06\/22\/%E5%8D%87%E7%BA%A7celery-%E5%88%B0-4.2.0-%E7%A2%B0%E5%88%B0%E7%9A%84%E5%9D%91\/","description":"<p>\u5728\u628a\u4ee3\u7801\u5f80 python3 \u8fc1\u79fb\u7684\u8fc7\u7a0b\u4e2d\u9700\u8981\u5347\u7ea7\u4e00\u4e9b\u7b2c\u4e09\u65b9\u5e93, \u5347\u7ea7\u4e86 gevent \u540e\u53d1\u73b0 celery \u6709\u95ee\u9898, \u4e8e\u662f\u5c1d\u8bd5\u628a celery \u4ece3.1.25 \u5347\u7ea7\u5230 4.2.0, \u4e2d\u95f4\u78b0\u5230\u4e86\u5f88\u591a\u95ee\u9898, \u8bb0\u5f55\u4e00\u70b9.<\/p>\n<h2 id=\"\u914d\u7f6e\u7684\u53d8\u5316\">\u914d\u7f6e\u7684\u53d8\u5316<\/h2>\n<p><code>CELERY_ACCEPT_CONENT<\/code> \u4e4b\u524d\u9ed8\u8ba4\u662f\u90fd\u5141\u8bb8\u7684,  4.0 \u5f00\u59cb\u9ed8\u8ba4\u503c\u53ea\u5141\u8bb8 json, \u56e0\u4e3a\u6211\u7528\u7684\u662fmsgpack, \u6240\u4ee5\u9700\u8981\u4fee\u6539\u8fd9\u4e2a\u914d\u7f6e\u8ba9\u5b83\u63a5\u53d7 msgpack.<\/p>\n<p><code>CELERY_RESULT_SERIALIZER<\/code> \u4e4b\u524d\u9ed8\u8ba4\u662fpickle, \u73b0\u5728\u9ed8\u8ba4\u4e5f\u53d8\u6210\u4e86json, \u5982\u679ctask \u7684\u8fd4\u56de\u7ed3\u679c\u662f binary \u7684\u8bdd, json \u65e0\u6cd5\u5904\u7406,\u8981\u4e48\u628a\u7ed3\u679c base64 \u7f16\u7801, \u8981\u4e48\u628a<code>CELERY_RESULT_SERIALIZER<\/code> \u914d\u7f6e\u6210 msgpack,  pickle \u660e\u663e py2 \/ 3 \u4e0d\u517c\u5bb9, \u6ca1\u7528.<\/p>"},{"title":"\u7f16\u5199 python 2\/3 \u517c\u5bb9\u4ee3\u7801","link":"https:\/\/blog.monsterxx03.com\/2018\/06\/16\/%E7%BC%96%E5%86%99-python-2\/3-%E5%85%BC%E5%AE%B9%E4%BB%A3%E7%A0%81\/","pubDate":"Sat, 16 Jun 2018 14:38:26 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/06\/16\/%E7%BC%96%E5%86%99-python-2\/3-%E5%85%BC%E5%AE%B9%E4%BB%A3%E7%A0%81\/","description":"<p><a href=\"https:\/\/blog.monsterxx03.com\/2018\/06\/07\/from-python2-to-python3\/\">\u4e0a\u4e00\u7bc7<\/a> \u91cc\u7b80\u5355\u5f97\u63d0\u4e86\u4e00\u70b9\u5f00\u59cb\u505a python 2 \u5230 python3 \u8fc1\u79fb\u65f6\u5019\u78b0\u5230\u7684\u95ee\u9898, \u548c\u5de5\u5177\u7684\u9009\u62e9(\u63a8\u8350\u7528 six).\u8fd9\u7bc7\u8bb2\u4e0b\u7f16\u5199 python 2 \/ 3 \u517c\u5bb9\u4ee3\u7801\u8981\u6ce8\u610f\u7684\u4e8b\u60c5.<\/p>\n<h2 id=\"_future_\">_<em>future<\/em>_<\/h2>\n<p>python2 \u91cc\u81ea\u5e26\u7684\u5411\u540e\u517c\u5bb9\u6a21\u5757\uff0c\u5c06 python3 \u7684\u4e00\u4e9b\u8bed\u6cd5\u884c\u4e3a backport \u5230 python2 \u91cc, \u4f7f\u7528\u7684\u65f6\u5019\u9700\u8981\u5728\u6587\u4ef6\u5934\u90e8\u58f0\u660e, \u4f5c\u7528\u57df\u53ea\u5728\u5f53\u524d\u6587\u4ef6.<\/p>\n<p>\u9996\u5148\u662f\u51e0\u4e2a\u5728 python 2.7 \u91cc\u4e0d\u7528\u7279\u610f\u5199\uff0c\u5df2\u7ecf\u9ed8\u8ba4\u5f00\u542f\u7684\u7279\u6027:<\/p>\n<ul>\n<li><code>from __future__ import nested_scopes<\/code> 2.2 \u5f00\u59cb\u5c31\u9ed8\u8ba4\u5f00\u542f\u4e86\uff0c\u7528\u4e8e\u4fee\u6539\u5d4c\u5957\u51fd\u6570\u5185\u7684\u53d8\u91cf\u641c\u7d22\u4f5c\u7528\u57df, \u5728\u6b64\u4e4b\u524d, \u5168\u5c40\u6a21\u5757\u7684\u4f18\u5148\u7ea7\u6bd4\u88ab\u5d4c\u5957\u51fd\u6570\u7684\u7236\u51fd\u6570\u8981\u9ad8, \u73b0\u5728\u90fd\u6ca1\u8fd9\u4e2a\u95ee\u9898\u4e86.<\/li>\n<li><code>from __future__ import generators<\/code>, yield \u5173\u952e\u8bcd, 2.3 \u9ed8\u8ba4\u652f\u6301.<\/li>\n<li><code>from __future__ import with_statement<\/code>, with \u5173\u952e\u8bcd, 2.6 \u9ed8\u8ba4\u652f\u6301.<\/li>\n<\/ul>\n<p>\u6211\u663e\u793a\u5f00\u542f\u7684\u4e24\u4e2a\u7279\u6027:<\/p>"},{"title":"\u6742\u8c08\u677e\u672c\u6e05\u5f20","link":"https:\/\/blog.monsterxx03.com\/2018\/06\/10\/%E6%9D%82%E8%B0%88%E6%9D%BE%E6%9C%AC%E6%B8%85%E5%BC%A0\/","pubDate":"Sun, 10 Jun 2018 17:15:29 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/06\/10\/%E6%9D%82%E8%B0%88%E6%9D%BE%E6%9C%AC%E6%B8%85%E5%BC%A0\/","description":"<p>\u53bb\u5e74\u5728 kindle \u4e0a\u4e70\u4e86\u5957\u677e\u672c\u6e05\u5f20\u7684\u5408\u96c6, \u603b\u5171\u670910\u672c, \u65ad\u65ad\u7eed\u7eed\u770b\u5230\u73b0\u5728\u7ec8\u4e8e\u770b\u5b8c\u4e86\u7b2c 9 \u672c&lt;\u9690\u82b1\u5e73\u539f&gt;, \u968f\u4fbf\u626f\u4e00\u70b9(\u5582\uff0c\u4e3a\u4ec0\u4e48\u4e0d\u770b\u5b8c\u6700\u540e\u4e00\u672c!<\/p>\n<p>\u677e\u672c\u6e05\u5f20 (1909 ~ 1992), \u793e\u4f1a\u6d3e\u63a8\u7406\u5f00\u521b\u4eba, \u8fd9\u5957\u4e66\u91cc\u7684\u4f5c\u54c1\u5404\u4e2a\u5e74\u4ee3\u90fd\u6709, \u6700\u6709\u540d\u7684&lt;\u7802\u4e4b\u5668&gt;(\u8c8c\u4f3c\u4ef2\u95f4\u59d0\u59d0\u62cd\u8fc7\u5267?) \u548c &lt;\u70b9\u4e0e\u7ebf&gt; \u5374\u6ca1\u6536\u5f55.<\/p>\n<p>\u672c\u683c\u6d3e\u8bb2\u7a76\u903b\u8f91\u7684\u7cbe\u5de7\uff0c \u6574\u4e2a\u6545\u4e8b\u5c31\u50cf\u5728\u73a9\u5bc6\u5ba4\u9003\u8131\u4e00\u6837, \u4e00\u73af\u6263\u4e00\u73af, \u6700\u540e\u8c1c\u5e95\u63ed\u5f00\u7684\u65f6\u5019\u8ba9\u4eba\u60ca\u547c&quot;\u5367\u69fd&quot;, \u5199\u7684\u5c31\u5f88\u68d2\u4e86, \u4f46\u5982\u679c\u88ab\u63d0\u524d\u5267\u900f\u4e86, \u5c31\u4e27\u5931\u4e86\u5927\u534a\u4e50\u8da3.<\/p>"},{"title":"From python2 to python3","link":"https:\/\/blog.monsterxx03.com\/2018\/06\/07\/from-python2-to-python3\/","pubDate":"Thu, 07 Jun 2018 16:41:57 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/06\/07\/from-python2-to-python3\/","description":"<p>This article won&rsquo;t provide perfect guide for porting py2 code to py3, just list the solutions I tried, the\nproblems I come to, and my choices. I haven&rsquo;t finished this project, also I haven&rsquo;t gave up so far :).<\/p>\n<p>Won&rsquo;t explain too much about the differences between py2 and py3, will write down some corner\ncases which are easy to miss.<\/p>\n<p>The codebase I&rsquo;m working on:<\/p>\n<ul>\n<li>Only support python2.7, don&rsquo;t consider python2.6<\/li>\n<li>1X repos, about half a million lines of code in total (calculated by cloc).<\/li>\n<li>These repos will import each other, bad design from early days, not easy to resolve, which means I can&rsquo;t switch to py3 one by one, I need write\npy2\/3 compatiblility code for them, and switch together(I&rsquo;m also considering solve the import problem first).<\/li>\n<li>Test coverage is not good, best is around 80%, lowest is 30%.<\/li>\n<\/ul>\n<h2 id=\"tools\">Tools<\/h2>\n<p><code>2to3<\/code>, a command line tools packaged with py2, it&rsquo;s a oneway porting to convert your code to py3, new code won&rsquo;t work under\npy2, since I need be compatible with py2 and py3 for long time, didn&rsquo;t try it.<\/p>\n<p><a href=\"http:\/\/python-future.org\/\">future<\/a>, it tries to make you write single clean python3.x code without ugly hack with six. I used it it first,\nbut come to many problems, will explain later.<\/p>"},{"title":"\u5728python3.7 \u4e2d\u5b9e\u73b0python2.7 \u7684\u5185\u7f6e hash \u51fd\u6570","link":"https:\/\/blog.monsterxx03.com\/2018\/06\/01\/%E5%9C%A8python3.7-%E4%B8%AD%E5%AE%9E%E7%8E%B0python2.7-%E7%9A%84%E5%86%85%E7%BD%AE-hash-%E5%87%BD%E6%95%B0\/","pubDate":"Fri, 01 Jun 2018 17:03:24 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/06\/01\/%E5%9C%A8python3.7-%E4%B8%AD%E5%AE%9E%E7%8E%B0python2.7-%E7%9A%84%E5%86%85%E7%BD%AE-hash-%E5%87%BD%E6%95%B0\/","description":"<p>\u6700\u8fd1\u7740\u624b\u51c6\u5907\u4ece python2.7 \u8fc1\u79fb\u5230 python3.7, \u8fd8\u6ca1\u5f00\u59cb\u5c31\u78b0\u5230\u4e00\u4e2a\u95ee\u9898. \u8001\u7cfb\u7edf\u91cc\u6709\u4e00\u90e8\u5206\u7adf\u7136\u662f\u5c06 python \u5185\u7f6e hash \u51fd\u6570\u7684\u7ed3\u679c\u5b58\u8fdb\u4e86\u6570\u636e\u5e93, \u8fd9\u4e2a\u505a\u6cd5\u7edd\u5bf9\u662f\u9519\u7684,\nhash \u7684\u7ed3\u679c\u672c\u6765\u5c31\u6ca1\u6709\u4fdd\u8bc1\u8fc7\u5728\u5404\u4e2a\u7248\u672c\u7684 python \u4e2d\u4fdd\u8bc1\u4e00\u81f4. \u800c\u4e14 python3 \u4e2d\u7b97\u6cd5\u5b8c\u5168\u53d8\u4e86, \u9ed8\u8ba4\u5728\u8fdb\u7a0b\u521d\u59cb\u5316\u7684\u65f6\u5019\u4f1a\u7528\u968f\u673a\u79cd\u5b50\u52a0\u8fdb hash \u8fc7\u7a0b, \u6240\u4ee5python \u8fdb\u7a0b\n\u4e00\u91cd\u542f\u7ed3\u679c\u5c31\u4e0d\u4e00\u6837\u4e86. \u6728\u5df2\u6210\u821f\uff0c \u76ee\u524d\u770b\u5c06\u6570\u636e\u5e93\u91cc\u7684\u503c\u5168\u90e8\u6539\u6389\u662f\u4e0d\u53ef\u80fd\u4e86, \u53ea\u80fd\u5728 python3 \u4e2d\u91cd\u65b0\u5b9e\u73b0\u4e00\u4e0b\u8fd9\u4e2a\u7b97\u6cd5.<\/p>\n<p>python2.7 \u4e2d\u7684hash \u7b97\u6cd5\u662f fnv (\u6709\u4fee\u6539), python3 \u4e2d\u53d8\u6210\u4e86 sip, <a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0456\">pep-456<\/a>.<\/p>"},{"title":"Use SNS & SQS to build Pub\/Sub System","link":"https:\/\/blog.monsterxx03.com\/2018\/05\/23\/use-sns-sqs-to-build-pub\/sub-system\/","pubDate":"Wed, 23 May 2018 18:05:28 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/05\/23\/use-sns-sqs-to-build-pub\/sub-system\/","description":"<p>Recently, we build pub\/sub system based on AWS&rsquo;s SNS &amp; SQS service, take some notes.<\/p>\n<p>Originally, we have an pub\/sub system based on redis(use BLPOP to listen to a redis list). It&rsquo;s\nreally simple, and mainly for cross app operations. Now we have needs to enhance it to support more complex\npubsub logic, eg: topic based distribution. It don&rsquo;t support redelivery as well, if subscribers failed to process\nthe message, message will be dropped.<\/p>\n<p>There&rsquo;re three obvious choices in my mind:<\/p>\n<ol>\n<li>kafka<\/li>\n<li>AMQP based system (rabbitmq,activemq &hellip;)<\/li>\n<li>SNS + SQS<\/li>\n<\/ol>\n<p>My demands for this system are:<\/p>\n<ul>\n<li>Support message persistence.<\/li>\n<li>Support topic based message distribution.<\/li>\n<li>Easy to manage.<\/li>\n<\/ul>\n<p>The data volume won&rsquo;t be very large, so performance and throughput won&rsquo;t be critical concerns.<\/p>\n<p>I choose SNS + SQS, main concerns are from operation side:<\/p>\n<ul>\n<li>kafka need zookeeper to support cluster.<\/li>\n<li>rabbitmq need extra configuration for HA, and AMQP model is relatively complex for programming.<\/li>\n<\/ul>\n<p>So my decision is:<\/p>\n<ul>\n<li>application publish message to SNS topic<\/li>\n<li>Setup multi SQS queues to subscribe SNS topic<\/li>\n<li>Let different application processes to subscribe to different queues to finish its logic.<\/li>\n<\/ul>\n<p>SQS and SNS is very simple, not too much to say, just some notes:<\/p>\n<ul>\n<li>SQS queue have two types, FIFO queue and standard queue. FIFO queue will ensure message order, and ensure exactly once delivery, tps is limited(3000\/s)\nstandard queue is at least once delivery, message order is not ensured, tps is unlimited. In my case, I use standard queue, order is not very important.<\/li>\n<li>SQS message size limit is 256KB.<\/li>\n<li>Use <a href=\"https:\/\/github.com\/p4tin\/goaws\">goaws<\/a> for local development, it has problem on processing message attributes, but I just use message body. messages only store in ram,\nwill be cleared after restarted.<\/li>\n<li>If you failed to deliver message to sqs from sns, can setup topic&rsquo;s <code>sqs failure feedback role<\/code> to log to cloudwatch, in most case it&rsquo;s caused by iam permission.<\/li>\n<li>Message in sqs can retain at most 14 days.<\/li>\n<li>Once a message is received by a client, it will be invisible to other clients in <code>visibility_timeout_seconds<\/code>(default 30s). It means if your client failed to process\nthe message, it will be redelivered after 30s.<\/li>\n<li>SQS client use long polling to receive message, set <code>receive_wait_time_seconds<\/code> to reduce api call to reduce fee.<\/li>\n<li>If your client failed to process a message due to bug, the message will be redelivered looply, set <code>redrive_policy<\/code> for the queue to limit retry count, and set a dead letter\nqueue to store those messages. You can decide how to handle them late.<\/li>\n<\/ul>\n<p>I setup SNS and SQS via terraform, used following resources:<\/p>"},{"title":"Migrate to Sqlalchemy","link":"https:\/\/blog.monsterxx03.com\/2018\/05\/20\/migrate-to-sqlalchemy\/","pubDate":"Sun, 20 May 2018 15:11:31 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/05\/20\/migrate-to-sqlalchemy\/","description":"<p>\u6700\u8fd1\u628a\u516c\u53f8 db \u5c42\u7684\u5c01\u88c5\u4ee3\u7801\u57fa\u4e8e sqlalchemy \u91cd\u5199\u4e86, \u8bb0\u5f55\u4e00\u4e9b.<\/p>\n<p>\u539f\u6765\u7684 db \u5c42\u4ee3\u7801\u5386\u53f2\u975e\u5e38\u53e4\u8001(10\u5e74\u4ee5\u4e0a&hellip;), \u6700\u65e9\u5199\u4ee3\u7801\u7684\u4eba\u65e9\u5c31\u4e0d\u5728\u4e86, \u95ee\u9898\u5f88\u591a:<\/p>\n<ul>\n<li>\u5b8c\u5168\u6ca1\u6709\u5355\u5143\u6d4b\u8bd5.<\/li>\n<li>\u66b4\u9732\u51fa\u7684\u63a5\u53e3\u547d\u540d\u5f88\u6df7\u4e71, \u591a\u6570\u662f\u4e3a\u4e86\u517c\u5bb9\u4e00\u4e9b\u5386\u53f2\u95ee\u9898.<\/li>\n<li>\u91cc\u9762\u5e26\u4e00\u5957 client \u7aef db sharding \u7684\u903b\u8f91, \u4f46\u5728\u65b0\u9879\u76ee\u91cc\u5b8c\u5168\u7528\u4e0d\u5230, \u8fd8\u5bfc\u81f4\u65e0\u6cd5\u505a join, \u65e0\u6cd5\u5b50\u67e5\u8be2, \u5f88\u4e0d\u65b9\u4fbf.<\/li>\n<li>\u8001\u7684 db \u4ee3\u7801\u6ca1\u6709 model \u5c42, \u548c db migration \u901a\u8fc7\u4e00\u79cd\u5f88 trick \u7684\u65b9\u5f0f\u7ed1\u5b9a\u5728\u4e00\u8d77\u5b9e\u73b0\u7684, \u5bfc\u81f4\u5f00\u53d1\u65f6\u5019\u5bf9\u7740\u4ee3\u7801\u5b8c\u5168\u65e0\u6cd5\u77e5\u9053\u6570\u636e\u5e93\u8868\u7ed3\u6784\uff0c\u53ea\u80fd\u76f4\u63a5\u770b\u6570\u636e\u5e93.<\/li>\n<\/ul>\n<p>\u91cd\u5199\u65f6\u5019\u8981\u8003\u8651\u5230\u7684:<\/p>"},{"title":"AWS \u7684 K8S CNI Plugin","link":"https:\/\/blog.monsterxx03.com\/2018\/04\/09\/aws-%E7%9A%84-k8s-cni-plugin\/","pubDate":"Mon, 09 Apr 2018 15:28:38 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/04\/09\/aws-%E7%9A%84-k8s-cni-plugin\/","description":"<p>EKS \u8fd8\u6ca1\u6709 launch, \u4f46 AWS \u5148\u5f00\u6e90\u4e86\u81ea\u5df1\u7684 CNI \u63d2\u4ef6, \u7b80\u5355\u770b\u4e86\u4e0b, \u8bf4\u8bf4\u5b83\u7684\u5b9e\u73b0\u548c\u5176\u4ed6 K8S \u7f51\u7edc\u65b9\u6848\u7684\u5dee\u522b.<\/p>\n<p>K8S \u96c6\u7fa4\u5bf9\u7f51\u7edc\u6709\u51e0\u4e2a\u57fa\u672c\u8981\u6c42:<\/p>\n<ul>\n<li>container \u4e4b\u95f4\u7f51\u7edc\u5fc5\u987b\u53ef\u8fbe\uff0c\u4e14\u4e0d\u901a\u8fc7 NAT<\/li>\n<li>\u6240\u6709 node \u5fc5\u987b\u53ef\u4ee5\u548c\u6240\u6709 container \u901a\u4fe1, \u4e14\u4e0d\u901a\u8fc7 NAT<\/li>\n<li>container \u81ea\u5df1\u770b\u5230\u7684 IP, \u5fc5\u987b\u548c\u5176\u4ed6 container \u770b\u5230\u7684\u5b83\u7684 ip \u76f8\u540c.<\/li>\n<\/ul>\n<h2 id=\"flannel-in-vpc\">Flannel in VPC<\/h2>\n<p>flannel \u662f K8S \u7684\u4e00\u4e2a CNI \u63d2\u4ef6, \u5728 VPC \u91cc\u4f7f\u7528 flannel \u7684\u8bdd, \u6709\u51e0\u4e2a\u9009\u62e9:<\/p>\n<ol>\n<li>\u901a\u8fc7 VXLAN\/UDP \u8fdb\u884c\u5c01\u5305, \u5c01\u5305\u5f71\u54cd\u7f51\u7edc\u6027\u80fd, \u800c\u4e14\u4e0d\u597d debug<\/li>\n<li>\u7528 aws vpc backend, \u8fd9\u79cd\u65b9\u5f0f\u4f1a\u628a\u6bcf\u53f0\u4e3b\u673a\u7684 docker \u7f51\u6bb5\u6dfb\u52a0\u8fdb vpc routing table, \u4f46\u9ed8\u8ba4 routing table \u91cc\u53ea\u80fd\u670950\u6761\u89c4\u5219, \u6240\u4ee5\u53ea\u80fd 50 \u4e2a node, \u53ef\u4ee5\u53d1 ticket \u63d0\u5347, \u4f46\u6570\u91cf\u592a\u591a\u4f1a\u5f71\u54cd vpc \u6027\u80fd.<\/li>\n<li>host-gw, \u5728\u6bcf\u4e2a node \u4e0a\u76f4\u63a5\u7ef4\u62a4\u96c6\u7fa4\u4e2d\u6240\u6709\u8282\u70b9\u7684\u8def\u7531, \u6ca1\u6d4b\u8bd5\u8fc7, \u611f\u89c9\u51fa\u95ee\u9898\u4e5f\u5f88\u96be debug, \u5047\u5982\u7528 autoscaling group \u7ba1\u7406 node \u96c6\u7fa4, \u80fd\u5426\u8ba9 K8S \u5728 scale in\/out \u7684\u65f6\u5019\u4fee\u6539\u6240\u6709\u8282\u70b9\u7684\u8def\u7531?<\/li>\n<\/ol>\n<p>\u4ee5\u4e0a\u65b9\u5f0f\u90fd\u53ea\u80fd\u5229\u7528 EC2 \u4e0a\u7684\u5355\u7f51\u5361, security group \u4e5f\u6ca1\u6cd5\u4f5c\u7528\u5728 pod \u4e0a.<\/p>"},{"title":"AWS lambda \u7684\u4e00\u4e9b\u5e94\u7528\u573a\u666f","link":"https:\/\/blog.monsterxx03.com\/2018\/03\/23\/aws-lambda-%E7%9A%84%E4%B8%80%E4%BA%9B%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF\/","pubDate":"Fri, 23 Mar 2018 17:40:54 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/03\/23\/aws-lambda-%E7%9A%84%E4%B8%80%E4%BA%9B%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF\/","description":"<p>\u8fd9\u51e0\u5e74\u5439 serverless \u7684\u6bd4\u8f83\u591a,  \u5728\u516c\u53f8\u5185\u90e8\u4e5f\u7528 lambda , \u8bb0\u5f55\u4e00\u4e0b, \u8fd9\u4e1c\u897f\u633a\u6709\u7528, \u4f46\u8fdc\u4e0d\u5230\u4e07\u80fd, \u573a\u666f\u6bd4\u8f83\u6709\u9650.<\/p>\n<p>lambda \u7684\u4ee3\u7801\u7684\u90e8\u7f72\u7528\u7684 <a href=\"https:\/\/serverless.com\">serverless<\/a> \u6846\u67b6, \u672c\u8eab\u652f\u6301\u591a\u79cd cloud \u5e73\u53f0, \u6211\u4eec\u5c31\u53ea\u5728 aws lambda \u4e0a\u4e86.<\/p>\n<p>\u6211\u57fa\u672c\u4e0a\u5c31\u628a lambda \u5f53\u6210 trigger \u548c web hook \u7528.<\/p>\n<h2 id=\"\u548c--auto-scaling-group-\u4e00\u8d77\u7528\">\u548c  auto scaling group \u4e00\u8d77\u7528<\/h2>\n<p>\u7ebf\u4e0a\u6240\u6709\u5206\u7ec4\u7684\u673a\u5668\u90fd\u662f\u7528 auto scaling group \u7ba1\u7406\u7684, \u53ea\u4e0d\u8fc7 stateless \u7684 server \u5f00\u4e86\u81ea\u52a8\u4f38\u7f29, \u5e26\u72b6\u6001\u7684 (ElasticSearch cluster, redis cache cluster) \u53ea\u7528\u6765\u7ef4\u62a4\u56fa\u5b9a size.<\/p>\n<p>\u5728\u5f80\u4e00\u4e2a group \u91cc\u52a0 server \u7684\u65f6\u5019, \u8981\u505a\u7684\u4e8b\u60c5\u633a\u591a\u7684, \u7ed9\u65b0 server \u6dfb\u52a0\u7ec4\u5185\u7f16\u53f7 tag, \u6dfb\u52a0\u5185\u7f51\u57df\u540d, provision, \u90e8\u7f72\u6700\u65b0\u4ee3\u7801.<\/p>\n<p>\u8fd9\u4e9b\u4e8b\u90fd\u7528 jenkins \u6765\u505a, \u4f46\u600e\u4e48\u89e6\u53d1 jenkins job \u5462?<\/p>"},{"title":"\u4e00\u6b21\u5931\u8d25\u7684\u6027\u80fd\u95ee\u9898\u6392\u67e5","link":"https:\/\/blog.monsterxx03.com\/2018\/03\/17\/%E4%B8%80%E6%AC%A1%E5%A4%B1%E8%B4%A5%E7%9A%84%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5\/","pubDate":"Sat, 17 Mar 2018 14:24:33 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/03\/17\/%E4%B8%80%E6%AC%A1%E5%A4%B1%E8%B4%A5%E7%9A%84%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5\/","description":"<p>\u4e00\u53f6\u969c\u76ee, \u4e0d\u89c1\u6cf0\u5c71. \u524d\u9635\u5b50\u4e00\u76f4\u5728\u6392\u67e5\u4e00\u4e2a\u6027\u80fd\u95ee\u9898, \u7ed3\u679c\u7531\u4e8e\u4e00\u4e9b\u60ef\u6027\u601d\u7ef4, \u8d39\u4e86\u597d\u5927\u52b2\u624d\u5f04\u660e\u767d\u539f\u56e0, \u800c\u4e14\u539f\u56e0\u975e\u5e38\u7b80\u5355&hellip;.\u628a\u8fd9\u4e8b\u8bb0\u5f55\u4e0b\u6765,\u514d\u5f97\u4ee5\u540e\u518d\u6389\u5751\u91cc\u53bb.<\/p>\n<p>\u73b0\u8c61\u662f\u5230\u4e86\u665a\u4e0a10\u70b9\u591a, server lantency \u7a81\u7136\u4e00\u77ac\u95f4\u53d8\u9ad8, \u4f46\u6301\u7eed\u65f6\u95f4\u5f88\u77ed\uff0c\u9a6c\u4e0a\u5c31\u4f1a\u6062\u590d, timeout \u7684\u8bf7\u6c42\u4e5f\u4e0d\u591a\uff0c\u5f71\u54cd\u4e0d\u5927.\u95ee\u9898\u5176\u5b9e\u4ece\u86ee\u4e45\u524d\u5c31\u51fa\u73b0\u4e86, \u4f46\u4e00\u76f4\u4e5f\u6ca1\u5f88\u91cd\u89c6, \u56e0\u4e3a\u6301\u7eed\u65f6\u95f4\u77ed,\u5f71\u54cd\u4e5f\u4e0d\u5927,\u7b80\u5355\u770b\u4e86\u4e0b\u4e5f\u6ca1\u770b\u51fa\u660e\u663e\u7684\u95ee\u9898, \u5c31\u4e00\u76f4\u6401\u7f6e\u7740. \u76f4\u5230\u6700\u8fd1\uff0c\u89c9\u5f97\u95ee\u9898\u53d8\u4e25\u91cd\u4e86, latency \u53d8\u7684\u66f4\u9ad8\u4e86\uff0c\u800c\u4e14\u572810\uff5e11\u70b9\u95f4\u591a\u6b21\u53d8\u9ad8, \u5f00\u59cb\u8ba4\u771f\u770b\u4e3a\u4ec0\u4e48.<\/p>"},{"title":"Access sensitive variables on AWS lambda","link":"https:\/\/blog.monsterxx03.com\/2018\/02\/28\/access-sensitive-variables-on-aws-lambda\/","pubDate":"Wed, 28 Feb 2018 21:45:23 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/02\/28\/access-sensitive-variables-on-aws-lambda\/","description":"<p>AWS lambda is convenient to run simple serverless application, but how to access sensitive data in code? like password,token&hellip;<\/p>\n<p>Usually, we inject secrets as environment variables, but they&rsquo;re still visable on lambda console. I don&rsquo;t use it in aws lambda.<\/p>\n<p>The better way is use <a href=\"https:\/\/docs.aws.amazon.com\/systems-manager\/latest\/userguide\/systems-manager-paramstore.html\">aws parameter store<\/a> as configuration center. It can work with KMS to encrypt your data.<\/p>\n<p>Code example:<\/p>\n<pre><code>client = boto3.client('ssm')\nresp = client.get_parameter(\n    Name='\/redshift\/admin\/password',\n    WithDecryption=True\n)\nresp:\n\n    {\n        &quot;Parameter&quot;: {\n            &quot;Name&quot;: &quot;\/redshift\/admin\/password&quot;,\n            &quot;Type&quot;: &quot;SecureString&quot;,\n            &quot;Value&quot;: &quot;password value&quot;,\n            &quot;Version&quot;: 1\n        }\n    }\n<\/code><\/pre>\n<p>Things you need to do to make it work:<\/p>\n<ul>\n<li>Create a new KMS key<\/li>\n<li>Use new created KMS key to encrypt your data in parameter store.<\/li>\n<li>Set a execution role for your lambda function.<\/li>\n<li>In the KMS key&rsquo;s setting page, add the lambda execution role to the list which can read this KMS key.<\/li>\n<\/ul>\n<p>Then your lambda code can access encrypted data at runtime, and you needn&rsquo;t set aws access_key\/secret_key, lambda execution role enable access to data in parameter store.<\/p>\n<p>BTW, parameter store support hierarchy(at most 15 levels), splitted by <code>\/<\/code>. You can retrive data under same level in one call, deltails can be found in doc, eg: <a href=\"http:\/\/boto3.readthedocs.io\/en\/latest\/reference\/services\/ssm.html#SSM.Client.get_parameters_by_path\">http:\/\/boto3.readthedocs.io\/en\/latest\/reference\/services\/ssm.html#SSM.Client.get_parameters_by_path<\/a><\/p>"},{"title":"Glow Infra Evolution","link":"https:\/\/blog.monsterxx03.com\/2018\/02\/23\/glow-infra-evolution\/","pubDate":"Fri, 23 Feb 2018 23:25:13 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/02\/23\/glow-infra-evolution\/","description":"<h1 id=\"glow-data-infrastructure-\u7684\u6f14\u5316\">Glow data infrastructure \u7684\u6f14\u5316<\/h1>\n<p>Glow \u4e00\u5411\u662f\u4e00\u4e2a data driven \u505a\u51b3\u7b56\u7684\u516c\u53f8\uff0c\u7a33\u5b9a\u9ad8\u6548\u7684\u5e73\u53f0\u662f\u5fc5\u4e0d\u53ef\u5c11\u7684\u652f\u6491, \u672c\u6587\u603b\u7ed3\u51e0\u5e74\u91cc\u516c\u53f8 data infrastructure \u7684\u6f14\u8fdb\u8fc7\u7a0b.<\/p>\n<p>\u7ed3\u5408\u4e1a\u52a1\u7279\u70b9\u505a\u6280\u672f\u9009\u578b\u548c\u5b9e\u73b0\u65f6\u5019\u7684\u51e0\u4e2a\u539f\u5219:<\/p>\n<ol>\n<li>real time \u5206\u6790\u7684\u9700\u6c42\u4e0d\u9ad8\uff0c\u65f6\u95f4 delta \u63a7\u5236\u57281 \u5c0f\u65f6\u4ee5\u5185\u53ef\u63a5\u53d7 .<\/li>\n<li>\u652f\u6301\u5feb\u901f\u7684\u4ea4\u4e92\u5f0f\u67e5\u8be2.<\/li>\n<li>\u5e95\u5c42\u5e73\u53f0\u5c3d\u91cf\u9009\u62e9 AWS \u6258\u7ba1\u670d\u52a1, \u51cf\u5c11\u7ef4\u62a4\u6210\u672c.<\/li>\n<li>\u9047\u5230\u6545\u969c, \u6570\u636e\u53ef\u4ee5 delay \u4f46\u4e0d\u80fd\u4e22.<\/li>\n<li>\u53ef\u56de\u6eaf\u5386\u53f2\u6570\u636e.<\/li>\n<li>\u6210\u672c\u53ef\u63a7.<\/li>\n<\/ol>\n<p>\u7528\u5230\u7684 AWS \u670d\u52a1:<\/p>\n<ul>\n<li>\u6570\u636e\u5b58\u50a8\u548c\u67e5\u8be2:  S3, Redshift (spectrum), Athena<\/li>\n<li>ETL: DMS, EMR, Kinesis, Firehose, Lambda<\/li>\n<\/ul>\n<p>\u5f00\u6e90\u8f6f\u4ef6: td-agent, maxwell<\/p>\n<p>\u6570\u636e\u6765\u6e90:<\/p>\n<ol>\n<li>\u7ebf\u4e0a\u4e1a\u52a1\u6570\u636e\u5e93<\/li>\n<li>\u7528\u6237\u6d3b\u52a8\u4ea7\u751f\u7684 metrics log<\/li>\n<li>\u4ece\u5404\u79cd\u7b2c\u4e09\u65b9\u670d\u52a1 api \u62c9\u4e0b\u6765\u7684\u6570\u636e (email\u4e4b\u7c7b)<\/li>\n<\/ol>\n<h2 id=\"\u6700\u65e9\u671f\">\u6700\u65e9\u671f<\/h2>\n<p>\u521a\u5f00\u59cb\u7684\u65f6\u5019\u4e1a\u52a1\u5355\u7eaf\uff0c\u6570\u636e\u91cf\u4e5f\u5c11, \u6240\u6709\u6570\u636e\u90fd\u7528 MySQL \u5b58\u50a8\uff0c\u642d\u4e86\u53f0 slave, \u5206\u6790\u67e5\u8be2\u90fd\u5728 slave \u4e0a\u8fdb\u884c.<\/p>"},{"title":"Get Real Client Ip on AWS","link":"https:\/\/blog.monsterxx03.com\/2018\/02\/01\/get-real-client-ip-on-aws\/","pubDate":"Thu, 01 Feb 2018 15:20:37 +0800","guid":"https:\/\/blog.monsterxx03.com\/2018\/02\/01\/get-real-client-ip-on-aws\/","description":"<p>If you run a webserver on AWS, get real client ip will be tricky if you didn&rsquo;t configure server right and write code correctly.<\/p>\n<p>Things related to client real ip:<\/p>\n<ul>\n<li>CloudFront (cdn)<\/li>\n<li>ALB (loadbalancer)<\/li>\n<li>nginx (on ec2)<\/li>\n<li>webserver (maybe a python flask application).<\/li>\n<\/ul>\n<p>Request sequence diagram will be like following:<\/p>\n<p><img src=\"https:\/\/blog.monsterxx03.com\/posts\/images\/cf-alb-nginx.png\" alt=\"req\"><\/p>\n<p>User&rsquo;s real client ip is forwarded by front proxies one by one in head <code>X-Forwarded-For<\/code>.<\/p>\n<p>For CloudFront:<\/p>\n<ul>\n<li>If user&rsquo;s req header don&rsquo;t  have <code>X-Forwarded-For<\/code>, it will set user&rsquo;s ip(from tcp connection) in <code>X-Forwarded-For<\/code><\/li>\n<li>If user&rsquo;s req already have <code>X-Forwarded-For<\/code>, it will append user&rsquo;s ip(from tcp connection) to the end of <code>X-Forwarded-For<\/code><\/li>\n<\/ul>\n<p>For ALB, rule is same as CloudFront, so the <code>X-Forwarded-For<\/code> header pass to nginx will be the value received from CloudFront + CloudFront&rsquo;s ip.<\/p>\n<p>For nginx, things will be tricky depends on your config.<\/p>\n<p>Things maybe involved in nginx:<\/p>\n<ul>\n<li>real ip module<\/li>\n<li>proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<\/li>\n<\/ul>\n<p>If you didn&rsquo;t use real ip module, you need to pass X-Forwarded-For head explictly.<\/p>\n<p><code>proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<\/code> will append ALB&rsquo;s ip to the end of <code>X-Forwarded-For<\/code> header received from ALB.<\/p>\n<p>So <code>X-Forwarded-For<\/code> header your webserver received will be <code>user ip,cloudfront ip, alb ip<\/code><\/p>\n<p>Or you can use real ip module to trust the value passed from ALB.<\/p>"},{"title":"DynamoDB","link":"https:\/\/blog.monsterxx03.com\/2017\/12\/15\/dynamodb\/","pubDate":"Fri, 15 Dec 2017 22:24:36 +0800","guid":"https:\/\/blog.monsterxx03.com\/2017\/12\/15\/dynamodb\/","description":"<p>DynamoDB \u662f AWS \u7684\u6258\u7ba1 NoSQL \u6570\u636e\u5e93\uff0c\u53ef\u4ee5\u5f53\u4f5c\u7b80\u5355\u7684 KV \u6570\u636e\u5e93\u4f7f\u7528\uff0c\u4e5f\u53ef\u4ee5\u4f5c\u4e3a\u6587\u6863\u6570\u636e\u5e93\u4f7f\u7528.<\/p>\n<h2 id=\"data-model\">Data model<\/h2>\n<p>\u7ec4\u7ec7\u6570\u636e\u7684\u5355\u4f4d\u662f table, \u6bcf\u5f20 table \u5fc5\u987b\u8bbe\u7f6e primary key, \u53ef\u4ee5\u8bbe\u7f6e\u53ef\u9009\u7684 sort key \u6765\u505a\u7d22\u5f15.<\/p>\n<p>\u6bcf\u6761\u6570\u636e\u8bb0\u4f5c\u4e00\u4e2a item, \u6bcf\u4e2a item \u542b\u6709\u4e00\u4e2a\u6216\u591a\u4e2a attribute, \u5176\u4e2d\u5fc5\u987b\u5305\u62ec primary key.<\/p>\n<p>attribute \u5bf9\u5e94\u7684 value \u652f\u6301\u4ee5\u4e0b\u51e0\u79cd\u7c7b\u578b:<\/p>\n<ul>\n<li>Number, \u7531\u4e8e DynamoDB \u7684\u4f20\u8f93\u534f\u8bae\u662f http + json, \u4e3a\u4e86\u8de8\u8bed\u8a00\u7684\u517c\u5bb9\u6027, number \u4e00\u5f8b\u4f1a\u88ab\u8f6c\u6210 string \u4f20\u8f93.<\/li>\n<li>Binary, \u7528\u6765\u8868\u793a\u4efb\u610f\u7684\u4e8c\u8fdb\u5236\u6570\u636e\uff0c\u4f1a\u7528 base64 encode \u540e\u4f20\u8f93.<\/li>\n<li>Boolean, true or false<\/li>\n<li>Null<\/li>\n<li>Document \u7c7b\u578b\u5305\u542b List \u548c Map, \u53ef\u4ee5\u4e92\u76f8\u5d4c\u5957.\n<ul>\n<li>List, \u4e2a\u6570\u65e0\u9650\u5236, \u603b\u5927\u5c0f\u4e0d\u8d85\u8fc7 400KB<\/li>\n<li>Map, \u5c5e\u6027\u4e2a\u6570\u65e0\u9650\u5236\uff0c\u603b\u5927\u5c0f\u4e0d\u8d85\u8fc7 400 KB, \u5d4c\u5957\u5c42\u7ea7\u4e0d\u8d85\u8fc7 32 \u7ea7.<\/li>\n<\/ul>\n<\/li>\n<li>Set,  \u4e00\u4e2a set \u5185\u5143\u7d20\u6570\u76ee\u65e0\u9650\u5236, \u65e0\u5e8f\uff0c\u4e0d\u8d85\u8fc7 400KB, \u4f46\u5fc5\u987b\u5c5e\u4e8e\u540c\u4e00\u7c7b\u578b, \u652f\u6301 number set, binary set, string set.<\/li>\n<\/ul>\n<h2 id=\"\u9009\u62e9-primary-key\">\u9009\u62e9 primary key<\/h2>\n<p>Table \u7684 primary key \u652f\u6301\u5355\u4e00\u7684 partition key \u6216\u590d\u5408\u7684 partition key + sort key. \u4e0d\u7ba1\u54ea\u79cd\uff0c\u6700\u540e\u7684\u7ec4\u6210\u7684primary key \u5728\u4e00\u5f20\u8868\u4e2d\u5fc5\u987b\u552f\u4e00.<\/p>"},{"title":"Handle outage","link":"https:\/\/blog.monsterxx03.com\/2017\/12\/10\/handle-outage\/","pubDate":"Sun, 10 Dec 2017 11:13:53 +0800","guid":"https:\/\/blog.monsterxx03.com\/2017\/12\/10\/handle-outage\/","description":"<p>A few weeks ago, production environment came to an outage, solve it cost me 8 hours (from 3am to 11am) although total down time is not long, really a bad expenrience. Finally, impact was mitigated, and I&rsquo;m working on a long term solution. I learned some important things from this accident.<\/p>\n<h2 id=\"the-outage\">The outage<\/h2>\n<p>I received alarms about live performance issue at 3am, first is server latency increaing, soon some service&rsquo;s health check failed due to high load.<\/p>\n<p>I did following:<\/p>\n<ol>\n<li>Check monitor<\/li>\n<li>Identify the problem is caused by KV system<\/li>\n<\/ol>\n<p>Okay, problem is here, I know the problem is KV system&rsquo;s performance issue. But I can&rsquo;t figure out the root case right now, I need a temporary solution.\nStraightward way is redirect traffic to slave instance. But I know it won&rsquo;t work (actually it is true), I come to similar issue before, did a fix for it, but seems it doesn&rsquo;t work.<\/p>\n<p>The real down time was not long, performance recovered to some degree soon, but latency was still high, not normal. I monitored it for long time, and tried to find out the root case until morning. Since traffic was growing when peak hour coming, performance became problem again.<\/p>"},{"title":"AWS DMS notes","link":"https:\/\/blog.monsterxx03.com\/2017\/10\/14\/aws-dms-notes\/","pubDate":"Sat, 14 Oct 2017 22:33:36 +0800","guid":"https:\/\/blog.monsterxx03.com\/2017\/10\/14\/aws-dms-notes\/","description":"<p>AWS&rsquo;s DMS (Data migration service) can be used to do incremental ETL between databases. I use it to load data from RDS (MySQL) to Redshift.<\/p>\n<p>It works, but have some concerns. Take some notes when doing this project.<\/p>\n<h2 id=\"prerequisites\">Prerequisites<\/h2>\n<p>Source RDS must:<\/p>\n<ul>\n<li>Enable automatic backups<\/li>\n<li>Increase binlog remain time, <code>call mysql.rds_set_configuration('binlog retention hours', 24);<\/code><\/li>\n<li>Set <code>binlog_format<\/code> to <code>ROW<\/code>.<\/li>\n<li>Privileges on source RDS: <code>REPLICATION CLIENT <\/code>, <code>REPLICATION SLAVE <\/code>, <code>SELECT<\/code> on replication target tables<\/li>\n<\/ul>\n<h2 id=\"ddl-on-source-table\">DDL on source table<\/h2>\n<p>Redshift has some limits on change columns:<\/p>\n<ul>\n<li>New column only must be added in the end<\/li>\n<li>Can&rsquo;t rename columns<\/li>\n<\/ul>\n<p>So for DDL on source MySQL, you can&rsquo;t add columns at non end postition, otherwise data in target table will corrupt. I disabled ddl changes target db:<\/p>\n<pre><code>    &quot;ChangeProcessingDdlHandlingPolicy&quot;:{  \n        &quot;HandleSourceTableDropped&quot;:false,\n        &quot;HandleSourceTableTruncated&quot;:false,\n        &quot;HandleSourceTableAltered&quot;:false\n    },\n<\/code><\/pre>\n<p>If source table schema changed, I just drop and reload target table on console.<\/p>\n<h2 id=\"control-write-speed-on-redshift\">Control write speed on Redshift<\/h2>\n<p>Since Redshift is an OLAP database, write operation is slow and concurrency is low, streaming data directly will have big impact on it.<\/p>\n<p>And we have may analysis jobs running on redshift all the time, directly streaming will lock target table and make my analysis jobs timeout.<\/p>\n<p>So I need to batch apply changes on DMS. Follow settings need to tweak in task settings json:<\/p>"},{"title":"Get all invalid PTR record on  Route53","link":"https:\/\/blog.monsterxx03.com\/2017\/09\/29\/get-all-invalid-ptr-record-on-route53\/","pubDate":"Fri, 29 Sep 2017 08:55:18 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/09\/29\/get-all-invalid-ptr-record-on-route53\/","description":"<p>I use autoscaling group to manage stateless servers. Servers go up and down every day.<\/p>\n<p>Once server is up, I will add a PTR record for it\u2019s internal ip. But when it\u2019s down, I didn\u2019t cleanup the PTR record. As times fly, a lot of invalid PTR records left in Route53.<\/p>\n<p>To cleanup those PTR records realtime, you can write a lambda function, use server termination event as trigger. But how to cleanup the old records at once?<\/p>\n<p>Straightforward way is write a script to call AWS API to get a PTR list, get ip from record, test whether the ip is live, if not, delete it.<\/p>\n<p>Since use awscli to delete a Route53 record is very troublesome (involve json format), you\u2019d better write a python script to delete them. I just demo some ideas to collect those records via shell.<\/p>\n<p>You can do it in a single line, but make things clear and easy to debug, I split it into several steps.<\/p>\n<h2 id=\"get-ptr-record-list\">Get PTR record list<\/h2>\n<pre><code>aws route53 list-resource-record-sets  --hosted-zone-id xxxxx --query &quot;ResourceRecordSets[?Type=='PTR'].Name&quot; |  grep -Po '&quot;(.+?)&quot;' | tr -d \\&quot; &gt; ptr.txt\n<\/code><\/pre>\n<p>ptr.txt will contain lines like:<\/p>\n<pre><code>1.0.0.10.in-addr.arpa.\n2.0.0.10.in-addr.arpa.\n<\/code><\/pre>\n<h2 id=\"get-ip-list-from-ptr-records\">Get ip list from PTR records<\/h2>\n<pre><code>cat ptr.txt | while read -r line ; do echo -n $line | tac -s. | cut -d. -f3- | sed 's\/.$\/\/' ; done &gt; ip.txt\n<\/code><\/pre>\n<p>ip.txt:<\/p>"},{"title":"Build private static website on S3","link":"https:\/\/blog.monsterxx03.com\/2017\/08\/19\/build-private-staticwebsite-on-s3\/","pubDate":"Sat, 19 Aug 2017 07:28:16 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/08\/19\/build-private-staticwebsite-on-s3\/","description":"<p>Build static website on S3 is very easy, but by default, it can be accessed by open internet.It will be super helpful if we can build website only available in VPC. Then we can use it to host internal deb repo, doc site\u2026<\/p>\n<p>Steps are very easy, you only need VPC endpoints and S3 bucket policy.<\/p>\n<p>AWS api is open to internet, if you need to access S3 in VPC, your requests will pass through VPC\u2019s internet gateway or NAT gateway. With VPC endpoints(can be found in VPC console), your requests to S3 will go through AWS\u2019s internal network. Currently, VPC endpoints only support S3, support for dynamodb is in test.<\/p>\n<p>To restrict S3 bucket only available in your VPC, need to set bucket policy (to host static website, enable static website support first). At first, I didn\u2019t check doc, try to restrict access by my VPC ip cidr, but it didn\u2019t work, I need to restrict by VPC endpoint id:<\/p>\n<pre><code>{\n  &quot;Version&quot;: &quot;2012-10-17&quot;,\n  &quot;Id&quot;: &quot;Policy1415115909152&quot;,\n  &quot;Statement&quot;: [\n    {\n      &quot;Sid&quot;: &quot;Access-to-specific-VPCE-only&quot;,\n      &quot;Principal&quot;: &quot;*&quot;,\n      &quot;Action&quot;: &quot;s3:GetObject&quot;,\n      &quot;Effect&quot;: &quot;Allow&quot;,\n      &quot;Resource&quot;: [&quot;arn:aws:s3:::my_secure_bucket&quot;,\n                   &quot;arn:aws:s3:::my_secure_bucket\/*&quot;],\n      &quot;Condition&quot;: {\n        &quot;StringEquals&quot;: {\n          &quot;aws:sourceVpce&quot;: &quot;vpce-1a2b3c4d&quot;\n        }\n      }\n    }\n  ]\n}\n<\/code><\/pre>\n<p>BTW, if you can config bucket policy restrict on VPC directly, with VPC endpoint you can limit to subnets. Details can be found in doc: <a href=\"http:\/\/docs.aws.amazon.com\/AmazonVPC\/latest\/UserGuide\/vpc-endpoints-s3.html\">http:\/\/docs.aws.amazon.com\/AmazonVPC\/latest\/UserGuide\/vpc-endpoints-s3.html<\/a><\/p>"},{"title":"\u65c5\u884c\u6563\u8bb0","link":"https:\/\/blog.monsterxx03.com\/2017\/08\/13\/%E6%97%85%E8%A1%8C%E6%95%A3%E8%AE%B0\/","pubDate":"Sun, 13 Aug 2017 15:18:52 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/08\/13\/%E6%97%85%E8%A1%8C%E6%95%A3%E8%AE%B0\/","description":"<p>\u524d\u9635\u5b50\u603b\u6709\u70b9\u5fc3\u70e6\u610f\u4e71\u7684\uff0c\u751f\u6d3b\u4e0a\u7684\uff0c\u5bb6\u91cc\u7684\uff0c\u5835\u5728\u4e00\u5757\uff0c\u5f04\u5f97\u81ea\u5df1\u90fd\u6709\u70b9\u75b2\u60eb\u4e86\uff0c8\u6708\u521d\u7684\u65f6\u5019\u53bb\u65e5\u672c\u4e1c\u5317\u901b\u4e86\u4e00\u5708\uff0c\u6070\u9022\u5f53\u5730\u796d\u5960\u5bc6\u96c6\u671f\uff0c\u4e5f\u5c31\u51d1\u4e86\u628a\u70ed\u95f9\uff0c\u8fd8\u633a\u6709\u610f\u601d\u3002<\/p>\n<p>\u884c\u7a0b: \u4e0a\u6d77 -&gt; \u4e1c\u4eac -&gt; \u76db\u5188 -&gt; \u516b\u6237 -&gt; \u5341\u548c\u7530\u6e56 -&gt; \u9752\u68ee -&gt; \u5f18\u524d -&gt; \u4e1c\u4eac -&gt; \u4e0a\u6d77, \u6ee1\u6ee1\u5f53\u5f53\u76847\u5929, \u61d2\u5f97\u8d34\u56fe\uff0c\u778e\u8bb0\u4e00\u70b9\u3002<\/p>\n<p>\u76db\u5188\u662f\u5ca9\u624b\u53bf\u7684\u9996\u5e9c\uff0c\u4f46\u521a\u5230\u7684\u65f6\u5019\u611f\u89c9\u771f\u662f\u4e2a\u5927\u4e61\u4e0b\u554a\uff0c\u5927\u767d\u5929\uff0c\u51fa\u4e86\u8f66\u7ad9\u533a\u57df\uff0c\u6b65\u884c1\u516c\u91cc\u591a\u7684\u65f6\u95f4\u91cc\u53ea\u78b0\u5230\u4e862\u4e2a\u4eba\uff0c\u4e00\u4e2a\u6865\u4e0b\u7761\u89c9\u7684\u5927\u53d4\uff0c\u4e00\u4e2a\u905b\u72d7\u7684\uff0c\u50cf\u4e2a\u9b3c\u57ce\u4f3c\u7684\uff0c\u8d85\u7ea7\u4e0d\u4e60\u60ef\u3002\u5230\u4e86\u665a\u4e0a\uff0c\u5f53\u5730\u6709\u4e09\u98d2\u821e\u796d\u5178\uff0c\u4e00\u4e0b\u5b50\u4e0d\u77e5\u4ece\u54ea\u5192\u51fa\u6765\u597d\u591a\u4eba\u3002\u5927\u5bb6\u805a\u5728\u4e00\u8d77\uff0c\u5404\u79cd\u8def\u8fb9\u644a\u4e70\u4e70\u4e70\uff0c\u5403\u5403\u5403\uff0c\u70ed\u95f9\u7684\u4e0d\u6562\u76f8\u4fe1\u662f\u767d\u5929\u90a3\u4e2a\u57ce\u5e02\u3002\u4e09\u98d2\u821e\u662f\u5f53\u5730\u4e00\u79cd\u4f20\u7edf\u821e\u8e48(\u4f20\u8bf4\u662f\u4e3a\u4e86\u5c01\u5370\u4e00\u4e2a\u4ec0\u4e48\u9b3c\u7684)\uff0c\u4e00\u8fb9\u8df3\u4e00\u8fb9\u524d\u8fdb\uff0c\u6709\u7684\u6253\u592a\u9f13\uff0c\u6709\u7684\u5439\u7b1b\uff0c\u6709\u7684\u7a7a\u624b\uff0c\u8df3\u7684\u4e13\u4e1a\u7684\u8fd8\u633a\u597d\u770b\u7684\uff0c\u4e5f\u6709\u5f88\u591a\u5145\u6570\u7684\u5c0f\u76c6\u53cb\u5566:). \u53c2\u52a0\u7684\u90fd\u662f\u5f53\u5730\u4e00\u4e9b\u56e2\u4f53\u548c\u4f01\u4e1a\uff0c\u57fa\u672c\u5c31\u5f53\u662f\u4e00\u6b21\u5927\u578b\u5e7f\u544a\u5de1\u6e38, \u5f53\u6253\u592a\u9f13\u7684\u65b9\u9635\u7ecf\u8fc7\u9762\u524d\u7684\u65f6\u5019\uff0c\u6c14\u52bf\u8fd8\u662f\u5f88\u9707\u64bc\u7684\u3002\u5728\u76db\u5188\u5446\u4e86\u4e24\u5929\uff0c\u4ece\u521a\u5230\u7684\u4e0d\u9002\u5e94\u4e00\u4e0b\u53d8\u5f97\u76f8\u5f53\u4eab\u53d7\u90a3\u91cc\u7684\u57ce\u5e02\u6c1b\u56f4, \u57ce\u5e02\u91cc\u5230\u5904\u90fd\u662f\u98ce\u94c3\u548c\u7d2b\u9633\u82b1\uff0c\u95f2\u9002\u7684\u751f\u6d3b\uff0c\u7b2c\u4e00\u6b21\u8fd9\u4e48\u5411\u5f80\u5728\u4e00\u4e2a\u57ce\u5e02\u751f\u6d3b\u3002<\/p>"},{"title":"Use redshift spectrum to do query on s3","link":"https:\/\/blog.monsterxx03.com\/2017\/07\/21\/use-redshift-spectrum-to-do-query-on-s3\/","pubDate":"Fri, 21 Jul 2017 03:10:58 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/07\/21\/use-redshift-spectrum-to-do-query-on-s3\/","description":"<h1 id=\"\u4f7f\u7528-redshift-spectrum-\u67e5\u8be2-s3-\u6570\u636e\">\u4f7f\u7528 redshift spectrum \u67e5\u8be2 S3 \u6570\u636e<\/h1>\n<p>\u901a\u5e38\u4f7f\u7528 redshift \u505a\u6570\u636e\u4ed3\u5e93\u7684\u65f6\u5019\u8981\u505a\u5927\u91cf\u7684 ETL \u5de5\u4f5c\uff0c\u4e00\u822c\u6d41\u7a0b\u662f\u628a\u5404\u79cd\u6765\u6e90\u7684\u6570\u636e\u6363\u9f13\u6363\u9f13\u4e22\u5230 S3 \u4e0a\u53bb\uff0c\u518d\u4ece S3 \u5012\u817e\u8fdb redshift. \u5982\u679c\u4f60\u6709\u5927\u91cf\u7684\u5386\u53f2\u6570\u636e\u8981\u5bfc\u8fdb redshift\uff0c\u8fd9\u4e2a\u8fc7\u7a0b\u5c31\u4f1a\u5f88\u75db\u82e6\uff0credshift \u5bf9\u4e00\u6b21\u5012\u5165\u5927\u91cf\u6570\u636e\u5e76\u4e0d\u53cb\u597d\uff0c\u4f60\u8981\u5206\u6279\u6765\u505a\u3002<\/p>\n<p>\u4eca\u5e744\u6708\u7684\u65f6\u5019\uff0c redshift \u53d1\u5e03\u4e86\u4e00\u4e2a\u65b0\u529f\u80fd spectrum, \u53ef\u4ee5\u4ece redshift \u91cc\u76f4\u63a5\u67e5\u8be2 s3 \u4e0a\u7684\u7ed3\u6784\u5316\u6570\u636e\u3002\u6700\u8fd1\u628a\u90e8\u5206\u6570\u636e\u4ed3\u5e93\u76f4\u63a5\u8fc1\u79fb\u5230\u4e86 spectrum, \u6b63\u597d\u6765\u8bb2\u8bb2\u3002<\/p>\n<h2 id=\"\u52a8\u673a\">\u52a8\u673a<\/h2>\n<p>Glow \u7684\u6570\u636e\u4ed3\u5e93\u5efa\u5728 redshift \u4e0a\uff0c \u53c8\u5206\u6210\u4e86\u4e24\u4e2a\u96c6\u7fa4\uff0c\u4e00\u4e2a ssd \u7684\u96c6\u7fa4\u5b58\u653e\u6700\u8fd1 4 \u4e2a\u6708\u7684\u6570\u636e\uff0c\u4f9b\u4ea7\u54c1\u5206\u6790\uff0cmetrics report, debug \u7b49\u7b49 adhoc \u7684\u67e5\u8be2\u30024\u4e2a\u6708\u4e4b\u524d\u7684\u6570\u636e\u5b58\u653e\u5728\u4e00\u4e2a hdd \u7684\u96c6\u7fa4\u91cc\uff0c\u4fbf\u5b9c\u5bb9\u91cf\u5927\uff0c\u67e5\u8be2\u6162\u3002<\/p>"},{"title":"Enable coredump on ubuntu 16.04","link":"https:\/\/blog.monsterxx03.com\/2017\/07\/15\/enable-coredump-on-ubuntu-16.04\/","pubDate":"Sat, 15 Jul 2017 02:35:52 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/07\/15\/enable-coredump-on-ubuntu-16.04\/","description":"<p>Coredump file is useful for debuging program crash. This post will show several settings related to coredump.<\/p>\n<h2 id=\"enable-coredump\">Enable coredump<\/h2>\n<p>If you run program from shell , enable coredump via <code>unlimit  -c unlimited<\/code>\uff0c then check <code>unlimit -a | grep core<\/code>, if it shows <code>unlimited<\/code>, coredump is enabled for your current session.<\/p>\n<p>If your program is hosted by systemd, you need to edit your program\u2019s service unit file\u2019s <code>[Service]<\/code> section, add <code>LimitCORE=infinity<\/code> to enable coredump.<\/p>\n<h2 id=\"coredump-location\">coredump location<\/h2>\n<p>Coredump file\u2019s location is determined by kernerl parameter <code>kernel.core_pattern<\/code>.<\/p>\n<p>On ubuntu 16.04 <code>kernel.core_pattern<\/code> default value is <code>|\/usr\/share\/apport\/apport %p %s %c %P<\/code>. Leading <code>|<\/code> means pass coredump file to following program. <code>%p %c %P<\/code> is used to create dump filename, their meaning can check via <code>man core<\/code>. apport will save dump file in \/var\/crash<\/p>\n<p>If your default disk partition don\u2019t have enough space to hold dump file, you can change <code>kernel.core_pattern<\/code> to another location, eg: <code>\/mnt\/core\/%e-%t.%P<\/code>. If redis-server crashes, the dump file will be something like \/mnt\/core\/redis-server-1500000000.1452. Also ensure crash process\u2019s running user have write privilege on target location.<\/p>\n<h2 id=\"systemd-coredump\">systemd-coredump<\/h2>\n<p>You can install systemd-coredump to control dump file deeply, like: size, compression\u2026.<\/p>\n<p>Its config file is \/etc\/systemd\/coredump.conf.<\/p>\n<p>After install, it will change <code>kernel.core_pattern<\/code> to <code>|\/lib\/systemd\/systemd-coredump %P %u %g %s %t 9223372036854775808 %e<\/code>.<\/p>"},{"title":"Python Web \u5e94\u7528\u6027\u80fd\u8c03\u4f18","link":"https:\/\/blog.monsterxx03.com\/2017\/07\/01\/python-web-%E5%BA%94%E7%94%A8%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98\/","pubDate":"Sat, 01 Jul 2017 23:38:24 +0800","guid":"https:\/\/blog.monsterxx03.com\/2017\/07\/01\/python-web-%E5%BA%94%E7%94%A8%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98\/","description":"<h1 id=\"python-web-\u5e94\u7528\u6027\u80fd\u8c03\u4f18\">Python web \u5e94\u7528\u6027\u80fd\u8c03\u4f18<\/h1>\n<p>\u4e3a\u4e86\u5feb\u901f\u4e0a\u7ebf\uff0c\u65e9\u671f\u5f88\u591a\u4ee3\u7801\u57fa\u672c\u662f\u600e\u4e48\u65b9\u4fbf\u600e\u4e48\u6765\uff0c\u8fd9\u6837\u5c31\u7559\u4e0b\u4e86\u5f88\u591a\u9690\u60a3\uff0c\u6027\u80fd\u4e5f\u4e0d\u662f\u5f88\u7406\u60f3\uff0cpython \u56e0\u4e3a GIL \u7684\u539f\u56e0\uff0c\u5728\u6027\u80fd\u4e0a\u6709\u5929\u7136\u52a3\u52bf\uff0c\u5373\u4f7f\u7528\u4e86 gevent\/eventlet \u8fd9\u79cd\u534f\u7a0b\u65b9\u6848\uff0c\u4e5f\u5f88\u5bb9\u6613\u56e0\u4e3a\u8017\u65f6\u7684 CPU \u64cd\u4f5c\u963b\u585e\u4f4f\u6574\u4e2a\u8fdb\u7a0b\u3002\u524d\u9635\u5b50\u5bf9\u57fa\u7840\u4ee3\u7801\u505a\u4e86\u4e9b\u91cd\u6784\uff0c\u6548\u679c\u663e\u8457\uff0c\u8bb0\u5f55\u4e00\u4e9b\u3002<\/p>\n<p>\u8bbe\u5b9a\u76ee\u6807:<\/p>\n<ul>\n<li>\u6027\u80fd\u63d0\u9ad8\u4e86\uff0c\u6700\u76f4\u63a5\u7684\u6548\u679c\u5f53\u7136\u662f\u80fd\u7528\u66f4\u5c11\u7684\u673a\u5668\u5904\u7406\u76f8\u540c\u6d41\u91cf\uff0c\u76ee\u6807\u662f\u5173\u95ed 20% \u7684 stateless webserver.<\/li>\n<li>\u5c3d\u91cf\u5728\u6846\u67b6\u4ee3\u7801\u4e0a\u505a\u6539\u52a8\uff0c\u4e0d\u52a8\u4e1a\u52a1\u903b\u8f91\u4ee3\u7801\u3002<\/li>\n<li>\u4f4e\u98ce\u9669 (\u5386\u53f2\u7ecf\u9a8c\u544a\u8bc9\u6211\u4eec\uff0c\u52a8\u6001\u4e00\u65f6\u723d\uff0c\u91cd\u6784\u706b\u846c\u573a&hellip;.)<\/li>\n<\/ul>\n<h2 id=\"\u6cbb\u6807\">\u6cbb\u6807<\/h2>\n<p>\u5e38\u89c1\u573a\u666f\u662f\u5927\u5bb6\u5f00\u5f00\u5fc3\u5fc3\u505a\u5b8c\u4e00\u4e2a feature\uff0c sandbox \u6d4b\u8bd5\u4e5f\u6ca1\u5565\u95ee\u9898\uff0c\u4e0a\u7ebf\u4e86\uff0c\u7ed3\u679c server load \u98d9\u5347\uff0c\u5404\u79cd timeout \u90fd\u6765\u4e86\uff0c\u8981\u4e48 rollback \u4ee3\u7801\uff0c\u8981\u4e48\u52a0\u673a\u5668\u3002\u95ee\u9898\u4ee3\u7801\u5728\u54ea?<\/p>"},{"title":"Build deb repository with fpm , aptly and s3","link":"https:\/\/blog.monsterxx03.com\/2017\/06\/23\/build-deb-repository-with-fpm-aptly-and-s3\/","pubDate":"Fri, 23 Jun 2017 09:40:58 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/06\/23\/build-deb-repository-with-fpm-aptly-and-s3\/","description":"<p>I\u2019m lazy, I don\u2019t want to be deb\/rpm expert, I don\u2019t want to maintain repo server. I want as less maintenance effort as possible. \ud83d\ude42<\/p>\n<p>Combine tools fpm, aptly with aws s3, we can do it.<\/p>\n<h2 id=\"use-fpm-to-convert-python-package-to-deb\">Use fpm to convert python package to deb<\/h2>\n<p><a href=\"https:\/\/fpm.readthedocs.io\/en\/latest\/\">fpm<\/a> can transform python\/gem\/npm\/dir\/\u2026 to deb\/rpm\/solaris\/\u2026 packages<\/p>\n<p>Example:<\/p>\n<pre><code>fpm -s python -t  deb -m xyj.asmy@gmail.com --verbose  -v 0.10.1 --python-pip \/usr\/local\/pip Flask\n<\/code><\/pre>\n<p>It will transform Flask 0.10.1 package to deb. Output package will be <code>python-flask_0.10.1_all.deb<\/code><\/p>\n<p>Notes:<\/p>\n<ul>\n<li>If python packages rely on some c libs like <code>MySQLdb<\/code> (libmysqlclient-dev), you need to install them on the machine to build deb binary.<\/li>\n<li>By default fpm use easy_install to build packages, some packages like httplib2 have permission bug with easy_install, so I use pip<\/li>\n<li>By default, msgpack-python will be convert to <code>python-msgpack-python<\/code>, I don\u2019t like it, so add <code>-n python-msgpack<\/code> to normalize the package name.<\/li>\n<li>Some package\u2019s dependencies\u2019 version number is not valid(eg: celery 3.1.25 deps pytz &gt;= dev), so I replace the dependencies with <code>--python-disable-dependency pytz -d 'pytz &gt;= 2016.7'<\/code><\/li>\n<li>fpm will not dowload package\u2019s dependency automatically, you need to do it by your self<\/li>\n<\/ul>\n<h2 id=\"use-aptly-to-setup-deb-repository\">Use aptly to setup deb repository<\/h2>\n<p><a href=\"https:\/\/www.aptly.info\/\">aptly<\/a> can help build a self host deb repository and publish it on s3.<\/p>"},{"title":"Debug python performance issue with pyflame","link":"https:\/\/blog.monsterxx03.com\/2017\/06\/05\/debug-python-performance-issue-with-pyflame\/","pubDate":"Mon, 05 Jun 2017 09:50:44 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/06\/05\/debug-python-performance-issue-with-pyflame\/","description":"<p>pyflame is an opensource tool developed by uber: <a href=\"https:\/\/github.com\/uber\/pyflame\">https:\/\/github.com\/uber\/pyflame<\/a><\/p>\n<p>It can take snapshots of running python process, combined with <a href=\"https:\/\/raw.githubusercontent.com\/brendangregg\/FlameGraph\/master\/flamegraph.pl\">flamegraph.pl<\/a>, can output flamegraph picture of python call stacks. Help analyze bottleneck of python program, needn\u2019t inject any perf code into your application, and overhead is very low.<\/p>\n<h2 id=\"basic-usage\">Basic Usage<\/h2>\n<p>sudo pyflame -s 10 -x -r 0.001 $pid | .\/flamegraph.pl &gt; perf.svg<\/p>\n<ul>\n<li>-s, how many seconds to run<\/li>\n<li>-r, sample rate (seconds)<\/li>\n<\/ul>\n<p>Your output will be something like following:<\/p>\n<p><img src=\"https:\/\/blog.monsterxx03.com\/wp-content\/uploads\/2017\/06\/Screen-Shot-2017-06-05-at-5.18.23-PM-300x160.png\" alt=\"\"><\/p>\n<p>Longer bar means more sample points located in it, which means this part code is slower so it has a higher chance seen by pyflame.<\/p>\n<p>In my case, the output graph has a long IDLE part. Pyflame can detect call stacks who are holding GIL, so if the running code doesn\u2019t hold GIL, pyflame don\u2019t know what it\u2019s doing, it will label them as IDLE. Following cases will be considered as IDLE:<\/p>\n<ul>\n<li>Your process is sleeping, do nothing.<\/li>\n<li>Waiting for IO.(eg: Your application is calling a very slow RPC server)<\/li>\n<li>Call libs written in C.<\/li>\n<\/ul>\n<p>The right part is real application logic code. You can check this part to get a sense of overview performance of your code.<\/p>\n<p>Also you can exclude the IDLE part from graph if you don\u2019t care about them, just apply <code>-x<\/code><\/p>"},{"title":"Designing data intensive application, reading notes, Part 2","link":"https:\/\/blog.monsterxx03.com\/2017\/05\/17\/designing-data-intensive-application-reading-notes-part-2\/","pubDate":"Wed, 17 May 2017 09:12:44 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/05\/17\/designing-data-intensive-application-reading-notes-part-2\/","description":"<p>Chapter 4, 5, 6<\/p>\n<h2 id=\"encoding-formats\">Encoding formats<\/h2>\n<p>xml, json, msgpack are text based encoding format, they can\u2019t carry binary bytes (useless you encode them in base64, size grows 33%). And they cary schema definition with data, wast a lot of space.<\/p>\n<p>thrift, protobuf are binary format, can take binary bytes, only carry data, the schema is defined with IDL(interface definition language). They have code generation tool to generate code to encode and decode data, along with check. Every field of data is binded with a tag(mapped to a field in IDL file). If a field is defined is required, it can\u2019t by removed or change tag value, otherwise old code will not be able to decode it.<\/p>\n<p>avro (used in hadoop), have a write schema and a read schema, when store a large file in avro format(contain many records with same schema), the avro write schama file is appended to the data. If use avro in RPC, the avro schema is exchanged during connection setup. When decoding avro, the lib will look both write schema and read schema, and translate write schema into read schema. Forward compatibility means that you can have a new version of the schema as writer and an old version of the schema as reader, backward compatibility means that you can have a new version of the schema as reader and an old version as writer.<\/p>"},{"title":"Designing data intensive application, reading notes, Part 1","link":"https:\/\/blog.monsterxx03.com\/2017\/05\/04\/designing-data-intensive-application-reading-notes-part-1\/","pubDate":"Thu, 04 May 2017 16:27:52 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/05\/04\/designing-data-intensive-application-reading-notes-part-1\/","description":"<p>Notes when reading chapter 2 \u201cData models and query languages\u201d, chapter 3 \u201cStorage and retrieval\u201d<\/p>"},{"title":"4\u6708\u5468\u672b\u6742\u8bb0","link":"https:\/\/blog.monsterxx03.com\/2017\/04\/23\/4%E6%9C%88%E5%91%A8%E6%9C%AB%E6%9D%82%E8%AE%B0\/","pubDate":"Sun, 23 Apr 2017 16:26:04 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/04\/23\/4%E6%9C%88%E5%91%A8%E6%9C%AB%E6%9D%82%E8%AE%B0\/","description":"<p>\u6708\u521d\u7684\u65f6\u5019\u642c\u4e86\u5bb6, \u4e4b\u540e\u7684\u5468\u672b\u4e00\u76f4\u5728\u5fd9\u4e9b\u7410\u7410\u788e\u788e\u7684\u4e8b\u60c5\uff0c\u561b\uff0c\u4ed4\u7ec6\u4e00\u60f3\uff0c\u9664\u4e86\u53bb\u5b9c\u5bb6\u642c\u4e86\u4e2a\u7535\u89c6\u67dc\u56de\u6765\u90fd\u4e0d\u8bb0\u5f97\u5e72\u4e86\u5565\u2026<\/p>\n<p>\u8fd9\u5468\u672b\u5fc3\u8840\u6765\u6f6e\u53bb\u542c\u4e86\u4e24\u4e2a\u8bb2\u5ea7\uff0c\u4e00\u4e2a\u4eba\u6587\u7684\uff0c\u4e00\u4e2a\u6280\u672f\u7684\uff0c\u8fd8\u90fd\u78b0\u5230\u4e86\u70b9\u6709\u610f\u601d\u7684\u4e8b\u60c5\u3002<\/p>"},{"title":"Infrastructure as Code","link":"https:\/\/blog.monsterxx03.com\/2017\/04\/21\/infrastructure-as-code\/","pubDate":"Fri, 21 Apr 2017 16:25:07 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/04\/21\/infrastructure-as-code\/","description":"<p>Create virtual resource on AWS is very convenient, but how to manage them will be a problem when your size grow.<\/p>\n<p>You will come to:<\/p>\n<ul>\n<li>How to explain the detail online settings for your colleagues (like: how our prod vpc is setup?what\u2019s the DHCP option set?), navigate around AWS console is okay, but not convenient.<\/li>\n<li>Who did what to which resource at when? AWS have a service called <code>Config<\/code>, can be used to track this change, but if you want to make things as clear as viewing git log, still a lot of works to do.<\/li>\n<\/ul>\n<p>Ideally, we should manage AWS resources like code, all changes kept in VCS, so called <code>Infrastructure as Code<\/code>.<\/p>\n<p>I\u2019ve tried three ways to do it:<\/p>\n<ul>\n<li>ansible<\/li>\n<li>CloudFormation<\/li>\n<li>terraform<\/li>\n<\/ul>\n<p>In this article, I&rsquo;ll compare them, however, the conclusion is to use terraform \ud83d\ude42<\/p>\n<h2 id=\"ansible\">Ansible<\/h2>\n<p>Provision tools, like ansible\/chef\/puppet, all can be used to create aws resources, but they have some common problems:<\/p>\n<ul>\n<li>Hard to track changes after bootstrap.<\/li>\n<li>No confident what it will do to existing resources.<\/li>\n<\/ul>\n<p>For example, I define a security group in ansibble:<\/p>\n<pre><code>ec2_group:\n  name: &quot;web&quot;\n  description: &quot;security group in web&quot;\n  vpc_id: &quot;vpc-xxx&quot;\n  region: &quot;us-east-1&quot;\n  rules:\n    - proto: tcp\n      from_port: 80\n      to_port: 80\n      cidr_ip: 0.0.0.0\/0\n<\/code><\/pre>\n<p>It will create a security group named \u201cweb\u201d in vpc-xxx. At first glance, it\u2019s convenient and straightforward.<\/p>"},{"title":"Concurrency in Go, Reading Notes","link":"https:\/\/blog.monsterxx03.com\/2017\/04\/19\/concurrency-in-go-reading-notes\/","pubDate":"Wed, 19 Apr 2017 16:26:58 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/04\/19\/concurrency-in-go-reading-notes\/","description":"<p>A few notes taken when reading <Concurrency in Go><\/p>"},{"title":"MySQL partition table","link":"https:\/\/blog.monsterxx03.com\/2017\/04\/05\/mysql-partition-table\/","pubDate":"Wed, 05 Apr 2017 16:23:32 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/04\/05\/mysql-partition-table\/","description":"<h1 id=\"overview\">Overview<\/h1>\n<p>MySQL has buildin partition table support, which can help split data accross multi tables,<\/p>\n<p>and provide a unified query interface as normal tables.<\/p>\n<p>Benefit:<\/p>\n<ul>\n<li>Easy data management: If we need to archive old data, and our table is partitioned by datetime, we can drop old partition directly.<\/li>\n<li>Speed up query based on partition key(partitoin pruning)<\/li>\n<\/ul>\n<p>Limit:<\/p>\n<ul>\n<li>For partition table, every unique key must use every column in table\u2019s partition expression(include primary key)<\/li>\n<li>For innodb engine, paritioned table can\u2019t have foreign key,and can\u2019t have columns referenced by foreign keys.<\/li>\n<li>For MyISAM engine, mysql version &lt;= 5.6.5, DML operation will lock all partition as a whole.<\/li>\n<\/ul>"},{"title":"ElasticSearch cluster","link":"https:\/\/blog.monsterxx03.com\/2017\/03\/22\/elasticsearch-cluster\/","pubDate":"Wed, 22 Mar 2017 16:22:32 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/03\/22\/elasticsearch-cluster\/","description":"<p>In this article, let\u2019s talk about ElasticSearch\u2019s cluster mode, which means multi nodes ElasticSearch.<\/p>\n<h2 id=\"basic-concepts\">Basic concepts<\/h2>\n<p>cluster: A collection of server nodes with same <code>cluster.name<\/code> settings in elasticsearch.yaml<\/p>\n<p>primary shards: Divide a index into multi parts(by default 5), shards of an index can be distributed over multi nodes. It enables scale index horizontally and make access to index parallelly(accross multi nodes).<\/p>\n<p>replicas: backup for shards, also replicas can handle search requests, which means you can scale your search capacity horizontally via replicas.<\/p>"},{"title":"Matrix 14 years later","link":"https:\/\/blog.monsterxx03.com\/2017\/03\/11\/matrix-14-years-later\/","pubDate":"Sat, 11 Mar 2017 16:21:31 +0000","guid":"https:\/\/blog.monsterxx03.com\/2017\/03\/11\/matrix-14-years-later\/","description":"<p>\u5fc3\u8840\u6765\u6f6e, \u53c8\u770b\u4e86\u904d\u9ed1\u5ba2\u5e1d\u56fd\u4e09\u90e8\u66f2, \u5f53\u5e74\u7684\u6c83\u5353\u65af\u57fa\u5144\u5f1f\u90fd\u53d8\u6210\u6c83\u5353\u65af\u57fa\u59d0\u59b9\u4e86, \u550f\u5618\u554a\u2026<\/p>\n<p>\u7b2c\u4e00\u6b21\u770b\u7684\u65f6\u5019, \u597d\u50cf\u662f\u521d\u4e2d\u5427, \u8bb0\u5f97\u770b\u7b2c\u4e09\u90e8\u8fd8\u662f\u59d1\u7236\u7684\u76d7\u7248\u789f\u4e0a\u770b\u7684, \u90a3\u5929\u8fd8\u62c9\u4e86\u4e2a\u540c\u5b66\u548c\u6211\u4e00\u8d77\u770b,\u7136\u540e\u8bf7\u4ed6\u5403\u4e86\u6ce1\u9762+\u51b0\u6dc7\u6dcb,\u7ed3\u679c\u4ed6\u56de\u5bb6\u5c31\u62c9\u809a\u4e86,\u62b1\u6028\u4e86\u6211\u597d\u4e45,\u6240\u4ee5\u5370\u8c61\u7279\u522b\u6df1\u523b,\u54c8\u54c8.<\/p>"},{"title":"Bigtable notes","link":"https:\/\/blog.monsterxx03.com\/2016\/12\/11\/bigtable-notes\/","pubDate":"Sun, 11 Dec 2016 16:20:24 +0000","guid":"https:\/\/blog.monsterxx03.com\/2016\/12\/11\/bigtable-notes\/","description":"<p>\u6742\u4e71\u7b14\u8bb0\uff0c\u8f85\u52a9\u8bfbpaper.<\/p>"},{"title":"GFS notes","link":"https:\/\/blog.monsterxx03.com\/2016\/11\/19\/gfs-notes\/","pubDate":"Sat, 19 Nov 2016 16:18:41 +0000","guid":"https:\/\/blog.monsterxx03.com\/2016\/11\/19\/gfs-notes\/","description":"<p>\u770b\u4e86\u4e0b\u5f88\u4e45\u524d google \u7684 GFS \u8bba\u6587\uff0c \u505a\u70b9\u7b14\u8bb0\u3002<\/p>"},{"title":"Migrate to encrypted RDS","link":"https:\/\/blog.monsterxx03.com\/2016\/10\/28\/migrate-to-encrypted-rds\/","pubDate":"Fri, 28 Oct 2016 16:17:30 +0000","guid":"https:\/\/blog.monsterxx03.com\/2016\/10\/28\/migrate-to-encrypted-rds\/","description":"<p>\u6700\u8fd1\u516c\u53f8\u5728\u505a HIPAA Compliance \u76f8\u5173\u7684\u4e8b\u60c5\uff0c\u5176\u4e2d\u8981\u6c42\u4e4b\u4e00\u662f\u6240\u6709db\u9700\u8981\u5f00\u542fencryption.<\/p>\n<p>\u6bd4\u8f83\u9ebb\u70e6\u7684\u662frds \u7684encryption \u53ea\u80fd\u5728\u521b\u5efa\u7684\u65f6\u5019\u8bbe\u5b9a\uff0c\u65e0\u6cd5\u4e4b\u540e\u4fee\u6539, \u6240\u4ee5\u5fc5\u987b\u5bf9\u7ebf\u4e0a\u7684db \u505a\u4e00\u6b21 migration.<\/p>"},{"title":"\u9b54\u6cd5\u4f7f","link":"https:\/\/blog.monsterxx03.com\/2016\/08\/06\/witch-night\/","pubDate":"Sat, 06 Aug 2016 16:16:23 +0000","guid":"https:\/\/blog.monsterxx03.com\/2016\/08\/06\/witch-night\/","description":"<p>\u6700\u8fd1\u5fc3\u8840\u6765\u6f6e\u628a&lt;\u9b54\u6cd5\u4f7f\u4e4b\u591c&gt;\u7684\u6e38\u620f\u901a\u5173\u4e86, \u90fd\u5df2\u7ecf\u662f5\u5e74?\u8fd8\u662f6\u5e74\u524d\u53d1\u552e\u7684\u4e86, \u56e0\u4e3a\u5f53\u5e74\u6c49\u5316\u8fdf\u8fdf\u4e0d\u53d1\u5e03, \u5c31\u4e00\u76f4\u6401\u7f6e\u4e86.<\/p>"},{"title":"MySQL \u7d22\u5f15\u4f18\u5316","link":"https:\/\/blog.monsterxx03.com\/2016\/07\/26\/mysql-index-optimization\/","pubDate":"Tue, 26 Jul 2016 16:13:54 +0000","guid":"https:\/\/blog.monsterxx03.com\/2016\/07\/26\/mysql-index-optimization\/","description":"<p>\u4ec0\u4e48\u662f\u7d22\u5f15,\u7d22\u5f15\u600e\u4e48\u5efa\u8fd9\u4e9b\u57fa\u672c\u7684\u5c31\u8df3\u8fc7\u4e0d\u8c08\u4e86,\u6574\u7406\u4e00\u4e9b\u524d\u6bb5\u65f6\u95f4\u4f18\u5316\u7ebf\u4e0a SQL \u67e5\u8be2\u65f6\u78b0\u5230\u7684\u4e00\u4e9b\u95ee\u9898. \u4e3b\u8981\u89e3\u51b3\u4e0b\u9762\u51e0\u4e2a\u95ee\u9898:<\/p>\n<ul>\n<li>\u5efa\u7acb\u7d22\u5f15\u600e\u6837\u9009\u62e9\u5408\u9002\u7684\u5217.<\/li>\n<li>\u600e\u6837\u8ba9 SQL \u80fd\u6709\u6548\u5229\u7528\u7d22\u5f15.<\/li>\n<li>\u5982\u679c\u5bf9 SQL \u6548\u7387\u8fdb\u884c\u8bc4\u4f30(\u5373\u8bbe\u7f6e\u7d22\u5f15\u524d\u540e\u662f\u5426\u771f\u7684\u6709\u6027\u80fd\u63d0\u5347).<\/li>\n<\/ul>"},{"title":"Redshift as data warehouse","link":"https:\/\/blog.monsterxx03.com\/2016\/07\/16\/redshift-as-data-warehouse\/","pubDate":"Sat, 16 Jul 2016 16:11:39 +0000","guid":"https:\/\/blog.monsterxx03.com\/2016\/07\/16\/redshift-as-data-warehouse\/","description":"<p>Glow \u7684 server infrastructure \u5168\u90e8\u642d\u5efa\u5728 AWS \u4e0a\uff0c\u4e00\u822c\u8981\u9009\u62e9\u4e00\u4e9b\u57fa\u7840\u670d\u52a1\u7684\u65f6\u5019\uff0c\u603b\u662f\u5148\u770b AWS, \u53ea\u8981\u529f\u80fd\u548c\u6210\u672c\u7b26\u5408\u8981\u6c42\uff0c\u4e0d\u4f1a\u7279\u610f\u9009\u62e9\u5f00\u6e90\u65b9\u6848\u3002<\/p>\n<p>\u6570\u636e\u4ed3\u5e93\u6211\u4eec\u9009\u62e9\u4e86 AWS \u7684 Redshift.<\/p>\n<p>\u5728\u4e00\u5e74\u591a\u7684\u4f7f\u7528\u8fc7\u7a0b\u4e2d Redshift \u7684\u6027\u80fd\u548c\u7a33\u5b9a\u6027\u90fd\u4e0d\u9519, \u5f53\u7136\u4e5f\u6709\u4e00\u4e9b\u5751, \u8fd9\u91cc\u6574\u7406\u4e0b\u5728\u4f7f\u7528 redshift \u7684\u8fc7\u7a0b\u4e2d\u7684\u4e00\u4e9b\u7ecf\u9a8c\u548c\u9047\u5230\u7684\u5751.<\/p>"},{"title":"MySQL innodb buffer pool","link":"https:\/\/blog.monsterxx03.com\/2016\/07\/16\/mysql-innodb-buffer-pool\/","pubDate":"Sat, 16 Jul 2016 16:07:14 +0800","guid":"https:\/\/blog.monsterxx03.com\/2016\/07\/16\/mysql-innodb-buffer-pool\/","description":"<p>\u6700\u8fd1\u5728\u5bf9\u516c\u53f8\u7684 MySQL \u670d\u52a1\u5668\u505a\u6027\u80fd\u4f18\u5316, \u4e00\u76f4\u5bf9 innodb \u7684\u5185\u5b58\u4f7f\u7528\u65b9\u5f0f\u4e0d\u662f\u5f88\u6e05\u695a, \u4e58\u8fd9\u673a\u4f1a\u505a\u70b9\u603b\u7ed3.<\/p>\n<p>\u5728\u914d\u7f6e MySQL \u7684\u65f6\u5019, \u4e00\u822c\u90fd\u4f1a\u9700\u8981\u8bbe\u7f6e <em>innodb_buffer_pool_size<\/em>, \u5728\u5c06 MySQL \u8bbe\u7f6e\u5728\u5355\u72ec\u7684\u670d\u52a1\u5668\u4e0a\u65f6, \u4e00\u822c\u4f1a\u8bbe\u7f6e\u4e3a\u7269\u7406\u5185\u5b58\u768480%.<\/p>\n<p>\u4e4b\u524d\u4e00\u76f4\u7591\u60d1 MySQL \u662f\u600e\u4e48\u7f13\u5b58\u6570\u636e\u7684(\u4e0d\u662f\u6307query cache), \u76f4\u89c9\u5e94\u8be5\u662fLRU, \u4f46\u5982\u679c query \u4e00\u4e0b\u4ece\u78c1\u76d8\u4e0a\u8bfb\u53d6\u5927\u91cf\u7684\u6570\u636e\u7684\u8bdd(\u5168\u8868\u626b\u63cf\u6216\u662f mysqldump), \u662f\u4e0d\u662f\u5f88\u5bb9\u6613\u5c31\u4f1a\u628a\u70ed\u6570\u636e\u7ed9\u8e22\u51fa\u53bb?<\/p>"},{"title":"About Me","link":"https:\/\/blog.monsterxx03.com\/about\/","pubDate":"Fri, 01 Jan 2016 23:49:46 +0800","guid":"https:\/\/blog.monsterxx03.com\/about\/","description":"<p>Work with tech, belive in magic, live on fun :)<\/p>\n<h3 id=\"side-projects\">Side projects<\/h3>\n<ul>\n<li><a href=\"https:\/\/github.com\/monsterxx03\/gospy\">https:\/\/github.com\/monsterxx03\/gospy<\/a>  non-Invasive goroutine inspector<\/li>\n<li><a href=\"https:\/\/github.com\/monsterxx03\/snet\">https:\/\/github.com\/monsterxx03\/snet<\/a>  transparent tcp proxy(mainly used in China), works on Linux &amp; MacOS<\/li>\n<\/ul>\n<h2 id=\"work-expenrience\">Work expenrience<\/h2>\n<h3 id=\"20216--now--xsky-ltd-\">2021.6 ~ Now  XSky Ltd (<a href=\"https:\/\/www.xsky.com\/\">https:\/\/www.xsky.com\/<\/a>)<\/h3>\n<p>Work as senior architect, participated in the design and development of HCI(Hyperconverged infrastructure) system from 0 to 1.<\/p>\n<p>It&rsquo;s a vm scheduling and management system.<\/p>\n<p>Main tech stack:<\/p>\n<ul>\n<li>Postgresql as DB, use logical replication as msg queue.<\/li>\n<li>VictoriaMetrics for monitoring.<\/li>\n<li>Etcd for leader election.<\/li>\n<li>code in golang<\/li>\n<\/ul>\n<p>Major achievements:<\/p>\n<ul>\n<li>Write a terraform provider for the product, which generates the terraform schema definition from an OpenAPI spec using code generation, uses reflection to implement generic Terraform CRUD.<\/li>\n<li>Designed and developed a HA solution for Postgresql based on Patroni(by client side service discovering)<\/li>\n<li>Build alerting system based on VictoriaMetrics, support both metrics &amp; event based alerting.<\/li>\n<li>Design and implement the upgrade path for the product.<\/li>\n<\/ul>\n<h3 id=\"201411--20215-glow-inc-\">2014.11 ~ 2021.5 Glow Inc (<a href=\"https:\/\/glowing.com\">https:\/\/glowing.com<\/a>)<\/h3>\n<p>Work as company&rsquo;s infrastructure architect:<\/p>\n<ul>\n<li>Responsible for AWS-based infrastructure design, selection, maintenance, and refactoring. System capacity planning, cost management.<\/li>\n<li>Identify bottlenecks in system performance and architecture scalability, refactor existing code, increase user base by 10X while keeping IT cost increase to only two times.<\/li>\n<li>Regular team training and technical sharing, as well as code quality control.<\/li>\n<\/ul>\n<h4 id=\"server-infra\">Server Infra<\/h4>\n<ul>\n<li>Develop and achieve SLOs for the business, including:\n<ul>\n<li>Availability: service uptime &gt;=99.99%<\/li>\n<li>Quality: p95 latency &lt; 200ms<\/li>\n<li>Core service p95 latency &lt; 50ms.<\/li>\n<\/ul>\n<\/li>\n<li>Implement infrastructure as code and use Terraform to codify the management of AWS infrastructure components such as VPC, Autoscaling Group, IAM permissions, DMS tasks, RDS, etc. All historical changes should be tracking.<\/li>\n<li>Fully migrating the architecture to EKS (AWS-managed Kubernetes) and upgrading it from version 1.10 to 1.18 without any downtime, such as containerizing the business applications and refactoring the monitoring and alerting solution from Datadog to Prometheus+Grafana.<\/li>\n<li>Based on Jenkins, using Groovy to write pipelines, achieve self-service deployment and rollback of business, and integrate SonarQube to ensure code quality control for the team.<\/li>\n<li>Database selection and optimization, e.g., using MySQL on RDS or AWS Aurora for relational databases, DynamoDB for key-value databases, Sentinel Redis for message queue brokers, Redis Cluster for caching, and ElasticSearch for search and analytics<\/li>\n<li>Performing daily troubleshooting and performance tuning in the production environment, and improving related toolchains, such as using Sentry for bug reporting, Jaeger for OpenTracing, and FluentBit + Loki + Syslog-ng for logging.<\/li>\n<li>Developing a management tool for EKS worker node groups using Golang, enabling seamless migration of stateless applications (such as web services and some message queue consumers) and stateful applications (such as Redis Sentinel HA and Redis Cluster).<\/li>\n<li>Assisting the company in achieving HIPAA compliance, which primarily involves implementing technical measures such as data-at-rest encryption, log anonymization, and access control for internal data.<\/li>\n<\/ul>\n<h3 id=\"code-framework-design-and-refactor\">Code framework design and refactor<\/h3>\n<ul>\n<li>Upgrading a Python project with over 600,000 lines of code from Python 2.7 to Python 3.6, performing a gradual rollout to production within three months without any downtime and without adding extra burden to business development. This was achieved by using SonarQube to perform syntax checks in the CI phase to prevent developers from submitting Python 2.7 incompatible code.<\/li>\n<li>Splitting a code repository was necessary as the early codebase consisted of over a dozen Python repositories that imported each other, leading to significant deployment and troubleshooting issues. To address this, the API frontend layer and business RPC layer were cleanly separated, and the RPC client was generated through code to synchronize with each repository (using AST traversal for syntax checks).<\/li>\n<li>Refactor the deduplication module in the business with Bloom filter to reduce the latency and storage of related business to around 1\/10 of the original.<\/li>\n<\/ul>\n<h3 id=\"data-warehourse\">Data warehourse<\/h3>\n<ul>\n<li>Build a data warehouse based on Redshift\/Spectrum and S3<\/li>\n<li>Design and implement ETL process using DMS, fluentd, argo-workflow, and Spark.<\/li>\n<li>Refactor an early complex reporting system (with over 10,000 lines of Python code) by separating the definition and calculation logic of metrics. After the transformation, the core Python code was reduced to 1,000 lines, and the rest was written in YAML. The system had not been significantly modified for five years. The purpose of the refactoring was to enable PAs (Product Analysts) who are not proficient in Python to define and launch business metrics independently.<\/li>\n<\/ul>\n<h3 id=\"20131--201410--unitedstackprevious-ustackcom-current-tfcloudcom\">2013.1 ~ 2014.10  UnitedStack(previous ustack.com, current tfcloud.com)<\/h3>\n<p>Main work is build a privatized OpenStack distribution, including:<\/p>"}]}}