Python程序员需要一个更好的dir()!
所以就写了一个:pdir2
支持搜索特定名字:
顺带认识了好多以前不知道的 __xxx__
所以就写了一个:pdir2
支持搜索特定名字:
顺带认识了好多以前不知道的 __xxx__
我注意到一个现象很久了:凡是英文网站,用户总是倾向于用真名。Quora 是个最极端的例子,比如随便点开一个 Quora Digest,可以看到全是实名+真实头像:
还有 SO:
相对地,中文世界里不论是什么网站,实名用户比例都很低。我认为出现这种区别的原因有以下几点:
1. 语言的限制
众所周知互联网诞生于西方世界,在很长一段时间内靠 ASCII,最多 Latin-1 就足够承载网上的所有内容了。举个最简单的例子,直到今天你的邮箱名仍然不能是 张三@gmail.com
,而域名现在虽然支持中文也基本没人用。对首次接触互联网的人而言,沿用自己的名字是最自然的选择,但对早期的中文用户而言这却不是一件容易的事。现在虽然没几个不支持中文的网站了,但我们至少都还有一个全 ascii 的邮箱名。
另一方面,英语已经成为了实质上的世界通用语,中国人只能去适应。很多人在刚开始学英语的时候会给自己起一个英文名,然后就出现在外企喊 Vivian 同时有五个人答应的情况。其实这完全没必要,说白了也是民族自卑情结的体现,随着中国地位提升,越来越多的人干脆不起英文名了。但即使不用英文名,为了能正常和老外进行文字交流,也必须把名字用拼音表示,因为他们打不出汉字而我们可以打出英文。结果就是,中国人习惯了在网络上使用一套不同于生活中的姓名系统,而这个名字是 zhangsan 还是 NB 已经不重要了。
2. 早期应用不同,email vs 论坛(bbs)
这是我认为最重要的原因,似乎少见有人提到。
Email 的诞生及使用早于普遍意义上的互联网。Email 在八十年代就被西方普遍使用了,而 Internet 到九十年代中期才普及。如果你是 John Smith,现在你要注册一个 email 账号和客户通信,你会用什么?多半是 johnsmith, jsmith 这类的——既然以熟人通信为目的,那么名字可识别、好记是第一位的,这样收件人看一眼就知道是谁发的,因为 email 本来就是 mail 的延续。
然而这只是西方世界情况。如果排除掉科研机构这种八十年代就开始使用 email 的用户,真正意义上成规模的中国网民接触的第一件事物并不是 email,而是 bbs 和门户网站。门户网站最多看看新闻,bbs 才是网民交流的地方。bbs 作为新生事物在现实生活中是没有的,所以其中的社交关系也是全新的而非现实的延续。既然可以重新选择,你会顶着一个父母决定的傻乎乎的名字去聊天撩妹么?不会。于是诞生了一些在今天看来十分土气,但在当时看来却极为时髦的网名:比如著名的 『轻舞飞扬』。而当时的各种文学作品里,也特别喜欢把这种网名和真实姓名带来的差异放大,比如网上看似玉树临风激扬文字的『轻舞飞扬』现实里却是个抠脚大汉(我胡扯的……)。所以,中文用户自打学会上网起,就习惯了给自己取一个网名。
写到这里我才猛然意识到,英文里根本就没有『网名』这个词!只有 username。
3. 西方人更注重个人品牌的构建
如果你观察一些知乎上的真成功人士,他们中很大一部分都是实名的。而打酱油点赞的吃瓜群众中,实名比例则低得夸张。这说明什么?一方面是真成功人士意识到了实名回答对于个人品牌构建的重要性,另一方面是他们能够输出足够的内容来建立个人品牌,而吃瓜群众不能,所以也不是很在乎。
虽然只是猜测,但我感觉西方国家的人更在意这一点。随着中国意识到这点的人增多,相信实名用户也会逐渐多起来。其实,构建个人品牌也未必一定要实名。比如 binux 大佬在演讲中都是直接介绍自己是 binux,至今我也不知道他的本名,但这并没有什么影响。比起是否实名,下面三个因素更加关键:
ID 既可以是实名,也可以是网名。只要满足上述三点,一般来讲就不会有传播上的阻碍。
4. 特殊国情
美国有棱镜,然而要不是登哥冒死叛逃我们永远也不会知道。中国,大家都懂的是吧,谁也不想没事被请喝茶,而且被人肉也是很麻烦的。
之前知乎有个反绿人士在现实生活中被威胁,退出知乎了。事情闹得很大,搞得人人自危。实验室师兄写论文做微博用户身份挖掘,每次做 presentation 必提“染香”和“秦火火”,然后我就知道不管你实不实名,其实都很危险。更不要提“寻衅滋事”这个罪名了,懂的人都懂。
隐私是个很蛋疼的事,想享受技术的福利,就不得不放弃一部分隐私。所以很多 Geek 扎堆于 Telegram,期待加密能让自己更安全。然而微信总是要用的,除非你完全断绝三次元社交。不过至少有一点可以做到,那就是不要把微信绑定手机号和银行卡。我现在很后悔绑了手机号,唯一的坚持就是不绑银行卡,虽然我知道没什么用,因为手机号是实名的。相对国外网站,国内网站和 App 极其喜欢窥探用户隐私,收集用户信息。之前我想买优酷的会员,结果发现这破网站居然要用手机号才能注册,去NM的,谁爱用谁用吧。然而国内网站能这么干,背后的逻辑是这么干有好处,既能收集数据又不会造成用户反感。所以说,有什么样的用户就有什么样的产品,都是被这帮完全不注重隐私的用户惯得。
总结
以上诸多因素造成的结果就是,中国网民习惯了不把网络 username 和真实姓名关联。文章的题目叫做《为什么英文互联网世界里实名比例如此之高?》,实际上高和低是相对的,文章说明了为什么中国网民实名比例低,其实也就解释了为什么英语世界实名比例高。或者说,实名是自然的,不实名才需要原因。
这一篇主要讲 Flow Control,包含 5.2 节和 6.9 节的内容。
Flow control 这个词相信大家并不陌生,因为 TCP 中也有。不过 HTTP/1.1 并未包含 flow control 机制,依靠 TCP 的 flow control 也工作得很好,为什么 HTTP/2 需要添加呢?原因很明显,因为 HTTP/2 引入了 stream 和 multiplexing,想让众多 stream 协同工作,就需要一种控制机制。
这一节讲了 flow control 的基本原则。挑几条解释一下:
Flow control is specific to a connection. Both types of flow control are between the endpoints of a single hop and not over the entire end-to-end path.
意思是说,flow control 的作用范围并不是从浏览器到所访问网站的“end-to-end path”,而是针对每个 connection 的。比如说,server 前面有一个 front-end proxy 如 Nginx,这时就会有两个 connection,browser <—> Nginx, Nginx <—> server。flow control 分别作用于两个 connection。详情参考这里。
H2 的 flow-control 是 receiver 控制 sender 发送速度的一种机制。这里的 receiver 和 sender 指的不是 client 和 server,而是谁当前在发送 frame,谁就是 sender,peer 则是 receiver。
flow-control 无法禁用。
RFC 只规定 WINDOW_UPDATE 的语义,而不规定具体的算法。不同的 HTTP/2 实现可以选择不同的 flow-control 策略。
HTTP/2 的 flow control 既可以作用于 stream,也可以作用于 connection。
下面具体讲一下 WINDOW_UPDATE。WINDOW_UPDATE 是一种 frame,payload 结构如下:
+-+-------------------------------------------------------------+
|R| Window Size Increment (31) |
+-+-------------------------------------------------------------+
Window Size Increment 是一个 31 位整数,取值范围 1~2^31-1。在说明其含义之前,还需要介绍另一个概念:flow-control window。
Flow-control window 被用来限制 sender 的发送速度。
用一张图来说明原理:sender 发送了两个 DATA frame,则 flow-control window 的大小就要减掉发送 DATA frame 的 payload 的大小。发送其它类型的 frame 不会减小窗口。不允许发送 payload 大小超过 window 的 DATA。
Sender 发送 DATA 给 receiver,receiver 接到之后必然需要通过某种方法通知 sender 来恢复 window,否则后续的 DATA 可能就发不过来了。怎么通知呢?正是通过 WINDOW_UPDATE。Receiver 接收到 DATA 之后,发送 WINDOW_UPDATE 给 sender,其中 Window Size Increment 的值代表 sender 应该把 window 增大多少。 注意这个值并不一定等于 DATA payload 大小,具体是多少取决于实现所用的算法。通过这种方式,receiver 就可以限制 sender 的发送速度了。Flow-control window 的大小实际上代表 receiver 处理接收到数据的速度快慢。
之前提到:HTTP/2 的 flow control 既可以作用于 stream,也可以作用于 connection。Connection 也有 flow-control window,如下图所示:
这里又涉及一个 RFC 中没讲清楚的问题:每个 stream/connection 到底维护几个 window?答案是每个 endpoint 各有一个,这两个 window 是不同且独立的。因为 stream 是双向的,理论上每个 endpoint 都可以作为 sender,所以两边都需要窗口来控制发送速度(在实现中,每个 endpoint 除了维护自己的 window,也会记录 peer window 的 size,就不展开讲了)。
Connection flow-control window 和 stream flow-control window 的关系可以总结为:一起减,分开加。“一起减”指的是任意 stream 发送 DATA,作为 sender 的 endpoint 的 connection 和 stream window 大小都要减少。“分开加”指的是 WINDOW_UPDATE 要么增大 stream 的 window,要么增大 connection 的 window:在 stream 0 上发送,增大 connection window,在非零 stream 上发送,增大对应 stream 的 window。
可以看到,HTTP/2 的 flow-contorl 和 TCP 的滑动窗口作用类似,但不建议用滑动窗口来类比,原因如下:
关于 flow control 还剩下一个重点没讲,那就是初始窗口大小。
Connection 和 stream 的初始 flow-control window 大小都是 65535,代表 65535 bytes。Connection 的初始窗口大小不能改变,但 stream 的可以,通过发送 SETTINGS frame,携带 SETTINGS_INITIAL_WINDOW_SIZE
,这个值即为新的 stream flow-control window 初始大小。
初始窗口大小的改变针对所有 stream 而非单个。对于非活跃 stream 而言,改变初始窗口大小对它们影响不大,只要之后真正开始在上面发数据时按新的大小生成窗口即可。
对于活跃 stream(open
和 half-closed
,参考笔记四),情况就比较复杂了。RFC 中规定:
When the value of SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST adjust the size of all stream flow-control windows that it maintains by the difference between the new value and the old value.
这就有可能造成窗口大小变为负数。举例如下:
1. 初始 window size = 65535
2. 在某个 stream 上发送了 60KB 的 DATA,更新 window size = 65536 - 60K
3. 这时,初始 window size 被设置为 16KB
4. 当前 window size
= 原来的 window size + 初始 window size 的变化值
= (65536 - 60K) + (16K - 65535)
= -44K
窗口大小为负数并不会造成错误,但会阻止 sender 发送 DATA。一旦出现这种情况,只有等待 WINDOW_UPDATE 增加窗口大小,才能继续发送 DATA。