<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.7">Jekyll</generator><link href="https://chinafzy.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://chinafzy.github.io/" rel="alternate" type="text/html" /><updated>2020-07-28T09:13:57+00:00</updated><id>https://chinafzy.github.io/feed.xml</id><title type="html">Java杂货铺</title><subtitle>写点什么吧.</subtitle><author><name>fzy</name><email>19781971@qq.com</email></author><entry><title type="html">参考我做一个blog</title><link href="https://chinafzy.github.io/blog/new-to-jekyll/" rel="alternate" type="text/html" title="参考我做一个blog" /><published>2222-12-19T13:08:11+00:00</published><updated>2222-12-19T13:08:11+00:00</updated><id>https://chinafzy.github.io/blog/new-to-jekyll</id><content type="html" xml:base="https://chinafzy.github.io/blog/new-to-jekyll/">&lt;h2 id=&quot;快速预览blog&quot;&gt;快速预览blog&lt;/h2&gt;

&lt;h3 id=&quot;-使用jekyll&quot;&gt;—— 使用Jekyll&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;我们需要用docker来运行，因为要保持简单的环境&lt;/strong&gt;&lt;/p&gt;

&lt;h4 id=&quot;clone项目到本机&quot;&gt;clone项目到本机&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/chinafzy/chinafzy.github.io&quot;&gt;https://github.com/chinafzy/chinafzy.github.io&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;创建jekyll的docker容器&quot;&gt;创建jekyll的docker容器&lt;/h4&gt;
&lt;p&gt;先进入到目录，然后创建docker容器，&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4000
&lt;span class=&quot;nv&quot;&gt;P2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;expr &lt;/span&gt;31729 + &lt;span class=&quot;nv&quot;&gt;$P&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;JEKYLL_VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3.8
docker run &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;blog&lt;span class=&quot;nv&quot;&gt;$P$U&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$P&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$P&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$P2&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$P2&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;:/srv/jekyll &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    jekyll/jekyll:&lt;span class=&quot;nv&quot;&gt;$JEKYLL_VERSION&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    /bin/bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;bundle; jekyll serve --port &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$P&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; -w -I -V --livereload --livereload-port &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$P2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; --future&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;P=4000，这个指定了你当前使用的端口，可以修改这个为其它值&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;第一次运行时候，会需要比较多的时间去下载。&lt;/p&gt;

&lt;h4 id=&quot;打开浏览器预览&quot;&gt;打开浏览器预览&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://localhost:4000/&quot;&gt;http://localhost:4000&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;jekyll参数说明可忽略&quot;&gt;jekyll参数说明（可忽略）&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://jekyllrb.com/docs/configuration/options/&quot;&gt;https://jekyllrb.com/docs/configuration/options/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;-P, –port：指定服务端口&lt;/li&gt;
  &lt;li&gt;-w, –watch：jekyll会监听文件的修改，立刻更新&lt;/li&gt;
  &lt;li&gt;-I, –incremental：配合上面的参数，jekyll在更新的时候只更新与修改过的文件相关的内容。&lt;br /&gt;
这个参数会带来一个bug：新增页面不能增加到分类和标签下，需要通过命令&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll clean &amp;amp;&amp;amp; jekyll build&lt;/code&gt;来强制刷新。&lt;/li&gt;
  &lt;li&gt;–livereload：页面会实时监控blog的修改，发生变动时候会自动刷新页面&lt;/li&gt;
  &lt;li&gt;–livereload-port：配合上面的，实时监控的port&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;-使用github&quot;&gt;—— 使用Github&lt;/h3&gt;

&lt;h4 id=&quot;fork本项目到你的github账号下&quot;&gt;Fork本项目到你的Github账号下&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/chinafzy/chinafzy.github.io&quot;&gt;https://github.com/chinafzy/chinafzy.github.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/new-blog/fork-git.png&quot; alt=&quot;fork my repository&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;修改repository的名称为usernamegithubio&quot;&gt;修改repository的名称为USERNAME.github.io&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USERNAME&lt;/code&gt;是你当前的Github账号名称。
&lt;img src=&quot;/assets/img/new-blog/change-repository-name.png&quot; alt=&quot;change it&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;访问url-httpsusernamegithubio&quot;&gt;访问url https://USERNAME.github.io&lt;/h4&gt;

&lt;p&gt;这个地址也可以在你的git仓库的settings中看见，如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/new-blog/enable-page.png&quot; alt=&quot;page url&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;修改配置&quot;&gt;修改配置&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.yml&lt;/code&gt;中，修改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Author&lt;/code&gt;部分，使用个人的配置&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# Site Author&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name             &lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fzy&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;avatar           &lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/assets/img/mny.jpg&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;bio              &lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;资深宅男，专业程序员.&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;location         &lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;BJ&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;email            &lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;19781971@qq.com&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;links&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Email&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fas&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-fw&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-envelope-square&quot;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# url: mailto:chinafzy1978@gmail.com&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Website&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fas&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-fw&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-link&quot;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# url: &quot;https://your-website.com&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Twitter&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fab&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-fw&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-twitter-square&quot;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# url: &quot;https://twitter.com/&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Facebook&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fab&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-fw&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-facebook-square&quot;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# url: &quot;https://facebook.com/&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;GitHub&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fab&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-fw&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-github&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://github.com/chinafzy&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Instagram&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fab&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-fw&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;fa-instagram&quot;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# url: &quot;https://instagram.com/&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;123&lt;/p&gt;</content><author><name>fzy</name><email>19781971@qq.com</email></author><summary type="html">快速预览blog</summary></entry><entry><title type="html">同步/异步/select/poll/epoll</title><link href="https://chinafzy.github.io/linux/sync-async-select-poll/" rel="alternate" type="text/html" title="同步/异步/select/poll/epoll" /><published>2020-05-14T00:00:00+00:00</published><updated>2020-05-14T00:00:00+00:00</updated><id>https://chinafzy.github.io/linux/sync-async-select-poll</id><content type="html" xml:base="https://chinafzy.github.io/linux/sync-async-select-poll/">&lt;h2 id=&quot;以吃饭为案例&quot;&gt;以吃饭为案例&lt;/h2&gt;
&lt;p&gt;民以食为天&lt;/p&gt;

&lt;h3 id=&quot;同步模式&quot;&gt;同步模式&lt;/h3&gt;
&lt;p&gt;单位食堂上了新的自助模式，经过几天的体验，很快就有人骂。领导派人调查，发现吃饭的模式大概是这样：&lt;/p&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;li&gt;有时候可能还要排队等座位&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;食堂负责人（据说是公司x总的亲戚）晚上汇报说：我们食堂很不错，同时容纳下来八百人呢！&lt;/p&gt;

&lt;p&gt;x总大骂：傻逼，容纳那么多人，都在排队。员工耽误时间，你挣钱慢，老子还跟着挨骂。有人告诉董事长说每天员工排队吃饭一小时半。老头子现在想砍我呢。&lt;/p&gt;

&lt;p&gt;食堂改革，势在必行！上报领导，下利小民！&lt;/p&gt;

&lt;h3 id=&quot;异步模式&quot;&gt;异步模式&lt;/h3&gt;
&lt;p&gt;秘书小李告诉x总，某部门程序员，3个人一组，商量好吃什么后，一个人负责拿餐具，一个选主食，一个选菜。最后一起去付账。比别人节省大半时间。&lt;/p&gt;

&lt;p&gt;x总依稀记得大学时候的功课，哦，这个就是异步模式啊！&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;不是强依赖关系的工作，就不应该顺序来做。&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;于是在食堂门口贴出告示，推广这个先进经验。&lt;br /&gt;
员工吃饭时间大大缩短。&lt;/p&gt;

&lt;p&gt;董事长大悦之余，问x总：怎么之前我没发现排队这么麻烦呢？&lt;br /&gt;
x总答复说：领导，因为当时都是我们几个给您拿的菜。我们就是您的分身。&lt;/p&gt;

&lt;p&gt;x总的季度报告：我们成功的在日常管理中引入了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;异步模式——分身有术&lt;/code&gt;，让普通员工也能享受到这样的便利。&lt;/p&gt;

&lt;h2 id=&quot;select模式&quot;&gt;select模式&lt;/h2&gt;
&lt;p&gt;公司和食堂都是蒸蒸日上，不断壮大，菜品数量也多了，员工吃饭时间又慢慢增加，怨言也增多。
董事长脾气慢慢变坏，各副总挨骂次数逐渐增加，大家得知原委后，一起压迫x总。&lt;/p&gt;

&lt;p&gt;x总经过调查，发现员工遇到这样的情况：&lt;br /&gt;
&lt;strong&gt;下单了几个菜，隔会儿去查一下这个菜有没有来，一会儿查一下另外一个菜，都快成神经病了。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;董事长听到后，呵呵一笑：&lt;br /&gt;
&lt;strong&gt;这些年轻人啊，too young too simple，哪用得着这样麻烦，问服务员就可以了。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;x总解释说：&lt;br /&gt;
领导，您是一直在VIP包厢。&lt;br /&gt;
对了，领导，您说到关键点了，我们给每个员工建立VIP服务。&lt;/p&gt;

&lt;p&gt;董事长也马上明白了：对对对。&lt;br /&gt;
不过又马上迷糊了：你要这样搞，我们食堂得增加多少包厢？多少服务人员？&lt;/p&gt;

&lt;p&gt;x总于是解释：&lt;br /&gt;
领导，咱们是科技公司，用科技手段来做这个：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VIP通道点菜&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;（以下的描述比对JDK的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.nio.channels.Selector&lt;/code&gt;，可以忽略括号内的技术内容）&lt;br /&gt;
食堂提供&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;点菜窗口&lt;/code&gt;（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Service&lt;/code&gt;），员工有个点菜器（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Selector&lt;/code&gt;），这个就是我们给员工提供的食堂VIP服务。&lt;br /&gt;
员工找到点菜窗口，建立服务请求（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SocketChannel#connect()&lt;/code&gt;），再将这次的服务注册到点菜器里面（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SocketChannel#register&lt;/code&gt;）。&lt;br /&gt;
从绑定后开始，员工可以随时查询点菜器（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Selector#select()&lt;/code&gt;），每次会返回0到若干个查询结果（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SelectionKey&lt;/code&gt;），每个查询结果里面包含&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;服务状态&lt;/code&gt;和绑定的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;服务窗口&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;有这些&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;服务状态&lt;/code&gt;：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;连接成功(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SelectionKey#OP_CONNECT&lt;/code&gt;)，&lt;/li&gt;
  &lt;li&gt;可以接受下单(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SelectionKey#OP_WRITE&lt;/code&gt;)，员工可以通过绑定的窗口开始下单点菜&lt;/li&gt;
  &lt;li&gt;菜已经准备好(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SelectionKey#OP_READ&lt;/code&gt;)，员工可以从绑定的窗口拿菜&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;董事长再度大悦，让x总汇报先进经验。&lt;/p&gt;

&lt;p&gt;x总说，我们成功的将先进的select模式引入到了我们的日常管理，彻底改变了我们的工作方式。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;select模式——一个工具完成全部的交互衔接管理&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&quot;poll&quot;&gt;poll&lt;/h2&gt;
&lt;p&gt;增加了食堂的流量后，后厨的压力增大，于是改造成先进的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;select&lt;/code&gt;模式。&lt;/p&gt;

&lt;p&gt;也会有点菜器，大体上与员工的差不多，主要的差别在于：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;服务通道是由员工发起的，&lt;/li&gt;
  &lt;li&gt;后厨只要监听几个窗口就可以了&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;但是在长时间使用后，发现后厨的订单量非常大，点菜器的处理效率跟不上。于是在这个基础上做了升级，点菜器进入到后厨的核心部分，高优先级；同时优化了结构算法。&lt;/p&gt;

&lt;p&gt;年底汇报，x总把这个技术提升换了个新名称&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll&lt;/code&gt;，再次夺得年终述职头彩。&lt;/p&gt;

&lt;p&gt;BTW：员工就餐的流程，因为单量不大，流程改进的意义不大了。即使一个部门百十人统一订餐，也就产生几百份菜的订餐。&lt;/p&gt;

&lt;h2 id=&quot;epoll&quot;&gt;epoll&lt;/h2&gt;
&lt;p&gt;时间继续前进，公司也在前进，员工数增加，食堂的服务量也在飞速增长。原有的工作流程再次体现出来不足，具体来说，流程本身的执行成本占据了比较多的工作时间。&lt;/p&gt;

&lt;p&gt;受启发于之前的流程改进，x总意识到：&lt;br /&gt;
&lt;strong&gt;在高流量下，工作重点应该倾向于流程控制&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;于是他决定由&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;流水线&lt;/code&gt;来作为控制者，具有最高权限：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;首先将操作分为内部操作和外部操作：
    &lt;ul&gt;
      &lt;li&gt;内部操作就是厨师们的工作，例如清洗原料，做菜，这些只是在厨房内部处理的事情&lt;/li&gt;
      &lt;li&gt;涉外操作是要跟外部发生来回传递的工作，例如接订单、回订单、找库房要原材料……&lt;br /&gt;
在涉外操作发生时候，是不可能立刻等到结果的&lt;/li&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;/ul&gt;</content><author><name>fzy</name><email>19781971@qq.com</email></author><category term="Linux" /><category term="Fav" /><summary type="html">以吃饭为案例 民以食为天</summary></entry><entry><title type="html">利用AWK处理日志</title><link href="https://chinafzy.github.io/linux/tips/awk/awk-and-log/" rel="alternate" type="text/html" title="利用AWK处理日志" /><published>2020-05-06T08:27:11+00:00</published><updated>2020-05-06T08:27:11+00:00</updated><id>https://chinafzy.github.io/linux/tips/awk/awk-and-log</id><content type="html" xml:base="https://chinafzy.github.io/linux/tips/awk/awk-and-log/">&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;

&lt;p&gt;大数据的功能自然比awk强大很多，但是它的工作流程过于漫长，awk的快捷灵活在部分情况下更合适：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;线上的紧急故障排查：这个时候肯定来不及在大数据里面慢慢折腾&lt;/li&gt;
  &lt;li&gt;新业务分析：有时候新业务的数据不一定来得及进大数据&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;学好awk，对于运维和高级后端开发来说都非常必要。&lt;/p&gt;

&lt;p&gt;本文档结合实际工作里面的案例，讲述如何使用AWK来进行日志做&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;性能分析/线上排障&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;业务分析&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;我们线上的nginx（见附录）是以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; &quot; |# &quot; &lt;/code&gt;来分隔字段的，主要字段有：&lt;/p&gt;
&lt;div class=&quot;language-conf highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;n&quot;&gt;log_format&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; 
  &lt;span class=&quot;s1&quot;&gt;'$remote_addr |# $remote_user |# $year-$month-$day $hour:$minute:$second |# $request |# '&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'$status |# $request_time |# $body_bytes_sent |# $http_referer |# $http_user_agent |# $http_x_forwarded_for |# '&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'$http_host |# $upstream_addr |# $upstream_status |# $upstream_response_time |# $scheme |# $content_type'&lt;/span&gt;;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;$remote_addr：来源IP&lt;/li&gt;
  &lt;li&gt;$http_x_forwarded_for：如果请求是经过了反向代理，这个字段解析原始的来源IP&lt;/li&gt;
  &lt;li&gt;$year-$month-$day $hour:$minute:$second：访问时间&lt;/li&gt;
  &lt;li&gt;$request：请求的内容，URI、方法(POST/GET…)、协议版本&lt;/li&gt;
  &lt;li&gt;$status：返回的状态码&lt;/li&gt;
  &lt;li&gt;$request_time：【重要】请求的全部处理时间（包括了网络传输）&lt;/li&gt;
  &lt;li&gt;$body_bytes_sent：返回的响应体大小&lt;/li&gt;
  &lt;li&gt;$upstream_response_time：【重要】nginx后端服务器的响应时间&lt;/li&gt;
  &lt;li&gt;$upstream_status：nginx后端服务的响应状态码&lt;/li&gt;
  &lt;li&gt;$upstream_addr：nginx后端服务器的地址端口&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这个日志也是非常有实用价值的。&lt;/p&gt;

&lt;h2 id=&quot;业务分析漏斗分析&quot;&gt;【业务分析】漏斗分析&lt;/h2&gt;
&lt;p&gt;开席先来个硬菜。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;漏斗分析&lt;/code&gt;是新业务分析的非常有用的一个手段，尤其是对于页面交互设计来说，可以看到我们的每个步骤的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;流失/留存/转换&lt;/code&gt;。&lt;br /&gt;
比如我们做了一个拉新活动，有3个页面：起始页 -&amp;gt; 抽奖页 -&amp;gt; 提交简单注册信息，我们会关注用户在哪一步流失了。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;funnel.awk&lt;/code&gt;会针对用户访问多个location的情况进行过滤，分析出来每一步的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;留存率&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-awk highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# awk -f funnel.awk -v v_locs=&quot;loc1;loc2;loc3&quot; nginx1.log nginx2.log ...&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f_locIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;locs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 获取一组用户行为的traceid，这里使用$request里面的udid参数来充当&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f_getTid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_arr1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_arr2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_arr1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;udid=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_arr1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bad request without udid: %s \n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log_file&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_arr1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_arr2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;amp;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_arr2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;BEGIN&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kc&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; [|]# &quot;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v_locs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;需要传入参数 v_locs &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/dev/stderr&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;111&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v_locs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;locs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[;,]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;lsize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;locs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# 使用 -v v_log_file=logfile 将调试信息打印到文件中&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#  此参数设置为 off 将关闭打印&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#  默认将打印到 /dev/stderr 中，&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;log_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v_log_file&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/dev/stderr&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;v_log_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;off&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt; 
      &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/dev/null&quot;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;v_log_file&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;locIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f_locIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;locIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;tid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f_getTid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# 记录这个tid+location的访问&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;rs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;locIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;locIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 记录第一步访问的tid&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;step1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;END&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;step1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;nx&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%10s %s \n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;%'d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个脚本的原理是：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;首先为一组行为指定一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trace_id&lt;/code&gt;（简称&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tid&lt;/code&gt;），作为行为跟踪。范例里面用udid来模拟，不是很严谨。&lt;/li&gt;
  &lt;li&gt;记录每个tid在location下的访问记录&lt;/li&gt;
  &lt;li&gt;记录下来，每个曾经访问过step1的tid&lt;/li&gt;
  &lt;li&gt;最后根据step1的访问记录，逐步计算后续步骤的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;留存&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;输出结果是&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;第一列：每个步骤的发生次数，基于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trace_id&lt;/code&gt;的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unique&lt;/code&gt;统计&lt;/li&gt;
  &lt;li&gt;第二列：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;留存率&lt;/code&gt;百分百&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;使用范例：&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;access.log | &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1000000&lt;/span&gt; | &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; funnel.awk &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;v_locs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;appOpen.action;updateToken.action;encryptedHomePage.action&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;切割accesslog文件&quot;&gt;切割access.log文件&lt;/h2&gt;
&lt;p&gt;如果日志文件比较大，将其按照小时或更小的时间单位来切割。&lt;br /&gt;
某些老旧的日志系统，改造比较麻烦，就可以用这样的方式来处理。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;split-by-hour.awk&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-awk highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# awk -f split-by-hour.awk access.log&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 用字符串 &quot; |# &quot; 来切割字段&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;BEGIN&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; [|]# &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# 切割日期时间，获取hour_minute_second&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;datatime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;.log&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;实用技巧：在AWK文件的开始加上注释，说明文件的使用方式。比较复杂的业务，还要加上备注说明。&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;摘取部分日志&quot;&gt;摘取部分日志&lt;/h2&gt;
&lt;p&gt;假设我们摘取早高峰（7点8点的日志）&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;select-timerange.awk&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-awk highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# awk -f select-timerange.awk access.log&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;BEGIN&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; [|]# &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# 切割日期时间，获取hour_minute_second&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;datatime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exit&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hms&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;next&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;实用技巧：AWK永远要优先考虑&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;退出处理 exit&lt;/code&gt;。&lt;/strong&gt;&lt;br /&gt;
对于有几千万数据的日志来说，尽早完成工作，退出处理，是必须的。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;实用技巧：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exit&lt;/code&gt;可以带一个参数，作为AWK运行后的shell返回值。&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'BEGIN { exit 111 }'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;
111
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;线上故障跟踪响应慢的请求&quot;&gt;【线上故障】跟踪响应慢的请求&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;对于线上系统来说：慢就是错。&lt;/strong&gt;&lt;br /&gt;
没有任何理由，响应慢，用户感受就差，扯什么都没用。&lt;/p&gt;

&lt;p&gt;因此，跟踪慢请求，是最基本的一个工作。&lt;/p&gt;

&lt;p&gt;一般我们是用这个命令来做：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tail -f access.log | awk -f select-slow.awk | tee slow.log&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;tail -f access.log，将实时跟进线上的日志&lt;/li&gt;
  &lt;li&gt;awk -f select-slow.awk，将过滤选择比较大的请求&lt;/li&gt;
  &lt;li&gt;tee slow.log，将把输入的内容同时发送到控制台和文件。  &lt;br /&gt;
这个是一个非常有实用价值的命令。与此类似的方式是开俩个命令，一个直接输入到文件，另外一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tail -f&lt;/code&gt;这个文件。&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-awk highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# awk -f select select-slow.awk access.log&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# awk -f select -v v_second=0.3 select-slow.awk access.log&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;BEGIN&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kc&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; [|]# &quot;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# 使用参数v_ms来指定最小的时间，默认值是0.1，也就是100毫秒&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;v_second&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;v_second&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;选择响应时间 &amp;gt;= %s 的请求\n\n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ms&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/dev/stderr&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;上面这个awk将选择响应时间在一定值（默认0.1秒）之上的请求。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;实用技巧：AWK可以通过传入参数的对部分关键值进行灵活控制。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;实用技巧：AWK可以往 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/stderr&lt;/code&gt; 打印输出调试语句。&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;线上故障跟踪-执行慢网络传输慢-的请求&quot;&gt;【线上故障】跟踪 执行慢/网络传输慢 的请求&lt;/h2&gt;
&lt;p&gt;在前一案例的基础上，将过滤条件修改一下，就可以做到其它效果。&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;待修改代码
    &lt;div class=&quot;language-awk highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;跟踪：执行慢&lt;br /&gt;
字段14&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$upstream_response_time&lt;/code&gt;代表的是后端服务器的执行时间，
    &lt;div class=&quot;language-awk highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$14&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;跟踪：网络传输慢&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$request_time - $upstream_response_time&lt;/code&gt;就是网络传输的时间
    &lt;div class=&quot;language-awk highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$14&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;线上故障分析网络慢的请求&quot;&gt;【线上故障】分析网络慢的请求&lt;/h2&gt;
&lt;p&gt;有些情况下，移动客户端（4G/3G网络) + 较大的响应体，就会产生比较多的网络消耗，拖累整体的响应时间。这个是需要定时做查询分析的，如果没有大数据，AWK也很方便。&lt;/p&gt;

&lt;p&gt;分析网络传输和数据大小的关系：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ana-network.awk&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-awk highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;# awk -f ana-network.awk access.log&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# awk -f ana-network.awk access.log -v &lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;rst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rst&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sep&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rst&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;BEGIN&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kc&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; [|]# &quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v_sizes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;v_sizes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1024 2048 4196&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[ ;,]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;将使用这些大小区间来统计响应时间: %s \n\n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/dev/stderr&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$14&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;sizeIdx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;maxTimes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizeIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;maxTimes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizeIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;minTimex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizeIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;minTimes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizeIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;minTimes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizeIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizeIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;sums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizeIdx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;second&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;END&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;_format&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%9s %9s %9s %9s %14s \n&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;size&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;count&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;max&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;min&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;avg&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; &amp;lt;= &quot;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; &amp;gt; &quot;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sizes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;maxTimes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;maxTimes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;minTimes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;minTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sums&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;线上日志大文件处理的注意事项&quot;&gt;线上日志大文件处理的注意事项&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;一定要先测试&lt;/strong&gt;
&lt;strong&gt;一定要先测试&lt;/strong&gt;
&lt;strong&gt;一定要先测试&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这个是个人的经验教训：线上AWK处理大文件，一定要先测试。&lt;/p&gt;

&lt;p&gt;线上的机器，如果原本有一定的压力，一个大磁盘操作就可能是压倒骆驼的最后那根稻草。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt;本身倒不是很严重，因为它最多只能占据一核CPU。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat&lt;/code&gt;带来的磁盘压力更可怕，在极端环境下，连锁反应就崩溃了。&lt;/p&gt;

&lt;p&gt;比如这样： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat access.log | head -10000 | awk -f ana.awk | more&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat&lt;/code&gt;来获取文件，或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zcat&lt;/code&gt;获取压缩文件&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head -10000&lt;/code&gt;获取前面的若干行，这个在测试阶段必须要加，哪怕是写一百万一个亿，也比不写的好。&lt;/li&gt;
  &lt;li&gt;最后的这个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;more&lt;/code&gt;是为了避免输出太多，到时候&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl + c&lt;/code&gt;都来不及。&lt;br /&gt;
个人非常熟练的情况下，这个环节可以忽略。&lt;br /&gt;
使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;less&lt;/code&gt;效果更好，因为它会进入到交互界面，支持查询。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;附录&quot;&gt;附录&lt;/h2&gt;

&lt;h3 id=&quot;accesslog&quot;&gt;access.log&lt;/h3&gt;
&lt;p&gt;这个是我们的部分nginx访问日志&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;157.255.131.183 |# - |# 2020-05-06 00:06:01 |# GET /bus/line!encRefreshLineDetail.action?stats_act=auto_refresh&amp;amp;refreshModule=&amp;amp;sign=MflpWbAMMtOhC%2B%2FLeOX8eA%3D%3D&amp;amp;language=1&amp;amp;cityId=014&amp;amp;transmission=&amp;amp;lineNo=M3853&amp;amp;phoneBrand=OPPO&amp;amp;gps_ts=1588688183510&amp;amp;lchsrc=icon&amp;amp;system_push_open=1&amp;amp;lat=22.545575&amp;amp;deviceType=OPPO+R11st&amp;amp;geo_type=gcj&amp;amp;o1=8b12a74508a73536d65afce26d88b16c107b2fc2&amp;amp;targetStationLng=113.96663137225858&amp;amp;cryptoSign=2d062170d1f4f8f450f02d0b27a3aa3a&amp;amp;lng=114.067892&amp;amp;first_src=app_oppo_store&amp;amp;vc=176&amp;amp;isNewLineDetail=1&amp;amp;gpstype=gcj&amp;amp;geo_lt=2&amp;amp;last_src=app_oppo_store&amp;amp;sstate=3&amp;amp;wifi_open=1&amp;amp;screenDensity=3.0&amp;amp;needAds=false&amp;amp;flpolicy=1&amp;amp;astate=1&amp;amp;bdStnLng=113.96009695847908&amp;amp;screenWidth=1080&amp;amp;cshow=other&amp;amp;nw=WIFI&amp;amp;stats_referer=searchHistory&amp;amp;lineName=M385&amp;amp;AndroidID=6fecf31956be2c36&amp;amp;mac=d4%3A1a%3A3f%3A5a%3Ab3%3A3d&amp;amp;bdStnLat=22.563166913371045&amp;amp;persistTravelId=&amp;amp;stationName=%E9%BE%99%E4%BA%95%E5%B7%A5%E4%B8%9A%E5%8C%BA&amp;amp;udid=9889906c-3280-49b0-9e0e-d26204d3fdfd&amp;amp;targetStationLat=22.568996038396172&amp;amp;direction=0&amp;amp;targetOrder=4&amp;amp;push_open=1&amp;amp;sv=8.1.0&amp;amp;geo_lac=550.0&amp;amp;screenHeight=1962&amp;amp;lineId=0755-M3853-0&amp;amp;showModule=1%2C1%3B2%2C1%3B3%2C1%3B4%2C1%3B&amp;amp;userAgent=Mozilla%2F5.0+%28Linux%3B+Android+8.1.0%3B+OPPO+R11st+Build%2FOPM1.171019.011%3B+wv%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Version%2F4.0+Chrome%2F62.0.3202.84+Mobile+Safari%2F537.36&amp;amp;userId=unknown&amp;amp;filter=1&amp;amp;paramsMakeUp=is&amp;amp;s=android&amp;amp;geo_lng=114.067892&amp;amp;geo_lat=22.545575&amp;amp;v=3.91.0&amp;amp;imei=868639038438756&amp;amp;stats_order=1-2&amp;amp;timeStamp=1588694762021&amp;amp;cryptoSignStr=c1ec5963f63c1608fadc1775284b58b5&amp;amp;dns_error=3 HTTP/1.1 |# 200 |# 0.040 |# 2676 |# - |# Dalvik/2.1.0 (Linux; U; Android 8.1.0; OPPO R11st Build/OPM1.171019.011) |# 120.229.52.6 |# api.chelaile.net.cn |# 172.17.17.49:8090 |# 200 |# 0.040 |# 158869476169224eca7f229150e5b1bd |# https |# -
172.17.16.121 |# - |# 2020-05-06 00:06:01 |# GET /bus/line!lineDetail.action?lineId=020-00601-1&amp;amp;direction=1&amp;amp;s=h5&amp;amp;v=3.3.19&amp;amp;sign=1&amp;amp;cityId=040&amp;amp;gpstype=gcj HTTP/1.1 |# 200 |# 0.020 |# 3883 |# http://web.chelaile.net.cn/ch5/index.html?utm_source=webapp_meizu_map&amp;amp;src=webapp_meizu_map&amp;amp;utm_medium=menu&amp;amp;hideFooter=1&amp;amp;gpstype=gcj&amp;amp;cityName=%E5%B9%BF%E5%B7%9E&amp;amp;cityId=040&amp;amp;supportSubway=1&amp;amp;cityVersion=0&amp;amp;lat=23.079135&amp;amp;lng=113.233398 |# Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36 |# - |# api.chelaile.net.cn |# 172.17.16.150:8090 |# 200 |# 0.020 |# 158869476173176148dfc5dadced730f |# http |# -
183.40.217.253 |# - |# 2020-05-06 00:06:01 |# GET /api/bus/line!encryptedLineDetail.action?s=h5&amp;amp;wxs=wx_app&amp;amp;sign=1&amp;amp;v=3.8.156&amp;amp;src=weixinapp_cx&amp;amp;ctm_mp=mp_wx&amp;amp;cityId=040&amp;amp;userId=okBHq0NX9JkqLhp6NllM4maiohW4&amp;amp;h5Id=okBHq0NX9JkqLhp6NllM4maiohW4&amp;amp;lat=23.075265&amp;amp;lng=113.28792&amp;amp;geo_lat=23.075265&amp;amp;geo_lng=113.28792&amp;amp;gpstype=wgs&amp;amp;isNewCity=0&amp;amp;lineId=002031512162&amp;amp;targetOrder=16&amp;amp;cryptoSign=4debff6219f5a201e5c73f4f38681c7c HTTP/1.1 |# 200 |# 0.024 |# 10260 |# https://servicewechat.com/wx71d589ea01ce3321/379/page-frame.html |# Mozilla/5.0 (Linux; Android 9; Redmi K20 Pro Build/PKQ1.181121.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.136 Mobile Safari/537.36 MicroMessenger/7.0.13.1640(0x27000D39) Process/appbrand4 NetType/4G Language/zh_CN ABI/arm64 WeChat/arm64 |# - |# web.chelaile.net.cn |# 172.17.16.19:80 |# 200 |# 0.024 |# https |# text
172.17.16.19 |# - |# 2020-05-06 00:06:01 |# GET /basesearch/client/clientSearch.action?s=h5&amp;amp;wxs=wx_app&amp;amp;sign=1&amp;amp;v=3.8.156&amp;amp;src=weixinapp_cx&amp;amp;ctm_mp=mp_wx&amp;amp;cityId=040&amp;amp;userId=okBHq0M7RNkwqFrLtia96iE16qlk&amp;amp;h5Id=okBHq0M7RNkwqFrLtia96iE16qlk&amp;amp;unionId=oSpTTjt3ei-o_zY3APX86wqPf1oA&amp;amp;lat=23.152059&amp;amp;lng=113.217306&amp;amp;geo_lat=23.152059&amp;amp;geo_lng=113.217306&amp;amp;gpstype=wgs&amp;amp;key=%E6%A7%8E%E5%A4%B4 HTTP/1.1 |# 200 |# 0.121 |# 807 |# https://servicewechat.com/wx71d589ea01ce3321/379/page-frame.html |# Mozilla/5.0 (Linux; Android 9; PAR-AL00 Build/HUAWEIPAR-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.116 Mobile Safari/537.36 MicroMessenger/7.0.13.1640(0x27000D39) Process/appbrand2 NetType/4G Language/zh_CN ABI/arm64 WeChat/arm64 |# - |# api.chelaile.net.cn |# 172.17.16.69:9397 |# 200 |# 0.121 |# 15886947616688c4aaf5c89c56fc9117 |# http |# application/json
111.85.198.3 |# - |# 2020-05-06 00:06:01 |# GET /bus/stop!versionUpdtControl.action?mac=&amp;amp;userId=&amp;amp;geo_lng=106.776500&amp;amp;timestamp=1588694761753&amp;amp;gps_ts=1588694758836&amp;amp;accountId=32979580&amp;amp;sstate=3&amp;amp;appStartId=1588694752593_1717703&amp;amp;userAgent=Mozilla/5.0%20(iPhone;%20CPU%20iPhone%20OS%2013_4_1%20like%20Mac%20OS%20X)%20AppleWebKit/605.1.15%20(KHTML,%20like%20Gecko)%20Mobile/15E148&amp;amp;vc=15902&amp;amp;gps_speed=-1&amp;amp;sv=13.4.1&amp;amp;geo_lat=26.570035&amp;amp;screenWidth=1125&amp;amp;imsi=46000&amp;amp;geo_lac=65.000000&amp;amp;localCityId=083&amp;amp;secret=6b6adab1a48b41eeb24cd5bbfe71ff78&amp;amp;gpsAccuracy=65.000000&amp;amp;deviceType=iPhoneX&amp;amp;idfa=C5C7308F-6878-4747-8F6B-9FF8EFF66737&amp;amp;idfv=58D2FB5E-AE56-4876-AA7D-060829C45FAF&amp;amp;screenHeight=2436&amp;amp;localIdCreateTime=1588405573863&amp;amp;rnver=5.90.2.16&amp;amp;sign=uZKiBqWIaewibCdqc78IUQ==&amp;amp;s=IOS&amp;amp;cityId=003&amp;amp;dpi=3&amp;amp;push_open=1&amp;amp;astate=1&amp;amp;wifi_open=1&amp;amp;locState=3&amp;amp;gps_accuracy=65&amp;amp;v=5.90.2&amp;amp;geo_type=wgs&amp;amp;nw=WiFi&amp;amp;language=1&amp;amp;vendor=apple&amp;amp;lchsrc=icon&amp;amp;udid=110b389dd2b86d5aae8ae31d145584047217a462&amp;amp;locOn=1 HTTP/1.1 |# 200 |# 0.003 |# 85 |# - |# lite/5.90.2 (iPhone; iOS 13.4.1; Scale/3.00) |# - |# api.chelaile.net.cn |# 172.17.17.84:8090 |# 200 |# 0.003 |# 1588694761796794d759e51cd04eaddf |# https |# -
183.202.39.142 |# - |# 2020-05-06 00:06:01 |# GET /bus/reminder!updateToken.action?last_src=app_oppo_store&amp;amp;s=android&amp;amp;push_open=1&amp;amp;token=73beb18f06338d74a8c7acf1586a4a5a&amp;amp;userId=unknown&amp;amp;astate=1&amp;amp;vc=176&amp;amp;sv=6.0.1&amp;amp;v=3.91.0&amp;amp;imei=864412039047636&amp;amp;system_push_open=1&amp;amp;udid=1156782f-7bae-4443-a3a6-ab73dcbd5be5&amp;amp;cityId=094&amp;amp;sign=MflpWbAMMtMTGBI10KL38g%3D%3D&amp;amp;wifi_open=1&amp;amp;mac=98%3A6f%3A60%3Acd%3A20%3Aa5&amp;amp;deviceType=OPPO+R9sk&amp;amp;lchsrc=icon&amp;amp;nw=WIFI&amp;amp;sstate=3&amp;amp;paramsMakeUp=is&amp;amp;AndroidID=b47a3dc850c07564&amp;amp;phoneBrand=OPPO&amp;amp;language=1&amp;amp;first_src=app_oppo_store&amp;amp;tokenType=0 HTTP/1.1 |# 200 |# 0.001 |# 77 |# - |# Dalvik/2.1.0 (Linux; U; Android 6.0.1; OPPO R9sk Build/MMB29M) |# - |# api.chelaile.net.cn |# 172.17.17.18:9090 |# 200 |# 0.001 |# 158869476181379ce549a22e8a36d369 |# https |# -
121.29.84.125 |# - |# 2020-05-06 00:06:01 |# GET /wow/user!query2.action?last_src=app_360_sj&amp;amp;s=android&amp;amp;push_open=1&amp;amp;userId=unknown&amp;amp;geo_lt=4&amp;amp;geo_lat=38.141958&amp;amp;astate=1&amp;amp;vc=162&amp;amp;sv=7.1.1&amp;amp;v=3.86.2&amp;amp;secret=62c0accde2f94d8da5f4d97e26a10a5f&amp;amp;imei=99000788013541&amp;amp;oaIdDeviceCode=1008611&amp;amp;system_push_open=1&amp;amp;udid=5a82f277-2495-485d-911f-c10c5a215523&amp;amp;oaIdDeviceSupport=notSupport&amp;amp;cityId=053&amp;amp;sign=MflpWbAMMtP1OS32RR%2FzsA%3D%3D&amp;amp;geo_type=gcj&amp;amp;deviceType=VCR-A0&amp;amp;mac=54%3Adc%3A1d%3Ab6%3Ae1%3A14&amp;amp;wifi_open=1&amp;amp;lchsrc=icon&amp;amp;sstate=3&amp;amp;nw=WIFI&amp;amp;paramsMakeUp=is&amp;amp;AndroidID=58af64db77839869&amp;amp;geo_lac=100.0&amp;amp;phoneBrand=Coolpad&amp;amp;accountId=86987530&amp;amp;oaId=unknown&amp;amp;language=1&amp;amp;first_src=app_qq_sj&amp;amp;geo_lng=114.586532 HTTP/1.1 |# 200 |# 0.022 |# 582 |# - |# Dalvik/2.1.0 (Linux; U; Android 7.1.1; VCR-A0 Build/VCRSCN00X1000MPX1711140) |# - |# api.chelaile.net.cn |# 172.17.17.100:9070 |# 200 |# 0.022 |# 158869476180911f1c2bb8903b917cff |# https |# -
119.123.206.62 |# - |# 2020-05-06 00:06:01 |# GET /sensors?project=default&amp;amp;token=fae3b5aa4801542a38bad43ba8f4f34d631ac3789c5475a4b5e065def990c68d&amp;amp;data=eyJkaXN0aW5jdF9pZCI6Im9rQkhxMEl3Qjlfb0ljbHVOektrNzhzVUc3eDQiLCJsaWIiOnsiJGxpYiI6Ik1pbmlQcm9ncmFtIiwiJGxpYl9tZXRob2QiOiJjb2RlIiwiJGxpYl92ZXJzaW9uIjoiMC42In0sInByb3BlcnRpZXMiOnsiJGxpYiI6Ik1pbmlQcm9ncmFtIiwiJGxpYl92ZXJzaW9uIjoiMC42IiwiJHVzZXJfYWdlbnQiOiJTZW5zb3JzQW5hbHl0aWNzIE1QIFNESyIsIiRuZXR3b3JrX3R5cGUiOiJ3aWZpIiwiJG1vZGVsIjoiaVBob25lIDc8aVBob25lOSwxPiIsIiRzY3JlZW5fd2lkdGgiOjM3NSwiJHNjcmVlbl9oZWlnaHQiOjYwMywiJG9zIjoiaU9TIiwiJG9zX3ZlcnNpb24iOiIxMi40LjEiLCJhcHBfbmFtZSI6Iui9puadpeS6hueyvuWHhuWunuaXtuWFrOS6pCIsImFwcF92ZXJzaW9uIjoiMy44LjE1NiIsImN1clBhZ2UiOiJob21lIiwiZGVzY3JpYiI6ImhvbWUiLCJzcmMiOiJ3ZWl4aW5hcHBfY3giLCJ1c2VyVHlwZSI6IndlY2hhdF9tcCIsInBsYXRmb3JtIjoiaW9zIiwiY2l0eSI6Iua3seWcsyIsImdlb19sbmciOiIxMTMuODY5MjE2OTE4OTQ1MzEiLCJnZW9fbGF0IjoiMjIuNTgzNDE5Nzk5ODA0Njg4IiwidXNlcklkIjoib2tCSHEwSXdCOV9vSWNsdU56S2s3OHNVRzd4NCIsIiRpc19maXJzdF9kYXkiOmZhbHNlfSwidHlwZSI6InRyYWNrIiwiZXZlbnQiOiJXRUNIQVRfTVBfUEFHRSIsIl9ub2NhY2hlIjoiMzM0MTQ4ODMzMTA0MyJ9 HTTP/1.1 |# 200 |# 0.001 |# 31 |# https://servicewechat.com/wx71d589ea01ce3321/379/page-frame.html |# Mozilla/5.0 (iPhone; CPU iPhone OS 12_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.12(0x17000c2d) NetType/WIFI Language/zh_CN |# - |# web.chelaile.net.cn |# 172.17.17.73:8106 |# 200 |# 0.001 |# https |# application/json
120.230.99.30 |# - |# 2020-05-06 00:06:01 |# GET /bus/reminder!updateToken.action?last_src=app_oppo_store&amp;amp;s=android&amp;amp;push_open=1&amp;amp;token=23cc4fe44ab8c81ccc5a5abbf0cbbe8f&amp;amp;userId=unknown&amp;amp;astate=1&amp;amp;vc=176&amp;amp;sv=6.0.1&amp;amp;v=3.91.0&amp;amp;secret=7a8236af24cc47ecb1fd84d566648d2a&amp;amp;imei=864315038933153&amp;amp;system_push_open=1&amp;amp;udid=91b7d1d2-5ef7-480b-add6-525eeff7748f&amp;amp;cityId=040&amp;amp;sign=MflpWbAMMtMkDPmv7pLXxA%3D%3D&amp;amp;wifi_open=1&amp;amp;mac=d4%3A50%3A3f%3A50%3A0e%3Add&amp;amp;deviceType=OPPO+R9sk&amp;amp;lchsrc=icon&amp;amp;nw=WIFI&amp;amp;sstate=3&amp;amp;paramsMakeUp=is&amp;amp;AndroidID=fcfa1a1616330e7&amp;amp;accountId=58143812&amp;amp;phoneBrand=OPPO&amp;amp;language=1&amp;amp;first_src=app_oppo_store&amp;amp;tokenType=0 HTTP/1.1 |# 200 |# 0.001 |# 77 |# - |# Dalvik/2.1.0 (Linux; U; Android 6.0.1; OPPO R9sk Build/MMB29M) |# - |# api.chelaile.net.cn |# 172.17.17.103:9090 |# 200 |# 0.001 |# 15886947618392e5366b12e672bdeab2 |# https |# -
112.96.118.28 |# - |# 2020-05-06 00:06:01 |# GET /bus/reminder!updateToken.action?last_src=app_oppo_store&amp;amp;s=android&amp;amp;push_open=1&amp;amp;token=01f582fb46ad1e9bd47c2eabf93f42c7&amp;amp;userId=unknown&amp;amp;astate=1&amp;amp;vc=175&amp;amp;sv=6.0.1&amp;amp;v=3.90.4&amp;amp;secret=8e38bc377a2d47cb8d2964f0a7ba80ea&amp;amp;imei=866491036515611&amp;amp;system_push_open=1&amp;amp;udid=741f2e45-5624-4e86-8364-0c44025231a5&amp;amp;cityId=019&amp;amp;sign=MflpWbAMMtM95KYtWgrN6Q%3D%3D&amp;amp;wifi_open=0&amp;amp;mac=30%3A84%3A54%3A6c%3A58%3A17&amp;amp;deviceType=OPPO+A57&amp;amp;lchsrc=icon&amp;amp;nw=MOBILE_LTE&amp;amp;sstate=3&amp;amp;paramsMakeUp=is&amp;amp;AndroidID=91b826d010703913&amp;amp;accountId=133077807&amp;amp;phoneBrand=OPPO&amp;amp;language=1&amp;amp;first_src=app_oppo_store&amp;amp;tokenType=0 HTTP/1.1 |# 200 |# 0.002 |# 77 |# - |# Dalvik/2.1.0 (Linux; U; Android 6.0.1; OPPO A57 Build/MMB29M) |# - |# api.chelaile.net.cn |# 172.17.17.18:9090 |# 200 |# 0.002 |# 1588694761847388a64bb9e328cee8d1 |# https |# -
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>fzy</name><email>19781971@qq.com</email></author><category term="Linux" /><category term="Tips" /><summary type="html">前言</summary></entry><entry><title type="html">HashMap的死锁（JDK7)</title><link href="https://chinafzy.github.io/java/cycle-ref-in-hashmap/" rel="alternate" type="text/html" title="HashMap的死锁（JDK7)" /><published>2020-02-01T00:00:00+00:00</published><updated>2020-02-01T00:00:00+00:00</updated><id>https://chinafzy.github.io/java/cycle-ref-in-hashmap</id><content type="html" xml:base="https://chinafzy.github.io/java/cycle-ref-in-hashmap/">&lt;h2 id=&quot;说明&quot;&gt;说明&lt;/h2&gt;
&lt;p&gt;早期JDK的HashMap，在多线程下，会出现各种问题：&lt;/p&gt;
&lt;ul&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;这里分析死锁产生的原理（或者说可能性）之一&lt;/p&gt;

&lt;h2 id=&quot;源码&quot;&gt;源码&lt;/h2&gt;
&lt;p&gt;http://hg.openjdk.java.net/icedtea/jdk7/jdk/file/tip/src/share/classes/java/util/HashMap.java&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;我们需要关注的是函数transfer下的while循环（行4-13）&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;transfer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rehash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newCapacity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;Entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rehash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indexFor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newCapacity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;newTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;它的主要逻辑：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;获取一个节点，&lt;/li&gt;
  &lt;li&gt;计算节点的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hash&lt;/code&gt;值，以及对应在新数组中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slot&lt;/code&gt;位置&lt;/li&gt;
  &lt;li&gt;查看slot位置上，是否已经有节点链：
    &lt;ul&gt;
      &lt;li&gt;如果没有，直接将新节点放入；&lt;/li&gt;
      &lt;li&gt;如果原来的位置上已有节点，将旧节点附加在新节点的后面，新节点成为链条的头部（因此叫&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;头插法&lt;/code&gt;），新节点放在slot位置上；&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;如果有剩余节点，继续循环&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;案例设定&quot;&gt;案例设定&lt;/h2&gt;
&lt;p&gt;假设有table数组长度是2，有俩个元素，key的hashCode分别是【3】和【7】。&lt;br /&gt;
原始的数据结构如下：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;0
1   【3】-&amp;gt; 【7】
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;现在要将其transfer为长度4的数组。&lt;/p&gt;

&lt;h2 id=&quot;正常的程序运行过程&quot;&gt;正常的程序运行过程&lt;/h2&gt;
&lt;p&gt;程序逻辑认定的正常运行过程如下：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;while循环第一次运行到最后&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;0
1 	
2
3   【3】
-- 以上是数组，以下是临时变量 --
e  =【7】
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;循环第二次运行到最后&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;0
1
2
3   【7】 -&amp;gt; 【3】

e = null
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e = null&lt;/code&gt;，整体循环结束&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;死锁的产生&quot;&gt;死锁的产生&lt;/h2&gt;
&lt;p&gt;假设我们有俩个线程，同时运行了transfer操作（这个非常容易发生）。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;俩个线程都完成第一个循环&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;俩个线程中数据结构变为：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;0
1 	
2
3   【3】

e  =【7】
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;线程1停留在这里，线程2继续完成第二个循环，结束退出&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;线程2里面看见的数据结构是这样&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;0
1
2
3   【7】 -&amp;gt;【3】

e = null
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;根据Java内存模型，节点之间的next指向关系会影响到线程1&lt;/p&gt;

&lt;p&gt;因此，线程1里面的数据结构就变成了：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;0
1 	
2
3   【3】

e  =【7】-&amp;gt;【3】
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;线程1的二次循环结束&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;0
1 	
2
3   【7】-&amp;gt;【3】

e  =【3】
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这个时候，e != null，还会继续循环&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;线程1的三次循环结束&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;0
1
2
3   【3】&amp;lt;-&amp;gt;【7】

e = null
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;e = null，整体循环结束&lt;/li&gt;
  &lt;li&gt;节点【3】【7】形成相互循环&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;死锁的爆发&quot;&gt;死锁的爆发&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;查询&lt;/code&gt;操作的key位于slot3上时候（例如hashCode是【11】），将产生死循环&lt;/p&gt;

&lt;h2 id=&quot;问题分析&quot;&gt;问题分析&lt;/h2&gt;
&lt;p&gt;这个问题的根源，在于：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;发生问题的key，它们在tranfer到新的数组后还位于一个slot上&lt;/li&gt;
  &lt;li&gt;链表的头插法&lt;/li&gt;
  &lt;li&gt;多线程&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;链表的头插法是其中的关键要素之一，这个不修改，问题就始终存在。下面是jdk7中HashMap的其它版本，这个问题依旧存在。&lt;/p&gt;

&lt;p&gt;https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/HashMap.java&lt;/p&gt;</content><author><name>fzy</name><email>19781971@qq.com</email></author><category term="Java" /><summary type="html">说明 早期JDK的HashMap，在多线程下，会出现各种问题： 数据掉了 数据删了又回来了 死锁</summary></entry><entry><title type="html">Kafka Broker 出现Too many open files</title><link href="https://chinafzy.github.io/linux/kafka-too-many-open-files/" rel="alternate" type="text/html" title="Kafka Broker 出现Too many open files" /><published>2019-06-25T23:08:11+00:00</published><updated>2019-06-25T23:08:11+00:00</updated><id>https://chinafzy.github.io/linux/kafka-too-many-open-files</id><content type="html" xml:base="https://chinafzy.github.io/linux/kafka-too-many-open-files/">&lt;h2 id=&quot;问题描述&quot;&gt;问题描述&lt;/h2&gt;

&lt;h3 id=&quot;环境&quot;&gt;环境&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;kafka server 0.10.0.1 （查看libs/kafka_2.10-0.10.0.1.jar）&lt;/li&gt;
  &lt;li&gt;5个broker&lt;/li&gt;
  &lt;li&gt;1000个partition，3份的存储&lt;/li&gt;
  &lt;li&gt;部分partition每秒数据有3000，一半以上的大概1000条&lt;/li&gt;
  &lt;li&gt;数据每条大概是100B&lt;/li&gt;
  &lt;li&gt;200个partition的数据被实时消费&lt;/li&gt;
  &lt;li&gt;使用机械硬盘&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;问题表现&quot;&gt;问题表现&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;外部无法连接&lt;/li&gt;
  &lt;li&gt;此时第一个kafka broker上的日志&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server.log&lt;/code&gt;大量出现错误
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;[2019-06-21 18:03:29,341] ERROR Error while accepting connection (kafka.network.Acceptor)
java.io.IOException: Too many open files
      at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
      at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
      at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
      at kafka.network.Acceptor.accept(SocketServer.scala:323)
      at kafka.network.Acceptor.run(SocketServer.scala:268)
      at java.lang.Thread.run(Thread.java:748)
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;查看kafka server的文件句柄&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lsof -p &amp;lt;pid&amp;gt;&lt;/code&gt;，里面有近十万的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;can't identify protocol&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;消费程序无法获取数据&lt;/li&gt;
  &lt;li&gt;到一定时候，有问题的broker可能崩溃。&lt;/li&gt;
  &lt;li&gt;重启出问题的broker后，问题解决。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;排查过程&quot;&gt;排查过程&lt;/h2&gt;

&lt;p&gt;因为数据是多副本，所以考虑将问题节点下线，但是下线后遇到问题，消费程序都不能从kafka消费。&lt;/p&gt;

&lt;p&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jstack&lt;/code&gt;连续多次抓取消费者Java进程，发现，&lt;/p&gt;

&lt;p&gt;但是这时用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kafka-console-consumer.sh&lt;/code&gt;来消费是可以。&lt;/p&gt;

&lt;p&gt;继续排查后，发现不同的消费方式会有不同的结果（在后续版本中，这些参数混乱被纠正了）：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;使用参数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--zookeeper localhost:2181&lt;/code&gt;可以消费&lt;/li&gt;
  &lt;li&gt;使用参数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--bootstrap-server localhost9092 --new-consumer&lt;/code&gt;的方式不可以消费&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;有伙伴怀疑，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__consumer_offset&lt;/code&gt;是单点的，使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kafka-topic.sh --describe&lt;/code&gt;看了之后，发现的确如此，而且单点位置放置在第一个broker上，因此当第一个broker出问题后，整个kafka集群不能消费。&lt;/p&gt;

&lt;p&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kafka-reassign-partitions.sh&lt;/code&gt;将&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__consumer_offset&lt;/code&gt;做三份，打散到多个broker后。问题解决。&lt;/p&gt;

&lt;h2 id=&quot;深入分析&quot;&gt;深入分析&lt;/h2&gt;

&lt;h3 id=&quot;__consumer_offset单点导致的网络连接问题&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__consumer_offset&lt;/code&gt;单点导致的网络连接问题&lt;/h3&gt;

&lt;h3 id=&quot;__consumer_offset单点问题的产生&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__consumer_offset&lt;/code&gt;单点问题的产生&lt;/h3&gt;</content><author><name>fzy</name><email>19781971@qq.com</email></author><category term="Linux" /><category term="Java" /><summary type="html">问题描述</summary></entry><entry><title type="html">Linux下的connection leak</title><link href="https://chinafzy.github.io/linux/connection-leak/" rel="alternate" type="text/html" title="Linux下的connection leak" /><published>2019-06-25T23:08:11+00:00</published><updated>2019-06-25T23:08:11+00:00</updated><id>https://chinafzy.github.io/linux/connection-leak</id><content type="html" xml:base="https://chinafzy.github.io/linux/connection-leak/"></content><author><name>fzy</name><email>19781971@qq.com</email></author><category term="Linux" /><summary type="html"></summary></entry><entry><title type="html">给程序员小伙伴的推荐</title><link href="https://chinafzy.github.io/program/recommand-for-programmer/" rel="alternate" type="text/html" title="给程序员小伙伴的推荐" /><published>2019-01-01T00:00:00+00:00</published><updated>2019-01-01T00:00:00+00:00</updated><id>https://chinafzy.github.io/program/recommand-for-programmer</id><content type="html" xml:base="https://chinafzy.github.io/program/recommand-for-programmer/">&lt;p&gt;新年伊始，给程序员小伙伴们推荐一下后端语言技能。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;第一是docker：&lt;br /&gt;
因为它是最有用的工具。可以很容易的在电脑上模拟各种服务器环境，实在是性能学习的必备法宝。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;第二是lua：是性能的超级法宝。关键时候，能给性能带来爆炸的提升。
    &lt;ul&gt;
      &lt;li&gt;lua+nginx/openresty的性能起点是几万qps，毫秒级响应，很多其他服务器的终点都达不到了。非常适合做【穿透+一定计算】的场景。&lt;/li&gt;
      &lt;li&gt;redis+lua，能做纳秒级事务，比如秒杀这些小东西。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;第三是java+设计模式/工程管理：&lt;br /&gt;
做小工具，java的语法有点累赘了，但是他的规范性在得到各种设计模式增强后，绝对是大工程的不二选择。&lt;br /&gt;
（没约束的）灵活性在工程里绝对致命的。小打小闹的做个工具/玩具，自然越灵活越好，但是代码量和功能增加，经手人来来往往，混乱不断引入，麻烦会不断突破性升级。
有志于深入程序的小伙伴，一定要抓住设计模式和软件工程管理。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;第四是工具级，spring boot：&lt;br /&gt;
所有的东西都是开箱即得，数据库、缓存、rest客户端……，在这个上面做快速开发绝对是当前最好的，而且性能还不错。&lt;br /&gt;
有志于互联网创业的小伙伴的不二选择，如果竞争对手搞什么php快速上线了，拿个浏览器就可以把他刷下线。&lt;/li&gt;
&lt;/ul&gt;</content><author><name>fzy</name><email>19781971@qq.com</email></author><category term="FAV" /><category term="Program" /><summary type="html">新年伊始，给程序员小伙伴们推荐一下后端语言技能。</summary></entry><entry><title type="html">继承还是聚合，设计模式的取舍？</title><link href="https://chinafzy.github.io/java/inherit-or-composite/" rel="alternate" type="text/html" title="继承还是聚合，设计模式的取舍？" /><published>2019-01-01T00:00:00+00:00</published><updated>2019-01-01T00:00:00+00:00</updated><id>https://chinafzy.github.io/java/inherit-or-composite</id><content type="html" xml:base="https://chinafzy.github.io/java/inherit-or-composite/">&lt;h2 id=&quot;从jdk的一个经典bug说起继承inherit的不足&quot;&gt;从JDK的一个经典bug说起继承(inherit)的不足&lt;/h2&gt;

&lt;p&gt;JDK实现了观察者设计模式，&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.util.Observable&lt;/code&gt;：可被观察的对象，主要函数：
    &lt;ul&gt;
      &lt;li&gt;addObserver()/deleteObserver()：增删观察者&lt;/li&gt;
      &lt;li&gt;notifyObservers()：通知观察者数据变动&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.util.Observer&lt;/code&gt;：观察调用的callback，函数：
    &lt;ul&gt;
      &lt;li&gt;update(Observable observable, Object obj)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;假设我要做一个UI类，在内部资源内容发生变动时候，需要&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;通知&lt;/code&gt;别的模块，观察者模式是最好的选择。&lt;br /&gt;
我们期望的代码是这样的：&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MgrView&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Observable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;monitor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Mgr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Observer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;monitor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addObserver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;do1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// ... 处理业务 ...&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;// 处理完了后发送通知 &lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;monitor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;但是我们在查看JDK自带的包，发现了一个问题：&lt;br /&gt;
Observable中的关键代码：控制Observable是否启用的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#setChanged()&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#clearChanged()&lt;/code&gt;，可见性是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;protected&lt;/code&gt;。&lt;br /&gt;
因此要使用这个类，只能&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;继承&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;从概念上说：我的类的基础特性是UI View；观察者模式只是它的一个分支特性，不是根本特性。&lt;br /&gt;
因此，继承Observable就是一个错误的方式。&lt;/p&gt;

&lt;p&gt;但是，JDK的观察者模式默认了是继承模式。这个给我们的使用带来了很大的麻烦。是一个完全错误的考虑。&lt;/p&gt;

&lt;p&gt;从技术层面来看，它后续还不能把那个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;protected&lt;/code&gt;升级为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public&lt;/code&gt;，因为这样的话，现有的子类如果有protected @Override这个方法的，就会出错了。&lt;/p&gt;

&lt;h2 id=&quot;简单结论何时适合做继承或者组合&quot;&gt;简单结论：何时适合做继承或者组合&lt;/h2&gt;
&lt;p&gt;从上面的例子延伸考虑：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;UIView是我们的组件的主要特性，组件“是一个(IsA)”UIView&lt;/li&gt;
  &lt;li&gt;组件还有可观察的次要属性，组件“有一个(HasA)”Observable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;把一个HasA的特性变成了IsA，就会让组件多出来很多莫名其妙的功能。&lt;/p&gt;

&lt;p&gt;这个是最简单也是最基础的分辨。但是有时候可以模糊执行：&lt;br /&gt;
&lt;strong&gt;如果没有IsA，而且这个需求没有后续发展，HasA可以用IsA来冒充&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;例如：要做一个临时的小工具，这个工具不是基于别的工具的基础上来做，而有“可观察”特性。这个时候，就可以直接继承Observable，也告诉使用的人，里面其他的函数别管了。&lt;/p&gt;

&lt;h2 id=&quot;从springboot的一个例子&quot;&gt;从SpringBoot的一个例子&lt;/h2&gt;
&lt;p&gt;SpringBoot里面可以很方便的配置对redis的集成，但是美中不足的是：&lt;br /&gt;
&lt;strong&gt;如果我们要同时访问多个redis，那就麻烦了&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;扩展的方式在别的地方有写，这里只是讨论这个设计的得失：&lt;/p&gt;

&lt;p&gt;一个应用，应该是有一个多个redis数据源，而不是只有一个。在spring-boot的设计中，很明显的感觉到，他把数据源的集成做成了IsA，而不是HasA。&lt;/p&gt;</content><author><name>fzy</name><email>19781971@qq.com</email></author><category term="Java" /><category term="Pattern" /><summary type="html">从JDK的一个经典bug说起继承(inherit)的不足</summary></entry><entry><title type="html">Java Tips</title><link href="https://chinafzy.github.io/java/java-tips/" rel="alternate" type="text/html" title="Java Tips" /><published>2018-12-19T13:08:11+00:00</published><updated>2018-12-19T13:08:11+00:00</updated><id>https://chinafzy.github.io/java/java-tips</id><content type="html" xml:base="https://chinafzy.github.io/java/java-tips/">&lt;h2 id=&quot;find-class-in-jars&quot;&gt;find class in jars&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.jar &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 4 &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Hlsi&lt;/span&gt; org.apache.util.CacheLRU.class &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-type-parameter-v-is-hiding-the-type-v&quot;&gt;The type parameter V is hiding the type V&lt;/h2&gt;
&lt;p&gt;A-E, P, V&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nd&quot;&gt;@SuppressWarnings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hiding&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;manage-java-version-on-macos&quot;&gt;Manage Java version on macos&lt;/h2&gt;

&lt;p&gt;https://stackoverflow.com/questions/21964709/how-to-set-or-change-the-default-java-jdk-version-on-os-x&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Find Installed Javas
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;/usr/libexec/java_home &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt;
Matching Java Virtual Machines &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:
  10.0.1, x86_64:	&lt;span class=&quot;s2&quot;&gt;&quot;Java SE 10.0.1&quot;&lt;/span&gt;	/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home
  1.8.0_172, x86_64:	&lt;span class=&quot;s2&quot;&gt;&quot;Java SE 8&quot;&lt;/span&gt;	/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home
  1.8.0_131, x86_64:	&lt;span class=&quot;s2&quot;&gt;&quot;Java SE 8&quot;&lt;/span&gt;	/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home
  1.8.0_65, x86_64:	&lt;span class=&quot;s2&quot;&gt;&quot;Java SE 8&quot;&lt;/span&gt;	/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home
  1.7.0_80, x86_64:	&lt;span class=&quot;s2&quot;&gt;&quot;Java SE 7&quot;&lt;/span&gt;	/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;switch java by JAVA_HOME variant
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;JAVA_HOME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;compiler识别exception&quot;&gt;compiler识别exception&lt;/h2&gt;
&lt;p&gt;以下代码在jdk6上编译失败，7及以上ok，原因是新的编译器能识别这个实际上的异常。&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;rouge-gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;rouge-code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RuntimeException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>fzy</name><email>19781971@qq.com</email></author><category term="Java" /><category term="Tips" /><summary type="html">find class in jars 1 find . -name *.jar -maxdepth 4 -exec grep -Hlsi org.apache.util.CacheLRU.class {} \;</summary></entry><entry><title type="html">代理和反向代理</title><link href="https://chinafzy.github.io/proxy-and-reverse/" rel="alternate" type="text/html" title="代理和反向代理" /><published>2018-12-18T23:08:11+00:00</published><updated>2018-12-18T23:08:11+00:00</updated><id>https://chinafzy.github.io/proxy-and-reverse</id><content type="html" xml:base="https://chinafzy.github.io/proxy-and-reverse/">&lt;p&gt;和小伙伴们闲聊，代理&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forward proxy&lt;/code&gt;和反向代理&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reverse proxy&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;最早的时候，就只有&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy&lt;/code&gt;的概念，但是自从反向代理&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reverse proxy&lt;/code&gt;的概念出现后，原来的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy&lt;/code&gt;就修订为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forward proxy&lt;/code&gt;。一般情况下，如果只说代理&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy&lt;/code&gt;，指的还是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forward proxy&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;下面来聊聊他们之间的差别。&lt;/p&gt;

&lt;h2 id=&quot;以借钱为案例比喻&quot;&gt;以借钱为案例比喻&lt;/h2&gt;
&lt;p&gt;假设我是某个童话王国的商人，做生意需要更多资金，但是对贷款业务不熟悉，于是找个中间人帮忙跑腿。去a银行借点，b富豪借点。&lt;br /&gt;
这个人，我们先称为&lt;strong&gt;代理&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;然后，在去找c银行的时候，行长说：由于风控（国家政策经济形势……以下节省十分钟演讲……），现在我们对小额贷款收缩了，办不了你这个。你要借钱，我介绍一个朋友给你认识吧，他有路子。&lt;/p&gt;

&lt;p&gt;懂事的你自然明白：&lt;strong&gt;这个人实际上也是从这个银行借钱出来，再借钱给你&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;但是银行不直接跟你玩，他指定了这个人做他的代理人，你只能跟这个人玩。&lt;br /&gt;
这个人就是银行的代理，我们暂时称他为&lt;strong&gt;反向代理&lt;/strong&gt;。&lt;/p&gt;

&lt;h2 id=&quot;从这个故事来解析&quot;&gt;从这个故事来解析&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;发起者，使用中介，到达目的地，这个就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;正向代理 forward proxy&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;目的地，把自己隐藏起来，让别人只能通过那个中介找到他，这个就是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;反向代理 reverse proxy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;反向代理的第一特征&quot;&gt;反向代理的第一特征&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;对于发起者来说，这个中介是不是完全“代表”了目的地，把目的地隐藏起来了，是关键差别一&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;举例来说：&lt;br /&gt;
童话故事里因为贷款太麻烦，存款利息又低，银行态度还特别拽，爱存不存。&lt;br /&gt;
然后民间出了个公司，可以存款+借贷。对于大家来说，存款利息高了，贷款利息低了，手续还特别方便。众人皆大欢喜。&lt;br /&gt;
突然天降灵符，说这个&lt;em&gt;不安全&lt;/em&gt;，上天有好生之德，我要管理这个，不允许你们这样做，我要保护大家。&lt;br /&gt;
于是大家又只能回去接受银行的盘剥和刁难。&lt;/p&gt;

&lt;p&gt;这个管理灵符，他隐藏并代表了被管理对象，因此是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reverse proxy&lt;/code&gt; 。&lt;br /&gt;
当然灵符还会宣传：自己代表了上天的意志，代表了历史的选择，也代表了人命的利益。&lt;/p&gt;

&lt;h2 id=&quot;反向代理的第二特征&quot;&gt;反向代理的第二特征&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;他可能会修改请求和答复&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;还是以童话王国的借钱为例，如果是我们找到的代理，他一般要手续费。&lt;/p&gt;

&lt;p&gt;但是如果是反向代理，很可能就变成这样了：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;借款人要接100w；&lt;/li&gt;
  &lt;li&gt;反向代理找银行拿120w，到期还款130w；&lt;/li&gt;
  &lt;li&gt;反向代理告诉借款人利息15w，信息服务费15w，要还130w——各种名目收钱，但合同字面的利息可能就只有15%；&lt;/li&gt;
  &lt;li&gt;反向代理人还说：还有中间人好处费20w——这个是借款人自愿送给他的，所以更不是利息了；&lt;/li&gt;
  &lt;li&gt;最后贷款人拿到80w，但是要还130w。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;反向代理俩头都骗，对客户端冒充服务器端，对服务器端冒充客户端。&lt;/p&gt;

&lt;p&gt;童话王国里面的普通老百姓搞不明白一个道理：&lt;br /&gt;
&lt;strong&gt;为什么银行贷款利息那么低，但是做生意的要去借高利贷？&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;用it案例来说&quot;&gt;用IT案例来说&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;由于某个不能说的秘密，大家不能访问不了技术网站，通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;代理&lt;/code&gt;来访问，这个是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forward proxy&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;公司为了方面大家看技术网站，搭了一个代理服务器，80端口指向stackoverflow，81端口指向github，这个就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reverse proxy&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;手机调试，走charless，不仅可以看见请求和答复，还可以修改，这个是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reverse proxy&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;</content><author><name>fzy</name><email>19781971@qq.com</email></author><category term="System" /><category term="Fav" /><summary type="html">和小伙伴们闲聊，代理forward proxy和反向代理reverse proxy。</summary></entry></feed>