<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on 备忘</title>
    <link>https://blog.witd.in/post/</link>
    <description>Recent content in Posts on 备忘</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>kongfei605@gmail.com (kongfei)</managingEditor>
    <webMaster>kongfei605@gmail.com (kongfei)</webMaster>
    <copyright>(c) 2022 witd. All rights reserved</copyright>
    <lastBuildDate>Mon, 27 Apr 2026 08:46:28 +0800</lastBuildDate>
    
	<atom:link href="https://blog.witd.in/post/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>桥下的时间</title>
      <link>https://blog.witd.in/2026/04/27/%E6%A1%A5%E4%B8%8B%E7%9A%84%E6%97%B6%E9%97%B4/</link>
      <pubDate>Mon, 27 Apr 2026 08:46:28 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2026/04/27/%E6%A1%A5%E4%B8%8B%E7%9A%84%E6%97%B6%E9%97%B4/</guid>
      <description>又看到那个老大爷，一辆自行车，一个马扎。
他静静坐着看来往的行人和车辆，旁边自行车像个老伙计一样守着。
老牛湾的村口也许太安静了，安静得只剩下回忆。
今天他推着自行车来到桥下，桥上是车流，是赶着去打卡和生存的轰鸣。
他撑开马扎，坐下，马扎旁边只有空气。</description>
    </item>
    
    <item>
      <title>从一个 Issue 谈 PID 1 与 Reaping 机制</title>
      <link>https://blog.witd.in/2025/12/29/%E4%BB%8E%E4%B8%80%E4%B8%AA-issue-%E8%B0%88-pid-1-%E4%B8%8E-reaping-%E6%9C%BA%E5%88%B6/</link>
      <pubDate>Mon, 29 Dec 2025 09:46:28 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2025/12/29/%E4%BB%8E%E4%B8%80%E4%B8%AA-issue-%E8%B0%88-pid-1-%E4%B8%8E-reaping-%E6%9C%BA%E5%88%B6/</guid>
      <description>在容器化部署日益普及的今天，我们经常会遇到一些在传统虚拟机部署中不常见的问题。Categraf 也收到过一个关于僵尸进程（Zombie Process）的反馈（Issue #1261）。Categraf 在容器内是1号进程，(尤其是exec插件、ibex agent)的子进程在退出后变成了僵尸进程，长期占用系统资源。
社区用户反馈记录, 本文将以该 Issue 为切入点，深入剖析僵尸进程产生的原因，解释 PID 1 的特殊性，并详细解读我们是如何通过引入 reapDaemon 来解决这个问题的。
1. 问题背景：为什么会有僵尸进程？ 在 Linux 系统中，当一个子进程结束运行（调用 exit 或被信号杀死）时，它并没有立即从系统中完全消失。它的进程描述符（Process Descriptor）仍然保留在内核中，包含进程号（PID）、退出状态等信息。此时，该进程被称为僵尸进程（Zombie Process），在 ps 命令中状态显示为 Z。
僵尸进程存在的目的是为了让父进程能够获取子进程的退出状态（通过 wait 或 waitpid 系统调用）。一旦父进程读取了这些信息，内核就会释放僵尸进程占用的所有资源，这个过程被称为 Reaping（收割）。
问题的根源 如果父进程在子进程结束前就退出了，或者父进程没有正确地调用 wait 来处理子进程的退出信号，那么这些子进程就会变成“孤儿进程”。
在 Linux 中，孤儿进程会被 PID 1（通常是 init 进程，如 systemd）收养。PID 1 有一个特殊的职责：它必须循环调用 wait 来清理所有被它收养的孤儿僵尸进程。
然而，在容器（Docker/Kubernetes）环境中，容器内的 PID 1 通常就是我们的应用程序本身（例如 Categraf），而不是 systemd。如果我们的 Go 程序没有显式地去处理 SIGCHLD 信号并调用 wait，那么那些因为 exec 插件或其他原因启动并退出的子进程，就会永久变成僵尸进程，导致 PID 资源耗尽。
2. 解决方案：引入 Reap Daemon 为了解决这个问题，我们需要让 Categraf 在作为 PID 1 运行时，具备类似 init 进程的“收割”能力。针对 Issue #1261，我们引入了一个轻量级的 reapDaemon 协程。</description>
    </item>
    
    <item>
      <title>Categraf SNMP 插件优化：解析带单位的监控指标</title>
      <link>https://blog.witd.in/2025/12/26/categraf-snmp-%E6%8F%92%E4%BB%B6%E4%BC%98%E5%8C%96%E8%A7%A3%E6%9E%90%E5%B8%A6%E5%8D%95%E4%BD%8D%E7%9A%84%E7%9B%91%E6%8E%A7%E6%8C%87%E6%A0%87/</link>
      <pubDate>Fri, 26 Dec 2025 09:46:28 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2025/12/26/categraf-snmp-%E6%8F%92%E4%BB%B6%E4%BC%98%E5%8C%96%E8%A7%A3%E6%9E%90%E5%B8%A6%E5%8D%95%E4%BD%8D%E7%9A%84%E7%9B%91%E6%8E%A7%E6%8C%87%E6%A0%87/</guid>
      <description>在监控领域，通过 SNMP 协议采集硬件设备的指标是非常常见的需求。然而，不同厂商的设备（如服务器、网络设备）返回的 SNMP 数据格式千差万别。最近，我们在开源项目 Categraf 中解决了一个有趣的数据解析问题，通过引入启发式提取算法，让 SNMP 插件能够自动处理带有单位后缀的复杂字符串指标。
背景：当数值带上了 &amp;laquo;尾巴&amp;raquo; Issue #1314 提出反馈，在使用 Categraf 采集某些服务器（例如浪潮机器）的 SNMP 指标时，设备返回的数据并不是纯粹的数字，而是包含了单位描述的字符串。
典型的返回结果如下：
SNMPv2-SMI::enterprises.37945.2.1.2.1.1.1.4.8.8... = STRING: &amp;quot;60 degree Celsius&amp;quot; SNMPv2-SMI::enterprises.37945.2.3.1.1.1.10.0.4... = STRING: &amp;quot;0.48 A&amp;quot;  对于流行的时序数据库来说，我们需要的是 60 或 0.48 这样的浮点数，以便进行存储、绘图和告警。&amp;raquo;60 degree Celsius&amp;raquo; 这样的字符串直接转换会失败，导致指标采集丢失。
挑战 Categraf 的 SNMP 插件在处理数据时，通常会尝试将获取到的值转换为浮点数（float64）。 在 Go 语言中，我们通常使用 strconv.ParseFloat 来完成这项工作。但是，这个标准库函数非常严格，一旦字符串中包含非数字字符（比如 &amp;laquo; degree Celsius&amp;raquo;），它就会直接报错并返回错误。
在面对数以千计的设备型号时，我们无法为每一种特殊的返回格式编写特定的正则规则，我们需要一种更通用的、能 &amp;laquo;猜&amp;raquo; 出数值的方法。
解决方案：启发式数据提取 之前社区和交流群里也有小伙伴多次提到数值转换问题，这次我们想找一个更通用的解决方案。 在PR#1317，引入了一个名为 heuristicsDataExtract 的通用处理函数。
核心逻辑 这个方案的核心思想不再是 &amp;laquo;验证字符串是否为数字&amp;raquo;，而是 &amp;laquo;从字符串中提取出最像数字的部分&amp;raquo;。
新的解析逻辑采用了字符遍历的方式，实现了以下功能：
智能扫描：逐个字符扫描字符串，寻找可能是数字的起始点。
兼容性支持：支持识别正负号（+, -）、小数点（.）以及科学计数法（e, E）。</description>
    </item>
    
    <item>
      <title>记一次被社区用户逼着修Bug经历</title>
      <link>https://blog.witd.in/2025/12/25/%E8%AE%B0%E4%B8%80%E6%AC%A1%E8%A2%AB%E7%A4%BE%E5%8C%BA%E7%94%A8%E6%88%B7%E9%80%BC%E7%9D%80%E4%BF%AEbug%E7%BB%8F%E5%8E%86/</link>
      <pubDate>Thu, 25 Dec 2025 09:46:28 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2025/12/25/%E8%AE%B0%E4%B8%80%E6%AC%A1%E8%A2%AB%E7%A4%BE%E5%8C%BA%E7%94%A8%E6%88%B7%E9%80%BC%E7%9D%80%E4%BF%AEbug%E7%BB%8F%E5%8E%86/</guid>
      <description>最近社区用户反馈了一个问题：使用最新版 Categraf (v0.4.34) 的 http_response 插件监控某域名 https://oa.sdu.edu.cn 时，报错 remote error: tls: handshake failure。但开发人员在自己的环境中测试却一切正常。吃瓜围观见issue, 用户对这个问题定性：&amp;raquo;希望在新版本中修复这个bug&amp;raquo;。
本文记录了该问题的完整排查过程、根因分析及最终修复方案。
1. 排查过程 欸？在我的环境明明好好的 复现的诡异性  开发环境 (Debian, 公网)：没有报错，能够正常通过 curl 和 Categraf 采集数据。 用户环境 (Anolis OS, 校园网环境)：curl 正常，但 Categraf 持续报错 tls: handshake failure。  初步怀疑方向集中在： 1. TLS 版本不匹配？ 2. 中间人设备（防火墙、WAF）干扰？ 3. DNS 解析差异？
关键线索：Cipher Suite 与 IP 协议 通过对比开发人员与用户在各自环境下执行 curl -vI https://oa.sdu.edu.cn 的详细日志，我们发现了具体的差异。
开发人员环境（正常） * Connected to oa.sdu.edu.cn (202.194.20.69) port 443 &amp;lt;-- IPv4 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * SSL connection using TLSv1.</description>
    </item>
    
    <item>
      <title>github runner改造日记</title>
      <link>https://blog.witd.in/2025/09/20/github-runner%E6%94%B9%E9%80%A0%E6%97%A5%E8%AE%B0/</link>
      <pubDate>Sat, 20 Sep 2025 10:30:41 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2025/09/20/github-runner%E6%94%B9%E9%80%A0%E6%97%A5%E8%AE%B0/</guid>
      <description>&lt;h1 id=&#34;自动化还是自动化&#34;&gt;自动化还是自动化&lt;/h1&gt;

&lt;p&gt;周五下午跟客户开完例会，稍微梳理了一下这周的需求，发现本周开源版和企业版都发布了很多版本。这里面包含我一直拖着没做的自动化环节。模块发布流程:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;打tag -&amp;gt; 触发github action -&amp;gt; goreleaser -&amp;gt; github scm / docker hub;&lt;/li&gt;
&lt;li&gt;镜像也是需要上传到国内公有云镜像市场的，方便交付同事交付;&lt;/li&gt;
&lt;li&gt;二进制包需要上传到公有云存储，方便交付客户和国内社区用户下载。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这里第一步完全是自动化的，第二步之前也是goreleaser来做得，但是呢github推镜像到国内的云镜像市场，那个时间瞬间就是小时起步了。通过测试发现办公网推国内的镜像市场非常快， 那就从免费的github runner 迁移到办公网内的台式机上。这一步其实需要很扎实的网络来保证跟github的通信, 不过这个改造后步骤1的时间降到了8分钟, 那这些工作就很值了。为了避免直接物理机上做一些骚操作，搞了一个runner的容器镜像。 如何构建镜像见&lt;a href=&#34;https://github.com/kongfei605/github-runner&#34;&gt;https://github.com/kongfei605/github-runner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>一次小的工程实践-看图猜成语</title>
      <link>https://blog.witd.in/2025/05/25/%E4%B8%80%E6%AC%A1%E5%B0%8F%E7%9A%84%E5%B7%A5%E7%A8%8B%E5%AE%9E%E8%B7%B5-%E7%9C%8B%E5%9B%BE%E7%8C%9C%E6%88%90%E8%AF%AD/</link>
      <pubDate>Sun, 25 May 2025 15:45:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2025/05/25/%E4%B8%80%E6%AC%A1%E5%B0%8F%E7%9A%84%E5%B7%A5%E7%A8%8B%E5%AE%9E%E8%B7%B5-%E7%9C%8B%E5%9B%BE%E7%8C%9C%E6%88%90%E8%AF%AD/</guid>
      <description>&lt;h1 id=&#34;一-背景&#34;&gt;一 背景&lt;/h1&gt;

&lt;p&gt;偶尔看到其他机器人有很多插件，有个看图猜成语的很有意思。连续一段时间都在处理客户的问题，刚好周五晚上，顺道做个适合当前框架的插件。&lt;/p&gt;

&lt;p&gt;看图猜成语是一个适合群聊的游戏，它是通过调用api实现的。这个api会返回一个图片链接和对应的成语, 再没有回答对正确答案之前，会逐渐做出提示。
&lt;img src=&#34;https://blog.witd.in/images/idiom/idiom.jpg&#34; alt=&#34;idiom.jpg&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>snmp插件采集超时问题</title>
      <link>https://blog.witd.in/2023/10/16/snmp%E6%8F%92%E4%BB%B6%E9%87%87%E9%9B%86%E8%B6%85%E6%97%B6%E9%97%AE%E9%A2%98/</link>
      <pubDate>Mon, 16 Oct 2023 10:45:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2023/10/16/snmp%E6%8F%92%E4%BB%B6%E9%87%87%E9%9B%86%E8%B6%85%E6%97%B6%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;h1 id=&#34;一-背景&#34;&gt;一 背景&lt;/h1&gt;

&lt;p&gt;客户反馈用&lt;code&gt;categraf&lt;/code&gt;的&lt;code&gt;snmp&lt;/code&gt;插件采集交换机出现数据断点，检查了&lt;code&gt;categraf&lt;/code&gt;日志，发现里面有大量超时&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;categraf: 2023/09/22 08:45:16 instances.go:180: agent udp://1.2.3.4:161 ins: gathering table bgp error: performing bulk walk for field peer_addr: request timeout (after 0 retries)
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;手工用&lt;code&gt;snmpwalk&lt;/code&gt;命令跑是正常的。作为对比，准备了一个脚本如下， 每1分钟请求一遍用户配置的oid。看categraf报超时的时刻，脚本是否也超时。最终发现categraf日志中出现超时，脚本正常采集。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/sh

while true
do
    cat oids   | while read oid
    do
         echo &amp;quot;$(date) oid: ${oid}&amp;quot;
         snmpwalk -v2c -c public  1.2.3.4   ${oid}
    done &amp;gt;&amp;gt;debug.log 2&amp;gt;&amp;amp;1
sleep 60s
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;之前社区也提了一个issue ,反馈v0.3.27版本采集snmp出现断点，v0.3.25 却没有问题。 &lt;a href=&#34;https://github.com/flashcatcloud/categraf/issues/639&#34;&gt;https://github.com/flashcatcloud/categraf/issues/639&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;对比v0.3.25到v0.3.27 的代码，v0.3.27 给snmp 增加了一个snmp_up 指标。 代码见 &lt;a href=&#34;https://github.com/flashcatcloud/categraf/pull/618/files。&#34;&gt;https://github.com/flashcatcloud/categraf/pull/618/files。&lt;/a&gt; 为了快速上报up指标，将snmp_up和其他oid放到了两个goroutine中。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>udp端口探活</title>
      <link>https://blog.witd.in/2023/08/19/udp%E7%AB%AF%E5%8F%A3%E6%8E%A2%E6%B4%BB/</link>
      <pubDate>Sat, 19 Aug 2023 21:45:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2023/08/19/udp%E7%AB%AF%E5%8F%A3%E6%8E%A2%E6%B4%BB/</guid>
      <description>&lt;h1 id=&#34;一-背景&#34;&gt;一 背景&lt;/h1&gt;

&lt;p&gt;商业客户反馈用&lt;code&gt;categraf&lt;/code&gt;的&lt;code&gt;net_response&lt;/code&gt;插件配置了&lt;code&gt;udp&lt;/code&gt;探测, 遇到报错了，如图
&lt;img src=&#34;https://blog.witd.in/images/udp_port_scanning/error.png&#34; alt=&#34;error.png&#34; /&gt;&lt;/p&gt;

&lt;p&gt;udp是无连接的，无法用建立连接的形式判断端口。 插件最初的设计是需要配置udp的发送字符，并且配置期望返回的字符串，&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[[instances]]
targets = [
      &amp;quot;127.0.0.1:161&amp;quot;,
]

protocol = &amp;quot;udp&amp;quot;

## string sent to the server
  send = &amp;quot;hello&amp;quot;
## expected string in answer
  expect = &amp;quot;hello&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;通过返回字符与期望字符是否相等，来判断端口是否连通。用户随即发了另一张图 ，用ncat 来探测端口是ok的
&lt;img src=&#34;https://blog.witd.in/images/udp_port_scanning/ncat.png&#34; alt=&#34;ncat.png&#34; /&gt;
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>2022总结--技术侧</title>
      <link>https://blog.witd.in/2023/01/29/2022%E6%80%BB%E7%BB%93--%E6%8A%80%E6%9C%AF%E4%BE%A7/</link>
      <pubDate>Sun, 29 Jan 2023 18:01:38 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2023/01/29/2022%E6%80%BB%E7%BB%93--%E6%8A%80%E6%9C%AF%E4%BE%A7/</guid>
      <description>&lt;p&gt;2022年终总结早就写了一部分，趁这两天头疼休息，把一些有意思的点,按照时间顺序整理到博客。&lt;/p&gt;

&lt;h4 id=&#34;3款vpn客户端的容器化&#34;&gt;3款vpn客户端的容器化&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;解决客户端共享的问题&lt;/li&gt;
&lt;li&gt;解决硬件绑定问题&lt;/li&gt;
&lt;li&gt;解决验证码依赖&lt;/li&gt;
&lt;li&gt;避免路由冲突&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;客户使用的vpn服务商各不相同;有些客户的vpn客户端再第一次登录后会绑定当前硬件;有些客户端除了用户名密码，还强制短信验证码登录。 随着客户越来越多,遇到路由冲突的可能性也会越来越高。&lt;/p&gt;

&lt;p&gt;容器化之后，客户端全部扔到一起，每个容器只需要暴露一个端口做代理即可，浏览和登录都可以利用这个端口。&lt;/p&gt;

&lt;p&gt;这里配合云厂商的数据热迁移，只用一台低配服务器就可以搞定。除了降本外，容器化客户端这里有个有意思的点，是如何解决只输入一次短信验证码？我的解决方案是通过tcp代理转到ssh 共享的session上。这里跟tcp转unix socket还有一些差异，还需要做一点特殊转换,利用转换就可以在其他机器上通过这个tcp代理登录了。转换细节后面再整理一篇博文介绍。&lt;/p&gt;

&lt;h4 id=&#34;tcl脚本&#34;&gt;tcl脚本&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;支持proxy&lt;/li&gt;
&lt;li&gt;支持relay&lt;/li&gt;
&lt;li&gt;支持password&lt;/li&gt;
&lt;li&gt;支持identity file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;大概5年前也简单学习了tcl的语法，整理了一个脚本发布在公司wiki上。后面整理到博客了,见&lt;a href=&#34;https://blog.witd.in/2018/11/17/%E4%B8%80%E4%BB%BD%E8%87%AA%E5%8A%A8%E7%99%BB%E5%BD%95%E8%84%9A%E6%9C%AC/&#34;&gt;一份登录脚本&lt;/a&gt;。 这次升级主要是配合vpn容器化，再加上重新整理，proxy/relay/password/identity file抽成单独的方法，并支持这些方式组合登录。留个坑，后面再发一遍博文单独介绍。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>FAQ 随手记</title>
      <link>https://blog.witd.in/2022/10/21/faq-%E9%9A%8F%E6%89%8B%E8%AE%B0/</link>
      <pubDate>Fri, 21 Oct 2022 06:28:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2022/10/21/faq-%E9%9A%8F%E6%89%8B%E8%AE%B0/</guid>
      <description>&lt;p&gt;一些采坑或者日常答疑问题的记录，这些问题有时不是很直观,有时排查链路比较长，为了避免反复排查同类问题，简单记录一下。&lt;/p&gt;

&lt;h4 id=&#34;1-cadvisor如何统计fd数目&#34;&gt;1.cadvisor如何统计fd数目&lt;/h4&gt;

&lt;p&gt;cadvisor获取容器cgroup路径下的cgroup.procs 拿到容器内所有进程pid,然后统计所有pid对应/proc/$pid/fd目录数&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.witd.in/images/suishouji/cadvisor_fd.png&#34; width=100%&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>kubernetes组件监控实践</title>
      <link>https://blog.witd.in/2022/10/18/kubernetes%E7%BB%84%E4%BB%B6%E7%9B%91%E6%8E%A7%E5%AE%9E%E8%B7%B5/</link>
      <pubDate>Tue, 18 Oct 2022 21:24:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2022/10/18/kubernetes%E7%BB%84%E4%BB%B6%E7%9B%91%E6%8E%A7%E5%AE%9E%E8%B7%B5/</guid>
      <description>&lt;h1 id=&#34;一-实践&#34;&gt;一 实践&lt;/h1&gt;

&lt;h2 id=&#34;1-1-角色与权限配置&#34;&gt;1.1 角色与权限配置&lt;/h2&gt;

&lt;p&gt;role和serviceaccount均以talk-test为前缀 , namespace为flashtalk&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations: {}
  labels:
    app: n9e
    component: categraf
  name: talk-test-role
rules:
  - apiGroups: [&amp;quot;&amp;quot;]
    resources:
      - nodes
      - nodes/metrics
      - services
      - endpoints
      - pods
    verbs: [&amp;quot;get&amp;quot;, &amp;quot;list&amp;quot;, &amp;quot;watch&amp;quot;]
  - apiGroups:
      - extensions
      - networking.k8s.io
    resources:
      - ingresses
    verbs: [&amp;quot;get&amp;quot;, &amp;quot;list&amp;quot;, &amp;quot;watch&amp;quot;]
  - nonResourceURLs: [&amp;quot;/metrics&amp;quot;, &amp;quot;/metrics/cadvisor&amp;quot;]
    verbs: [&amp;quot;get&amp;quot;]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations: {}
  labels:
    app: n9e
    component: categraf
  name: talk-test-serviceaccount
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations: {}
  labels:
    app: n9e
    component: categraf
  name: talk-test-rolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: talk-test-role
subjects:
- kind: ServiceAccount
  name: talk-test-serviceaccount
  namespace: flashtalk
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>kubernetes node 相关指标梳理</title>
      <link>https://blog.witd.in/2022/10/07/kubernetes-node-%E7%9B%B8%E5%85%B3%E6%8C%87%E6%A0%87%E6%A2%B3%E7%90%86/</link>
      <pubDate>Fri, 07 Oct 2022 08:55:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2022/10/07/kubernetes-node-%E7%9B%B8%E5%85%B3%E6%8C%87%E6%A0%87%E6%A2%B3%E7%90%86/</guid>
      <description>&lt;p&gt;这一篇我们梳理node相关的指标，话不多说，先上指标。&lt;/p&gt;

&lt;p&gt;1.kubelet自身指标梳理&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
gc的时间统计（summary指标）

# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
goroutine 数量

# HELP go_threads Number of OS threads created.
# TYPE go_threads gauge
os的线程数量


# HELP kubelet_cgroup_manager_duration_seconds [ALPHA] Duration in seconds for cgroup manager operations. Broken down by method.
# TYPE kubelet_cgroup_manager_duration_seconds histogram
操作cgroup的时长分布，按照操作类型统计

# HELP kubelet_containers_per_pod_count [ALPHA] The number of containers per pod.
# TYPE kubelet_containers_per_pod_count histogram
pod中container数量的统计(spec.containers的数量)


# HELP kubelet_docker_operations_duration_seconds [ALPHA] Latency in seconds of Docker operations. Broken down by operation type.
# TYPE kubelet_docker_operations_duration_seconds histogram
操作docker的时长分布，按照操作类型统计

# HELP kubelet_docker_operations_errors_total [ALPHA] Cumulative number of Docker operation errors by operation type.
# TYPE kubelet_docker_operations_errors_total counter
操作docker的错误累计次数，按照操作类型统计

# HELP kubelet_docker_operations_timeout_total [ALPHA] Cumulative number of Docker operation timeout by operation type.
# TYPE kubelet_docker_operations_timeout_total counter
操作docker的超时统计，按照操作类型统计

# HELP kubelet_docker_operations_total [ALPHA] Cumulative number of Docker operations by operation type.
# TYPE kubelet_docker_operations_total counter
操作docker的累计次数，按照操作类型统计

# HELP kubelet_eviction_stats_age_seconds [ALPHA] Time between when stats are collected, and when pod is evicted based on those stats by eviction signal
# TYPE kubelet_eviction_stats_age_seconds histogram
驱逐操作的时间分布，按照驱逐信号(原因)分类统计

# HELP kubelet_evictions [ALPHA] Cumulative number of pod evictions by eviction signal
# TYPE kubelet_evictions counter
驱逐次数统计，按照驱逐信号（原因）统计

# HELP kubelet_http_inflight_requests [ALPHA] Number of the inflight http requests
# TYPE kubelet_http_inflight_requests gauge
请求kubelet的inflight请求数,按照method path server_type统计
注意与每秒的request数区别开

# HELP kubelet_http_requests_duration_seconds [ALPHA] Duration in seconds to serve http requests
# TYPE kubelet_http_requests_duration_seconds histogram
请求kubelet的请求时间统计,按照method path server_type统计

# HELP kubelet_http_requests_total [ALPHA] Number of the http requests received since the server started
# TYPE kubelet_http_requests_total counter
请求kubelet的请求数统计,按照method path server_type统计

# HELP kubelet_managed_ephemeral_containers [ALPHA] Current number of ephemeral containers in pods managed by this kubelet. Ephemeral containers will be ignored if disabled by the EphemeralContainers feature gate, and this number will be 0.
# TYPE kubelet_managed_ephemeral_containers gauge
当前kubelet管理的临时容器数量

# HELP kubelet_network_plugin_operations_duration_seconds [ALPHA] Latency in seconds of network plugin operations. Broken down by operation type.
# TYPE kubelet_network_plugin_operations_duration_seconds histogram
网络插件的操作耗时分布 ，按照操作类型(operation_type)统计
如果 --feature-gates=EphemeralContainers=false，否则一直为0

# HELP kubelet_network_plugin_operations_errors_total [ALPHA] Cumulative number of network plugin operation errors by operation type.
# TYPE kubelet_network_plugin_operations_errors_total counter
网络插件累计操作错误数统计，按照操作类型(operation_type)统计

# HELP kubelet_network_plugin_operations_total [ALPHA] Cumulative number of network plugin operations by operation type.
# TYPE kubelet_network_plugin_operations_total counter
网络插件累计操作数统计，按照操作类型(operation_type)统计

# HELP kubelet_node_name [ALPHA] The node&#39;s name. The count is always 1.
# TYPE kubelet_node_name gauge
node name

# HELP kubelet_pleg_discard_events [ALPHA] The number of discard events in PLEG.
# TYPE kubelet_pleg_discard_events counter
PLEG(pod lifecycle event generator) 丢弃的event数统计

# HELP kubelet_pleg_last_seen_seconds [ALPHA] Timestamp in seconds when PLEG was last seen active.
# TYPE kubelet_pleg_last_seen_seconds gauge
PLEG上次活跃的时间戳

# HELP kubelet_pleg_relist_duration_seconds [ALPHA] Duration in seconds for relisting pods in PLEG.
# TYPE kubelet_pleg_relist_duration_seconds histogram
PLEG relist pod时间分布

# HELP kubelet_pleg_relist_interval_seconds [ALPHA] Interval in seconds between relisting in PLEG.
# TYPE kubelet_pleg_relist_interval_seconds histogram
PLEG relist 间隔时间分布

# HELP kubelet_pod_start_duration_seconds [ALPHA] Duration in seconds for a single pod to go from pending to running.
# TYPE kubelet_pod_start_duration_seconds histogram
pod启动时间(从pending到running)分布
kubelet watch到pod时到pod中contianer都running后
（watch各种source channel的pod变更）

# HELP kubelet_pod_worker_duration_seconds [ALPHA] Duration in seconds to sync a single pod. Broken down by operation type: create, update, or sync
# TYPE kubelet_pod_worker_duration_seconds histogram
pod状态变化的时间分布， 按照操作类型（create update sync）统计
worker就是kubelet中处理一个pod的逻辑工作单位

# HELP kubelet_pod_worker_start_duration_seconds [ALPHA] Duration in seconds from seeing a pod to starting a worker.
# TYPE kubelet_pod_worker_start_duration_seconds histogram
kubelet watch到pod到worker启动的时间分布

# HELP kubelet_run_podsandbox_duration_seconds [ALPHA] Duration in seconds of the run_podsandbox operations. Broken down by RuntimeClass.Handler.
# TYPE kubelet_run_podsandbox_duration_seconds histogram
启动sandbox的时间分布

# HELP kubelet_run_podsandbox_errors_total [ALPHA] Cumulative number of the run_podsandbox operation errors by RuntimeClass.Handler.
# TYPE kubelet_run_podsandbox_errors_total counter
启动sanbox出现error的总数

# HELP kubelet_running_containers [ALPHA] Number of containers currently running
# TYPE kubelet_running_containers gauge
当前containers运行状态的统计
按照container状态统计，created running exited

# HELP kubelet_running_pods [ALPHA] Number of pods that have a running pod sandbox
# TYPE kubelet_running_pods gauge
当前处于running状态pod数量

# HELP kubelet_runtime_operations_duration_seconds [ALPHA] Duration in seconds of runtime operations. Broken down by operation type.
# TYPE kubelet_runtime_operations_duration_seconds histogram
容器运行时的操作耗时
(container在create list exec remove stop等的耗时)

# HELP kubelet_runtime_operations_errors_total [ALPHA] Cumulative number of runtime operation errors by operation type.
# TYPE kubelet_runtime_operations_errors_total counter
容器运行时的操作错误数统计(按操作类型统计)

# HELP kubelet_runtime_operations_total [ALPHA] Cumulative number of runtime operations by operation type.
# TYPE kubelet_runtime_operations_total counter
容器运行时的操作总数统计(按操作类型统计)

# HELP kubelet_started_containers_errors_total [ALPHA] Cumulative number of errors when starting containers
# TYPE kubelet_started_containers_errors_total counter
kubelet启动容器错误总数统计(按code和container_type统计)
code包括ErrImagePull ErrImageInspect ErrImagePull ErrRegistryUnavailable ErrInvalidImageName等
container_type一般为&amp;quot;container&amp;quot; &amp;quot;podsandbox&amp;quot;

# HELP kubelet_started_containers_total [ALPHA] Cumulative number of containers started
# TYPE kubelet_started_containers_total counter
kubelet启动容器总数

# HELP kubelet_started_pods_errors_total [ALPHA] Cumulative number of errors when starting pods
# TYPE kubelet_started_pods_errors_total counter
kubelet启动pod遇到的错误总数(只有创建sandbox遇到错误才会统计）

# HELP kubelet_started_pods_total [ALPHA] Cumulative number of pods started
# TYPE kubelet_started_pods_total counter
kubelet启动的pod总数

# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
统计cpu使用率

# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
允许进程打开的最大fd数

# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
当前打开的fd数量

# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
进程驻留内存大小

# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
进程启动时间

# HELP rest_client_request_duration_seconds [ALPHA] Request latency in seconds. Broken down by verb and URL.
# TYPE rest_client_request_duration_seconds histogram
请求apiserver的耗时统计(按照url和请求类型统计verb)

# HELP rest_client_requests_total [ALPHA] Number of HTTP requests, partitioned by status code, method, and host.
# TYPE rest_client_requests_total counter
请求apiserver的总次数(按照返回码code和请求类型method统计)

# HELP storage_operation_duration_seconds [ALPHA] Storage operation duration
# TYPE storage_operation_duration_seconds histogram
存储操作耗时(按照存储plugin(configmap emptydir hostpath 等 )和operation_name分类统计)
# HELP volume_manager_total_volumes [ALPHA] Number of volumes in Volume Manager
# TYPE volume_manager_total_volumes gauge
本机挂载的volume数量统计(按照plugin_name和state统计
plugin_name包括&amp;quot;host-path&amp;quot; &amp;quot;empty-dir&amp;quot; &amp;quot;configmap&amp;quot; &amp;quot;projected&amp;quot;)
state(desired_state_of_world期状态/actual_state_of_world实际状态）
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>kubernetes控制面指标梳理</title>
      <link>https://blog.witd.in/2022/09/04/kubernetes%E6%8E%A7%E5%88%B6%E9%9D%A2%E6%8C%87%E6%A0%87%E6%A2%B3%E7%90%86/</link>
      <pubDate>Sun, 04 Sep 2022 08:55:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2022/09/04/kubernetes%E6%8E%A7%E5%88%B6%E9%9D%A2%E6%8C%87%E6%A0%87%E6%A2%B3%E7%90%86/</guid>
      <description>&lt;h1 id=&#34;kubernetes组件指标梳理&#34;&gt;kubernetes组件指标梳理&lt;/h1&gt;

&lt;p&gt;本文梳理指标对应的的kubernetes版本为1.23.1, etcd版本为3.5.1&lt;/p&gt;

&lt;h2 id=&#34;kube-apiserver-指标&#34;&gt;kube-apiserver 指标&lt;/h2&gt;

&lt;p&gt;kuber-apiserver暴露了148个指标，梳理后比较重要的指标如下。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# HELP apiserver_request_duration_seconds [STABLE] Response latency distribution in seconds for each verb, dry run value, group, version, resource, subresource, scope and component.
# TYPE apiserver_request_duration_seconds histogram
apiserver响应的时间分布，按照url 和 verb 分类
一般按照instance和verb+时间 汇聚

# HELP apiserver_request_total [STABLE] Counter of apiserver requests broken out for each verb, dry run value, group, version, resource, scope, component, and HTTP response code.
# TYPE apiserver_request_total counter
apiserver的请求总数，按照verb、 version、 group、resource、scope、component、 http返回码分类统计

# HELP apiserver_current_inflight_requests [STABLE] Maximal number of currently used inflight request limit of this apiserver per request kind in last second.
# TYPE apiserver_current_inflight_requests gauge
当前最大请求数(利用channel大小限流), 按mutating(非get list watch的请求) 和 readOnly (get list watch)分别限制
超过max-requests-inflight(默认值400)  和 max-mutating-requests-inflight（默认200） 的请求会被限流
apiserver变更时要注意观察，也是反馈集群容量的一个重要指标

# HELP apiserver_response_sizes [STABLE] Response size distribution in bytes for each group, version, verb, resource, subresource, scope and component.
# TYPE apiserver_response_sizes histogram
apiserver 响应大小，单位byte, 按照verb、 version、 group、resource、scope、component分类统计

# HELP watch_cache_capacity [ALPHA] Total capacity of watch cache broken by resource type.
# TYPE watch_cache_capacity gauge
按照资源类型统计的watch缓存大小

# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
每秒钟用户态和系统态cpu消耗时间, 计算apiserver进程的cpu的使用率

# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
apiserver的内存使用量（单位:Byte)

# HELP workqueue_adds_total [ALPHA] Total number of adds handled by workqueue
# TYPE workqueue_adds_total counter
apiserver中包含的controller的工作队列，已处理的任务总数

# HELP workqueue_depth [ALPHA] Current depth of workqueue
# TYPE workqueue_depth gauge
apiserver中包含的controller的工作队列深度，表示当前队列中要处理的任务的数量，数值越小越好 
例如APIServiceRegistrationController admission_quota_controller
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>kubernetes环境鉴权与自动发现</title>
      <link>https://blog.witd.in/2022/08/20/kubernetes%E7%8E%AF%E5%A2%83%E9%89%B4%E6%9D%83%E4%B8%8E%E8%87%AA%E5%8A%A8%E5%8F%91%E7%8E%B0/</link>
      <pubDate>Sat, 20 Aug 2022 16:43:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2022/08/20/kubernetes%E7%8E%AF%E5%A2%83%E9%89%B4%E6%9D%83%E4%B8%8E%E8%87%AA%E5%8A%A8%E5%8F%91%E7%8E%B0/</guid>
      <description>&lt;h1 id=&#34;kubernetes环境鉴权与自动发现&#34;&gt;kubernetes环境鉴权与自动发现&lt;/h1&gt;

&lt;p&gt;概览文章中提到了k8s的鉴权模式，简单回顾下：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RBAC： Role-based access control 是基于角色的访问控制&lt;/li&gt;
&lt;li&gt;ABAC： Atrribute-based access control 是基于属性的访问控制&lt;/li&gt;
&lt;li&gt;Node Authorization： 节点鉴权，专门用户kubelet发出的api请求进行鉴权&lt;/li&gt;
&lt;li&gt;Webhook Authorization： webhook是一种http回调，kube-apiserver配置webhook时， 会设置回调webhook的规则，这些规则中包含了调用的api
group、version、operation、scope等信息。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;有细心的小伙伴指出，RBAC的角色可以作为ABAC的属性来配置。 感谢小伙伴指正，ABAC可以更细粒度的控制权限，相应配置起来也更复杂。&lt;/p&gt;

&lt;h2 id=&#34;kubernetes-鉴权&#34;&gt;kubernetes 鉴权&lt;/h2&gt;

&lt;p&gt;选定RBAC模式后，关于角色，有Role和ClusterRole，对应对象的绑定分别为: RoleBinding 和 ClusterRoleBinding。
Role创建后归属于特定的namespace，一般与特定namespace的权限绑定，而ClusterRole 不属于任何namespace，通常与一组权限绑定。&lt;/p&gt;

&lt;p&gt;ClusterRole通常用于
+ 定义指定namespace资源的访问权限，并在某个namespace范围内授予访问权限；
+ 定义指定namespace资源的访问权限，并在跨namespace范围内授予访问权限；
+ 定义集群范围内的资源访问权限。&lt;/p&gt;

&lt;p&gt;官方文档推荐，如果在单个namespace内定义角色则使用Role，如果是定义集群范围的角色，则使用ClusterRole。
要监控kubernetes组件和集群范围内业务以及为了通用性，所以我们选择ClusterRole 和 ClusterRoleBinding。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>kubernetes监控</title>
      <link>https://blog.witd.in/2022/08/13/kubernetes%E7%9B%91%E6%8E%A7/</link>
      <pubDate>Sat, 13 Aug 2022 20:43:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2022/08/13/kubernetes%E7%9B%91%E6%8E%A7/</guid>
      <description>&lt;h1 id=&#34;kubernetes监控&#34;&gt;kubernetes监控&lt;/h1&gt;

&lt;p&gt;云原生包含了开源软件、云计算和应用架构的元素。云计算解决开源软件的运行门槛问题，同时降低了运维成本和基础架构成本; 云原生给出了更多的应用架构规范, 更聚焦于能力和生态。随着kubernetes在基础设施的大规模落地，监控的需求也发生了变化，建设一套更符合云原生规范的监控体系势在必行。&lt;/p&gt;

&lt;h2 id=&#34;一-监控需求变化&#34;&gt;一 监控需求变化&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;指标周期变短:  相比物理机时代， 基础设施动态化，Pod销毁重建非常频繁，监控指标跟随Pod的生命周期。&lt;/li&gt;
&lt;li&gt;指标数量增加: 随着微服务化流行，指标的数量也大幅增长，研发工程师也更愿意埋点，获取服务状态；各种采集器层出不穷，指标应采尽采&lt;/li&gt;
&lt;li&gt;指标维度更加丰富：物理机时代监控多从资源视角出发，更关注机器、交换机、中间件的采集；新的监控维度更加丰富，维度标签动辄几十上百个，甚至组合会有高基数问题&lt;/li&gt;
&lt;li&gt;基础设施复杂度变高，监控难度增加：kubernetes组件和应用架构模型都需要投入时间去了解学习。kubernetes本身组件都通过/metrics接口暴露了监控数据，但是缺少体系化的文档指导和最佳实践总结&lt;/li&gt;
&lt;li&gt;自动发现更重要：相比物理机时代的静态采集，自动发现采集目标的能力变得更重要&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>一次oom问题排查</title>
      <link>https://blog.witd.in/2022/04/11/%E4%B8%80%E6%AC%A1oom%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5/</link>
      <pubDate>Mon, 11 Apr 2022 21:32:56 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2022/04/11/%E4%B8%80%E6%AC%A1oom%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5/</guid>
      <description>&lt;h3 id=&#34;问题描述&#34;&gt;问题描述&lt;/h3&gt;

&lt;p&gt;收到基础组件错误报警, 检查发现ES oom.&lt;/p&gt;

&lt;h3 id=&#34;问题排查&#34;&gt;问题排查&lt;/h3&gt;

&lt;p&gt;10:21:50 vmtools 申请4kB(order=0) 内存触发了OOM .&lt;/p&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;Apr 11 10:21:50  kernel: &lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;vmtoolsd&lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt; invoked oom-killer: gfp_mask=0x280da, &lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;order=0&lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;, oom_score_adj=0
Apr 11 10:21:50  kernel: vmtoolsd cpuset=/ mems_allowed=0
Apr 11 10:21:50  kernel: CPU: 6 PID: 867 Comm: vmtoolsd Not tainted 3.&lt;span style=&#34;color:#007f7f&#34;&gt;10&lt;/span&gt;.&lt;span style=&#34;color:#007f7f&#34;&gt;0&lt;/span&gt;-693.&lt;span style=&#34;color:#007f7f&#34;&gt;21&lt;/span&gt;.&lt;span style=&#34;color:#007f7f&#34;&gt;1&lt;/span&gt;.&lt;span style=&#34;color:#007f7f&#34;&gt;el7&lt;/span&gt;.&lt;span style=&#34;color:#007f7f&#34;&gt;x86_64&lt;/span&gt; &lt;span style=&#34;color:#f00&#34;&gt;#&lt;/span&gt;1
Apr 11 10:21:50  kernel: Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.&lt;span style=&#34;color:#007f7f&#34;&gt;00&lt;/span&gt; 12/12/2018
Apr 11 10:21:50  kernel: Call Trace:
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff816ae7c8&amp;gt;] dump_stack+0x19/0x1b
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff816a9b90&amp;gt;] dump_header+0x90/0x229
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff810ecec2&amp;gt;] ? ktime_get_ts64+0x52/0xf0
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff8114140f&amp;gt;] ? delayacct_end+0x8f/0xb0
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff8118a884&amp;gt;] oom_kill_process+0x254/0x3d0
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff8118a32d&amp;gt;] ? oom_unkillable_task+0xcd/0x120
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff8118a3d6&amp;gt;] ? find_lock_task_mm+0x56/0xc0
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff8118b0c6&amp;gt;] out_of_memory+0x4b6/0x4f0
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff816aa694&amp;gt;] __alloc_pages_slowpath+0x5d6/0x724
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff811912a5&amp;gt;] __alloc_pages_nodemask+0x405/0x420
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff811d8a75&amp;gt;] alloc_pages_vma+0xb5/0x200
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff811b6c50&amp;gt;] handle_mm_fault+0xb60/0xfa0
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff81333563&amp;gt;] ? number.&lt;span style=&#34;color:#007f7f&#34;&gt;isra&lt;/span&gt;.&lt;span style=&#34;color:#007f7f&#34;&gt;2&lt;/span&gt;+0x323/0x360
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff816bb504&amp;gt;] __do_page_fault+0x154/0x450
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff816bb835&amp;gt;] do_page_fault+0x35/0x90
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff816b7768&amp;gt;] page_fault+0x28/0x30
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff81336539&amp;gt;] ? copy_user_generic_unrolled+0x89/0xc0
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff8122b369&amp;gt;] ? seq_read+0x2c9/0x3e0
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff812756b0&amp;gt;] proc_reg_read+0x40/0x80
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff812054ef&amp;gt;] vfs_read+0x9f/0x170
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff812063bf&amp;gt;] SyS_read+0x7f/0xe0
Apr 11 10:21:50  kernel: [&amp;lt;ffffffff816c0715&amp;gt;] system_call_fastpath+0x1c/0x21
Apr 11 10:21:50  kernel: Mem-Info:
Apr 11 10:21:50  kernel: active_anon:2911137 inactive_anon:58987 isolated_anon:0&lt;span style=&#34;color:#f00&#34;&gt;#&lt;/span&gt;012 active_file:231 inactive_file:1006 isolated_file:193&lt;span style=&#34;color:#f00&#34;&gt;#&lt;/span&gt;012 unevictable:941692 dirty:28 writeback:0 unstable:0&lt;span style=&#34;color:#f00&#34;&gt;#&lt;/span&gt;012 slab_reclaimable:57650 slab_unreclaimable:23641&lt;span style=&#34;color:#f00&#34;&gt;#&lt;/span&gt;012 mapped:69758 shmem:206054 pagetables:15540 bounce:0&lt;span style=&#34;color:#f00&#34;&gt;#&lt;/span&gt;012 free:33111 free_pcp:150 free_cma:0
Apr 11 10:21:50  kernel: Node 0 DMA &lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;free:15840kB&lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt; min:64kB low:80kB &lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;high:96kB&lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt; active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15988kB managed:15904kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:32kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
Apr 11 10:21:50  kernel: lowmem_reserve[]: 0 2977 &lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;16015&lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt; 16015
Apr 11 10:21:50  kernel: Node 0 DMA32 &lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;free:61692kB&lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt; min:12544kB low:15680kB &lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;high:18816kB&lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt; active_anon:2234420kB inactive_anon:41828kB active_file:0kB inactive_file:28kB unevictable:526724kB isolated(anon):0kB isolated(file):0kB present:3129152kB managed:3048960kB mlocked:526724kB dirty:0kB writeback:0kB mapped:55232kB shmem:147496kB slab_reclaimable:70336kB slab_unreclaimable:44232kB kernel_stack:12192kB pagetables:9352kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:88 all_unreclaimable? yes
Apr 11 10:21:50  kernel: lowmem_reserve[]: 0 0 &lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;13037&lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt; 13037
Apr 11 10:21:50  kernel: Node 0 Normal &lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt;free:54912kB min:54968kB&lt;span style=&#34;color:#f00&#34;&gt;##&lt;/span&gt; low:68708kB high:82452kB active_anon:9410128kB inactive_anon:194120kB active_file:924kB inactive_file:3996kB unevictable:3240044kB isolated(anon):0kB isolated(file):772kB present:13631488kB managed:13350504kB mlocked:3240044kB dirty:112kB writeback:0kB mapped:223800kB shmem:676720kB slab_reclaimable:160264kB slab_unreclaimable:50300kB kernel_stack:9600kB pagetables:52808kB unstable:0kB bounce:0kB free_pcp:600kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:650 all_unreclaimable? no
Apr 11 10:21:50  kernel: lowmem_reserve[]: 0 0 0 0
Apr 11 10:21:50  kernel: Node 0 DMA: 0*4kB 0*8kB 0*16kB 1*32kB (U) 1*64kB (U) 1*128kB (U) 1*256kB (U) 0*512kB 1*1024kB (U) 1*2048kB (M) 3*4096kB (M) = 15840kB
Apr 11 10:21:50  kernel: Node 0 DMA32: 4174*4kB (UEM) 1746*8kB (UEM) 1143*16kB (UEM) 387*32kB (EM) 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 61336kB
Apr 11 10:21:50  kernel: Node 0 Normal: 13786*4kB (UE) 19*8kB (U) 1*16kB (M) 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 55312kB
Apr 11 10:21:50  kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
Apr 11 10:21:50  kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
Apr 11 10:21:50  kernel: 273226 total pagecache pages
Apr 11 10:21:50  kernel: 0 pages in swap cache
Apr 11 10:21:50  kernel: Swap cache stats: add 0, delete 0, find 0/0
Apr 11 10:21:50  kernel: Free swap  = 0kB
Apr 11 10:21:50  kernel: Total swap = 0kB
Apr 11 10:21:50  kernel: 4194157 pages RAM
Apr 11 10:21:50  kernel: 0 pages HighMem/MovableOnly
Apr 11 10:21:50  kernel: 90315 pages reserved&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;此时node0 normal 4kB 是包含E类型的内存页的，为什么会申请失败，先计算一下?
&lt;code&gt;UME, 分别 表示UNMOVABEL/RECLAIMABAL/MOVABLE)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>datadog agent代码分析之日志数据流转</title>
      <link>https://blog.witd.in/2022/03/06/datadog-agent%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8B%E6%97%A5%E5%BF%97%E6%95%B0%E6%8D%AE%E6%B5%81%E8%BD%AC/</link>
      <pubDate>Sun, 06 Mar 2022 20:06:56 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2022/03/06/datadog-agent%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8B%E6%97%A5%E5%BF%97%E6%95%B0%E6%8D%AE%E6%B5%81%E8%BD%AC/</guid>
      <description>&lt;h3 id=&#34;背景&#34;&gt;背景&lt;/h3&gt;

&lt;p&gt;去年11月份研究了一下开源的datadog agent代码(7.32.1), 整理了一篇文档。&lt;/p&gt;

&lt;h3 id=&#34;1-日志数据流转&#34;&gt;1 日志数据流转&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;tailer首先从log文件读取，将读取的内容源源不断地发送到 decoder的 input channel中&lt;/li&gt;
&lt;li&gt;decoder 从自身的input channel读取数据 ，判断数据是否需要截断，将数据写入line parser的 input channel&lt;/li&gt;
&lt;li&gt;line parser从自身的input channel读取数据，解析内容、status、时间戳等，写入line handler的 input channel&lt;/li&gt;
&lt;li&gt;line handler从自身的input channel 读取数据，去除空格，发送到自身的output channel&lt;/li&gt;
&lt;li&gt;tailer forwardMessage 从decoder的output channel（与line handler共享）读取数据，添加tag后， 发送给pipeline的 input channel&lt;/li&gt;
&lt;li&gt;processor 从自身的input channel（pipe line的input channel）读取数据，encode后（比如encode为json/pb格式），发送到sender的input channel&lt;/li&gt;
&lt;li&gt;sender 从input channel读取数据，最后又将message写入pipeline的output channle&lt;/li&gt;
&lt;li&gt;sender将message的content发送给datadog 后台，发送时默认不压缩传输，http支持gzip压缩传输，tcp不支持压缩。&lt;/li&gt;
&lt;li&gt;pipeline的output channel初始传入的是auditor的 input channel。 auditor从input channel 读取数据，写入内存 ，定时器从buffer刷入磁盘，另外一个定时器定期清理内存过期数据&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
    
    <item>
      <title>kubernetes e2e test</title>
      <link>https://blog.witd.in/2021/10/26/kubernetes-e2e-test/</link>
      <pubDate>Tue, 26 Oct 2021 11:26:10 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2021/10/26/kubernetes-e2e-test/</guid>
      <description>&lt;h3 id=&#34;一-背景描述&#34;&gt;一 背景描述&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;线上最大的集群增长即将达到社区的最大节点数，团队比较关注, 按照当前线上的使用方式单个集群能支撑到多大规模， 因此安排了这次测试。
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;二-测试版本及配置信息&#34;&gt;二 测试版本及配置信息&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;kubernetes 1.12.4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;硬件配置：&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;cpu&lt;/th&gt;
&lt;th&gt;mem&lt;/th&gt;
&lt;th&gt;disk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2*Intel-E5-2670v3&lt;/td&gt;
&lt;td&gt;8*16G&lt;/td&gt;
&lt;td&gt;12*300G&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;集群由294台M10构成,  单位：台&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;集群&lt;/th&gt;
&lt;th&gt;etcd台数&lt;/th&gt;
&lt;th&gt;master台数&lt;/th&gt;
&lt;th&gt;node数&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;挂载集群&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;283&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;测试集群&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;8k（hollow-node）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&#34;三-模型简述&#34;&gt;三 模型简述：&lt;/h3&gt;

&lt;p&gt;1 社区认为每个node上30个pod是正常负载，因此饱和性测试最终生成8k*30=24w 个pod。 记录24w pod生成时间，计算出调度的吞吐量。这个过程主要是用用于模拟集群大面积故障 ，恢复全部服务的时间。  =》 Scheduling throughput&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>docker-runc关闭kmem</title>
      <link>https://blog.witd.in/2021/03/16/docker-runc%E5%85%B3%E9%97%ADkmem/</link>
      <pubDate>Tue, 16 Mar 2021 15:01:30 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2021/03/16/docker-runc%E5%85%B3%E9%97%ADkmem/</guid>
      <description>&lt;h3 id=&#34;问题描述&#34;&gt;问题描述&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;值班同学反馈线上一台centos7的物理机container层kmem打开了 kubepods层kmem是关闭的。
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.witd.in/images/runckmem/docker_kmem.png&#34; width=100%&gt;&lt;/p&gt;

&lt;h3 id=&#34;问题排查&#34;&gt;问题排查&lt;/h3&gt;

&lt;p&gt;kubelet如果是打开了kmem，从kubepods层就能看到slabinfo的内容，因此排除是kubelet版本低的问题。继续排查18版本的docker-runc代码部分，发现runc中默认是打开kmem的。&lt;/p&gt;

&lt;p&gt;13和18版本runc关于kmem部分的代码对比&lt;/p&gt;

&lt;table style=&#34;border-collapse: collapse; border: none;&#34;&gt;
&lt;tr style=&#34;border: none;&#34;&gt;
&lt;td style=&#34;border: none;&#34; width=100%&gt;docker13 runc&lt;/td&gt;
&lt;td style=&#34;border: none;&#34; width=100%&gt;docker18 runc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&#34;border: none;&#34;&gt;
&lt;td style=&#34;border: none;&#34;&gt;&lt;img src=&#34;https://blog.witd.in/images/runckmem/runc13_kmem.png&#34; width=100%&gt;&lt;/td&gt;
&lt;td style=&#34;border: none;&#34;&gt;&lt;img src=&#34;https://blog.witd.in/images/runckmem/runc18_kmem.png&#34; width=100%&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>sys.kernel.threads-max默认值</title>
      <link>https://blog.witd.in/2021/03/16/sys.kernel.threads-max%E9%BB%98%E8%AE%A4%E5%80%BC/</link>
      <pubDate>Tue, 16 Mar 2021 10:25:30 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2021/03/16/sys.kernel.threads-max%E9%BB%98%E8%AE%A4%E5%80%BC/</guid>
      <description>&lt;h3 id=&#34;背景&#34;&gt;背景&lt;/h3&gt;

&lt;p&gt;物理机时代,业务根据&lt;code&gt;/proc/sys/kernel/threads-max&lt;/code&gt;设置线程池大小。容器（特指docker）该值仍然获取的是物理机上的信息，而容器规格一般比物理机小，再根据这个值获取信息设置容器内线程数就不准确了。物理机上这个值受哪些资源影响，因此有了这篇文章。&lt;/p&gt;

&lt;h3 id=&#34;梳理&#34;&gt;梳理&lt;/h3&gt;

&lt;p&gt;内核版本4.18 线程数限制为[20,0x3fffffff]&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.witd.in/images/maxthreads/min_threads.png&#34; width=100%&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.witd.in/images/maxthreads/max_threads.png&#34; width=100%&gt;
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>eBPF实战之超时问题排查</title>
      <link>https://blog.witd.in/2020/09/19/ebpf%E5%AE%9E%E6%88%98%E4%B9%8B%E8%B6%85%E6%97%B6%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5/</link>
      <pubDate>Sat, 19 Sep 2020 18:12:30 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2020/09/19/ebpf%E5%AE%9E%E6%88%98%E4%B9%8B%E8%B6%85%E6%97%B6%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5/</guid>
      <description>&lt;h3 id=&#34;问题描述&#34;&gt;问题描述&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;线上A模块访问B模块,A模块部署在物理机,B模块部署在容器上。早晚高峰A访问B会出现超时报警。
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;问题排查&#34;&gt;问题排查&lt;/h3&gt;

&lt;p&gt;业务方找到我们排查，我首先申请了监控中提示超时的两台机器权限，看一下超时规律
&lt;img src=&#34;https://blog.witd.in/images/single_timeout_stat.png&#34; alt=&#34;timeout&#34; /&gt;
登录10.167.8.25容器所在的宿主机常规排查&lt;/p&gt;

&lt;p&gt;dmesg显示如下,联系值班同学和系统部同学硬件报修。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;EDAC sbridge MC1: HANDLING MCE MEMORY ERROR&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;漂移容器10.167.8.252后，10.167.41.18 在两台物理机上小时级别日志中会出现近10次
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>docker源码快速阅读</title>
      <link>https://blog.witd.in/2020/09/19/docker%E6%BA%90%E7%A0%81%E5%BF%AB%E9%80%9F%E9%98%85%E8%AF%BB/</link>
      <pubDate>Sat, 19 Sep 2020 09:11:38 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2020/09/19/docker%E6%BA%90%E7%A0%81%E5%BF%AB%E9%80%9F%E9%98%85%E8%AF%BB/</guid>
      <description>&lt;h3 id=&#34;阅读前准备&#34;&gt;阅读前准备&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;git: https://github.com/moby/moby.git
branch: v18.06.3-ce
ide: goland2020.2 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;配置goland的build tag &lt;img src=&#34;https://blog.witd.in/images/goland_build_tag.png&#34; alt=&#34;build tag&#34; /&gt;&lt;/p&gt;

&lt;p&gt;一起见证docker 代码中套路
&lt;code&gt;exec.Command=&amp;gt; cmd.Start() =&amp;gt; cmd.Wait()&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&#34;进程模型&#34;&gt;进程模型&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;docker   
  |      
  V       
dockerd -&amp;gt; containerd ---&amp;gt; shim -&amp;gt; runc -&amp;gt; runc init -&amp;gt; process1
                      |--&amp;gt; shim -&amp;gt; runc -&amp;gt; runc init -&amp;gt; process2
                      +--&amp;gt; shim -&amp;gt; runc -&amp;gt; runc init -&amp;gt; process3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>记一次第三方库的PR</title>
      <link>https://blog.witd.in/2019/12/13/%E8%AE%B0%E4%B8%80%E6%AC%A1%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%93%E7%9A%84pr/</link>
      <pubDate>Fri, 13 Dec 2019 09:09:11 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2019/12/13/%E8%AE%B0%E4%B8%80%E6%AC%A1%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%93%E7%9A%84pr/</guid>
      <description>&lt;h3 id=&#34;背景&#34;&gt;背景&lt;/h3&gt;

&lt;p&gt;线上很多场景可能会用到pstree，比如查看容器的所有子进程，回滚任务需要杀死正在运行中的子进程。&lt;/p&gt;

&lt;h3 id=&#34;一个轻量级的库&#34;&gt;一个轻量级的库&lt;/h3&gt;

&lt;p&gt;我们选用的是一个轻量级的pstree。&lt;code&gt;github.com/sbinet/pstree&lt;/code&gt;这个库比较简单，首先遍历/proc/ 获取所有PID&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;files, err := filepath.Glob(&amp;quot;/proc/[0-9]*&amp;quot;)
...
procs := make(map[int]Process, len(files))
	for _, dir := range files {
		proc, err := scan(dir)
		if err != nil {
			return nil, fmt.Errorf(&amp;quot;could not scan %s: %w&amp;quot;, dir, err)
		}
		if proc.Stat.Pid == 0 {
			// process vanished since Glob.
			continue
		}
		procs[proc.Stat.Pid] = proc
	}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后，scan()是读取/proc/[pid]/stat，获取pid和相应的ppid、name等信息
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>网卡驱动升级导致容器网络设备丢失问题</title>
      <link>https://blog.witd.in/2019/12/10/%E7%BD%91%E5%8D%A1%E9%A9%B1%E5%8A%A8%E5%8D%87%E7%BA%A7%E5%AF%BC%E8%87%B4%E5%AE%B9%E5%99%A8%E7%BD%91%E7%BB%9C%E8%AE%BE%E5%A4%87%E4%B8%A2%E5%A4%B1%E9%97%AE%E9%A2%98/</link>
      <pubDate>Tue, 10 Dec 2019 09:09:11 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2019/12/10/%E7%BD%91%E5%8D%A1%E9%A9%B1%E5%8A%A8%E5%8D%87%E7%BA%A7%E5%AF%BC%E8%87%B4%E5%AE%B9%E5%99%A8%E7%BD%91%E7%BB%9C%E8%AE%BE%E5%A4%87%E4%B8%A2%E5%A4%B1%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;h3 id=&#34;背景&#34;&gt;背景&lt;/h3&gt;

&lt;p&gt;线上网络采用macvlan方案。线上宿主创建的vlan id是3 ，对应的接口是eth0.3 或 bond4.3&lt;/p&gt;

&lt;h3 id=&#34;现象描述&#34;&gt;现象描述&lt;/h3&gt;

&lt;p&gt;i40e网卡升级驱动，理论上不需要重启宿主，几秒后即可自动恢复。但是线上宿主升级驱动后，容器内的网络设备却丢失了，当前场景下kubelet 会自动重建容器，但是重建容器成本较高，尤其对于静态容器而言。理论上网络设备可以自行创建并添加到对应的namespace。&lt;/p&gt;

&lt;p&gt;简单描述就是网卡驱动升级后，容器关联的网络接口消失，容器被重建。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>kmem accounting导致的cgroup泄漏问题</title>
      <link>https://blog.witd.in/2019/12/09/kmem-accounting%E5%AF%BC%E8%87%B4%E7%9A%84cgroup%E6%B3%84%E6%BC%8F%E9%97%AE%E9%A2%98/</link>
      <pubDate>Mon, 09 Dec 2019 20:01:38 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2019/12/09/kmem-accounting%E5%AF%BC%E8%87%B4%E7%9A%84cgroup%E6%B3%84%E6%BC%8F%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;h3 id=&#34;现象描述&#34;&gt;现象描述&lt;/h3&gt;

&lt;p&gt;宿主机上创建容器时失败，kubelet log中可见报错信息&lt;code&gt;mkdir /sys/fs/cgroup/memory/kubepods/burstable/pod79fe803c-072f-11e9-90ca-525400090c71/b98d4aea818bf9d1d1aa84079e1688cd9b4218e008c58a8ef6d6c3c106403e7b: no space left on devic&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这个问题是kubernetes 1.9版本引入的，kubelet创建容器时&lt;code&gt;EnableKernelMemoryAccounting&lt;/code&gt;导致的。&lt;a href=&#34;https://www.malasuk.com/doc/kernel-doc-3.10.0/Documentation/cgroups/memory.txt&#34;&gt;kernel memory&lt;/a&gt; 在内核4.0以下的版本只是一个实验特性，存在使用后不能删除cgroup的问题，造成cgroup泄漏。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   Kernel memory support is a work in progress, and the current version provides basically functionality. (See Section 2.7)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;关于这个问题的复现和分析，网络上有很多文章, 解决方案简单总结就是宿主机重启+关闭kmem accounting的kubelet。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;k8s社区issue &lt;a href=&#34;https://github.com/kubernetes/kubernetes/issues/61937&#34;&gt;https://github.com/kubernetes/kubernetes/issues/61937&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;moby 社区的issue &lt;a href=&#34;https://github.com/moby/moby/issues/29638&#34;&gt;https://github.com/moby/moby/issues/29638&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;腾讯的分析&lt;a href=&#34;https://tencentcloudcontainerteam.github.io/2018/12/29/cgroup-leaking/&#34;&gt;https://tencentcloudcontainerteam.github.io/2018/12/29/cgroup-leaking/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;还有这篇&lt;a href=&#34;http://www.linuxfly.org/kubernetes-19-conflict-with-centos7/?from=groupmessage&#34;&gt;http://www.linuxfly.org/kubernetes-19-conflict-with-centos7/?from=groupmessage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;kakuli&lt;/code&gt;同学这篇文章&lt;a href=&#34;http://likakuli.com/post/2019/06/cgroup%E6%B3%84%E9%9C%B2/&#34;&gt;cgroup泄露问题&lt;/a&gt;对kubelet相关代码进行了详细的分析，并提供了1.12.4版本（我们的线上版本）的修复方案。 k8s社区在版本1.14，提供了开关可以关闭&lt;code&gt;kmem accounting&lt;/code&gt;。
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>golang http client 关闭重用连接两种方法</title>
      <link>https://blog.witd.in/2019/02/25/golang-http-client-%E5%85%B3%E9%97%AD%E9%87%8D%E7%94%A8%E8%BF%9E%E6%8E%A5%E4%B8%A4%E7%A7%8D%E6%96%B9%E6%B3%95/</link>
      <pubDate>Mon, 25 Feb 2019 10:06:41 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2019/02/25/golang-http-client-%E5%85%B3%E9%97%AD%E9%87%8D%E7%94%A8%E8%BF%9E%E6%8E%A5%E4%B8%A4%E7%A7%8D%E6%96%B9%E6%B3%95/</guid>
      <description>&lt;p&gt;同事有个模块会定期获取宿主机上的所有容器信息，代码中使用http client 请求docker engine获取容器信息。运行后收到用户反馈，程序导致系统fd泄漏,修复后代码如下，比原来代码多了一句 &lt;code&gt;req.Close=true&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    client := &amp;amp;http.Client{
        Timeout: time.Duration(timeout) * time.Millisecond,
        Transport: &amp;amp;http.Transport{
            Dial: unixDial,
        },
    }

    req, err := http.NewRequest(&amp;quot;GET&amp;quot;, url, nil)
    if err != nil {
        return nil, fmt.Errorf(&amp;quot;NewRequest(): url = %s, err = %s&amp;quot;, url, err)
    }

    req.Close = true // fd leak without setting this
    resp, err := client.Do(req)
    ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;因为我自己有个清理容器数据的代码也有类似逻辑。代码如下，但是这个清理容器的模块是运行一次就退出的（磁盘资源紧张时才运行） 所以没有这个问题。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  tr := &amp;amp;http.Transport{Dial: fakeDial, } 
    client := &amp;amp;http.Client{Transport: tr}
    resp, err := client.Get(&amp;quot;http://localhost/containers/json&amp;quot;)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;翻了下源码发现这段注释&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    // Close indicates whether to close the connection after
    // replying to this request (for servers) or after sending this
    // request and reading its response (for clients).
    //
    // For server requests, the HTTP server handles this automatically
    // and this field is not needed by Handlers.
    //
    // For client requests, setting this field prevents re-use of
    // TCP connections between requests to the same hosts, as if
    // Transport.DisableKeepAlives were set.
    Close bool
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>一份自动登录脚本</title>
      <link>https://blog.witd.in/2018/11/17/%E4%B8%80%E4%BB%BD%E8%87%AA%E5%8A%A8%E7%99%BB%E5%BD%95%E8%84%9A%E6%9C%AC/</link>
      <pubDate>Sat, 17 Nov 2018 22:00:53 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2018/11/17/%E4%B8%80%E4%BB%BD%E8%87%AA%E5%8A%A8%E7%99%BB%E5%BD%95%E8%84%9A%E6%9C%AC/</guid>
      <description>&lt;p&gt;背景:登录到relay需要输入token+密码， 然后选择中控机。&lt;/p&gt;

&lt;p&gt;需求:k8s机房大概有X个了，master ip 记不住，这次要给自动登录脚本加一个展示机器列表的功能，选择ip 或hostname 的序号进行登录,登录其他node机器时 只需要直接gg hostname 即可。 gg prod 会展示 master 列表,输入 master对应的序号，回车即可登录到master.&lt;/p&gt;

&lt;p&gt;花时间学习了tcl的语法 完成了这个脚本。&lt;/p&gt;

&lt;p&gt;先设置线上机器的ssh 会话复用 ,这样每天只需要输入一次token ，其他时间不需要再输入token了&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;host *
    Protocol 2
    ServerAliveInterval 30
    ServerAliveCountMax 3
host xxxx.xxx.efg
    ControlMaster auto
    ControlPath ~/.ssh/master-%r@%h
host xxx.xxx.abc
    ControlMaster auto
    ControlPath ~/.ssh/master-%r@%h
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>golang邮件抄送</title>
      <link>https://blog.witd.in/2018/04/01/golang%E9%82%AE%E4%BB%B6%E6%8A%84%E9%80%81/</link>
      <pubDate>Sun, 01 Apr 2018 17:38:53 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2018/04/01/golang%E9%82%AE%E4%BB%B6%E6%8A%84%E9%80%81/</guid>
      <description>&lt;p&gt;最近接触的一个api模块中使用了smtp.SendMail发送邮件。因为要实现cc功能，看了下源码，简单记录下。&lt;/p&gt;

&lt;p&gt;smtp中关于SendMail的声明&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SendMail(addr string, a Auth, from string, to []string, msg []byte) error
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;参数依次是,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    addr: smtp server地址，格式为hostname:port 或者 ip:port;
    a: smtp PlainAuth信息, 包含identity, username, password, host, 即身份id、用户名、密码、smtp服务器host. identify 一般为空，表明identity与username一致;
    from: 发件邮箱
    to: 收件人地址列表,包含to，cc，bcc的所有收件地址
    msg: 邮件内容,包含邮件header和body
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;来一个栗子&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>用Makefile做一点微小的工作</title>
      <link>https://blog.witd.in/2017/10/02/%E7%94%A8makefile%E5%81%9A%E4%B8%80%E7%82%B9%E5%BE%AE%E5%B0%8F%E7%9A%84%E5%B7%A5%E4%BD%9C/</link>
      <pubDate>Mon, 02 Oct 2017 08:53:45 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2017/10/02/%E7%94%A8makefile%E5%81%9A%E4%B8%80%E7%82%B9%E5%BE%AE%E5%B0%8F%E7%9A%84%E5%B7%A5%E4%BD%9C/</guid>
      <description>&lt;p&gt;有一个内网服务的模块，升级过程大体是在一个目录A中git pull-&amp;gt;go build， 然后B目录中备份-&amp;gt;stop-&amp;gt;替换-&amp;gt;start。这个模块有个control.sh负责起停模块，有个build.sh负责编译,备份是靠cp module module.bak。这样就可能会有备份版办覆盖的问题，比较好的方式是使用模块的版本号作为备份文件后缀。&lt;/p&gt;

&lt;p&gt;总的需求就是自动化，可以编译/备份/升级/回滚。备份时候希望按照版本号进行，回滚的时候可以按照指定版本号进行回滚。这种升级方式不可取，作为一个过渡的临时方案.&lt;/p&gt;

&lt;p&gt;改造第一步，利用golang 的&lt;code&gt;ldflags&lt;/code&gt; 在模块编译的时候给模块指定版本号。版本号就用 &lt;code&gt;short commit id + date&lt;/code&gt;的格式。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>迁移SLB过程中的一次踩坑记录</title>
      <link>https://blog.witd.in/2017/05/30/%E8%BF%81%E7%A7%BBslb%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%9A%84%E4%B8%80%E6%AC%A1%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95/</link>
      <pubDate>Tue, 30 May 2017 20:19:14 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2017/05/30/%E8%BF%81%E7%A7%BBslb%E8%BF%87%E7%A8%8B%E4%B8%AD%E7%9A%84%E4%B8%80%E6%AC%A1%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95/</guid>
      <description>&lt;p&gt;流量入口迁移到云的负载均衡。第二天收到合作方的反馈，提示连接被重置，我们将流量重新切回老入口。简单排查后发现，使用java的合作方出现 connection reset，而其他(如python)的调用方并没有此类报错。安卓客户端也是部分机型报错。&lt;/p&gt;

&lt;h3 id=&#34;1-初步排查&#34;&gt;1.初步排查&lt;/h3&gt;

&lt;p&gt;跟调用方要了一个demo，在我本地机器上跑了一下，发现并没有被重置。抓包对比发现:jdk1.7默认使用TLSv1.0请求https服务，被reset；jdk1.8默认使用TLSv1.2请求https服务,不会被reset。Java HttpClient可以通过SSLContext指定TSL版本避免这个问题, 但是推动调用方去改，显然不妥。&lt;/p&gt;

&lt;p&gt;jdk1.8使用TSLv1.2握手,访问新的入口 &lt;img src=&#34;https://blog.witd.in/034.png&#34; alt=&#34;034.png&#34; /&gt;
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>golang并发访问map</title>
      <link>https://blog.witd.in/2017/05/06/golang%E5%B9%B6%E5%8F%91%E8%AE%BF%E9%97%AEmap/</link>
      <pubDate>Sat, 06 May 2017 22:17:00 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2017/05/06/golang%E5%B9%B6%E5%8F%91%E8%AE%BF%E9%97%AEmap/</guid>
      <description>&lt;p&gt;golang的map不是线程安全的,官方文档解释也给出了解释&lt;a href=&#34;https://golang.org/doc/faq#atomic_maps&#34;&gt;Why are map operations not defined to be atomic?&lt;/a&gt;。因此对于已经爬取过的url,不能直接使用map作标记。利用map加锁可以解决并发访问的问题，但是写锁也会导致无法读，怎么优雅的加锁是一个问题.&lt;/p&gt;

&lt;p&gt;这个&lt;a href=&#34;https://github.com/DeanThompson/syncmap&#34;&gt;syncmap&lt;/a&gt;将map分片，利用bdkr将字符串hash到不同的map分片，这样一来，锁的粒度变小。

关于BDKR补充&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>《穷查里宝典》读书笔记</title>
      <link>https://blog.witd.in/2017/04/24/%E7%A9%B7%E6%9F%A5%E9%87%8C%E5%AE%9D%E5%85%B8%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Mon, 24 Apr 2017 12:29:18 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2017/04/24/%E7%A9%B7%E6%9F%A5%E9%87%8C%E5%AE%9D%E5%85%B8%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</guid>
      <description>这本书的中文名翻译得有点意思，翻译的人应该是把自己对芒格的崇拜放到译作中，也或许是为了引导读者购买？
书是芒格的演讲汇总，其中穿插着一些引导和解释性的文字。注释类的应该多用脚注，书中用了很多小括号来解释，读起来会影响流畅度。
个人感触最深的是芒格提出的关于心理学的几条原理和例子，做事情之前应该按照这些清单检查一遍，自己是否已经陷入到心理陷阱心理中。一个没有学过心理学的人总结出来的关于心理学的经验，很有趣，配合书中的例子，也很有说服力。</description>
    </item>
    
    <item>
      <title>2017书单</title>
      <link>https://blog.witd.in/2017/04/20/2017%E4%B9%A6%E5%8D%95/</link>
      <pubDate>Thu, 20 Apr 2017 18:14:14 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2017/04/20/2017%E4%B9%A6%E5%8D%95/</guid>
      <description>&lt;p&gt;2017&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;《第一本docker书》
《穷查里宝典》
《郁闷的中国人》
《张择端《清明上河图》导览》
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>收益计算--基金篇</title>
      <link>https://blog.witd.in/2016/11/27/%E6%94%B6%E7%9B%8A%E8%AE%A1%E7%AE%97--%E5%9F%BA%E9%87%91%E7%AF%87/</link>
      <pubDate>Sun, 27 Nov 2016 14:01:56 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/11/27/%E6%94%B6%E7%9B%8A%E8%AE%A1%E7%AE%97--%E5%9F%BA%E9%87%91%E7%AF%87/</guid>
      <description>&lt;h2 id=&#34;一-基金的收益来源&#34;&gt;一 基金的收益来源&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://blog.witd.in/2016/11/20/%E6%8C%87%E6%95%B0%E5%9F%BA%E9%87%91%E5%9F%BA%E7%A1%80/&#34;&gt;指数基金基础&lt;/a&gt; 文章中提到基金收益来自于所投资的股票整体升值，这是因为指数基金标的只是指数的成份股， 而普通基金的标的还可能包括一部分银行存款/公司债券。因此， 基金的收益可以分成三部分&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;利息： 来自银行存款和基金所投资的债券。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;股利：来自于股息和红利&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;资本利得：股票 证券的价差。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>神奇公式</title>
      <link>https://blog.witd.in/2016/11/27/%E7%A5%9E%E5%A5%87%E5%85%AC%E5%BC%8F/</link>
      <pubDate>Sun, 27 Nov 2016 12:26:25 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/11/27/%E7%A5%9E%E5%A5%87%E5%85%AC%E5%BC%8F/</guid>
      <description>&lt;p&gt;神奇公式依据以下两点对公司进行排位：资本收益率和股票收益率。这些因素可以用几种不同的方式进行衡量&lt;/p&gt;

&lt;p&gt;1.资本收益率&lt;/p&gt;

&lt;p&gt;EBIT/（净运营资本+净固定资产）&lt;/p&gt;

&lt;p&gt;资本收益率时指息税前利润（EBIT）与占用的有形资本的比值。之所以用这个比值而不是更常用的股本收益率（ROE，收益/股本）或者资产收益率（ROA,收益/资产），有几个原因。&lt;/p&gt;

&lt;p&gt;由于各个公司的债务水平和税率不同，使用息税前利润可以反映公司的收益状况，可以使我们了解和比较不同公司的营业收益，避免出现由于税率和负债水平不同而导致的曲解。对每个公司而言，将经营产生的实际收益（EBIT）与用于生产这些收益的资产的成本（占用的有形资本）相比成为可能。
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>指数基金基础</title>
      <link>https://blog.witd.in/2016/11/20/%E6%8C%87%E6%95%B0%E5%9F%BA%E9%87%91%E5%9F%BA%E7%A1%80/</link>
      <pubDate>Sun, 20 Nov 2016 12:21:37 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/11/20/%E6%8C%87%E6%95%B0%E5%9F%BA%E9%87%91%E5%9F%BA%E7%A1%80/</guid>
      <description>&lt;h2 id=&#34;一-定义&#34;&gt;一 定义&lt;/h2&gt;

&lt;p&gt;指数基金的投资理念是在证券市场上选定一部分符合条件的证券或股票，这些证券可以通过客观标准（如：总资本，总股本，成交量，主营业务）选定，也可以通过主观标准(如成长性，被市场低估的程度)选定；被选定的证券或股票共同构成一个指数，每一个证券都拥有一个确定的权重（即该证券或股票在整个投资组合中所占的比例），指数基金经理按照这个指数购买证券或股票，建立一个与指数完全相同或基本相同的投资组合，这样就创造了一只指数基金。&lt;/p&gt;

&lt;h3 id=&#34;1-理论基础&#34;&gt;1 理论基础&lt;/h3&gt;

&lt;p&gt;指数基金的理论基础是建立在有效市场假说基础上的随机游走理论。&lt;/p&gt;

&lt;p&gt;有效市场：如果在一个证券市场中，价格完全反映了所有可以获得的信息，那么就称这样的市场为有效市场。 英语Efficient-market hypothesis，缩写为EMH，又译为有效市场假说，一个经济学假说，由尤金·法马（Eugene Fama）于1970年深化并提出的。&lt;/p&gt;

&lt;p&gt;随机游走：一种数学统计模型，它是一连串的轨迹所组成，其中每一次都是随机的。它能用来表示不规则的变动形式。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>golang时间小结</title>
      <link>https://blog.witd.in/2016/11/05/golang%E6%97%B6%E9%97%B4%E5%B0%8F%E7%BB%93/</link>
      <pubDate>Sat, 05 Nov 2016 18:16:59 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/11/05/golang%E6%97%B6%E9%97%B4%E5%B0%8F%E7%BB%93/</guid>
      <description>&lt;p&gt;1.求前一天的日期(字符串输出)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;    now := time.Now()
    yesterday := now.AddDate(0, 0, -1)
    dt := yesterday.Format(&amp;quot;20060102&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;2.求一天0:00:00到23:59:59 (报表查询)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;    now := time.Now()
    yesterday := now.AddDate(0, 0, -1)
    year, month, day := yesterday.Date()
    yesterday_start := time.Date(year, month, day, 0, 0, 0, 0, now.Location())
    yesterday_end := time.Date(year, month, day, 23, 59, 59, 0, now.Location())
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>《奇特的一生》读书笔记</title>
      <link>https://blog.witd.in/2016/10/28/%E5%A5%87%E7%89%B9%E7%9A%84%E4%B8%80%E7%94%9F%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Fri, 28 Oct 2016 11:09:16 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/10/28/%E5%A5%87%E7%89%B9%E7%9A%84%E4%B8%80%E7%94%9F%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;h2 id=&#34;一-简介&#34;&gt;一 简介&lt;/h2&gt;

&lt;p&gt;书的作者格拉宁对苏联科学家柳比歇夫进行了尽可能全面的评价，而不是三七开的俗套。书中描写柳比歇夫运用时间统计法安排自己的生活与工作。这个方法统计的格式是时间/地点/事件/耗时。正如作者所说，柳比歇夫建立了内在感知时间的系统，能准确估计事件的耗时，几乎没有什么误差。后面的章节也解释了为什么这种方法适合大多数人，这种方法的收益，这样做会不会框定太死，会不会把人变成机器。&lt;/p&gt;

&lt;p&gt;时间统计法的缘起，是1918年柳比歇夫从部队复员回来，开始从事纯学术工作。那会他已经提出他一生的奋斗目标—创立生物自然分类法。而这个目标非常耗时，终其一生也只能完成一小部分。这个目标需要付出比常人更多的时间和经历，因此他开始寻找方法。每项工作需要多少时间？时间应该怎么分配？ 正是对人生目标进行思考，引发他对时间分配的思考。关键是这个传奇人物还相对低调，《奇特的一生》作者正是从分析他的日志中发现和总结时间统计方法。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>我的blog又搬家了</title>
      <link>https://blog.witd.in/2016/09/28/%E6%88%91%E7%9A%84blog%E5%8F%88%E6%90%AC%E5%AE%B6%E4%BA%86/</link>
      <pubDate>Wed, 28 Sep 2016 16:37:46 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/09/28/%E6%88%91%E7%9A%84blog%E5%8F%88%E6%90%AC%E5%AE%B6%E4%BA%86/</guid>
      <description>&lt;h3 id=&#34;我的blog又搬家了&#34;&gt;我的blog又搬家了&lt;/h3&gt;

&lt;p&gt;20130429 blog从免费空间搬到独立域名wbook.in,购买域名送一年主机，不过这个主机不能登陆，只能写博客。&lt;/p&gt;

&lt;p&gt;域名和主机到期后，又续费了两年，这样大概到2017年3月份。但是遇到几次博客无法打开，虽然找卖家给解决了，但是响应及时性和可控性方面与预期还是差很远。&lt;/p&gt;

&lt;p&gt;因此，20160928 我的blog开始使用国外VPS。&lt;/p&gt;

&lt;p&gt;域名到期后，跟原来的卖家协商只买域名，价格太不划算，卖家把wbook.in域名续费到20180302，导致我没办法继续使用这个域名。20170302 ，开始启用域名&lt;code&gt;witd.in&lt;/code&gt;
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>sync.Pool使用场景–gin之context维护</title>
      <link>https://blog.witd.in/2016/08/31/sync.pool%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AFgin%E4%B9%8Bcontext%E7%BB%B4%E6%8A%A4/</link>
      <pubDate>Wed, 31 Aug 2016 18:40:04 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/08/31/sync.pool%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AFgin%E4%B9%8Bcontext%E7%BB%B4%E6%8A%A4/</guid>
      <description>&lt;p&gt;gin是开源的优秀golang web框架之一，github repo:&lt;a href=&#34;https://github.com/gin-gonic/gin&#34;&gt;https://github.com/gin-gonic/gin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;gin的pool是sync.Pool类型&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;Engine struct {
    ...
    pool sync.Pool
    ...
}
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>pg.v4和sharding.v4之Transaction使用小结</title>
      <link>https://blog.witd.in/2016/08/27/pg.v4%E5%92%8Csharding.v4%E4%B9%8Btransaction%E4%BD%BF%E7%94%A8%E5%B0%8F%E7%BB%93/</link>
      <pubDate>Sat, 27 Aug 2016 12:19:41 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/08/27/pg.v4%E5%92%8Csharding.v4%E4%B9%8Btransaction%E4%BD%BF%E7%94%A8%E5%B0%8F%E7%BB%93/</guid>
      <description>&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;type User struct{
TableName string `sql:&amp;quot;user_?SHARD&amp;quot;`
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;postgres中user表按uid进行sharding存储。这样会有16张表user_0到user_f。pg.v4 中关于事务可以使用 方法一和方法二&lt;/p&gt;

&lt;p&gt;方法一&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;err := getDB().RunInTransaction(func(tx *pg.Tx) error {
    q := fmt.Sprintf(&amp;quot;INSERT INTO user_%s (id,x,x,x) VALUES(default,y,y,y) RETURNING *&amp;quot;,shard_str)
    _, err := this.shard().QueryOne(this,q,this)
    return err
})
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>pg.ErrNoRows和pg.ErrMultiRows</title>
      <link>https://blog.witd.in/2016/08/17/pg.errnorows%E5%92%8Cpg.errmultirows/</link>
      <pubDate>Wed, 17 Aug 2016 14:18:01 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/08/17/pg.errnorows%E5%92%8Cpg.errmultirows/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/go-pg/pg&#34;&gt;golang pg.v4&lt;/a&gt;的Select，返回结果有可能是0行 1行或者多行，如果根据返回的行数进行下一步的insert 或update，应该怎么做？
 
如果使用&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;b:= &amp;amp;[]Book{}
err:= db.Model(b).Where(&amp;quot;blabla&amp;quot;).Select()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;除非是数据库连接异常才会抛出error,而&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;b:= &amp;amp;Book{}
err:= db.Model(b).Where(&amp;quot;blabla&amp;quot;).Select()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;会在select没有结果时抛出&lt;code&gt;pg.ErrNoRows&lt;/code&gt; ，有多行时抛出&lt;code&gt;pg.ErrMultiRows&lt;/code&gt;，1行时返回&lt;code&gt;nil&lt;/code&gt;，数据库异常时&lt;code&gt;error&lt;/code&gt;。
看下源码实现:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;db.go&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;func (db *DB) Model(model interface{}) *orm.Query {
    return orm.NewQuery(db, model)
}
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>2016书单</title>
      <link>https://blog.witd.in/2016/08/10/2016%E4%B9%A6%E5%8D%95/</link>
      <pubDate>Wed, 10 Aug 2016 14:32:25 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/08/10/2016%E4%B9%A6%E5%8D%95/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;《穷查理宝典》&lt;/li&gt;
&lt;li&gt;《The Go programming language》&lt;/li&gt;
&lt;li&gt;《算法的乐趣》&lt;/li&gt;
&lt;li&gt;《哲学的慰藉》&lt;/li&gt;
&lt;li&gt;《The little book that still beats the market》&lt;/li&gt;
&lt;li&gt;《身份的焦虑》&lt;/li&gt;
&lt;li&gt;《十万分之一的偶然》&lt;/li&gt;
&lt;li&gt;《上瘾五百年》&lt;/li&gt;
&lt;li&gt;《奇特的一生》&lt;/li&gt;
&lt;li&gt;《知行合一 王阳明》</description>
    </item>
    
    <item>
      <title>2016买房不能错过的4大技巧</title>
      <link>https://blog.witd.in/2016/07/16/2016%E4%B9%B0%E6%88%BF%E4%B8%8D%E8%83%BD%E9%94%99%E8%BF%87%E7%9A%844%E5%A4%A7%E6%8A%80%E5%B7%A7/</link>
      <pubDate>Sat, 16 Jul 2016 14:35:51 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/07/16/2016%E4%B9%B0%E6%88%BF%E4%B8%8D%E8%83%BD%E9%94%99%E8%BF%87%E7%9A%844%E5%A4%A7%E6%8A%80%E5%B7%A7/</guid>
      <description>&lt;p&gt;整理自《简七理财进化论》&lt;/p&gt;

&lt;h1 id=&#34;一-选哪个城市&#34;&gt;一 选哪个城市&lt;/h1&gt;

&lt;hr /&gt;

&lt;h2 id=&#34;1-如何选&#34;&gt;1 如何选&lt;/h2&gt;

&lt;p&gt;方法：将目标城市过去5年的人口/GDP/财政收入数据列出来进行对比；&lt;/p&gt;

&lt;p&gt;注:人口数据使用教育局公布的小学生数据代替，比使用常驻人口更准确些；关于GDP可以再参考本外币存款等数据；&lt;/p&gt;

&lt;p&gt;用这个方法计算可以发现三个结论：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;南方城市比北方城市好；&lt;/li&gt;
&lt;li&gt;省会城市普遍比地级市好；&lt;/li&gt;
&lt;li&gt;民营经济发达的城市比国有经济占主导的城市更好；&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;注：可以1利用上市公司数量；2私募基金数量；3民营老板的富豪榜上榜人数来判断一个城市的民营经济是否活跃
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>《第一次买保险就买对》笔记</title>
      <link>https://blog.witd.in/2016/07/12/%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B9%B0%E4%BF%9D%E9%99%A9%E5%B0%B1%E4%B9%B0%E5%AF%B9%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Tue, 12 Jul 2016 14:45:47 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/07/12/%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B9%B0%E4%BF%9D%E9%99%A9%E5%B0%B1%E4%B9%B0%E5%AF%B9%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;我们都期待一种生活，在这种生活里，每个人都安居乐业，相安无事，万事顺意。可是，这样的理想世界并不存在，世界上每分每秒都在发生意外。
我当然期望那不是我们，不是我们的家庭。可我无法保证。
我能保证的是，尽我的能力使家人不会在遭受内心痛苦的同时遭受金钱的打击。因为我知道，真正的爱不是我活多久就照顾你多久，而是你活多久我就照顾你多久
 –《第一次买保险就买对》&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&#34;七步搞定你的保障&#34;&gt;七步搞定你的保障&lt;/h2&gt;

&lt;h3 id=&#34;第一步-明确保险需求&#34;&gt;第一步：明确保险需求&lt;/h3&gt;

&lt;p&gt;A 为了保障&lt;/p&gt;

&lt;p&gt;B 为了理财&lt;/p&gt;

&lt;h3 id=&#34;第二步-明确人身保险险种&#34;&gt;第二步：明确人身保险险种&lt;/h3&gt;

&lt;p&gt;被保险人的保险状态/年龄&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;儿童未参与工作的青年–非保障重点，适当配置意外险&lt;/li&gt;
&lt;li&gt;参与工作的青壮年–保障重点，标准保险配置：意外险+寿险+重疾险&lt;/li&gt;
&lt;li&gt;大于50岁或这即将/已经退休–非保障重点，适当配置意外险&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;第三步-明确保险额度&#34;&gt;第三步：明确保险额度&lt;/h3&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>《设计模式》笔记</title>
      <link>https://blog.witd.in/2016/07/08/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Fri, 08 Jul 2016 14:58:04 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/07/08/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;p&gt;看了《敏捷软件开发(原则模式与实践)》，感受Java的设计原则和模式真的很棒，看了这本书收获很多。关于设计原则/模式的笔记记录如下。
 &lt;/p&gt;

&lt;h2 id=&#34;一-设计的臭味&#34;&gt;一 设计的臭味&lt;/h2&gt;

&lt;h3 id=&#34;1-僵化性&#34;&gt;1 僵化性&lt;/h3&gt;

&lt;p&gt;难以对软件进行改动。如果单一的改动会导致有依赖关系的模块中的连锁改动，那么设计就是僵化的。&lt;/p&gt;

&lt;h3 id=&#34;2-脆弱性&#34;&gt;2 脆弱性&lt;/h3&gt;

&lt;p&gt;进行一个改动时，程序的许多地方就可能出现问题。&lt;/p&gt;

&lt;h3 id=&#34;3-牢固性&#34;&gt;3 牢固性&lt;/h3&gt;

&lt;p&gt;设计中包含有对其他系统有用的部分，但把这些部分从系统中分离出来所需要的努力和风险是巨大的。&lt;/p&gt;

&lt;h3 id=&#34;4-粘滞性&#34;&gt;4 粘滞性&lt;/h3&gt;

&lt;p&gt;软件的粘滞性 与环境的粘滞性（耦合关系很重的一些指标， 绝对路径，绝对依赖等）。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>关于golang sync.Pool</title>
      <link>https://blog.witd.in/2016/05/29/%E5%85%B3%E4%BA%8Egolang-sync.pool/</link>
      <pubDate>Sun, 29 May 2016 12:04:13 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/05/29/%E5%85%B3%E4%BA%8Egolang-sync.pool/</guid>
      <description>&lt;p&gt;golang 官方为了解决对象重用问题提供了临时对象池：&lt;a href=&#34;https://golang.org/src/sync/pool.go&#34;&gt;https://golang.org/src/sync/pool.go&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;对象池，是指提供了对象复用功能。临时是指对象池的没有引用的对象在每两分钟一次的GC中会被全部清理掉。有点坳口，下面我们来看一段代码。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;package main

import (
    &amp;quot;log&amp;quot;
    &amp;quot;runtime&amp;quot;
    &amp;quot;sync&amp;quot;
)

func main() {
    p := &amp;amp;sync.Pool{
        New: func() interface{} {
            return 0
        },
    }
    a := p.Get().(int)
    p.Put(1)
    b := p.Get().(int)
    log.Println(a, b)
    p.Put(3)
    p.Put(4)
    p.Put(5)
    log.Println(p.Get()) //返回 3 4 5中的任意一个。
    //主动调用GC  pool中对象会被清理掉
    runtime.GC()
    p.Put(2)
    c := p.Get().(int)
    log.Println(c)
}
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>vps安全配置(一)</title>
      <link>https://blog.witd.in/2016/05/29/vps%E5%AE%89%E5%85%A8%E9%85%8D%E7%BD%AE%E4%B8%80/</link>
      <pubDate>Sun, 29 May 2016 10:31:25 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/05/29/vps%E5%AE%89%E5%85%A8%E9%85%8D%E7%BD%AE%E4%B8%80/</guid>
      <description>&lt;h1 id=&#34;背景故事&#34;&gt;背景故事&lt;/h1&gt;

&lt;p&gt;本周一（2016.05.23）上午刘同学的服务器上的数据被清空，对方勒索3个比特比，目前比特比价格在2900+，3个比特币近9000大洋。 网络上没有绝对安全，能做的就是尽量提高黑客暴力猜解的成本。这里总结下关于ssh安全方面的设置。&lt;/p&gt;

&lt;h1 id=&#34;一-配置说明&#34;&gt;一 配置说明&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt; 修改ssh默认端口&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;修改端口后，对方依旧可以靠扫描端口来尝试，不过服务器一般还会有http之类的端口，这里只是增加了扫描的成本。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;禁止root远程登录
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;root用户是每个系统都存在的用户，如果不禁止root远程登录，土贼在暴力猜解时，只需要猜解密码而不需要猜解登录的用户名。&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>pg.v4 update小结</title>
      <link>https://blog.witd.in/2016/05/14/pg.v4-update%E5%B0%8F%E7%BB%93/</link>
      <pubDate>Sat, 14 May 2016 15:09:15 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/05/14/pg.v4-update%E5%B0%8F%E7%BB%93/</guid>
      <description>&lt;p&gt;go-pg是golang实现的postgresql client，项目页：&lt;a href=&#34;https://github.com/go-pg/pg。&#34;&gt;https://github.com/go-pg/pg。&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;按项目页说明使用Update有3中用法 ：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Update all columns except primary keys.
err := db.Update(&amp;amp;book)
// UPDATE &amp;quot;books&amp;quot; SET title = &#39;my title&#39;, text = &#39;my text&#39; WHERE id = 1

// Update only column &amp;quot;title&amp;quot;.
res, err := db.Model(&amp;amp;book).Set(&amp;quot;title = ?title&amp;quot;).Where(&amp;quot;id = ?id&amp;quot;).Update()
// UPDATE &amp;quot;books&amp;quot; SET title = &#39;my title&#39; WHERE id = 1

// Update only column &amp;quot;title&amp;quot;.
res, err := db.Model(&amp;amp;book).Column(&amp;quot;title&amp;quot;).Update()
// UPDATE &amp;quot;books&amp;quot; SET title = &#39;my title&#39; WHERE id = 1
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>pandas sum函数小结</title>
      <link>https://blog.witd.in/2016/01/31/pandas-sum%E5%87%BD%E6%95%B0%E5%B0%8F%E7%BB%93/</link>
      <pubDate>Sun, 31 Jan 2016 15:19:27 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2016/01/31/pandas-sum%E5%87%BD%E6%95%B0%E5%B0%8F%E7%BB%93/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://pandas.pydata.org/pandas-docs/version/0.17.1/generated/pandas.DataFrame.sum.html&#34;&gt;sum()函数文档&lt;/a&gt;中说sum的作用是Return the sum of the values for the requested axis ，即返回指定栏或列的值的和。&lt;/p&gt;

&lt;p&gt;函数有4个有名参数，
&lt;code&gt;axis=None, skipna=None, level=None, numeric_only=None, **kwargs&lt;/code&gt; 。 不指定任何参数时即给axis赋值。&lt;/p&gt;

&lt;p&gt;当sum(1)时是求行的和，当sum(0)时是求列的和。理解这个用法时参考了这个链接：&lt;a href=&#34;http://blog.mathandpencil.com/column-and-row-sums/&#34;&gt;http://blog.mathandpencil.com/column-and-row-sums/&lt;/a&gt;
 &lt;/p&gt;

&lt;p&gt;If you want to do a row sum in pandas, given the dataframe df:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;python df.sum(axis=1)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and a column sum:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;python df.sum(axis=0)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>《西游记》第一次读书笔记</title>
      <link>https://blog.witd.in/2015/07/31/%E8%A5%BF%E6%B8%B8%E8%AE%B0%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Fri, 31 Jul 2015 11:19:41 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2015/07/31/%E8%A5%BF%E6%B8%B8%E8%AE%B0%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;p&gt;第一次完整读完《西游记》，竟然是在上下班的地铁上完成的，果然时间在不经意间就溜走了。
 
读完之后对鲁迅说的&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;“描神画鬼，毫无对证，本来可以专靠了神思，所谓’天马行空’似地挥写了，然而他们写出来的，也不过是三只眼睛，长颈子，就是在常见的人体上，增加了眼睛一只，增长了颈子二三尺而已。”
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;有了些许了解，写神仙也都是从作者自身的理解出发，因此描写中带出了很多人性私心方面的内容。这也使我想到86版《西游记》的编剧很厉害，编排出符合大众容易接受的情节，使整个电视剧中的人物和情节都很纯粹和简洁。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>伟大的博弈：华尔街金融帝国的崛起(1653-2011)</title>
      <link>https://blog.witd.in/2015/06/01/%E4%BC%9F%E5%A4%A7%E7%9A%84%E5%8D%9A%E5%BC%88%E5%8D%8E%E5%B0%94%E8%A1%97%E9%87%91%E8%9E%8D%E5%B8%9D%E5%9B%BD%E7%9A%84%E5%B4%9B%E8%B5%B71653-2011/</link>
      <pubDate>Mon, 01 Jun 2015 11:56:56 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2015/06/01/%E4%BC%9F%E5%A4%A7%E7%9A%84%E5%8D%9A%E5%BC%88%E5%8D%8E%E5%B0%94%E8%A1%97%E9%87%91%E8%9E%8D%E5%B8%9D%E5%9B%BD%E7%9A%84%E5%B4%9B%E8%B5%B71653-2011/</guid>
      <description>&lt;p&gt;今天读完《伟大的博弈》，书中介绍了华尔街近350年的兴衰史。关于某些重点事件的同一时期的其他事件，书中也进行了描述，有趣的是作者并没有特意强调这些事件的因果关系，留给读者很多想象和思考的空间。每章节之后还有译者附加的同一时期东西方历史大事件。&lt;/p&gt;

&lt;p&gt;1854年 ，美国颁布《堪萨斯-内布拉斯加法案》 允许堪萨斯 内布拉斯加可以公开蓄奴，7月共和党成立，这个法案导致工业化和奴隶制度的矛盾，这导致州内部的矛盾，继而引发了后来的南北战争。 后面还有很多不露声色的描述，比如次贷危机后，各个利益阶层的博弈，参议员通过，众议院驳回的各种金融监管改革法案。 这些都说明：一切矛盾或者制度的冲突/阶级的对立，都是利益的冲突。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>shell两例</title>
      <link>https://blog.witd.in/2014/10/21/shell%E4%B8%A4%E4%BE%8B/</link>
      <pubDate>Tue, 21 Oct 2014 15:25:33 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2014/10/21/shell%E4%B8%A4%E4%BE%8B/</guid>
      <description>&lt;h3 id=&#34;1-需求-求加权平均值&#34;&gt;1.需求：求加权平均值。&lt;/h3&gt;

&lt;p&gt;简化下：文件中有两列，我要统计两列乘积 和所有乘积的和&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;echo &amp;quot;1 2
3 4
5 6&amp;quot; |awk &#39;BEGIN{i=1}{ a[i++]=$1*$2;sum+=$1*$2;}END{for(i in a ){print i,a[i]};print sum}&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;写出如下方式， 说明就理解awk是按行处理了&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;echo &amp;quot;1 2
3 4
5 6&amp;quot; |awk &#39;{ a[NR]=$1*$2;sum+=$1*$2;}END{for(i in a ){print i,a[i]};print sum}&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>python空格与tab转换</title>
      <link>https://blog.witd.in/2014/10/04/python%E7%A9%BA%E6%A0%BC%E4%B8%8Etab%E8%BD%AC%E6%8D%A2/</link>
      <pubDate>Sat, 04 Oct 2014 15:51:01 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2014/10/04/python%E7%A9%BA%E6%A0%BC%E4%B8%8Etab%E8%BD%AC%E6%8D%A2/</guid>
      <description>&lt;p&gt;vim中&lt;/p&gt;

&lt;p&gt;TAB替换为空格：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:set ts=4
:set expandtab
:%retab!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;空格替换为TAB：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;:set ts=4
:set noexpandtab
:%retab!
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>2014&amp;2015书单</title>
      <link>https://blog.witd.in/2013/11/26/20142015%E4%B9%A6%E5%8D%95/</link>
      <pubDate>Tue, 26 Nov 2013 16:22:20 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2013/11/26/20142015%E4%B9%A6%E5%8D%95/</guid>
      <description>&lt;p&gt;2015&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;《小狗钱钱》
《Go Web编程》
《程序员跳槽全攻略》
《故事新编》
《富爸爸穷爸爸》
《人人都爱经济学》
《编程大师访谈录》
《分析的力量》
《一本书读懂财报》
《西游记》
《Git权威指南》
《伟大的博弈：华尔街金融帝国的崛起(1653-2011)》
《男人这东西》
《失乐园》
《爱的流放地》
《再爱一次》
《无影灯》
《Redis设计与实现》
《起风了》
《笑话方法论》
《红拂夜奔》
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>shell命令小结</title>
      <link>https://blog.witd.in/2013/06/16/shell%E5%91%BD%E4%BB%A4%E5%B0%8F%E7%BB%93/</link>
      <pubDate>Sun, 16 Jun 2013 15:35:04 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2013/06/16/shell%E5%91%BD%E4%BB%A4%E5%B0%8F%E7%BB%93/</guid>
      <description>&lt;p&gt;1、列出头十个最耗内存的进程&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;ps aux | sort -rnk +4 | head
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ps 输出格式如下：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ps aux
USER      PID       %CPU    %MEM    VSZ    RSS    TTY    STAT    START    TIME    COMMAND
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;sort -k是指定排序的字段。ps命令输出的第4个字段是内存占用率。&lt;/p&gt;

&lt;p&gt;2、列出当前目录里最大的10个文件。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;du -s * | sort -rn | head
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>php_extend</title>
      <link>https://blog.witd.in/2013/05/17/php_extend/</link>
      <pubDate>Fri, 17 May 2013 18:24:23 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2013/05/17/php_extend/</guid>
      <description>&lt;p&gt;当初安装php时都是默认安装，今天给机器添加硬件监控时用到了认证，程序是php写的，里面有个curl_init（）函数，执行时报错。因此，需要让php支持curl函数。
原先编译的php目录在&lt;code&gt;/home/thur/softbin/php&lt;/code&gt;目录下；&lt;/p&gt;

&lt;p&gt;php源代码在&lt;code&gt;/home/thur/softdir/php-5.3.24&lt;/code&gt;目录下。&lt;/p&gt;

&lt;h4 id=&#34;1-找到当前运行的php版本的源代码目录-如-php-5-2-10&#34;&gt;1.找到当前运行的php版本的源代码目录，如 php-5.2.10。&lt;/h4&gt;

&lt;p&gt;进入curl扩展库目录。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;cd /home/thur/softdir/php-5.3.24/ext/curl
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>sendmail -t 实现邮件抄送</title>
      <link>https://blog.witd.in/2013/05/02/sendmail--t-%E5%AE%9E%E7%8E%B0%E9%82%AE%E4%BB%B6%E6%8A%84%E9%80%81/</link>
      <pubDate>Thu, 02 May 2013 18:21:41 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2013/05/02/sendmail--t-%E5%AE%9E%E7%8E%B0%E9%82%AE%E4%BB%B6%E6%8A%84%E9%80%81/</guid>
      <description>&lt;p&gt;在发送文件MAIL_FILE的内容中添加&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;Cc: $cc_list
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;senmail&lt;/code&gt; 发送参数使用 -t参数，形如：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;/usr/lib/sendmail -t &amp;lt; ${MAIL_FILE}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这样在发送邮件时会自动扫描发送文件中的To Cc等内容。
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>磁盘检查</title>
      <link>https://blog.witd.in/2013/05/02/%E7%A3%81%E7%9B%98%E6%A3%80%E6%9F%A5/</link>
      <pubDate>Thu, 02 May 2013 18:02:52 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2013/05/02/%E7%A3%81%E7%9B%98%E6%A3%80%E6%9F%A5/</guid>
      <description>&lt;p&gt;机器死机重启后需要对/home分区进行检查&lt;/p&gt;

&lt;p&gt;以root权限执行&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;df命令可以查看磁盘分区使用情况，但这里使用是为了获取/home 所对应的设备文件，在磁盘扫描的时候会用到这个/dev/sda3参数&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;df -h
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;Filesystem Size Used Avail Use% Mounted on&lt;/li&gt;
&lt;li&gt;/dev/sda2 …………xx…………………….. /&lt;/li&gt;
&lt;li&gt;/dev/sda3 …..  …..xx……………………. /home&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;umount /home&lt;/code&gt; 或者&lt;code&gt;umount /dev/sda3&lt;/code&gt; #卸载/home对应的设备文件&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;这时提示/home对应的设备忙，因为有一些进程在使用该分区&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;fuser -m /home&lt;/code&gt; #显示使用/home分区的进程ID
&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>直视骄阳</title>
      <link>https://blog.witd.in/2013/05/01/%E7%9B%B4%E8%A7%86%E9%AA%84%E9%98%B3/</link>
      <pubDate>Wed, 01 May 2013 17:54:08 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2013/05/01/%E7%9B%B4%E8%A7%86%E9%AA%84%E9%98%B3/</guid>
      <description>&lt;p&gt;学校图书馆印刷的一个小册子上会有老师和同学推荐一些书目，其中有一本《直视骄阳–征服死亡恐惧》带给我的震撼不亚于弗洛伊德的《梦的解析》，但是这本书跟《梦的解析》的不同点是把心理问题归结于死亡还是性。当时读完这本书就随便写了一点东西，到现在好多细节都记不起来了，今天有空，翻了下网络资料加上原来记下的，凑一篇东西。&lt;/p&gt;

&lt;p&gt;书上对作者亚隆的介绍：IRVIN YALOM是斯坦福大学终身教授、心理治疗界公认的大师、纽约时报畅销小说家，著有《爱情刽子手》《当尼采哭泣》等畅销心理小说，以及《给心理治疗师的礼物》《日益亲近》等心理治疗经典。作者以75岁高龄探讨人们心中普遍存在却被长期否认和压抑的死亡恐惧，书中除23个实际案例和许多文学名著、电影作品中的例子以外，作者还以一位普通老者的身份对内心的死亡恐惧进行了自我表露和深刻剖析，非常难得。&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>APM编译安装</title>
      <link>https://blog.witd.in/2013/04/30/apm%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85/</link>
      <pubDate>Tue, 30 Apr 2013 17:38:19 +0800</pubDate>
      <author>kongfei605@gmail.com (kongfei)</author>
      <guid>https://blog.witd.in/2013/04/30/apm%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85/</guid>
      <description>&lt;p&gt;软件包存放路径：&lt;code&gt;/home/thur/opdir/soft&lt;/code&gt;，部署路径：&lt;code&gt;/home/thur/local/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;soft目录下有AMP和freetype,jpeg,libpng,mhash,php,curl,gd,libmcrypt,libxml,zlib安装包；&lt;/p&gt;

&lt;p&gt;tar zxvf 相应的安装包.tar.gz&lt;/p&gt;

&lt;h2 id=&#34;一-准备&#34;&gt;一 准备&lt;/h2&gt;

&lt;p&gt;首先在/home/thur/local下建立相应的目录，&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;mkdir -p /home/thur/local/{apache,freetype,jpeg,libpng,mhash,php,curl,gd,libmcrypt,libxml,mysql,zlib}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>