<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>哈巴狗</title>
	<atom:link href="http://www.habadog.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.habadog.com</link>
	<description>讨论架构技术的狗窝</description>
	<lastBuildDate>Fri, 23 Oct 2015 10:29:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.2</generator>
		<item>
		<title>微信为啥这么省流量（技术宅入）</title>
		<link>http://www.habadog.com/2015/10/23/wechat-use-less-data/</link>
		<comments>http://www.habadog.com/2015/10/23/wechat-use-less-data/#comments</comments>
		<pubDate>Fri, 23 Oct 2015 10:29:37 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>
		<category><![CDATA[app]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=730</guid>
		<description><![CDATA[无线时代，流量敏感。微信在登录后，要向服务器同步非常多的数据，很费流量。技术上如何进行流量优化，这是本文要讨论的问题。<p class="read-more"><a href="http://www.habadog.com/2015/10/23/wechat-use-less-data/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>前言：“客户端上传时间戳”的玩法，你玩过么？一起聊聊时间戳的奇技淫巧！</p>
<p>缘起：无线时代，流量敏感。APP在登录后，往往要向服务器同步非常多的数据，很费流量，技术上有没有节省流量的方法呢？这是本文要讨论的问题。</p>
<p><strong>问题一：APP</strong><strong>登录时需要拉取什么数据？</strong><br />
答：APP登陆时，一般要拉取两类数据，一类是“id列表型数据”，一类是“信息详情型数据”，以微信为例，需要拉取<br />
（1）好友列表List&lt;user-id&gt;，即所有好友的id（id+name）<br />
user_frined{uid, friend-uid, friend-name}<br />
（2）群组列表List&lt;group-id&gt;，即所有加入群的id（id+name）<br />
（3）群友列表Map&lt;group-id, List&lt;group-user-id&gt;&gt;，所有群友的id（id+name）<br />
（4）好友详情Map&lt;user-id, User&gt;，所有好友的详情（昵称，备注，标签，地区，相册等）<br />
user{uid, nick-name, memo, locate, tag}<br />
（5）群组详情Map&lt;group-id, Group&gt;，所有群组的详情（二维码，公告，是否免打扰等）<br />
（6）群友详情Map&lt;group-id, Map&lt;user-id, User&gt;&gt;，所有群友的详情（昵称，备注，标签，地区，相册等）<br />
（7）其他，例如离线消息…</p>
<p><strong>问题二：能不能在登录的过程中不拉取这些数据，而在登录后拉取？</strong><br />
答：如果登录时不拉取，登陆后刷好友列表，刷群列表，群成员会很慢。<br />
如果登录时拉取，登陆过程可能会很慢（微信的“大月亮背景”要等多长时间？QQ登录要等30s？）。<br />
为了保证登录后的体验，一般是在登录过程中拉取。</p>
<p><strong>问题三：能不能直接复用客户端本地的数据？</strong><br />
答：不能直接复用客户端本地的数据，因为不能确保本地的数据是最新的。</p>
<p><strong>核心问题：每次登录都需要拉取，太费流量了，有没有优化方法？</strong><br />
答：常用优化方法有两种<br />
（1）延迟拉取，按需拉取<br />
（2）时间戳</p>
<p><strong>问题五：延迟拉取，按需拉取为什么有效？为什么能够减少拉取流量？</strong><br />
答：用户在使用APP的过程中，有些数据是一定会使用到的，有些数据是不一定会使用到的。对于一定会使用到的数据，登录时拉取可以提升后续用户体验。对于不一定会使用到的数据，登录时拉取可能浪费流量，这些数据如果进行“延迟拉取”，可以节省流量。</p>
<p><strong>问题六：哪些数据不登录后不一定会使用，可以延迟拉取？</strong><br />
答：这个问题的答案和业务紧密相关，以微信为例<br />
一定会使用到的数据：好友列表（主页面要展示user-name），群组列表（主界面要展示group-name）<br />
不一定会使用到的数据：好友详情，群组详情，群友列表，群友详情<br />
故，对于微信，登录时只需要拉取好友列表（id+name）与群组列表（id+name）即可，而其他数据，等用户真正点击和使用时再拉取即可，这样就可以大大减少拉取流量。</p>
<p><strong>问题七：时间戳为什么有效？为什么能够减少拉取流量？</strong><br />
答：本地数据不能直接使用的原因是，不确定数据是否最新，拉取服务器时间戳与本地时间戳进行比对，如果本地是最新的数据，就能避免重新拉取。id列表数据的变化频度是比较低的（增加id，减少id），时间戳机制非常的有效。</p>
<p><strong>问题八：加入时间戳机制后，数据拉取流程有什么变化？</strong><br />
答：假设有100个好友，以好友详情数据的拉取为例，没有时间戳之前，直接向服务器拉取这100个好友的详情数据。<br />
在有了时间戳之后，数据拉取流程变为：<br />
（1）先拉取100个好友的时间戳<br />
（2）客户端将100个好友的时间戳与本地时间戳对比，找出差异，假设有10个好友的信息发生了变化，时间戳改变了<br />
（3）拉取10个有变化的好友的信息<br />
优点是：大大减少了数据传输量（由拉取100个好友，降低到拉取10个好友）<br />
缺点是：增加了一次网络交互（原来直接拉取，现在需要分别拉取时间戳与差异数据）</p>
<p><strong>问题九：使用时间戳的同时，能否降低网络交互次数呢？</strong><br />
答：可以！<br />
客户端对时间戳的使用，往往采取“客户端拉取时间戳”+“客户端比对时间戳”+“客户端再次拉取差异数据”的方式进行，“时间戳比对”的的CPU计算发生在客户端，其实，这个计算可以转嫁到服务器，步骤为：<br />
（1）客户端上传100个好友的时间戳<br />
（2）服务端收到客户端上传的时间戳，与最新时间戳对比，找出差异，假设有10个好友的信息发生了变化，服务端可以直接将有差异的10个好友的数据返回<br />
优点是：客户端减少了一次网络请求<br />
缺点是：比对时间戳差异的CPU计算由“端”转嫁到了“云”</p>
<p><strong>问题十：你怎么知道微信是这么做的？</strong><br />
答：我不知道微信是怎么做的，微信比较出名，所以标题党了一把，抱歉。“客户端上传时间戳”的方法，58帮帮APP是这么做的，希望对业界同仁有启示作用。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/10/23/wechat-use-less-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>巧妙测量服务器之间的时间差</title>
		<link>http://www.habadog.com/2015/10/22/time-diff/</link>
		<comments>http://www.habadog.com/2015/10/22/time-diff/#comments</comments>
		<pubDate>Thu, 22 Oct 2015 07:55:44 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>
		<category><![CDATA[网络编程]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=725</guid>
		<description><![CDATA[每台服务器都有自己的本地时间，如何来测量两台服务器本地时间的差值呢？<p class="read-more"><a href="http://www.habadog.com/2015/10/22/time-diff/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>巧妙测量服务器之间的时间差</p>
<p><strong>缘起：无绝对时钟</strong><br />
Fischer Lynch Paterson定理是分布式理论中非常重要的一个定理，其结论相当悲观：在一个多进程异步系统中，由于没有全局绝对时钟，一定不存在一个一致的消息投递协议。</p>
<p><strong>工程折衷：单点序列化</strong><br />
每个进程，每台服务器都有自己的本地时钟，跨服务器的本地时钟比较是没有意义的，这一点很好理解，服务器A上的本地时间ta=1，服务器B上的本地时间tb=2，虽然ta&lt;tb，但我们并不能说ta一定早发生，因为两台服务器的本地时间会有差异。<br />
工程上，可以使用一台单点服务器来分发序列号，或者使用这台单点服务器来进行序列化，来模拟全局时钟。</p>
<p><strong>问题的提出：既然两台服务器的本地时间存在差值，如何来测量两台服务器之间的时间差呢？</strong><br />
答案是，发包测量。<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/10/time.png"><img src="http://www.habadog.com/wp-content/uploads/2015/10/time.png" alt="" title="time" width="174" height="95" class="alignnone size-full wp-image-727" /></a><br />
发包流程如上图：<br />
1）服务器A记录一个本地时间Ta1，然后向服务器B发送一个报文<br />
2）服务器B接收到报文后取本地时间Tb放入到报文中，并将报文发回给服务器A<br />
3）服务器A收到回复报文后，记录本地时间Ta2<br />
很容易知道，Ta1和Ta2取的是服务器A的本地时间，Tb取的是服务器B的本地时间。<br />
假设报文往返耗时是相同的（这个假设很合理），那么<br />
x = (Ta2 &#8211; Ta1)/2<br />
如果，你硬要说这个x通过一次测量不准确的话，可以发1亿次往返请求，来求出一个相对精确的x值<br />
假设服务器A与服务器B的绝对时间是相同的（这个假设不合理），那么<br />
Tb = Ta1 + x = (Ta2 + Ta1)/2<br />
可实际上，服务器A与服务器B存在一个时间差，不妨设时间差是“德尔塔”，那么<br />
Tb + “德尔塔” = Ta1 + x= (Ta2 + Ta1)/2<br />
于是，<strong>“德尔塔” = (Ta2 + Ta1)/2– Tb</strong><br />
这个“德尔塔”就是服务器A与服务器B的时间差</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/10/22/time-diff/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>无线APP日志上报优化实践</title>
		<link>http://www.habadog.com/2015/10/21/app-log-report/</link>
		<comments>http://www.habadog.com/2015/10/21/app-log-report/#comments</comments>
		<pubDate>Wed, 21 Oct 2015 12:25:08 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>
		<category><![CDATA[app]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=719</guid>
		<description><![CDATA[无线时代，APP流量敏感，为了统计APP内用户行为往往需要上报日志，上报日志如何进行流量优化，这是本文将要讨论的问题。<p class="read-more"><a href="http://www.habadog.com/2015/10/21/app-log-report/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>无线APP日志上报优化实践</p>
<p>缘起：无线时代，APP流量敏感，为了统计APP内用户行为，或者需要收集某些产品数据，往往需要进行日志上报，日志上报往往又非常费流量，有没有一些好的节省流量的优化方法呢，这是本文将要讨论的问题。</p>
<p><strong>一、APP可不可以不进行日志上报，而单纯从服务器日志统计用户的行为和产品数据？</strong><br />
答：不行，有些用户行为是不会与服务器进行交互的（例如TAB的点击），从服务器日志无法完成所有统计。</p>
<p><strong>二、APP通常有一些什么方法来上报日志？</strong><br />
答：常用方法有三种：<br />
1）利用类似于Google Analytics的第三方工具进行上报，优点是无需开发，缺点是不能做个性化统计<br />
2）自己制订私有协议进行上报（例如TCP二进制协议），优点是节省流量，缺点是开发成本高<br />
3）使用HTTP上报，例如通过GET参数传递需要上报的数据，这种方案使用最为广泛</p>
<p><strong>三、APP上报日志协议细节是怎么样的？</strong><br />
答：一般是在web-server下放置一个空文件，APP通过发起HTTP请求访问这个空文件，通过GET参数传递数据，通过分析access日志来得到想要的数据。GET协议一般又有两种方式，约定格式法 + KV法<br />
1）<strong>约定格式法</strong>：约定分隔符，约定占位符，约定每个字段的含义，例如：<br />
<a href="http://daojia.com/up?%5bbj%5d%5b20151021%5d%5b1939%5d%5b1%5d%5blogin">http://daojia.com/up?[bj][20151021][1939][1][login</a>]<br />
APP和server约定好，空白文件是up，分隔符是[]，第一个字段[bj]是城市，第二个字段[20151021]是日期，第三个字段[1939]是时间，第四个字段[1]是用户id，第五个字段[login]是行为<br />
这个方法的缺点是，扩展性较差，有时候某些字段没有值，也必须在相应的位置保留占位符（因为每个字段是什么含义都是事先约定好的），要想新增统计项，只能在GET后面新增[]<br />
2）<strong>KV法</strong>：通过自解释的kv方式来上报数据，上面的例子用KV法来上报，则上报形式为：<br />
<a href="http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login">http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login</a><br />
这个方法的优点是扩展性好（好太多了），缺点是上报数据量比较大，KEY其实是冗余的字符<br />
笔者强烈建议使用第二种方法来上报数据，后文会简述一些流量的优化方法</p>
<p><strong>四、APP上报日志，流量很大，主要矛盾是什么？</strong><br />
答：笔者了解到的主要矛盾有：<br />
1）无效的流量较多，HTTP请求内有很多无效数据<br />
2）URL冗余，每次都要上报URL<br />
3）KEY冗余，每次都要上报KEY<br />
4）上报频度高，每当用户进行了一个操作都要日志上报的话，HTTP量还是很大的</p>
<p><strong>五、有什么优化的方法？</strong><br />
答：针对上述1）-4）的主要矛盾，逐一进行优化：<br />
1）手动构造HTTP请求，尽可能多的去除HTTP中的无效数据，只保留GET /up HTTP/1.1和GET传递的数据<br />
2）使用尽可能短的域名来接收上报的日志，例如s.daojia.cn/a<br />
3）使用尽可能短的KEY来标识数据，例如city=bj可以优化为c=bj，日志收集方注意规范好KEY<br />
4）批量非实时上报，先将数据保存到APP本地存储（例如sqlite中），定时上报，这类优化对于PV类，SUM类，AVG类统计尤为有效，例如，要统计登录按钮的点击次数，三次点击，传统统计可能需要上报三次<br />
<a href="http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login">http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login</a><br />
<a href="http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login">http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login</a><br />
<a href="http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login">http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login</a><br />
优化后，只需要上报一次（注意加了一个count=3的参数）<br />
<a href="http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login&amp;count=3">http://daojia.com/up?city=bj&amp;date=20151021&amp;time=1939&amp;uid=1&amp;action=login&amp;count=3</a></p>
<p><strong>六、非实时上报，数据时效性怎么保证？在什么时机进行日志上报呢？</strong><br />
答：数据的时效性会有一定的影响，但问题不大。为了优化，会在这样的一些时间点进行上报：<br />
1）<strong>特殊时间点</strong>：APP打开时，APP关闭时等<br />
2）<strong>按时间上报</strong>：例如每隔10分钟上报一次<br />
3）<strong>按数据量上报</strong>：例如每收集10条记录才上报一次<br />
一般来说上述三种优化方法会结合进行</p>
<p><strong>七、还有其他什么优化方案？</strong><br />
答：数据压缩也是一种常见的优化方案</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/10/21/app-log-report/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>无线APP时代HTTP请求DNS优化</title>
		<link>http://www.habadog.com/2015/10/20/app-http-dns/</link>
		<comments>http://www.habadog.com/2015/10/20/app-http-dns/#comments</comments>
		<pubDate>Tue, 20 Oct 2015 13:12:25 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[dns]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=715</guid>
		<description><![CDATA[无线时代，网络稳定性差，应用流量敏感，APP与server之间每次HTTP请求都需要DNS解析，有没有优化方法呢？<p class="read-more"><a href="http://www.habadog.com/2015/10/20/app-http-dns/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>无线APP时代HTTP请求DNS优化</p>
<p>缘起：无线时代，网络稳定性差，应用流量敏感，APP与server之间每次HTTP请求都需要DNS解析，有没有优化方法呢？</p>
<p><strong>一、PC时代，HTTP请求处理过程</strong><br />
<a href="http://www.habadog.com/wp-content/uploads/2015/10/http1.png"><img class="alignnone size-full wp-image-716" title="http1" src="http://www.habadog.com/wp-content/uploads/2015/10/http1.png" alt="" width="260" height="180" /></a><br />
（1）浏览器、或者PC客户端访问DNS服务器，由域名拿到IP（一般来说是个nginx的IP）<br />
（2）浏览器、或者PC客户端用IP访问nginx<br />
（3）nginx将请求分发给实际处理HTTP请求的web-server</p>
<p><strong>二、无线APP时代的特点</strong><br />
（1）DNS解析的时间不能忽略<br />
（2）一旦DNS被劫持，整个APP就挂了（还记得N年前baidu的域名被劫持的事情么？）</p>
<p><strong>三、一种不需要DNS解析的HTTP请求优化方案</strong><br />
<a href="http://www.habadog.com/wp-content/uploads/2015/10/http2.png"><img class="alignnone size-medium wp-image-717" title="http2" src="http://www.habadog.com/wp-content/uploads/2015/10/http2-300x145.png" alt="" width="300" height="145" /></a><br />
（1）第一次访问时，先拉取server的ip-list保存到本地，访问过程与普通HTTP访问过程相同<br />
（2）未来访问时，客户端直接使用ip-list中的IP来访问server，不再需要DNS<br />
（3）如果DNS被劫持，直接尝试使用ip-list中的IP访问</p>
<p><strong>四、潜在的问题</strong><br />
（1）虽然少了一步DNS查询和一步nginx中转，那怎么做负载均衡呢？<br />
答：APP随机访问ip-list中的IP</p>
<p>（2）使用nginx可以方便的增加后端的服务，不使用nginx如何做水平扩展呢？<br />
答：直接在ip-list中增加ip即可</p>
<p>（3）每次访问都要访问ip-list，还是挺废流量的，还有其他优化方案么？<br />
答：增加一个版本号，第一次拉取ip-list时，不但把ip-list放到APP本地，并把版本号也拿到。未来不用每次都拿ip-list，而是先拿版本号，如果版本号不变，直接使用本地的ip-list。只有版本号变化时，才需要重新拉取ip-list</p>
<p>（4）还有其他什么好处？<br />
答：使用nginx不好做异构服务器的负载均衡，即难以根据后端服务的处理能力来分配负载。使用ip-list，只要加上一个权重参数，即可实现异构服务器的负载均，例如：<br />
192.168.1.1， 10<br />
192.168.1.2， 10<br />
192.168.1.3， 20<br />
可以看到，第三个后端服务的处理能力是前两个的两倍，APP做负载均衡时考虑上第二个参数即可</p>
<p><strong>五、再次总结这种方案的好处</strong><br />
（1）不需要每次请求做DNS解析，节省时间<br />
（2）不需要每次请求做nginx转发，节省时间<br />
（3）不需要每次拉取拉取ip-list，节省流量<br />
（4）DNS被劫持时仍可以使用本地ip</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/10/20/app-http-dns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>im协议设计选型（上）</title>
		<link>http://www.habadog.com/2015/05/20/im-protocol-choose/</link>
		<comments>http://www.habadog.com/2015/05/20/im-protocol-choose/#comments</comments>
		<pubDate>Wed, 20 May 2015 11:52:25 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[未分类]]></category>
		<category><![CDATA[架构师]]></category>
		<category><![CDATA[即时通讯]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=706</guid>
		<description><![CDATA[im协议设计选型（上）<p class="read-more"><a href="http://www.habadog.com/2015/05/20/im-protocol-choose/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>im协议设计选型（上）</p>
<p>周末在一个Qcon群里分享了一些im技术，抽取出其中im协议选型相关的内容，和大家一起探讨。</p>
<p>分享人：58沈剑，58同城技术委员会主席，高级架构师，优秀讲师。前百度hi团队成员，负责过58同城im系统的架构设计。</p>
<p><strong>一、im协议的分层设计</strong><br />
所谓“协议”是双方共同遵守的规则，例如：离婚协议，停战协议。协议有语法、语义、时序三要素。<br />
（1）语法：即数据与控制信息的结构或格式<br />
（2）语义：即需要发出何种控制信息，完成何种动作以及做出何种响应<br />
（3）时序：即事件实现顺序的详细说明<br />
今天的重点是在“协议选型”上，重点讲选哪种协议。</p>
<p>im协议设计主要分为三层：<strong>应用层、安全层、传输层</strong>。<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/05/protocol.jpg"><img class="alignnone size-full wp-image-707" title="protocol" src="http://www.habadog.com/wp-content/uploads/2015/05/protocol.jpg" alt="" width="114" height="90" /></a><br />
后文将详细介绍这三层的协议应该如何选型与设计。</p>
<p><strong>二、im应用层协议设计</strong><br />
应用层协议选型，常见的有三种：<strong>文本协议、二进制协议、流式XML协议</strong>。<br />
<strong> （1）文本协议</strong><br />
文本协议是指 “贴近人类书面语言表达”的通讯传输协议，典型的协议是http协议，一个http协议大致长成这样：<br />
GET / HTTP/1.1<br />
User-Agent: curl<br />
Host: musicml.net<br />
Accept: */*<br />
文本协议的特点是：<br />
a.可读性好，便于调试<br />
b.扩展性也好（通过key:value扩展）<br />
c.解析效率一般（一行一行读入，按照冒号分割，解析key和value）<br />
d.对二进制的支持不好 ，比如语音／视频<br />
im中，msn使用的是文本协议</p>
<p><strong>（2）二进制协议</strong><br />
二进制协议是指binary协议，典型是ip协议，以下是ip协议的一个图示：<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/05/ip.jpg"><img class="alignnone size-medium wp-image-710" title="ip" src="http://www.habadog.com/wp-content/uploads/2015/05/ip-300x90.jpg" alt="" width="300" height="90" /></a><br />
二进制协议一般定长包头和可扩展变长包体 ，每个字段固定了含义 ，例如IP协议的前4个bit表示协议版本号 （Version）。<br />
二进制协议有这样一些特点：<br />
a.可读性差，难于调试<br />
b.扩展性不好 ，如果要扩展字段，旧版协议就不兼容了，所以一般设计时会有一个Version字段<br />
c.解析效率超高（几乎没有解析代价）<br />
对二进制的支持不好 ，比如语音／视频<br />
im中，QQ使用的时二进制协议。</p>
<p><strong>（3）流式XML协议</strong><br />
im的准标准协议xmpp就是使用流式XML，像gtalk，校内通这些im都是基于xmpp的，让我们来看一个xmpp协议的例子：</p>
<div id="_mcePaste">&lt;message</div>
<div id="_mcePaste">to=&#8217;romeo@example.net&#8217;</div>
<div id="_mcePaste">from=&#8217;juliet@example.com&#8217;</div>
<div id="_mcePaste">type=&#8217;chat&#8217;</div>
<div id="_mcePaste">xml : lang=&#8217;en&#8217;&gt;</div>
<div id="_mcePaste">&lt;body&gt;Wherefore art thou, Romeo?&lt;/body&gt;</div>
<div id="_mcePaste">&lt;/message&gt;</div>
<p>从xml标签中大致可以判断这是一个romeo发给juliet的聊天消息。<br />
xmpp协议可以实现跨域的互通。例如gtalk和校内通用户聊天。只要服务端实现了s2s服务（server to server） ，不过现在的im基本没有互通需求 ，所以这个服务基本没有人实现。<br />
Xmpp协议有几个特点：<br />
a.它是准标准协议，可以跨域互通<br />
b.XML的优点，可读性好，扩展性好<br />
c.解析代价超高（dom解析）<br />
d.有效数据传输率超低（大量的标签）<br />
个人旗帜鲜明的强烈不建议使用xmpp，特别是无线端im，如果要用，一定要自己做压缩 ，减少网络流量（用过xmpp的同学都清楚，发一个登录包需要多少交互，要浪费多少流量）。</p>
<p><strong>实际的栗子</strong><br />
下面来看一个im协议的实际例子 ，一般常见的做法是：定长二进制包头，可扩展变长包体。<br />
包体可以使用用文本、XML等扩展性好的协议。<br />
包头负责传输和解析效率，与业务无关。包体保证扩展性，与业务相关。</p>
<p>这是一个实际的16字节im二进制定长包头：<br />
//sizeof(cs_header)=16<br />
struct cs_header<br />
{<br />
uint32_t version;<br />
uint32_t magic_num;<br />
uint32_t cmd;<br />
uint32_t len;<br />
uint8_t data[];<br />
}__attribute__((packed));<br />
前4个字节是version；<br />
接下来的4个字节是个“魔法数字（magic_num）“，用来保证数据错位或丢包问题，常见的做法是，包头放几个约定好的特殊字符，包尾放几个约定好的特殊字符 约定好，发给你的协议，某几个字节位置，是0x 01020304 ，才是正常报文；<br />
接下来是command（命令号），用来区分是keepalive报文、业务报文、密钥交换报文等；<br />
len（包体长度），告知服务端要接收多长的包体。</p>
<p>这是一个实际的可扩展im变长包体：<br />
message CUserLoginReq<br />
{<br />
optional string username = 1;<br />
optional string passwd = 2;<br />
}</p>
<p>message CUserLoginResp<br />
{<br />
optional uint64 uid =1;<br />
}<br />
使用的是google的Protobuf协议（玩过的人都懂），可以看到，登录请求包传入的是用户名与密码，登录响应包返回的是用户的uid。<br />
当然，除了Protobuf，可选择的可扩展包体协议还有xml、json、mcpack（大家懂？）等。<br />
个人旗帜鲜明的推荐Protobuf，主要有几个原因：<br />
a.现成的解析库种类多，可以生成C++、Java、php等代码<br />
b.自带压缩功能<br />
c.在工业界已广泛应用<br />
d.google制造</p>
<p><strong>三、im安全层协议设计</strong><br />
im协议，消息的保密性非常重要 ，谁都不希望自己聊天内容被看到，所以安全层是必不可少的。<br />
<strong> 1、SSL</strong><br />
证书管理微微复杂，代价有点高。</p>
<p><strong>2、自行加解密</strong><br />
自己来搞加解密，核心在于密钥的生成与管理，密钥管理方式有多种，主要有这么三种：<br />
<strong> （1）固定密钥</strong><br />
服务端和客户端约定好一个密钥，同时约定好一个加密算法（eg：AES ），每次客户端im在发送前，就用约定好的算法，以及约定好的密钥加密再传输，服务端收到报文后，用约定好的算法，约定好的密钥再解密。这种方式，密钥和算法对程序员都是透明的。</p>
<p><strong>（2）一人一密钥</strong><br />
简单说来就是每个人的密钥是固定的，但是每个人之间又不同，其实就是在固定密钥的算法中包含用户的某一特殊属性，比如用户uid、手机号、qq号等。</p>
<p><strong>（3）动态密钥（一session一密钥）</strong><br />
动态密钥，一Session一密钥的安全性更高，每次会话前协商密钥。<br />
密钥协商的过程要经过2次非对称密钥的随机生成，1次对称加密密钥的随机生成，具体详情这里不展开，有兴趣的同学可以看下SSL密钥协商额过程。</p>
<p><strong>四、im传输层协议设计</strong><br />
可选的协议有TCP和UDP<br />
现在的im传输层基本都是使用TCP，有了epoll等技术后，多连接就不是瓶颈了，单机几十万链接没什么问题。58同城现在线上单机连接好像是10w？（可能单机性能测试可以到百万，线上一般跑到几十万）</p>
<p>关于QQ使用UDP的问题<br />
个人不清楚QQ使用UPD的初衷，但猜测是因为10多年前C10K问题没有得到很好解决，一台服务器支撑不了1W个TCP连接 ，腾讯的同时在线量高，没办法，只有用UDP了 ，但UDP又不可靠，故只能在UDP上实现TCP的超时／重传／确认等机制</p>
<p><strong>五、收尾</strong><br />
关于QQ使用UDP协议，在讨论的过程中，有同学提出了一个非常好的问题“无线环境下，UDP更好，可以做到状态无关，而TCP不稳定，进出电梯就要断线，用户体验不好”。<br />
其实吧，<strong>“用户状态可以设计的与连接状态无关”</strong>，如果大家感兴趣，后续我可以撰文和大家聊一聊，传输层使用TCP，怎么做到在线状态与底层连接无关。</p>
<p>ps：文本只介绍了im协议选型，只是协议设计的上半部分，选型完之后，协议细节如何设计也没有展开讲，后续会撰文讨论《im协议设计细节（下）》。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/05/20/im-protocol-choose/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>webim如何保证消息的可靠投递</title>
		<link>http://www.habadog.com/2015/04/29/webim-msg-send-ack/</link>
		<comments>http://www.habadog.com/2015/04/29/webim-msg-send-ack/#comments</comments>
		<pubDate>Wed, 29 Apr 2015 15:52:33 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=699</guid>
		<description><![CDATA[webim如何保证消息的可靠投递<p class="read-more"><a href="http://www.habadog.com/2015/04/29/webim-msg-send-ack/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>《webim如何保证消息的可靠投递》</p>
<p>消息的可靠性，即消息的不丢失和不重复，是im系统中的一个难点。当初qq在技术上（当时叫oicq）因为以下两点原因才打败了icq：<br />
1）<span style="color: #ff0000;">qq的消息投递可靠</span>（消息不丢失，不重复）<br />
2）<span style="color: #ff0000;">qq的垃圾消息少</span>（它antispam做得好，这也是一个难点，但不是本文重点讨论的内容）<br />
今天，本文将用十分通俗的语言，来讲述webim系统中消息可靠性的问题。</p>
<p><strong>一、报文类型</strong><br />
im的客户端与服务器通过发送报文（也就是请求包）来完成消息的传递，报文分为三种，<strong>请求报文</strong>（request，后简称为为R），<strong>应答报文</strong>（acknowledge，后简称为A），<strong>通知报文</strong>（notify，后简称为N），这三种报文的解释如下：<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/04/1type.png"><img class="alignnone size-full wp-image-700" title="1type" src="http://www.habadog.com/wp-content/uploads/2015/04/1type.png" alt="" width="257" height="150" /></a><br />
R：客户端主动发送给服务器的报文<br />
A：服务器被动应答客户端的报文，一个A一定对应一个R<br />
N：服务器主动发送给客户端的报文</p>
<p><strong>二、普通消息投递流程</strong><br />
用户A给用户B发送一个“你好”，很容易想到，流程如下：<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/04/2send.png"><img class="alignnone size-full wp-image-701" title="2send" src="http://www.habadog.com/wp-content/uploads/2015/04/2send.png" alt="" width="270" height="130" /></a><br />
1）client-A向im-server发送一个消息请求包，即msg:R<br />
2）im-server在成功处理后，回复client-A一个消息响应包，即msg:A<br />
3）如果此时client-B在线，则im-server主动向client-B发送一个消息通知包，即msg:N（当然，如果client-B不在线，则消息会存储离线）</p>
<p><strong>三、上述消息投递流程出现的问题</strong><br />
从流程图中容易看到，<span style="color: #ff0000;">发送方client-A收到msg:A后，只能说明im-server成功接收到了消息，并不能说明client-B接收到了消息</span>。在若干场景下，可能出现msg:N包丢失，且发送方client-A完全不知道，例如：<br />
1）服务器崩溃，msg:N包未发出<br />
2）网络抖动，msg:N包被网络设备丢弃<br />
3）client-B崩溃，msg:N包未接收<br />
结论是悲观的：<span style="color: #ff0000;">接收方client-B是否有收到msg:N，发送方client-A完全不可控</span>，那怎么办呢？</p>
<p><strong>四、应用层确认+im消息可靠投递的六个报文</strong><br />
upd是一种不可靠的传输层协议，tcp是一种可靠的传输层协议，tcp是如何做到可靠的？答案是：超时、重传、确认。<br />
要想实现应用层的消息可靠投递，必须加入应用层的确认机制，即：要想让发送方client-A确保接收方client-B收到了消息，必须让接收方client-B给一个消息的确认，这个应用层的确认的流程，与消息的发送流程类似：<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/04/3ack.png"><img class="alignnone size-full wp-image-702" title="3ack" src="http://www.habadog.com/wp-content/uploads/2015/04/3ack.png" alt="" width="258" height="128" /></a><br />
4）client-B向im-server发送一个ack请求包，即ack:R<br />
5）im-server在成功处理后，回复client-B一个ack响应包，即ack:A<br />
6）则im-server主动向client-A发送一个ack通知包，即ack:N<br />
至此，发送“你好”的client-A，在收到了ack:N报文后，才能确认client-B真正接收到了“你好”。<br />
会发现，一条消息的发送，分别包含（上）（下）两个半场，即msg的R/A/N三个报文，ack的R/A/N三个报文，<span style="color: #ff0000;">一个应用层即时通讯消息的可靠投递，共涉及6个报文，这就是im系统中消息投递的最核心技术</span>（如果某个im系统不包含这6个报文，不要谈什么消息的可靠性）。</p>
<p><strong>五、可靠消息投递存在什么问题</strong><br />
期望六个报文完成消息的可靠投递，但实际情况下：<br />
1）msg:R，msg:A报文可能丢失，此时直接提示“发送失败”即可，问题不大<br />
2）msg:N，ack:R，ack:A，ack:N这四个报文都可能丢失（原因如第二章所述，可能是服务器奔溃、网络抖动、或者客户端奔溃），此时<span style="color: #ff0000;">client-A都收不到期待的ack:N报文，即client-A不能确认client-B是否收到“你好”</span>，那怎么办呢？</p>
<p><strong>六、消息的超时与重传</strong><br />
client-A发出了msg:R，收到了msg:A之后，在一个期待的时间内，如果没有收到ack:N，client-A会尝试将msg:R重发。可能client-A同时发出了很多消息，故client-A需要在本地维护一个<span style="color: #ff0000;">等待ack队列</span>，并配合timer超时机制，来记录哪些消息没有收到ack:N，以定时重发。<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/04/4waitack.png"><img class="alignnone size-full wp-image-703" title="4waitack" src="http://www.habadog.com/wp-content/uploads/2015/04/4waitack.png" alt="" width="131" height="87" /></a><br />
一旦收到了ack:N，说明client-B收到了“你好”消息，对应的消息将从“等待ack队列”中移除。</p>
<p><strong>七、消息的重传存在什么问题</strong><br />
第五章提到过，msg:N报文，ack:N报文都有可能丢失：<br />
1）msg:N报文丢失，说明client-B之前压根没有收到“你好”报文，超时与重传机制十分有效<br />
2）ack:N报文丢失，说明client-B之前已经收到了“你好”报文（只是client-A不知道而已），<span style="color: #ff0000;">超时与重传机制将导致client-B收到重复的消息</span>，那怎么办呢？<br />
启示：<br />
平时使用qq，或许大伙都有类似的体验，弹出一个对话框“<strong>因为网络原因，消息发送失败，是否要重发</strong>”，此时，<span style="color: #ff0000;">有可能是对方没有收到消息</span>（发送方网络不好，msg:N丢失），<span style="color: #ff0000;">也可能已经收到了消息</span>（接收方网络不好，反复重传后，ack:N依然丢失），出现这个提示时，大伙不妨和对端确认一下，看是哪种情况。</p>
<p><strong>八、消息的去重</strong><br />
解决方法也很简单，<span style="color: #ff0000;">由发送方client-A生成一个消息去重的msgid，保存在“等待ack队列”里，同一条消息使用相同的msgid来重传，供client-B去重</span>，而不影响用户体验。</p>
<p><strong>九、其他</strong><br />
1）上述设计理念，<span style="color: #ff0000;">由客户端重传，可以保证服务端无状态性</span>（架构设计基本准则）<br />
2）如果client-B不在线，im-server<span style="color: #ff0000;">保存了离线消息后，要伪造ack:N发送给client-A</span><br />
3）<span style="color: #ff0000;">离线消息的拉取，为了保证消息的可靠性，也需要有ack机制</span>，但由于拉取离线消息不存在N报文，故实际情况要简单的多，即先发送offline:R报文拉取消息，收到offline:A后，再发送offlineack:R删除离线消息</p>
<p><strong>十、总结</strong><br />
1）<span style="color: #ff0000;">im系统是通过超时、重传、确认、去重的机制来保证消息的可靠投递，不丢不重</span><br />
2）切记，<span style="color: #ff0000;">一个“你好”的发送，包含上半场msg:R/A/N与下半场ack:R/A/N的<strong>6个报文</strong></span></p>
<p>个人消息是一个1对1的ack，群消息就没有这么简单了，群消息存在一个扩散系数，如果大家感兴趣，下一次将和大家讨论im群消息的可靠投递。<br />
【完】</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/04/29/webim-msg-send-ack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>webim使用http长轮询如何保证消息的绝对实时性</title>
		<link>http://www.habadog.com/2015/04/28/webim-msg-ontime/</link>
		<comments>http://www.habadog.com/2015/04/28/webim-msg-ontime/#comments</comments>
		<pubDate>Tue, 28 Apr 2015 14:36:55 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=691</guid>
		<description><![CDATA[webim使用http长轮询如何保证消息的绝对实时性。<p class="read-more"><a href="http://www.habadog.com/2015/04/28/webim-msg-ontime/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>《webim使用http长轮询如何保证消息的绝对实时性》</p>
<p><strong>一、webim如何实现消息推送</strong><br />
webim通常有三种方式实现推送通道：<br />
1）WebSocket<br />
2）FlashSocket<br />
3）http轮询<br />
其中1）和2）是用Tcp长连接实现的，其消息的实时性很好理解，但这两种方案都存在一些局限性，不通用.<br />
3）才算是webim实现消息推送的“正统”方案，用http短连接轮询的方式实现“伪长连接”，既然是轮询，有朋友就对消息的实时性产生了质疑。本文就是要解答，webim使用http长轮询如何保证消息的绝对实时性。</p>
<p><strong>二、人们为什么会误解http长轮询不实时</strong><br />
<span style="color: #ff0000;"> 什么是轮询？</span>我擦，这个该怎么解释咧。<br />
举个栗子，在火车上想上洗手间，挤到洗手间旁，却发现洗手间有人，于是你只能回座位继续等。过了N分钟，又朝洗手间的方向挤过去，却发现洗手间还是有人，又只能回坐等。这么一而再，再而三的每隔N分钟去洗手间查看洗手间是否有蹲位，这就是轮询。</p>
<p><span style="color: #ff0000;">webim用轮询的方式拉取消息会存在什么问题？</span><br />
webim每隔N分钟，轮询调用 “获取消息”接口，有可能出现消息的延时，某一时刻刚拉取完消息，突然又产生了一条新消息，这条消息就必须等到N分钟之后，再次发起“获取消息”轮询时，才有机会获取到。</p>
<p><span style="color: #ff0000;">减小轮询时间间隔是否能解决消息延时的问题？</span><br />
减小轮询时间间隔的确可以缩短延时时间，但也不能保证消息绝对的实时，同时又会产生新的副作用，绝大部分的轮询调用，都没有消息返回，造成服务端极大的资源浪费。</p>
<p>很多人基于上述直觉，认为webim使用http长轮询的方式拉取消息，会导致消息有延时，其实，webim的http长轮询根本不是这么玩的。</p>
<p><strong>三、长轮询实际怎么玩</strong><br />
<span style="color: #ff0000;"> 消息连接</span><br />
webim和webserver之间建立一条http连接，专门用作消息通道，这条连接叫http消息连接【见下图】<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/04/1msg_connection.png"><img class="alignnone size-full wp-image-692" title="1msg_connection" src="http://www.habadog.com/wp-content/uploads/2015/04/1msg_connection.png" alt="" width="177" height="247" /></a></p>
<p><span style="color: #ff0000;">消息连接的4大特性</span><br />
1）没有消息到达的时候，这个http消息连接将被夯住，不返回，由于http是短连接，这个http消息连接最多被夯住90秒，就会被断开（这是浏览器或者webserver的行为）</p>
<p>2）在1）的情况下，如果http消息连接被断开，立马再发起一个http消息连接【见下图中的步骤1、2】<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/04/2connection_timeout.png"><img class="alignnone size-full wp-image-693" title="2connection_timeout" src="http://www.habadog.com/wp-content/uploads/2015/04/2connection_timeout.png" alt="" width="299" height="252" /></a></p>
<p>3）在1）和2）的配合下，浏览器与webserver之间将永远有一条消息连接在（极限情况下会出现情况4）），每次收到消息时，这个消息连接就能及时将消息带回浏览器页面，并且在返回后，会立马再发起一个http消息连接【见下图中的步骤1、2、3】<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/04/3msg_come.png"><img class="alignnone size-medium wp-image-694" title="3msg_come" src="http://www.habadog.com/wp-content/uploads/2015/04/3msg_come-300x240.png" alt="" width="300" height="240" /></a></p>
<p>4）如果消息到达时，上一个http消息连接正在返回，没有http消息连接可用（理论上http消息连接的返回是瞬时的，没有连接可用出现的概率极小），则将消息暂存入消息池中，下一个消息连接到达后（上一个消息连接返回后，根据2）和3）会立马返回新的消息连接，无等待时间），将消息带回，并又立刻返回生成新的消息连接【见下图中的步骤1、2、3、4、5、6、7】<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/04/4msg_come_without_connection.png"><img class="alignnone size-medium wp-image-695" title="4msg_come_without_connection" src="http://www.habadog.com/wp-content/uploads/2015/04/4msg_come_without_connection-300x174.png" alt="" width="300" height="174" /></a></p>
<p><span style="color: #ff0000;">上述1-4就能够保证一直有一条http消息连接在，以保证webim消息推送的绝对实时性</span>。</p>
<p><strong>四、结论</strong><br />
<span style="color: #ff0000;"> webim通过http长轮询可以保证消息的绝对实时性。这种实时性的保证不是通过增加轮询频率来保证的，而是通过夯住http消息连接来保证的，在大部分时间没有实时消息的情况下，这个http消息连接对于webserver的请求压力是90秒1次，能够大大节省了web服务器资源。</span></p>
<p>下一章，笔者将讨论webim消息的可靠性（<span style="color: #ff0000;">如何做到webim消息不丢不重</span>）。<br />
【完】</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/04/28/webim-msg-ontime/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>秒杀系统架构优化思路</title>
		<link>http://www.habadog.com/2015/04/27/seckill/</link>
		<comments>http://www.habadog.com/2015/04/27/seckill/#comments</comments>
		<pubDate>Mon, 27 Apr 2015 14:45:50 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=687</guid>
		<description><![CDATA[秒杀系统架构优化思路。<p class="read-more"><a href="http://www.habadog.com/2015/04/27/seckill/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>《秒杀系统架构优化思路》</p>
<p>上周参加Qcon，有个兄弟分享秒杀系统的优化，其观点有些赞同，大部分观点却并不同意，结合自己的经验，谈谈自己的一些看法。</p>
<p><strong>一、为什么难</strong><br />
秒杀系统难做的原因：库存只有一份，所有人会在集中的时间读和写这些数据。<br />
例如小米手机每周二的秒杀，可能手机只有1万部，但瞬时进入的流量可能是几百几千万。<br />
又例如12306抢票，亦与秒杀类似，瞬时流量更甚。</p>
<p><strong>二、常见架构</strong><br />
<a href="http://www.habadog.com/wp-content/uploads/2015/04/4layer.png"><img class="alignnone size-full wp-image-688" title="4layer" src="http://www.habadog.com/wp-content/uploads/2015/04/4layer.png" alt="" width="97" height="176" /></a><br />
流量到了亿级别，常见站点架构如上：<br />
1）浏览器端，最上层，会执行到一些JS代码<br />
2）站点层，这一层会访问后端数据，拼html页面返回给浏览器<br />
3）服务层，向上游屏蔽底层数据细节<br />
4）数据层，最终的库存是存在这里的，mysql是一个典型</p>
<p><strong>三、优化方向</strong><br />
1）将请求尽量拦截在系统上游：传统秒杀系统之所以挂，请求都压倒了后端数据层，数据读写锁冲突严重，并发高响应慢，几乎所有请求都超时，流量虽大，下单成功的有效流量甚小【一趟火车其实只有2000张票，200w个人来买，基本没有人能买成功，请求有效率为0】<br />
2）充分利用缓存：这是一个典型的读多些少的应用场景【一趟火车其实只有2000张票，200w个人来买，最多2000个人下单成功，其他人都是查询库存，写比例只有0.1%，读比例占99.9%】，非常适合使用缓存</p>
<p><strong>四、优化细节</strong><br />
<span style="color: #ff0000;"> 4.1）浏览器层请求拦截</span><br />
点击了“查询”按钮之后，系统那个卡呀，进度条涨的慢呀，作为用户，我会不自觉的再去点击“查询”，继续点，继续点，点点点。。。有用么？平白无故的增加了系统负载（一个用户点5次，80%的请求是这么多出来的），怎么整？<br />
a）产品层面，用户点击“查询”或者“购票”后，按钮置灰，禁止用户重复提交请求<br />
b）JS层面，限制用户在x秒之内只能提交一次请求<br />
如此限流，80%流量已拦。</p>
<p><span style="color: #ff0000;">4.2）站点层请求拦截与页面缓存</span><br />
浏览器层的请求拦截，只能拦住小白用户（不过这是99%的用户哟），高端的程序员根本不吃这一套，写个for循环，直接调用你后端的http请求，怎么整？<br />
a）同一个uid，限制访问频度，做页面缓存，x秒内到达站点层的请求，均返回同一页面<br />
b）同一个item的查询，例如手机车次，做页面缓存，x秒内到达站点层的请求，均返回同一页面<br />
如此限流，又有99%的流量会被拦截在站点层</p>
<p><span style="color: #ff0000;">4.3）服务层请求拦截与数据缓存</span><br />
站点层的请求拦截，只能拦住普通程序员，高级黑客，假设他控制了10w台肉鸡（并且假设买票不需要实名认证），这下uid的限制不行了吧？怎么整？<br />
a）大哥，我是服务层，我清楚的知道小米只有1万部手机，我清楚的知道一列火车只有2000张车票，我透10w个请求去数据库有什么意义呢？对于写请求，做请求队列，每次只透有限的写请求去数据层，如果均成功再放下一批，如果库存不够则队列里的写请求全部返回“已售完”<br />
b）对于读请求，还要我说么？cache抗，不管是memcached还是redis，单机抗个每秒10w应该都是没什么问题的<br />
如此限流，只有非常少的写请求，和非常少的读缓存mis的请求会透到数据层去，又有99.9%的请求被拦住了</p>
<p><span style="color: #ff0000;">4.4）数据层闲庭信步</span><br />
到了数据这一层，几乎就没有什么请求了，单机也能扛得住，还是那句话，库存是有限的，小米的产能有限，透这么多请求来数据库没有意义。</p>
<p><strong>五、总结</strong><br />
没什么总结了，上文应该描述的非常清楚了，对于秒杀系统，再次重复下笔者的两个架构优化思路：<br />
1）尽量将请求拦截在系统上游<br />
2）读多写少的常用多使用缓存</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/04/27/seckill/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>“所罗门王结”启示：跳出禁锢看问题</title>
		<link>http://www.habadog.com/2015/03/03/jie/</link>
		<comments>http://www.habadog.com/2015/03/03/jie/#comments</comments>
		<pubDate>Tue, 03 Mar 2015 10:41:43 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=684</guid>
		<description><![CDATA[“所罗门王结”启示：跳出禁锢看问题。<p class="read-more"><a href="http://www.habadog.com/2015/03/03/jie/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><strong>“所罗门王结”启示：跳出禁锢看问题</strong></p>
<p><strong>“所罗门王结”是什么？</strong><br />
“所罗门王结”是难以解决的问题的代称。</p>
<p><strong>“所罗门王结”的来源？</strong><br />
公元前223年冬天，马其顿亚历山大大帝进兵亚西亚。当他到达亚西亚的弗尼吉亚城时，听说城里有个著名的预言：几百年前，弗尼吉亚的戈迪亚斯王在其牛车上系了一个复杂的绳结，并宣告谁能解开它，谁就会成为亚西亚王。自此以后，每年都有很多人来看戈迪亚斯打的结。各国的武士和王子都来试解这个结，可总是连绳头都找不到，他们甚至不知道从何入手。亚历山大对这个预言非常感兴趣，命人带他去看这个神秘之结。<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/03/jie.png"><img src="http://www.habadog.com/wp-content/uploads/2015/03/jie-300x196.png" alt="" title="jie" width="300" height="196" class="alignnone size-medium wp-image-685" /></a><br />
亚历山大仔西观察着这个结，许久许久，始终连绳头都没找着，亚历山大不得不佩服戈迪亚斯王。这时，他突然想到：“为什么不用自己的行动规则来解开这个绳结呢？”于是，亚历山大拔出剑来，对准绳结，狠狠的一剑把绳结劈成了两半，这个保留了数百载的难解之结，就这样轻易地被解开了。亚历山大不墨守成规，用最简单的思维，最直接的办法，找准目标，先行动起来，不仅解开了数百载的绳结，也注定了他必然成为亚西亚王。</p>
<p><strong>“所罗门王结”的启示？</strong><br />
1）遇到问题不能盲动，观察清楚才能一击必中；<br />
2）目标就是目标，手段就是手段，手段从来都是为目标服务，不要陷在手段的泥潭里而失去了目标，只有目标明确才能找到最有效的手段；<br />
3）有时越复杂的问题，解决的方法越简单；<br />
4） 当问题千头万绪时，无从着手时，连根拔起不失为明智之举。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/03/03/jie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>抢红包统计学（技术贴，知道为啥自己抢不到了吧）</title>
		<link>http://www.habadog.com/2015/02/28/weixin-red-bag/</link>
		<comments>http://www.habadog.com/2015/02/28/weixin-red-bag/#comments</comments>
		<pubDate>Sat, 28 Feb 2015 09:20:02 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=676</guid>
		<description><![CDATA[抢红包统计学（技术贴，知道为啥自己抢不到了吧）<p class="read-more"><a href="http://www.habadog.com/2015/02/28/weixin-red-bag/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><strong>抢红包统计学（技术贴，知道为啥自己抢不到了吧）</strong></p>
<p>转自“统计之都”：<a href="http://cos.name/2015/02/lucky-money/">http://cos.name/2015/02/lucky-money/</a></p>
<p>原文作者：Yixuan</p>
<p><strong>一、引言</strong><br />
过年前微信群里面流行起来一种“红包接力”的玩法，大概的规则是：<span style="color: #ff0000;">群里面先由一人发一个红包，然后大家开始抢，其中“手气最佳”的那个人继续发新一轮的红包，之后不断往复循环。</span><br />
这时候大家或许就会问了，一直这么玩下去会有什么结果呢？是“闷声赚大钱”了，还是“错过几个亿”了？是最终实现“共同富裕”了，还是变成“寡头垄断”了？要解答这些问题，就得先了解一些统计学的知识，然后模拟一些随机实验，得到的结果或许会让你大跌眼镜呢。</p>
<p><strong>二、红包初级模型：“切面条法”</strong><br />
微信的红包是一个个抢的，所以很容易给人以这样的印象：红包一堆钱摆在那里，第一个人闭眼抓一把，第二个人再抓一把，等等。但是倘若果真如此，后来的人总体而言就要吃亏。这样既不公平，也不满足现实中的观察。<br />
让我们先考虑最符合直觉的模型，<strong>“切面条法”</strong>：<span style="color: #ff0000;">假如你有一根面条要随机分成5根，怎么分？闭上眼睛剁4刀就行了。换成数学语言，就是在一条线段上随机扔4个点，分成5段。</span><br />
现在你要把红包分成5份，好办，拿出你刚才剁的面条，每一根面条有多长，对应的红包就塞多少钱。<br />
以下就是切面条法模拟分红包的一个实例，总金额为1元，分成5个：<br />
0.02669467， 0.248426309，0.23745777，0.35864430，0.12877695<br />
这贫富差距也太大了吧？如果红包总金额是100，那么领得最多的人可以得到35.86元，而最少的只有2.67元。第一名得到三分之一多的钱，最后一名不到三十分之一？其实这完全不极端。对于这种分法，我们可以数学上证明，当1块钱（或者长度为1的面条）分成n份儿的时候：<br />
1）最大值的期望为 1/n*(1/n+1/(n-1)+1/(n-2)+…+1)，<br />
2）而最小值的期望为 1/n^2。<br />
这真是朱门酒肉臭，路有冻死骨啊。虽然这恐怕和很多人的印象相符，但毕竟也太悬殊了，能不能增加一个调节杆，让红包间的差异稍微小一点呢？</p>
<p><strong>三、红包进阶模型：“狄利克雷分布”</strong><br />
回顾一下刚才的切面条模型要点：<br />
<span style="color: #ff0000;"> 1）一次可以生成n个随机数，且总和为1</span>，这样每个数乘以红包总金额就是每个人分得的钱；<br />
<span style="color: #ff0000;"> 2）每个随机数的期望应该均等，即n分之一</span>，这是为了保证大家抢红包机会平等；<br />
现在我们为它增加一个第三条：<br />
<span style="color: #ff0000;"> 3）有一个参数可以用来调节红包的“公平”程度</span>。比如100元的红包发给10个人，如果每人都是10元左右，我们认为这种分配更公平些；如果最少的才0.8元，最多的有20元，显然就有失公允了（不幸的是作者好几次碰到这种情况）。<br />
在众多的随机变量分布中，有一个“狄利克雷分布”非常适合上面列出的这些情况。狄利克雷分布本身有n个参数，但为了满足条件2，我们可以只用一个参数 α 来决定它的具体形式。α 越大，每人分得的金额比例就越倾向于平均，反之则波动性越大。我们开始提出的切面条分法，恰恰就是当α=1的时候，狄利克雷分布的最简单状态。<br />
刚才切面条的结果，也就是α=1时的狄利克雷分布生成的随机数<br />
0.02669467，0.248426309，0.23745777，0.35864430，0.12877695<br />
而下面是α=10时的一组随机数<br />
0.2459250，0.2722147，0.1717301，0.1398133，0.1703169<br />
可以看出，当α=1时，金额分配的变动性非常大，而在α=10的情形下，金额的分配就平均多了。</p>
<p><strong>四、模拟“红包接力”玩法</strong><br />
有了上述假想的红包分配机制，我们就可以来模拟红包接力的游戏。首先假设我们有一个50人的群，每人初始手头上的可用金额为50元，每次红包的总金额是20元，发放给10个人，其中抢得最大红包金额的人将发出下一轮的红包。如果某人发完红包后余额变成了负值，就不能再继续抢红包，因为他/她已经发不起下轮红包了，但允许现在其余额为负。<br />
我们设定 α=2，并让红包接力100次，最后的模拟结果如下：有两位朋友不幸破产了，而最后资产最多的有92.20元，几乎翻了一倍。<br />
一个很明显的事实是，破产的玩家都是因为“中头奖”中得太多了，导致入不敷出。相反，最终收得92.20元的这位玩家属于“闷声发大财”。经统计，他获得第一名0次，第二名3次，第三名2次，第四名2次，第五名4次，等等。<br />
当然，概率面前人人平等，没有谁能预知自己抽中红包后会是最大的还是最小的，所以从对称性的角度考虑，个人选择的结果是完全随机的。但是，从整个群的角度来看，<span style="color: #ff0000;">有一个指标却在悄悄发生变化，那就是这个群的“贫富差距”。</span></p>
<p><strong>五、平均还是独大？基尼系数来判断</strong><br />
我们注意到，在游戏最开始的时候，大家的资金都是一样的50元，而在100次接力之后，几家欢喜几家愁，贫富差距被拉大了。于是我们有两个很自然的问题：<br />
<span style="color: #ff0000;"> 1）如何量化这种贫富差距？<br />
2）随着游戏的进程，贫富差距会有怎样的变化？</span><br />
对于第一个问题，<span style="color: #ff0000;">贫富差距的量化，我们可以借用经济学中的一个概念来予以回答，那就是所谓的“基尼系数”（Gini Coefficient）</span>。<strong>基尼系数通常被用来衡量一个国家居民收入的公平性，其取值在0到1之间，越大表示贫富差距越大，即少部分的人掌握了这个经济体大部分的收入。</strong>基尼系数的计算公式本文不展开讨论，对于之前的模拟游戏结果，计算出的基尼系数是0.2551。<br />
这个结果的绝对数值可能并没有太大的意义，因此我们在每一轮接力之后都计算出当时这个群的基尼系数，然后观察它的变化。结果如下：<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/02/lucky_money_5.png"><img class="alignnone size-medium wp-image-677" title="lucky_money_5" src="http://www.habadog.com/wp-content/uploads/2015/02/lucky_money_5-300x225.png" alt="" width="300" height="225" /></a><br />
在这里我们将接力次数延长到了500次。可以看出，<span style="color: #ff0000;">随着接力的进行，基尼系数的整体趋势是在不断变大的，意味着贫富差距会随着游戏的进行变得越来越大。</span>这其实很好理解：总是会有人因为拿了太多头奖而破产，这样财富会在越来越少的人中间进行分配，所以相应地贫富差距就拉大了。</p>
<p><strong>六、红包越“公平”，贫富差距越大</strong><br />
前面提到，在我们的模型中有一个参数 α 用来控制红包金额分配的“公平”程度（记得上文的结论么：α 越大，每人分得的金额比例就越倾向于平均）。下图展示了一组随机模拟实验的结果，其中我们模拟了20次红包接力的游戏，10次取 α=2， 另外10次取 α=20。每次游戏中，红包都接力了500次。<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/02/lucky_money_6.png"><img class="alignnone size-medium wp-image-678" title="lucky_money_6" src="http://www.habadog.com/wp-content/uploads/2015/02/lucky_money_6-300x225.png" alt="" width="300" height="225" /></a><br />
可以看出，红线和蓝线虽然有所重叠，但总体来看蓝线的取值要比红线更大，也就是说，<span style="color: #ff0000;">红包金额越“公平”，贫富差距反而会越大。</span></p>
<p>这个结论看起来可能有些反直觉，但其实也合情合理：如果红包的分配是绝对公平的，那么第一名得到的金额就将是2元，而下一轮又必须送出20元，所以 总共亏损18元；如果红包金额的波动性很大，就会有一部分人得到的金额小于2元，而第一名就会得到更多，也就更不容易破产。所以说，一个规则是否真的“公平”，不能只看其表面。</p>
<p><strong>七、更多有趣的玩法</strong><br />
除了前面提到的这个规则，我们还可以考虑一系列其他更有趣的玩法：<br />
玩法1：之前的规则记为1号；<br />
玩法2：第一个红包金额为20，第二个为21， 第三个为22，……到30后又递减至20，以此反复；<br />
玩法3：下一个红包的总金额是上一轮的最大金额加10；<br />
玩法4：下一个红包的总金额是上一轮最大金额的4倍，30封顶；<br />
玩法5：下一个红包的总金额是上一轮最大金额的5倍，30封顶；<br />
你一定奇怪玩法4和玩法5只差一个数，为什么要单独列出来。这里可以先剧透一下，原因是它们有着天壤之别。在给出结果之前，大家可以先根据自己的直觉给这几种玩法排个序，看最后哪种玩法的贫富差距最大（基尼系数），然后再和下面的结果对比一下，看看是否真的让你大跌眼镜了。</p>
<p>3</p>
<p>2</p>
<p>1<br />
下面是这五种玩法的对比图，全部取10个红包，α=2，初始20元。每种玩法我们模拟10次，也就是有10条基尼系数曲线。<br />
<a href="http://www.habadog.com/wp-content/uploads/2015/02/lucky_money_7.png"><img class="alignnone size-medium wp-image-679" title="lucky_money_7" src="http://www.habadog.com/wp-content/uploads/2015/02/lucky_money_7-300x225.png" alt="" width="300" height="225" /></a><br />
可以看出，<span style="color: #ff0000;">按照贫富差距排序，从大到小分别是：玩法5&gt;玩法2&gt;玩法1&gt;玩法3&gt;玩法4</span>。<br />
怎么样，你猜对了吗？<br />
我相信你一定被4和5之间的“天壤之别”惊呆了。为什么一个是最大，而另一个甚至是平坦的呢？<br />
其实，规则里面4和5这两个系数非常关键。<span style="color: #ff0000;">在α=2、分10个包的条件下，第一名平均能拿到红包金额的23%左右。4乘以23%得到0.92&lt;1，换言之红包会变得越来越小。</span><br />
比如第一轮最大如果是4，下一轮的总金额就是16；这一轮最大可能就变成了3，那么再下一轮总金额就变成了12……到了后来，总金额小于1分钱，就保持不变了（图中的水平线部分）。<br />
<span style="color: #ff0000;"> 相比之下，5乘以23%得到115%，结果红包会变得越来越大</span>，而由于我们设定了30块钱封顶，会让每个红包稳定在30元附近，因此贫富差距就按照“正常”的趋势逐渐加大了。</p>
<p><strong>八、最后的话</strong><br />
正如开篇所言，这只是红包算法的一个模型，并不一定就是背后的真实算法。从经验和直觉上来看，这个模型（特别是在α较小时）对现实的模拟还算令人满意，不过严格的科学方法当然要做统计分析来验证这一模型是否符合现实了——鉴于验证繁琐，红包数据收集不易，而且本身就是个娱乐项目，此处就不再对此较真。<br />
最后提醒大家的是，红包主要还是在过年的时候图个喜庆，游戏有风险，抢包需谨慎。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/02/28/weixin-red-bag/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一幅图秒懂LoadAverage（负载）</title>
		<link>http://www.habadog.com/2015/02/27/what-is-load-average/</link>
		<comments>http://www.habadog.com/2015/02/27/what-is-load-average/#comments</comments>
		<pubDate>Fri, 27 Feb 2015 06:48:12 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=665</guid>
		<description><![CDATA[一幅图秒懂LoadAverage（负载）<p class="read-more"><a href="http://www.habadog.com/2015/02/27/what-is-load-average/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div id="_mcePaste"><strong>一幅图秒懂LoadAverage（负载）</strong></div>
<div><strong><br />
</strong></div>
<div><strong>一、什么是Load Average？</strong></div>
<div id="_mcePaste">系统负载（System Load）是系统CPU繁忙程度的度量，即有多少进程在等待被CPU调度（进程等待队列的长度）。</div>
<div id="_mcePaste">平均负载（Load Average）是一段时间内系统的平均负载，这个一段时间一般取1分钟、5分钟、15分钟。</div>
<div><strong><br />
</strong></div>
<div id="_mcePaste"><strong>二、如何查看Load？</strong></div>
<div id="_mcePaste">top命令，w命令，uptime等命令都可以查看系统负载：</div>
<div id="_mcePaste">[shenjian@dev02 ~]$ uptime</div>
<div id="_mcePaste">13:53:39 up 130 days,  2:15,  1 user,  load average: 1.58, 2.58, 5.58</div>
<div id="_mcePaste">如上所示，dev02机器1分钟平均负载，5分钟平均负载，15分钟平均负载分别是1.58、2.58、5.58</div>
<div><strong><br />
</strong></div>
<div id="_mcePaste"><strong>三、Load的数值是什么含义？</strong></div>
<div id="_mcePaste">把CPU比喻成一条（单核）马路，进程任务比喻成马路上跑着的汽车，Load则表示马路的繁忙程度：</div>
<div id="_mcePaste"><span style="color: #ff0000;">Load小于1</span>：表示完全不堵车，汽车在马路上跑得游刃有余：</div>
<div id="_mcePaste"><a href="http://www.habadog.com/wp-content/uploads/2015/02/load0.5.png"><img class="alignnone size-full wp-image-666" title="load0.5" src="http://www.habadog.com/wp-content/uploads/2015/02/load0.5.png" alt="" width="189" height="45" /></a>[ Load&lt;1，单核]</div>
<div id="_mcePaste"><span style="color: #ff0000;">Load等于1</span>：马路已经没有额外的资源跑更多的汽车了：</div>
<div id="_mcePaste"><a href="http://www.habadog.com/wp-content/uploads/2015/02/load1.png"><img class="alignnone size-full wp-image-667" title="load1" src="http://www.habadog.com/wp-content/uploads/2015/02/load1.png" alt="" width="188" height="43" /></a>[Load==1，单核]</div>
<div id="_mcePaste"><span style="color: #ff0000;">Load大于1</span>：汽车都堵着等待进入马路：</div>
<div id="_mcePaste"><a href="http://www.habadog.com/wp-content/uploads/2015/02/load5.png"><img class="alignnone size-full wp-image-668" title="load5" src="http://www.habadog.com/wp-content/uploads/2015/02/load5.png" alt="" width="271" height="46" /></a>[Load&gt;1，单核]</div>
<div id="_mcePaste"><span style="color: #ff0000;">如果有两个CPU</span>，则表示有两条马路，此时即使Load大于1也不代表有汽车在等待：</div>
<div id="_mcePaste"><a href="http://www.habadog.com/wp-content/uploads/2015/02/load2.png"><img class="alignnone size-full wp-image-669" title="load2" src="http://www.habadog.com/wp-content/uploads/2015/02/load2.png" alt="" width="190" height="57" /></a>[Load==2，双核，没有等待]</div>
<div><strong><br />
</strong></div>
<div id="_mcePaste"><strong>四、什么样的Load值得警惕（单核）？</strong></div>
<div id="_mcePaste">Load &lt; 0.7时：系统很闲，马路上没什么车，要考虑多部署一些服务</div>
<div id="_mcePaste">0.7 &lt; Load &lt; 1时：系统状态不错，马路可以轻松应对</div>
<div id="_mcePaste">Load == 1时：系统马上要处理不多来了，赶紧找一下原因</div>
<div id="_mcePaste">Load &gt; 5时：马路已经非常繁忙了，进入马路的每辆汽车都要无法很快的运行</div>
<div><strong><br />
</strong></div>
<div id="_mcePaste"><strong>五、三个Load值要先看哪一个？</strong></div>
<div id="_mcePaste">结合具体情况具体分析：</div>
<div id="_mcePaste">1）1分钟Load&gt;5，5分钟Load&lt;1，15分钟Load&lt;1：短期内繁忙，中长期空闲，初步判断是一个“抖动”，或者是“拥塞前兆”</div>
<div id="_mcePaste">2）1分钟Load&gt;5，5分钟Load&gt;1，15分钟Load&lt;1：短期内繁忙，中期内紧张，很可能是一个“拥塞的开始”</div>
<div id="_mcePaste">3）1分钟Load&gt;5，5分钟Load&gt;5，15分钟Load&gt;5：短中长期都繁忙，系统“正在拥塞”</div>
<div id="_mcePaste">4）1分钟Load&lt;1，5分钟Load&gt;1，15分钟Load&gt;5：短期内空闲，中长期繁忙，不用紧张，系统“拥塞正在好转”</div>
<div><strong><br />
</strong></div>
<div id="_mcePaste"><strong>六、Load总结</strong></div>
<div id="_mcePaste"><a href="http://www.habadog.com/wp-content/uploads/2015/02/load0.5.png"><img class="alignnone size-full wp-image-666" title="load0.5" src="http://www.habadog.com/wp-content/uploads/2015/02/load0.5.png" alt="" width="189" height="45" /></a>[ Load&lt;1，单核]</div>
<div id="_mcePaste"><a href="http://www.habadog.com/wp-content/uploads/2015/02/load1.png"><img class="alignnone size-full wp-image-667" title="load1" src="http://www.habadog.com/wp-content/uploads/2015/02/load1.png" alt="" width="188" height="43" /></a>[Load==1，单核]</div>
<div id="_mcePaste"><a href="http://www.habadog.com/wp-content/uploads/2015/02/load5.png"><img class="alignnone size-full wp-image-668" title="load5" src="http://www.habadog.com/wp-content/uploads/2015/02/load5.png" alt="" width="271" height="46" /></a>[Load&gt;1，单核]</div>
<div id="_mcePaste"><a href="http://www.habadog.com/wp-content/uploads/2015/02/load2.png"><img class="alignnone size-full wp-image-669" title="load2" src="http://www.habadog.com/wp-content/uploads/2015/02/load2.png" alt="" width="190" height="57" /></a>[Load==2，双核]</div>
<div id="_mcePaste">希望上面一幅图对大家理解Load Average有帮助，赶快uptime一下，看一下自己系统的负载吧。</div>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/02/27/what-is-load-average/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>提高软技能（一）如何高效解决问题</title>
		<link>http://www.habadog.com/2015/02/25/1-how-to-solve-problem/</link>
		<comments>http://www.habadog.com/2015/02/25/1-how-to-solve-problem/#comments</comments>
		<pubDate>Wed, 25 Feb 2015 09:32:00 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>
		<category><![CDATA[软技能]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=660</guid>
		<description><![CDATA[提高软技能（一）如何高效解决问题<p class="read-more"><a href="http://www.habadog.com/2015/02/25/1-how-to-solve-problem/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>解决问题的能力，不仅是技术人需要的通用技能，任何纵横职场的人都需要它，甚至可以这么说，“<span style="color: #ff0000;">一个人解决问题的能力决定了ta对公司的价值</span>”。解决什么问题其实不重要，本文将从一系列有趣的小问题出发，讨论一个互联网技术人解决问题的通用思路。</p>
<p><strong>问题一</strong>：鸡兔共一笼，100只头，320只脚，问几只鸡，几只兔子？<br />
解决方法：设鸡为x，兔子为y，列方程x+y=100，2x+4y=320，解方程得x=40，y=60，即鸡40只，兔子60只。<br />
<strong>结论一</strong>：<span style="color: #ff0000;">利用已有的知识解决出现的问题是最常见的解决问题的方法。</span><br />
<strong>然而</strong>，每个人的知识都是有限的，已有的知识未必是最佳解决，以问题一为例，假如面临这个问题的人是一个小学生或者不懂二元一次方程的人，他会怎么办呢？他会对着动物们（鸡和兔子）发号施令：<br />
“所有动物抬起左脚” =&gt; 共100只动物，原来320只脚，抬起左脚后还剩220只脚。<br />
“所有动物抬起右脚” =&gt; 共100只动物，又抬起了一只脚，还剩120只脚。<br />
鸡只有2只脚，此时所有鸡都一屁股坐在地上了，于是剩下120只脚都是兔子的2只脚，于是总共120/2=60只兔子。<br />
这个方法可解释性很强，很容易懂，简称“左脚一抬，右脚一抬，屁股一坐”，鸡兔同笼问题解决之。</p>
<p><strong>问题二</strong>：鸡兔共一笼，100只头，220只脚，问几只鸡，几只兔子？<br />
解决方法：“左脚一抬，右脚一抬，屁股一坐”，220-100-100=20，20/2=10，即10只兔子，90只鸡<br />
<strong>结论二</strong>：<span style="color: #ff0000;">利用已有的经验能够快速解决问题。</span><br />
<strong>然而</strong>，知识和经验都有失效的时候，见问题三</p>
<p><strong>问题三</strong>：屈直的胸口有几颗痣<br />
我操，这是什么问题，完全不知道如何下手，初步猜测屈直是一个人或者动物，她胸口有几颗痣我怎么知道。遇到一个完全陌生的问题时，知识和经验完全起不了作用，这个时候怎么办？<br />
怎么办？<br />
怎么办？<br />
怎么办？<br />
各位解题达人，你们每天难道不会遇到完全陌生的问题么，你们是如何解决的呢？<br />
<strong>结论三</strong>：没错，“<span style="color: #ff0000;">内事不觉问老婆，外事不觉问百度</span>”。你遇到过的问题，别人说不定也遇到过，技术人最常见的解决问题的方式，不就是到百度里搜搜看么。<br />
于是乎，把“屈直的胸口有几颗痣”放到百度一一搜，哇擦咧，居然……，还有美图……，罢了罢了，非礼勿视，大家就不要去百度里搜了。<br />
<strong>然而</strong>，百度不是万能的，技术人经常遇到一些根本百度不出来的技术难题，这时候怎么办呢？</p>
<p><strong>问题四</strong>：今天第一次去58同城面试，在大厅等着，好紧张，好想上厕所，但不知道58的厕所在哪里，谁能帮帮我？<br />
我去，这都是什么问题，不是几颗痣就是找厕所。先想想1）知识2）经验，好像解决不了。百度搜一把“58同城的厕所”，结果都是“神奇的网站”，怎么办？<br />
怎么办？<br />
怎么办？<br />
怎么办？<br />
各位解题达人，你们每天难道不会遇到百度搞不定的问题么，你们是如何解决的呢？<br />
<strong>结论四</strong>：没错，<span style="color: #ff0000;">找个熟手问问</span>。58同城前台的MM好漂亮，问一下，咦，“E座一楼东头尽头”，问题解决。<br />
<strong>然而</strong>，有些百度搞不定的问题，周围也没有有经验的熟手，这下怎么办呢？</p>
<p><strong>问题五</strong>：碰到一个“百度也搞不定，问同事也搞不定”的问题，怎么办？<br />
怎么办？<br />
怎么办？<br />
怎么办？<br />
各位解题达人，遇到这类问题，你们是如何解决的呢？<br />
<strong>结论五</strong>：<span style="color: #ff0000;">自己刻苦钻研，是这类问题的唯一解决方案</span>。<br />
某个问题的“首杀”，能获得非常多的“经验值”，能get“新技能”，能让你成为某个小领域内的“熟手”，此时建议将问题的解决过程记录下来，让未来再次遇到这类问题的人通过百度来解决类似的问题，这，将是你对世界巨大的贡献。</p>
<p>最后稍微<strong>总结</strong>一下“高效解决问题”的方法：<br />
1）<span style="color: #ff0000;">运用自己的知识</span>解决问题（二元一次方程，记得么？）<br />
2）<span style="color: #ff0000;">运用自己的经验</span>解决问题（“左脚一抬，右脚一抬，屁股一坐”，记得么？）<br />
3）<span style="color: #ff0000;">巧用搜索引擎</span>解决问题（“屈直的胸口有几颗痣”，千万别去百度搜，太黄太暴力）<br />
4）<span style="color: #ff0000;">询问周围的熟手</span>以解决问题（58同城的厕所在哪里，问前台的漂亮MM吧）<br />
5）<span style="color: #ff0000;">刻苦钻研，成为熟手，记录问题解决过程并分享</span>（这是你对世界巨大的贡献）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/02/25/1-how-to-solve-problem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>程序员提高工作效率的15个技巧【Facebook】</title>
		<link>http://www.habadog.com/2015/02/13/more-productivity/</link>
		<comments>http://www.habadog.com/2015/02/13/more-productivity/#comments</comments>
		<pubDate>Fri, 13 Feb 2015 08:03:30 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[架构师]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=657</guid>
		<description><![CDATA[程序员提高工作效率的15个技巧【Facebook】<p class="read-more"><a href="http://www.habadog.com/2015/02/13/more-productivity/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>程序员提高工作效率的15个技巧【Facebook】</p>
<p>1，Days always fill up. Only plan for 4-5 hours of real work per day.<br />
其实每天只有4-5个小时能专心编码，充分利用这些时间。</p>
<p>2，Work more when you&#8217;re in the zone. Relax when you&#8217;re not.<br />
在状态的时候多干一些，不在状态时可以就去做个大保健。<br />
It&#8217;s normal to have days where you just can&#8217;t work and days where you&#8217;ll work 12 hours straight.<br />
编码在状态，连续几天加班是很正常的哟。</p>
<p>3，Stop multi-tasking. It merely kills your focus.<br />
CPU可以并行，人却不能，同时干几件事只能分散你的注意力，程序员务必单核。</p>
<p>4，Set up a work routine and stick to it. Your body will adapt.<br />
良好的编码习惯，你的身体亦会配合你的工作，记得要持之以恒。</p>
<p>5，We&#8217;re always more focused and productive with limited time.<br />
给自己的工作设定时间节点，这样会让你更专心和高效。</p>
<p>6，Start with short tasks to get the ball rolling.<br />
把系统分解，从小的工作做起。</p>
<p>7，Doing is better than perfect.<br />
先实现，再优化。做系统时先别整太多“万一&#8230;”，先把功能完成去应付PM吧。</p>
<p>8，More work hours doesn&#8217;t mean more prouctivity.<br />
加班并不是万能的，提高效率才是正道。</p>
<p>9，A single meeting can blow a whole afternoon.<br />
少开会。</p>
<p>10，Keep the same context throughout the day.<br />
专心干一件事，少切换上下文。沟通，设计，编码，测试等切换只会降低效率。</p>
<p>11，Only ever work on the thing that will have the biggest impact.<br />
划分事情的紧急优先 程度，并把最重要的完成（往往是线上bug）。</p>
<p>12，If something can be done 80% as well by someone else, delegate!<br />
某件事别人能至少做到八成，就授权给他吧！</p>
<p>13，Yesterday&#8217;s home runs don&#8217;t win today&#8217;s games.<br />
别扯过去的辉煌，做好手头的工作。</p>
<p>14，Always take notes.<br />
多记。</p>
<p>15，Take breaks. Sometimes.<br />
过年了，就别再背电脑回家。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/02/13/more-productivity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>【转】微信，是怎么过来的（2010-2015）</title>
		<link>http://www.habadog.com/2015/02/06/where-does-weixin-come-from/</link>
		<comments>http://www.habadog.com/2015/02/06/where-does-weixin-come-from/#comments</comments>
		<pubDate>Fri, 06 Feb 2015 07:27:29 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[产品经理]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=653</guid>
		<description><![CDATA[微信，是怎么过来的（2010-2015）。<p class="read-more"><a href="http://www.habadog.com/2015/02/06/where-does-weixin-come-from/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>微信，是怎么过来的（2010-2015）</p>
<p>作者：啃饼（kenbintrys）</p>
<p><strong>第一章 微信-创世纪</strong></p>
<p>微信的成功，让我相信：没有什么是不可能的。</p>
<p>2010年后，广研的发展到了一个瓶颈期，邮箱的布局已经相当完善，阅读空间也已到了强弩之末，那年最大的兴奋莫过于邮箱漂流瓶，一个简单的功能，却让邮箱的活跃用户翻了一番。</p>
<p>团队要发展，但巧妇难为无米之炊，一时之间不知道可以做什么了。于是那段时间发生了一个不可思议的事情，团队第一次对未来的发展方向做了大的规划，规划很宏大，计划做一个产品矩阵，包括邮箱、阅读、存储、记事本等，基本上把团队几年之间尝试过的产品重新做了梳理，每一个都将是一个独立的门户，从一个产品内的四个功能变成四个产品。</p>
<p>而10年的移动互联网正处在爆发的前夜，团队当然对这个发展趋势早有布局，邮箱早在08年就开始布局移动端产品，从最初的wapmail到后来的塞班版客户端，手机开发团队在10年也逐渐成熟起来。</p>
<p>当时确定的四大产品方向，除了邮箱外，其余三个都没有移动端，但都做了规划。由于手机开发团队规模的限制，如果我没记错的话，当时只启动了一个新产品的开发－－记事本，而且只是在ios平台试错。当时手机开发团队大部分人都是做塞班系统的开发，而ios和android作为新生的智能手机平台，它的重要性不言而喻。但那个时候ios和android平台作为新平台开发者相当少，开发团队只能临时拼凑，ios团队是从公司其他部门转岗过来的两个做windows客户端的同事，android是从塞班团队抽出来一个同事招了两个实习生开始干起来的。</p>
<p>2010年10月，一个产品的发布在互联网行业一石激起千层浪：kik messenger，这个应用有多火？它直接导致2011年成千上万的类kik应用被研发出来，这其中就包括后来大红大紫的微信、米聊、line和kacao。</p>
<p>kik messenger的火爆源于它的极致简单跨平台，它是为移动而生的应用，几乎不花任何力气就在很短的时间基于手机通讯录建立起自己的关系链，这对于很多web2.0时代的sns应用来说，是不可能做到的。很短时间内，它就以席卷一切的气势开始革命，首当其冲的是各国的运营商们，这个跨平台跨国界的手机通讯工具，它可以在不同的手机终端实现文本图片的消息沟通，秒杀短信和彩信体验，它的体验之极致，甚至让当时的手机巨头－－黑莓－－在自己的手机平台封杀它。</p>
<p>在kik甫一出现之际，小龙就预见它的火爆之势。小龙当时给pony发了一封邮件谈这个事情，并申请广研团队做一个类似的应用出来。而pony也极为赞许，并为这个应用起了一个名字－－微信。</p>
<p>当时做了一个多月的记事本立即停止，开始投入微信的开发中，很多代码直接复用过来，目标只有一个：快。</p>
<p>就这样，十个人的微信团队又一次在没有任何经验的情况启动了一个试错的项目，这次是三个平台（ios、android、塞班）同时进行。</p>
<p>而据说当时公司还有其他团队也在同时做类似的事情，且团队要强大的多，人力丰富有经验。但是，广研的小团队文化，为了取悦自己的巨大信念，使得广研微信团队能够在几个团队中脱颖而出，第一个完成了产品开发，只用了不到四个月时间，在2011年1月21号于ios平台首先发布了它的1.0版本。</p>
<p>在11年初的春节期间，当pony第一次使用微信并给出“体验很赞”的评价时，微信团队的信心达到了前所未有的高度。</p>
<p>但，此时，广研的其他同事却并不看好这个体验简单到有些简陋的手机应用。</p>
<p><strong>第二章 微信-冲出重围</strong></p>
<p>微信的成功，除了团队的努力，时机的把握也很重要。</p>
<p>11年2月，新年伊始。上一年年底的兴奋似乎已经逝去，微信在经过一个春节的讨论之后，尝鲜的人开始散去，只有很少的同事还在用着这个应用，因为那个时候有ios和android智能手机的同事还很少。微信并没有像kik那样在很短的时间积聚大量的用户。</p>
<p>当时大家普遍不看好这个简单的应用。理由大致是：功能太简单了；qq会杀死所有的类kik应用－－它只要做一个手机客户端。公司当时正在忙活着微博大战，虽然有几个团队同时在做类kik应用，但公司内对这些应用的关注并不高。</p>
<p>但是公司的高层对这个应用还是寄予重望的，开年第二天，tony亲自过来南方通信大厦给微信团队打气。而且，我们也能明显感觉到小龙已经把注意力完全转移到这款手机应用上面。</p>
<p>2月底，harvey突然找到我，直接了当的问我：要不要过去微信做客户端？然后又解释说：过去微信团队只是暂时的，如果产品做不成，还是要回到阅读空间团队继续做下去。</p>
<p>当时我很纠结，在机器学习和数据挖掘上刚刚找到感觉，放弃它很是不舍。harvey让我考虑后再答复他。</p>
<p>我没有想太久，那天下午就答复了harvey：我去。</p>
<p>2011年3月1号，正式加入微信团队，成为ios客户端的第三个开发工程师，进小黑屋。</p>
<p>当时ios开发团队的andy给了我两本书，《objc基础教程》和《ios3.0开发技术大全》，让我在一周内看完第二周参加开发。</p>
<p>虽然从来没做过客户端开发，但是我一直觉得客户端开发没什么难度，况且我钻研计算机学科最难的课题－－机器学习和数据挖掘－－有一段时间了，普通的开发工作对我来说真是小菜一碟的事情，harvey当时也对我说：客户端开发只要上网找找资料学习一下，和同事讨论一下就可以解决大部分问题了。</p>
<p>确实没错。</p>
<p>我两天就把两本书翻了一遍，接下来的几天开始阅读代码，andy的代码还是比较容易读懂的，我在一个本子上画了两天流程图基本搞清楚了底层的大部分逻辑。在第一周的最后一天，我写了一个ios的“hello，world”。</p>
<p>第二周开始，从一个小需求开始，一点点堆积objc代码。一周下来，也是相当的纯熟了。于是接下来就参与了一个后来颇为重要的功能的开发－－群功能。</p>
<p>在3月份，接连发了两个版本，但是用户数据依然不见起色。</p>
<p>很快，我们在4月初又发了第四个版本，这个版本微信的四个tab位置被确定下来，最初的四个tab分别是：微信、通讯录、找朋友和设置。其中，找朋友这个tab可以看出当时微信的急迫，在这里，系统通过通讯录联系人、qq好友、qq邮箱联系人甚至企业域名邮箱联系人等多种关系链给你推荐好友，以期在很短的时间内能够积聚到用户。</p>
<p>但，用户数据依然不见起色。</p>
<p>另外一款应用的火爆引起了我们的注意：talkbox。这个发语音短消息的应用有着与kik类似的逻辑，但语音无疑是最大的亮点。类似的功能qq很早就做过，但一直不温不火，但是当它被放到手机上之后，瞬间捕获了大量的用户。</p>
<p>另外一方面，智能手机在这个时候开始高速普及，尤其是iphone4的发布，以革命之势席卷了整个手机市场。</p>
<p>小龙判断：智能手机和pc是完全不同的，基于智能手机平台的功能和pc上也是完全不同的。</p>
<p>也是从那个时候开始，团队就一直在挖掘手机平台的各种可能，不断尝试利用手机天然的能力做出极致简单且自然的功能。</p>
<p>很快，我们决定要做语音。问题来了，团队没有做过多媒体的经验，语音需要的编解码能力如果等着公司相关部门支持，怕是一个月也未必搞得定。当时我自告奋勇要求去搞语音引擎，虽然有信心，但内心很虚，一方面从来没有接触过语音编解码，另一方面，小龙和harvey判断用户对流量很敏感，我们要做到比talkbox更小的流量（三分之一的流量）但却要一样的品质。</p>
<p>两天后，我发邮件给小龙：搞定了。那是我在广研做过的最有成就感的事情，估计那个时候小龙内心一定默念：呐尼！但这绝不是最后一次。类似的事情很快又一次发生在2.5版本的视频功能上，同样的要求（whatsapp四分之一的流量）编解码只用了四天时间，那次我通宵了两晚，并且在旅游的时候还在写代码，一时之间成为团队笑谈。</p>
<p>其实我只是把开源项目做了适配，在ios上跑了起来，内里逻辑并没有太花时间去理解，我知道，项目的速度很重要，先完成再理解。后来很多的项目都是在这样的情况下完成的。</p>
<p>经过一个月的努力，微信2.0语音版终于在5月初发布了（这是正式第一版本，之前的版本都加了beta）。当我们看到用户数据一柱擎天的时候，很久以来压抑在团队头上的石头开始粉碎。</p>
<p>接下来的发展，我们一直在追赶当时另外一个很火爆的类kik应用－－米聊。我们当时从米聊的账号分配算法可以估计到他们的用户量，然后与自己的用户量做对比。但其实，我感觉大家并不担心米聊，以我们的产品研发速度和公司的用户基数，超越米聊是时间问题，大家真正担心的，是同门的另一个应用－－QQ。</p>
<p>但，作为一个处在生存期的应用，必须一个假想敌来超越（这也算是广研做产品的一个潜规则吧），那就米聊吧。</p>
<p>当时用户对微信、米聊甚至talkbox，感觉是差不多的，大家都在谈论着这三个应用谁抄袭谁，后来米聊做了涂鸦功能，他们的同事在知乎发表文章，说静等微信抄袭。</p>
<p>微信给的答复是8月初的2.5版本，除了那个我通宵两夜的视频功能外，那个版本最大的惊喜莫过于附近的人。可以这么说，语音版奠定了微信的基础，但真正让外界感受到微信强大的，是附近这个功能。</p>
<p>当附近的人发布的时候，相信很多人有这样的惊叹：微信原来有这么多人在用啊！</p>
<p>是的，我们很快甩开了所有竞争对手。</p>
<p>当国庆节那天我们发布摇一摇的时候，微信的地位已经是似乎无法撼动了。</p>
<p>但是，我们的担心还在，那个内心的幽灵一直挥之不去，团队依然崩的很紧不敢松懈。</p>
<p>本章结束。</p>
<p>另外多说一句：微信的“弹性工作制”也是从那个时候开始的，以前广研的作息最晚不过10点，从微信2.0之后，通宵会经常出现。</p>
<p><strong>第三章 微信-平台化</strong></p>
<p>朋友圈和公众号是伟大的发明。</p>
<p>文字、图片、语音和群是微信作为通讯工具的基础，附近的人和摇一摇则进一步拓展了通讯的范围，向社交演进。到这个时候，微信已经是一个相当完备的移动通讯应用。</p>
<p>朋友圈是必然的。</p>
<p>QQ邮箱作为pc端仅次于QQ即时通讯工具的第二大通讯工具，它向社交的演进是受限的，因为用户上网交流的主场景不在邮箱，所以QQ邮箱选择从阅读切入社交，它遇到的困难远大于qzone。</p>
<p>而微信是移动端上网聊天的主场景，用户在移动端的主要活动聚集地，它天然的适合做社交，所以，微信有朋友圈是必然的。</p>
<p>朋友圈的成功有两个基础。</p>
<p>其一是阅读空间在社交领域三年的浸淫，让团队对社交有了比较深入的理解。</p>
<p>其二是超强的团队执行力。</p>
<p>第一点在前面阅读空间的文章中已经说的比较多了。主要谈谈第二点，朋友圈的整个研发过程耗时4个月，投入的人力不超过十个，但却在这短短的4个月时间内，团队完成了完整的30多个版本的开发迭代，我们形象的把这个开发过程叫做回转开发流程，每天上午，开发团队通过邮件接收产品经理整理出的下一个版本功能点启动开发，傍晚的时候把功能交付给小龙和产品经理，他们在晚上就当前版本讨论分析，然后在下半夜给出新的想法甚至方向，产品经理在天刚亮的时候把想法细化为一个个功能点发邮件给开发。周而复始。</p>
<p>当团队决定要发布朋友圈的时候，我想大家已经到了极限了，因为那时候还有bug没有解决，小龙说：bug也是一种文化，就发了。</p>
<p>朋友圈发布前，小龙和harvey打了一个赌，他们赌三个月之后的朋友圈日发图量的规模，小龙认为可以达到1000万，harvey觉得是200万。这个问题的答案我就不说了，各位可以自己去猜。</p>
<p>朋友圈的体验，相信很多人已经再熟悉不过了。咋一看他和facebook没什么区别，都是一个消息timeline的体验，但是用过一段时间后，你会发现本质的不同。朋友圈延续了微信的双向好友关系，没有向二度关系扩散，把用户隐私保护作为设计的基础，你在微信中无论是聊天还是晒命，都是没有任何压力的。</p>
<p>当然，朋友圈的体验还有很多体现产品情怀的细节。但保护隐私我觉得是最key的设计点。之后，微信内其他的任何功能，双向好友关系是设计的底线，不能逾越。</p>
<p>那么，在微信内看到的都是好友的信息，怎样看到更多丰富的内容呢？这就回到了阅读这个命题。</p>
<p>这次给出的解决方案是－－公众号。</p>
<p>关于公众号的话题，我打算在之后谈及微信商业化的时候再详细展开，我觉得它是一个潘多拉盒子。</p>
<p>2012-2014年的移动互联网，朋友圈和公众号的影响力相信大家都看到了。在它们出现之前，微信是一个成功的产品，在它们出现之后，微信成为了一个平台，在公司的战略中，它真正成为了一个与qq并驾齐驱（甚至领先）的双引擎之一。</p>
<p>2011年，微信有语音、附近的人、摇一摇；2012年，微信有朋友圈和公众号；接下来呢？</p>
<p>商业化和国际化。</p>
<p>有幸参与了微信从一个成功的产品演进为一个平台的过程，更庆幸接下来的两年里全程参与了微信的商业化进程，这又是一次学习与探索的历程，这段时间接触的人和事，各种感受给了我极大的冲击。</p>
<p>这段时间比较忙，更新无法保证及时，也没有时间雕琢，写的比较粗糙。最后奉送一个小故事作为收尾吧。</p>
<p>朋友圈本来是打算在2012年春节前发布的，团队一直绷的很紧坚持到春节前两天，在那天发生了两件事情，第一件事情是两位核心开发同事因为一点小事吵了起来，整层楼都听到了他们的怒恐。第二件事情是当天晚上我们团队去给一个同事送行（请假回家过年），全部人吃饭到10点还没回来，老大们急坏了，以为我们罢工了。这两件事情，最后给我们带来两个好消息，其一是年前不用发布了。其二是年后经过更加密集的迭代，有了一个更完美的朋友圈。</p>
<p>就这样吧。</p>
<p><strong>第四章 微信-商业化</strong></p>
<p>微信的商业化布局在2012年底就已经付诸行动了。当时的讨论范围非常广泛，支付、卡券、微生活、微电商、游戏等等都经过很多的讨论，这个大讨论牵涉了公司内几乎所有的bg和部门。</p>
<p>讨论是发散的，但执行是聚焦的。</p>
<p>微信商业化是三层架构：最底层是微信的社交平台，它聚集了海量的用户，这是商业化的养分；第二层是开放公众平台，它连接所有的主体（服务和内容提供方），这是商业化的土壤；第三层是业务，包括游戏、支付业务、广告、O2O、电商、企业、硬件等，这是商业化的收成。</p>
<p>微信商业化从启动以来的这两年，在这个框架下逐步展开。</p>
<p>这个框架是非常清晰明了的，逻辑也比较简单，并无特别。但是与其他大的平台相比，执行起来却差别很大，我觉得百度强于技术、阿里强于商业、QQ强于运营，而微信强于产品，这就必然导致几大平台走出不同的商业化道路。</p>
<p>在微信的商业化决策中，一直还是以产品需求为导向的。小龙和团队讨论任何的商业化项目，主题一直是围绕着用户的需求展开的，战略、战术、竞争等等不会成为焦点。</p>
<p>问题来了。</p>
<p>商业是喧嚣的，不去吆喝怎么做生意呢？但是微信是用户的家园，是不能容忍喧嚣，尤其是，微信一直坚守为用户构建一个舒适的环境，没有干扰、没有隐私暴露、轻松可信赖。要在维护这个环境的前提下做商业化，难度是很高的。在C与B的博弈中，微信是倾斜于C的。</p>
<p>小龙在设计微信的过程中，提炼了很多的准则。除了上篇文章提到的不可逾越双向好友关系之外，有另外一个准则最能解释微信的各种商业化设计。</p>
<p>微信内的信息是和用户相关的，不是系统推送的。</p>
<p>这个准则延伸出去，有很多的结论。比如，不要做过度的活动推广，不要诱导分享，不要诱导关注，信息流要清晰，信息流突出好友等等。</p>
<p>这条准备保证了：微信是用户的，微信不是商家的，微信也不是微信团队的。用户打开微信，期待看到的是自己关注的信息，自己好友的消息，而不是系统推荐的不痛不痒的信息。</p>
<p>当然，这条准则不是强制性的，它是强制建议性。商业化是一个复杂的课题，有很多意想不到的事情。有一些重要的合作伙伴，他们提供关键的信息给微信用户，但需要微信给他们提供入口作为条件。微信在可控的前提下，提供了一些这样的入口，不过这些入口的收效却甚微。这就从另外一方面佐证了这个准则的正确，系统推荐的信息用户不待见。</p>
<p>但是，遵守这条准则执行起来很难很难。</p>
<p>其一，执行团队很难找到合适的B端一起参与项目开发。用户接收的信息流往往是需要B端角色一起参与，微信要求他们提供优质的内容，但是能够提供优质内容的B端很少，所以微信的B端运营规则显得很严，打压很厉害。</p>
<p>其二，微信商业化项目的设计很难。一般都会引入好友关系，会通过加强用户参与互动把功能做起来，但是这些功能无论怎样设计，都会太接近朋友圈，朋友圈在这里成了一个过不去的坎。团队在几个领域的项目中进行了几十次的迭代尝试，最终没有一个能够通过验收。</p>
<p>2014年，团队在电商、O2O、服务等领域做了很多的尝试，但是很少有项目能够达到满意的效果，真的是举步维艰。这一年，团队是在挫折中学习与探索。</p>
<p>不过，还是有一些成功的项目的。</p>
<p>游戏是第一个商业化项目，也是目前最成功的一个商业化项目。2013年的飞机大战打响了微信商业化的第一枪。</p>
<p>飞机大战这个小游戏多说一下，它和我的关系忒大了。</p>
<p>最初小龙只打算做一个坦克大战的动画作为5.0的启动页，不过那会我开小差在玩游戏引擎，顺便就做了一个飞机大战的demo。小龙看了之后觉得不错，让我们尝试把它做的更完整更有意思一些，于是我拉了一个小团队开始做这个事情，我们奋战了一个多星期，几乎每天都通宵的节奏做了四个不同的版本，美术、音效、玩法经过激烈的pk迅速换了一遍又一遍。我们甚至做了商业化的策划。</p>
<p>飞机大战的稳定性是很关键的，因为每一个用户启动微信都会先玩这个小游戏，如果出问题，所有用户就进不了微信了，当时我的领导甚至对我说，如果稳定性有问题，你可以卷铺盖走人了。</p>
<p>经过小伙伴们一个月的努力，最终飞机大战获得了不错的效果。那年回家，一路上听着不断的“求求求”的枪声，还是挺过瘾的。</p>
<p>上篇文章我提到过，公众号是一个潘多拉盒子。最初我觉得公众号是为了解决在微信上阅读的需求而设计的，它的订阅－推送模式说明了这一点。（我想，是不是小龙觉得团队太久没有阅读都变low了：）但是，公众号设计成一套消息系统，使得它拥有了无限的可能性，我又想到小龙很早之前提的统一通信的理想，公众号的设计我觉得是在完成这个理想。</p>
<p>从最初解决阅读的媒体订阅号，到后来连接一切的服务号，公众号给微信开了一个好大的口子。整个中国为这个小小的号沸腾了。但是团队一直以做优质平台为目标，两年多以来一直在非常谨慎的探索中为平台增加能力，节奏显得很慢，内外的质疑声越来越大，大家都不看好公众平台的商业化价值。</p>
<p>直到，团队在公众号的最下面开了一个口子，尝试做效果广告。这是一次成功的试验，效果超乎团队预期。优质的内容充分展示了它的商业价值，也更加坚定了团队做好优质的决心。微信广告团队一直没有以提升收入作为目标，团队通过不懈的学习与探索，坚实基础，努力把自己打造为最优质的效果广告平台，为用户提供有价值的信息。</p>
<p>微信商业化的故事一篇文章是写不完的。面向未来，各种挑战层出不穷，单纯的试错法也面临复杂问题的挑战，底层社交平台也面临发展的挑战，公众平台面临很多竞争对手对规则的挑战。后面的压力会越来越大。</p>
<p>但是，有两样东西还在：正确的方向和团队的激情。我相信，我们还是可以做的更好的。</p>
<p>完。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/02/06/where-does-weixin-come-from/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>互联网广告生态系统介绍</title>
		<link>http://www.habadog.com/2015/02/06/internet-ads-intro-2015/</link>
		<comments>http://www.habadog.com/2015/02/06/internet-ads-intro-2015/#comments</comments>
		<pubDate>Fri, 06 Feb 2015 06:53:52 +0000</pubDate>
		<dc:creator>habadog</dc:creator>
				<category><![CDATA[产品经理]]></category>
		<category><![CDATA[广告定价]]></category>

		<guid isPermaLink="false">http://www.habadog.com/?p=649</guid>
		<description><![CDATA[互联网广告生态系统介绍。<p class="read-more"><a href="http://www.habadog.com/2015/02/06/internet-ads-intro-2015/">继续阅读 &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><strong>互联网广告生态系统介绍</strong></p>
<p><strong>一、互联网广告生态系统</strong><br />
广告生态系统主要是三个主体的博弈：<span style="color: #ff0000;">广告主（advertiser），媒体平台（medium），受众（audience）</span>，即广告主希望通过媒体去影响受众，广告的本质功能是广告主借助了某种广泛受众的媒体的力量，完成较低成本的用户触达。广告是大部分互联网公司的主要收入源，例如百度90%以上的收入来自广告，从这个意义上讲，百度是一个不折不扣的互联网媒体公司。</p>
<p><strong>第一方：广告主</strong><br />
广告主是整个生态圈内广告需求的发起方，广告主最关心的问题是<span style="color: #ff0000;">“广告效果”</span><br />
<span style="color: #ff0000;"> 品牌广告</span>是最主要的传统广告，它最主要的目的是创造独特的品牌或产品形象，目的在于提升长期的离线转化率。例如：可口可乐的广告，我们很难判断可口可乐的广告，对于短期卖出了几瓶可口可乐有什么直接关联。<br />
品牌广告的核心指标：<br />
<span style="color: #ff0000;"> 触达率（reach）</span>，多少人看过<br />
<span style="color: #ff0000;"> 触达频率（frequency）</span>，用户多频繁的观看</p>
<p><span style="color: #ff0000;">效果广告</span>是互联网广告的重要形式，这类广告在短期内有明确的目的和明确的效果就，例如购买、注册。所以互联网广告最常见的收费方式就是按照效果付费。<br />
效果广告的核心指标：<br />
<span style="color: #ff0000;"> 点击（click）</span>，这类互联网广告可以按照点击付费，广告圈提到非常多的一个词是cpc，按照点击付费（cost per click）。<br />
<span style="color: #ff0000;"> 行为（action）</span>，也有按照行为付费的，即cpa（cost per action），例如：下载一份简历5角钱。</p>
<p><strong>第二方：媒体平台</strong><br />
媒体平台是整个生态圈内平台的架设方，它有很高的话语权，媒体平台最关心的问题是<span style="color: #ff0000;">“库存总收益”</span><br />
例如，对于百度来说，pv和uv是相对固定的，这些就是库存，有限的库存如何获得最大化的利润，这些是媒体最关心的问题。</p>
<p><strong>第三方：受众</strong><br />
受众是整个生态圈内广告的访问者，即普通用户。普通用户才不关心广告效果，平台收益什么的，他们甚至反感和排斥广告，他们最关注的是<span style="color: #ff0000;">“信息的质量”</span>，他们希望从媒体平台上获取高质量的信息。</p>
<p>可以看到，互联网广告其实是媒体平台对“商业收益”和“用户体验”的一个权衡和折衷，他们希望在对用户体验伤害尽可能小的情况下获取尽可能高的收益，这也是现在“内容广告”兴起的原因。</p>
<p><strong>另外一个群体：为广告主服务的公司</strong><br />
广告制作公司：广告主只知道要打广告，用什么样的创意来打广告，海报用“姚明”还是“易建联”，这些问题可以寻求专业的广告制作公司来解决。</p>
<p><strong>二、互联网广告效果评价指标</strong><br />
互联网广告效果主要这样一些评价方式：<br />
<strong> impression</strong>：广告在受众面前的展示次数<br />
<strong> UV</strong>（unique visitor）：广告被多少人浏览<br />
<strong> click</strong>：广告被点击了多少次<br />
<strong> ctr</strong>（click through rate），广告点击率，即点击次数click与展示次数impression的比值</p>
<p><strong>三、计算广告学中的核心问题</strong><br />
MAX(a1,a2,…,an)∑(i=1&#8230;n)ROI(ai,ui,ci)<br />
<span style="color: #ff0000;"> 计算广告学就是一个“最佳匹配”（best math）问题，在给定用户（user），给定上下文（context）的情况下，如何展示一组广告（ads），使得ROI最高。</span></p>
<p>一些常用的技术解决方案：<br />
1）<span style="color: #ff0000;">特征提取</span>，受众定向，把u和c打上标签<br />
2）<span style="color: #ff0000;">ctr预估</span>，对每一次展示都进行优化<br />
3）<span style="color: #ff0000;">个性化推荐技术</span></p>
<p><strong>四、互联网广告分类</strong><br />
​文本广告（Textual Ads）类主要有两类：<br />
<span style="color: #ff0000;"> 搜索广告</span>（Search Ads）：通过搜索关键词展现的广告，如Google Adwords。值得一提的是，Google前20位关键词占了Adwords搜索广告总收入的70% 。<br />
<span style="color: #ff0000;"> 上下文广告</span>（Contextual Ads）：阅读内容时展示的与内容相关的广告，如Google Adsense。<br />
展示广告（Display Ads）类主要也有两类：<br />
<span style="color: #ff0000;"> 图片广告</span>，大量垃圾站的banner，左侧栏，右侧栏，中间过度栏充斥着这类“美女图片广告”。<br />
<span style="color: #ff0000;"> 视频广告</span>，大家一定对优酷和爱奇艺视频前的60秒视频恨之入骨，没办法，这是他们主要的收入来源。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.habadog.com/2015/02/06/internet-ads-intro-2015/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
