上次关于mongo objectID的激烈讨论后续:
ziyu:
这个话题过去一段时间了,但还是再补充一下我的观点吧:
我并不认为mongoose它这个函数的实现里混用12和24的长度判断的做法是好的(这里说清楚我并没有要和图图争)。很多coder会习惯让抽象出来的函数能够兼容更多的场景,所谓通用性。但作为校验函数而言,这样的做法反倒使得函数本身的功能界定模糊,从而导致没有看过源码的使用者无法正确利用它达成校验的目的。我非常支持像@Renzh 提的PR,将 24 字节表征的 hex string 单独作为一种校验对象,清晰准确,代表了上层业务逻辑的使用方式。
虽然说校验函数写得不好,但是还是希望大家能够理解 12 个字节长度这个点。ObjectId 的规范里并没有规定一定要使用 24 个字符的 hex string 。所以用来存储 12 个字节长度的 binary string,也需要能够理解它的合法性。
我当时有提到在 socket 场景下会存在用 string 来存储并处理 binary 的可能性。原因是我曾使用 nodejs 写过一些设备的通信协议栈,其中有种设备就是共享单车的蓝牙锁协议。它是通过 socket 发送一连串 16 进制的编码。在它的通信协议里,有个很重要的编码分割段:0x7E
标识一段结构体的起始位置 0x7F
标识它的结束位置,其中还有掺杂一些其他特殊定义的编码需要处理。相比于直接处理 Buffer 数组,将它直接 toString(‘latin1’)
后 (注意不是 toString(‘hex’)
,to hex 会使得字符串长度翻倍,同时你处理一些特殊编码时必须得连取 2 位字符,非常麻烦),可以利用正则表达式以及 replace 方法快速批处理很多转义事务。JS 本身并没有 binary 类型,但 string 是可以作为 binary string 来用的,并且在特定场景下是非常方便的。
👍8
Sean:
3 确实是我没想到的
zengxian:
学习了
xxj 杨学昊:
3这个有点巧妙
WangSiyuan:
3这点学习了
不知道3这种用法有没有可能:content里出现 0x7E
或者 0x7F
导致出现问题
之前做rtmp协议解析时,因为content长度写在header里,就只能从头读到尾...
ziyu:
思远提到的问题很好,协议里解决方式是有一个 转义编码的,具体忘了是啥,假设叫 0x7a 吧 你理解成\
就行了。
👍1
ziyu:
然后转义编码连续出现的时候解析为原本的字符,也就是 \ => \
Sean:
巧妙谈不上吧,我想了一下我要怎么按三的方式去处理逻辑。
我得先去查一下 0x7E
对应的ascii字符是什么,刚看了一下是 ~
所以你这里写了一个正则去匹配 /^~(.+)\$/ ,这里我只有一个问题,这真的是大家想要的解决方案么?
👀1
Sean:
我其实观点是,三点里提到的1,2我想整个后端是没有疑问的
Sean:
但你不应该去过度合理化一些不合理的行为
Sean:
我确实没想到js的binary处理这么不方便,但知道这个结论后我会觉得就多一个js可complain的点。
想想这个思路是否合理:
因为一个语言的限制,我们不得不使用一种非常hack的方式来处理代码。
这种hack的方式被不需要的地方沿用了,给一部分人造成了误解
因为这种方式的存在所以合理化这种方式。
Sean:
我个人觉得,“用string来表示一段非二进制的binary”这种行为,无论在哪门语言里都是不应该被推荐的
ziyu:
我并不认为这个方式是hack的,反倒是一种很自然的处理方式。
你指的沿用是指哪里?
这种处理的确是合理的。
看起来图图的观点是停留在类型是一种表示对吧。但要注意的是,这里确切的说不是用 string 来表示一段非二进制的binary,而是使用 String 对象来处理一段 binary 数据。这就是我说的类型只是抽象,我们真正处理的是底层数据。类型是告诉了编译器内存长度的分配方方式和使用方式,而这里我们不是用string做可读的表征,而是做了运算
Sean:
我觉得比较好的方式如:
不抽象,例如c/c++/rust 语言里的 u8[]
抽象,例如elixir里的BitString
WangSiyuan:
(二进制确实不方便... 但也能接受。多一些位运算之类的
ziyu提的那种办法在某些场景下是能大幅度让其方便的。
我接触到的协议一般都是按照三段的方式定义。
fixed header: 定长头,一般可以读到当前消息类型,以及变长头的长度。
变长header:按照 fixed header给的长度直接 .readBuffer(N) 。用于获取data区域的长度,如果更复杂的协议,可能data区域还有别的东西。
content: 一般根据变长header给的信息来读取。
因为是tcp协议,所以实际上就是一个stream流。中间读错了的话,要么是解包代码写错了,要么是对方发错了
我当时的写法就是
fixedHeader = await socket.read(FIX_HEADER_LENGTH)
{ messageType, len } = parseFixedHeader(fiexHeader)
header = await socket.read(len)
content = await socket.read(parseHeader(header).len)
里面用的 socket.read 方法是自己实现的,因为数据不见得能在一个packet里发完整。
至于如何读取 Header Buffer里的信息,就有各种办法了。
比如用string、或者一个字段一个字段的读,也可以像Python那样
https://docs.python.org/3/library/struct.html#examples
record = b'raymond \x32\x12\x08\x01\x08'
name, serialnum, school, gradelevel = unpack('<10sHHb', record)
Sean:
我的 “表示” 其实意思是 “代表“, represent。
我觉得不应该用string represent a slice of binary是有很严密的逻辑的:
string是包含语义的,其实我们处理上他的语义是字符数组(而非字节数组)
string包含很多处理string特有的方法,而这些方法对于binary未必适用
比如我们常用的 string#length 取的是字节长度么?
不是的,即使在node里 "我我".length === 2 而不是比如真实的6个字节。
下面的输出是什么?
"你好".slice(1)
你去遍历string的时候期待的到底是
for const char of string
还是
for const bit of string
Sean:
js在string的处理上其实很不好,反而“易于“你去用他处理binary了
Sean:
关于string的一些特点可以看看
https://mortoray.com/2013/11/27/the-string-type-is-broken/
Musing MortorayMusing Mortoray | mortoray
The string type is broken
My previous article, “We don’t need a string type“, caused a bit of stir. Though the feedback is mixed, there is a common theme of a string being a useful feature. After doing a bit more research I can determine only one thing: most current string types are broken!
Many of us believe our strings are capable of more than what they actually do. We rely on their functionality without actually checking that its valid. This can easily lead to programs which do not work correctly, particularly with respect to internationalization. In most cases it seems we would be better off without a string type.
Evaluate
I looked at how strings behave in a few basic situations. I’ll go over…
ziyu:
你对我的观点还是有些过度解读了。你说的这些点都是对的,JS的string的确存在很多的不足,我的视野里当然也是默认大家都知道这样的问题,比如对中文编码的长度。
ziyu:
关于如何理解 binary string 可以看这里:
https://developer.mozilla.org/en-US/docs/Web/API/DOMString/Binary
澄清一下最开始的回复里面:
1. .toString() toString('latin1')
2. 0x7E,0x7F
只是我记忆中的编码,由于时间久远,可能不够准确,但正则式里面是支持用 \xhh
的写法,不用写出 ascii 字符
MDN Web DocsMDN Web Docs
Binary strings
JavaScript strings are UTF-16 encoded strings. This means that each code unit requires two bytes of memory and is able to represent 65535 different code points. A subset of these strings is represented by UTF-16 strings containing only ASCII characters (i.e., characters whose code point does not exceed 127). For instance, the string "Hello world!" belongs to the ASCII subset, while the string "ÀÈÌÒÙ" does not. A binary string is a concept similar to the ASCII subset, but instead of limiting the range to 127, it allows code points until 255. Its purpose however is not to represent characters, but binary data. The size of the data so represented is twice as big as it would be in normal binary…
Sean:
是跑远了,反过来我发现我刚那段和你之前说的
“要理解抽象类型背后的本质“其实是一样的“正确的废话“。
我感觉是我们同样理解了“抽象类型背后的本质“后,我认为类型依然重要,你认为不那么重要。
回去一句一句对着回答的话
看起来图图的观点是停留在类型是一种表示对吧。但要注意的是,这里确切的说不是用 string 来表示一段非二进制的binary,而是使用 String 对象来处理一段 binary 数据。
不是,我想表达的是“代表“所以利用string来处理binary也是一样的。
类型是告诉了编译器内存长度的分配方式和使用方式,而这里我们不是用string做可读的表征,而是做了运算
我其实不理解后半句想表达的意思。
我上面那段话本质上是想举一些string不便处理binary的场景以证明用string代表binary的不合理性。当然我也注意到了你说的是:在特定的场景下使用string会特别的方便。
Sean:
你给我发的文章最后赫然写着
JavaScript typed arrays provide a mechanism for accessing raw binary data much more efficiently.
ziyu:
是的,但是不够用
ziyu:
它的优势是access,而我们还有其他上层运算,只能说是对它再进行一了层抽象,以二进制字符串的形式来处理
ziyu:
在那个场景下,数组类型这层抽象就是不够用的。需要再对它的类型进行抽象,就是二进制字符串了。我并不是认为类型不重要,而是认为在特定场景下用符合语言特性的特定类型,来处理特定事务,是合理且自然的。(很多「特定」限制了它的传播范围)
Sean:
是,这是js的问题,你因此使用string是不得已而为之或者取巧。
我的观点是,不要合理化这种迫不得已。
你看这篇文章的论点其实很清楚
js里没有设计binary string,
但因为web app的需求,过去不得不使用string来处理binary,但这“slow and error-prone”
因此才引入 typed arrays
ziyu:
如果规则上有更优的方式,那么谁还会迫不得已呢?
ziyu:
既然是规则下的,那么不是合理且自然的么?
Sean:
自然不是
Sean:
规则下可做的事情多了去了。。。我们不还是制定了更多规则避免做一些“不合理“的行为么 (edited)
Sean:
比如js规则里string,number,object随便传,自动转换,
如果这合理且自然为什么有type announcement,有ts,即使raw js的库里也写了各种type guard呢。
ziyu:
这句话倒也没错。确实是需要制定更多规则。但似乎还是在于对 binary string 的定义上认为它不合理。但在我看来,它只是不那么好,而不是不合理。
Sean:
fine,我觉得表达的清楚了,感觉后面应该就是各自坚持了,不如就到此为止?
ziyu:
对于使用 UINT32 类型来作为最多能支持 32 种开关 FLAG 的变量,来说,你会不会觉得不合理?
👍1
Sean:
挺好的问题。
让我想想
Sean:
唉我虽然能想到些用32位int来表示32flag的弊端,但总体来说又觉得合理(因为有很多位处理操作符)
Sean:
不过想这个的时候想提一下binary和bitstring在erlang里有完全独立的类型,可能是因为其是为电信通信设计的,从一开始就考虑了二进制处理的问题。
👍2
关于rust的讨论
xxj 杨学昊:
https://twitter.com/haoel/status/1308243550761443328?s=12
Hao ChenHao Chen @haoel
对我来说,Rust的那些所有权,lifetime,trait等都是很好的东西。然而,我想用Rust尝试写个链表,写个并发排序,代码写完后,各种编译不过,一次次挫败后,在某个地方找到个“秘籍”(是的,就是那种不为人知的秘籍),才顺利通关。后面发现需要N多这种秘籍才能把程序写下去……这才是Rust最大的问题……
TwitterTwitter | Sep 22nd
看来不止我一个拿rust做oj(
knight42:
rust 标准库里就有一个双向链表的实现 https://doc.rust-lang.org/std/collections/struct.LinkedList.html。并发也有 rayon https://docs.rs/rayon/1.4.0/rayon/ 能提供比较 high level 的 API
☕️2
knight42:
rust 想要在编译期保证 memory safe 自然是要做很多 trade-off 的,这也导致它跟很多主流语言的心智模型不太一样,所以不能参考以前的经验,可能这也是让人觉得需要很多“秘籍“的原因
一些文章分享
呆唯:
https://blog.cloudflare.com/moobot-vs-gatebot-cloudflare-automatically-blocks-botnet-ddos-attack-topping-at-654-gbps/
cloudflare如何检测ddos
zengxian:
在线上使用canary测试的时候,如果有bug即使很快发现自动回滚也会影响到少量用户,这篇文章介绍了“dark” canary这个方法,把线上流量复制到dark canary部署,丢弃response和对数据库的写操作,对用户无感知,不过dark canary部署的维护难度比较高 https://engineering.linkedin.com/blog/2020/production-testing-with-dark-canaries
☕️2👍1
zengxian:
https://mp.weixin.qq.com/s/Ovq8LPZJDdoe7L-9F9pstg
这篇介绍mongo4.4新特性挺完整的,很多很好的小feature和优化比如hidden index,降低了复制延迟,simultaneous indexing,resumable initial sync,time-based oplog
👍7
ziyu:
https://ai.googleblog.com/2020/09/advancing-nlp-with-efficient-projection.html
@wentao 刚提到的谷歌最新的NLP模型进展,是基于 PRADO 改进的 pQRNN 模型,效果媲美 BERT 但参数量更少。他们开源了 PRADO 模型。
👍5
WangSiyuan: 这篇论文解析蛮好的:
https://draveness.me/papers-maelstrom
本文要介绍的是 2018 年 OSDI 期刊中的论文 —— Maelstrom: Mitigating Datacenter-level Disasters by Draining Interdependent Traffic Safely and Efficiently1,Facebook 通过流量管理系统 Maelstrom 转发数据中心的流量,在出现一个或者多个数据中心故障时,减轻故障对业务造成的影响。
Renzh:
动画演示HyperLogLog http://content.research.neustar.biz/blog/hll.html
👍2
zengxian: newrelic刚发了篇文章介绍如何通过三个阶段搭建可观测性体系,有挺强的实践参考意义,里面也包含一些关于Observability的基本概念介绍
https://newrelic.com/resources/ebooks/3-phased-approach-to-observability
punky:
编辑器之争可能真的可以告一段落了
https://blog.robenkleene.com/2020/09/21/the-era-of-visual-studio-code/