升级MacBook Pro M1 Pro啦

因为上海疫情原因,定制的21款MacBook Pro 16 inch足足等待了两个月才到手。

这是自己的第三台MacBook Pro,具有基本一样的功能和外观设计理念,尤其是那个电饭锅magsafe充电口。所不同的是,这是一台搭载苹果M1 Pro CPU的机器。机器到手后,前后断断续续花了半个月把应用、数据和环境都配置好了。简单记录一下自己的这次迁移记录。

系统迁移及兼容性

自己现在在用的是2015款MacBook Pro 15 inch. 考虑到M1架构与Intel架构的差异性,以及看了一些power user的反馈,这次迁移没有使用Time Machine。而是直接 one by one 配置安装配置的方式。最开始以为工作量会比较大,但实际迁移过程中发现,自己常用的应用也就那么几个。而自己最开始比较畏惧的环境配置,因为之前很早就做了云同步,所以也是比预期快很多的就完成了配置。

在M1上运行Intel架构的应用,会经过 Rosetta 2 转换,有大概20%的性能损失。在活动监视器上面,也可以通过 kind 查到到。目前常用的软件基本都能兼容,这块目前没有遇到什么问题。

开发环境

golang的环境可以一路next配置完,目前还没有发现任何兼容性问题,而且编译速度极快。

自己是重度 alfred 用户,从10年前开始切换到mac, 就购买了mega授权。但是切换到新机器后,发现很多workflow依赖的python都没法工作了(macOS 12.3以后移除了python)。恢复的话主要两步:1、自己下载安装python; 2、因为python路径发生了变化,还需要更新workflow到兼容m1的版本 或者 手动修改workflow中写错的路径。

java 8 环境,如果追求m1原生和性能,可以考虑 azul jdk,但是可能存在一些兼容性问题。主要是一些依赖的lib可能没有m1原生版本。因此,我的选择是同时安装了一个 oracle 版本备用。

使用感受

关于M1 Pro/Max的性能,我推荐极客湾的苹果M1 Pro/M1 Max评测. 这里聊一下自己作为一个典型的开发者的使用感受:

  • magsafe回归了,140w快充太赞了。magsafe充电口也是为什么我的上一台macbook一直坚守在2015款的重要原因。而140w的快充基本上稍微补点电就可以用半天,对于有时候动辄一天的会来说,基本没有了续航焦虑。
  • 整机功耗非常低,日常开发非常安静,风扇基本不转。从系统监控看,95%情况下,功耗在15w以下。不得不感慨苹果的精准刀法,这个功耗你用ipad原装20w充电头其实也能勉强用,但是就是会时而触发从电池借电。而根据我之前的经验,这会非常容易造成电池鼓包。因此,我现在随身携带的是一个 type-c PD的应急充电头是30w的,同时满足手机电脑充电,我推荐你也这样做。
  • 刘海摄像头还算能接受,基本不影响日常使用。这么大的挖孔当前只有一个1080p的摄像头肯定是战未来的,毕竟库克是库存管理大师。这也就意味着,这代的MacBook Pro模具应该会有相当长的一段时间。颇有点iPhone 12回滚iPhone 4的味道。
  • 指纹识别比较方便,在这个基本都标配的时代,只能说是中规中矩。
  • 键盘也随着magsafe的恢复,基本重新回到了2015款的手感。但是键程显然还是比2015款短,能有80%的舒适度吧。

新的笔记本到手半个月了,即使加上之前2个多月的等待,这段时间用来下来也是挺开心的。苹果在这个产品线上重新找到了当年 Pro 的那个味道,自己也很久没用到能让自己如此满意的电子产品。配上好鞍,重新出发!

温故而知新之 https proxy

周六昏昏欲睡的下午,顺手用 goproxy 写了个小工具。功能部分不到两个小时就搞定了,但是在处理 https proxy 部分,希望实现一个自定义feature时,调试了挺长时间。这大大打击了自诩可以手撕 https/tls 的自我信心😝。于是顺手看了一下这块的实现部分。

原理上,https proxy 的处理,都是以客户端 CONNECT 请求开始,后续的请求都是通过这次建立的连接进行 req-rsp 交互。一句话就能讲完,很简单,对吧?对也不对。正确的部分在于,原理的确就是这样的,但是如何使用这个连接,以及如何处理其中的安全问题让这一块有很多细节需要考虑。所谓魔鬼在细节中,这也是这块最有意思的地方。

以 goproxy 这块的实现为例,通过 CONNECT 建立连接以后,请求的的交互主要支持4种方式

  • ConnectAccept
  • ConnectHijack
  • ConnectHTTPMitm
  • ConnectMitm

ConnectAccept 是最基本的方式,只负责在 tcp 层建立远端和客户端的连接,这个连接具体怎么用,由客户端自己与远端交互决定。各个平台、各个客户端都支持这种方式,基本上没有兼容性问题。

ConnectHijack 与后面的两种方式本质上同一种类型,都可以认为是 Hijack 类型。这里涉及一个很重要的概念 Hijack, 这个在 golang 标准库中有非常准确详细的解释,搬运如下:

也就是相较于 ConnectAccept, proxy 不再是中间的小透明,而是可以接管连接,在中间实现一些自定义有意思的功能,这也是 MITM 的基石。所不同的是:

  • ConnectHijack 要求在业务自己在应用层实现这块逻辑,优点就是一切尽在掌握,可以实现很多有意思的功能。
  • ConnectHTTPMitm 是一种 https 降级为 http 的一种实现。也就是 https 通过这个 proxy 后,都被降级为 http 请求与远端交互。优点是可以 offload TLS 这层的加解密和签名开销,但是完全没有安全性。因此,这种一种古老的方式已经不被绝大部分 client 支持了。
  • ConnectMitm 则是一种经典实现,把客户端的 https 请求在中间做中转,然后还是以 https 的方式发送到远端。这是被client广泛支持的方式,因此兼容性较好。

需要说明的是:

  • Hijack 类型都依赖CA证书,这也是为什么你手机、电脑设备里面的CA根证书很重要,不要随便信任和安装来路不明证书的原因。
  • goproxy 在 ConnectHTTPMitmConnectMitm 的实现中,都会再次调用 filterRequest 执行 OnRequest 的 handler, 因此要在你的 request handler 中识别和处理这种经过转换的请求,否则会出现 loop 以及请求失败的情况。

从原理到实现,基本就拆解完了。其实也没有什么高深的部分,正如很多东西,不过是温故而知新,进一寸有一寸的欢喜。

闭关这一年

去年的这个时候,工作上进入阶段性闭关。近年这个时候,到了出关的时候。也是一种巧合。

一年时间,俯仰之间。在一年的中点,少了一点理所当然时间朋友的感觉,有得有失,冷暖自知。

在目标感与企图心之间,自己缺少了一些区别感。一年之后的现在回头,我想前者更多的是自己,而后者更多的别人。没有褒贬之分,而是要有区别感,这很重要。

不久前妞儿问我之前14年在毕业典礼上讲的十年之约还算数吗?我信誓旦旦的说,当然算数,但是却少了许多坚定。如同前端时间看到同窗好友的朋友圈,不禁疯狂点赞的同时,也感慨十年一剑的隐忍不易与静水流深。

我承认我至今依然非常迷恋宏大的叙事。但是,这种宏大叙事更多是传达别人或者历史的认知,而不是自己的认知。很多时候,当听众遇到良师,是一种幸运,当时会自然的陷入一种智力和体力的偷懒。下半年依然会密切关注身边的朋友,依然会用有限的资本积累感受时代和经济的温度,位置上希望自己能更上前一步,然后更向前一步。