2022-01-04 Go1.18概览
在2021年年底,Go
推出了1.18Beta
版本。由于正式版本没有完全敲定,普通开发人员没有必要研究到底层实现,但如果能先形成一个全局上的认知,能帮助我们领先一步。
关于1.18的核心改动,是 对泛型(Generics)的支持。Go语言的泛型语法比较简单,如下:
1 | type numeric interface { |
如果要在实际工程上落地,还有很多考量点,我这边重点提三点:
- 主流IDE的支持 - 包括Goland与VSCode,尽量帮助开发者能在编码时发现问题;
- 历史库的迁移与兼容 - 实现泛型后,许多主流库会有大量的冗余函数,如何提供迁移方案,值得我们去关注;
- 泛型的最佳工程实践 - 作为一种新特性,Go的泛型如何应用在工程中、尤其是复杂工程中,需要一定的实践摸索,并总结规律(可借鉴其余支持泛型的语言);
除了泛型,另外一个比较大的特性就是Fuzzy Testing
。
这个特性是为单元测试提供更全面的数据输入,这样就能覆盖更多的case,提前发现问题。关键词Fuzzy
支持的主要特性是将一个输入参数,从具体的值变成范围,如原先输入a=1
,现在支持a
输入范围为[-10,10]
。在跑单元测试时,大量的Fuzzy
肯定会带来一定的性能压力,这时可以引入一定的并发特性。
总体来说,Go1.18
对工程侧的影响更多地是提高代码的 简洁性。新特性的学习成本很低,我们不用过于急着引入,可以多花时间学习底层原理。
Go Blog - https://go.dev/blog/go1.18beta1
Medium - https://betterprogramming.pub/golang-1-18-what-you-need-to-know-a5701f7e14ab
2022-01-05 CNCF-概览
CNCF作为云原生的代表性组织,提供了大量开源的软件,以及配套的、开箱即用的解决方案。有很多朋友对CNCF和云原生的认识可能仍停留在新闻报道里。今天,我先带大家在整体上入个门,后续选择具有代表性的软件进行分析。
由于篇幅所限,我的分享只会提重点知识,帮大家建立这部分的知识框架,更详细的内容需要大家自行学习。
CNCF的概览可以参考这个全景图 - https://landscape.cncf.io/,更新迭代非常频繁。其中,最核心的为下面五块:
- App Definition and Development 应用定义与开发
- Database 数据库
- Streaming & Messaging 流处理和消息通信
- Application Definition & Image Build 应用定义与镜像构建
- Continuous Integration & Delivery 持续集成与交付
- Orchestration & Management 编排和管理
- Scheduling & Orchestration 调度与编排
- Coordination & Service Discovery 协调与服务发现
- Remote Procedure Call 远程过程调用
- Service Proxy 服务代理
- API Gateway API网关
- Service Mesh 服务网格
- RunTime 运行时
- Cloud Native Storage 云原生存储
- Container Runtime 容器运行时
- Cloud Native Network 云原生网络
- Provisioning 提供者
- Automation & Configuration 自动化与配置
- Container Registry 容器注册
- Security & Compliance 安全与合规
- Key Management 密钥管理
- Observability and Analysis 可观察性和分析
- Monitoring 监控
- Logging 日志
- Tracing 跟踪
- Chaos Engineering 混沌工程
其余还包括Kubernetes的平台提供商、Serverless、成员、认证的服务提供商等周边内容,并不在我们讨论的范围之内。但从基金会来看,它提供了一整套生态,非常有助于落地。
那么,如何认识这五块呢?其实Landscape提供了很好的图形效果,我们只要记住两点:
- 应用定义与开发、编排和管理、运行时、提供者 这四块是自上而下的核心链路,下层为上层提供能力支撑
- Observability and Analysis 是核心链路旁边的重要支撑
相信到这里,你对CNCF已经有了初步认识。
2022-01-06 《我做系统架构的一些原则》From 陈皓
今天,给大家推荐一篇来自左耳朵耗子-陈皓的文章。
- 关注于真正的收益而不是技术本身
- 以应用服务和 API 为视角,而不是以资源和技术为视角
- 选择最主流和成熟的技术
- 完备性会比性能更重要
- 制定并遵循服从标准、规范和最佳实践
- 重视架构扩展性和可运维性
- 对控制逻辑进行全面收口
- 不要迁就老旧系统的技术债务
- 不要依赖自己的经验,要依赖于数据和学习
- 千万要小心 X – Y 问题,要追问原始需求
- 激进胜于保守,创新与实用并不冲突
以上11点,理解会因人而异,我重点挑三个争议性比较大的聊聊,其余的内容建议大家阅读原文。
完备性会比性能更重要
借用书中的一句话:使用最科学严谨的技术模型为主,并以不严谨的模型作为补充,也就是先紧后松。
有不少开发者在实际工程中的实践往往相反:为了追求快速落地,会希望毕其功于一役,引入所谓的“一站式解决方案”(如例子中NoSQL),但实践下来引入大量的问题,让后人叫苦不迭。
关于这个问题,我个人有三个思考:
- 不断提高自己的基础能力。很多架构上的局限性,往往是设计者停留于自己的舒适区,不愿意往前一步。
- 分清主次、合理分工。 在设计时,我们要分清楚核心功能和非核心功能,懂得取舍,将功能交由合适的模块或软件。
- 功能的实现不是对应到单模块,而是整个系统的涌现。性能问题的解法不仅仅限于单个软件,而是有一整套生态,可以多去查一些大厂的分享。
不要迁就老旧系统的技术债务
为了缩小讨论范围,我对这里 技术债务 做一个收口:不仅仅是指有弊端的技术问题,更是需要投入时间精力等成本去维护。有技术债务,不代表就一定要去还,而需要一个契机 - 维护的成本 > 修复的收益。
举个例子,某个程序写得很烂,性能很差:
- 前期可以通过扩容快速解决,上线后业务收益很高,那就是 成本大于收益,不需要排到最高优先级去修复;
- 但随着业务收益稳定下来,增长只有个位数,但发现在机器上投入的成本很高,通过优化预计能缩容50%,可以让总收益提升20%,那这时还技术债务的优先级就很高了。
还技术债,技术能力只是一个基本,以下两点更为重要:
- 评估成本与收益,尽可能地做到有数据支撑,有助于决策者下决心还债;
- 用更长远、更广维度地看待技术债务问题,不要拆东墙补西墙。
激进胜于保守,创新与实用并不冲突
这个观点是很aggressive的,遇到这样的观念冲突时,决策者找不到客观标准去评估,就很难有二义性的定义:要么激进,要么保守;要么创新,要么实用。这种情况下,我遇到过的比较好的解法有两种:
- 决策者自身技术能力强,能掌控团队技术的大致走向。
- 决策者和执行者之间培养出足够的信任,适当评审与把控,放权实践。
第一种情况在实际工作场景中并不多见,尤其当团队规模很大时,就像CTO往往不是公司技术最强的那位。所以,我更倾向于大家多尝试第二种途径。
当然,我也遇到过很多效果不好的解法,比如说:决策者既然不清楚怎么做才好,那就找2个执行者进行battle,一个代表创新方,另一个代表保守方。也许在少数情况下,最后能帮助决策者找到正确的方向;但更多的实际场景中,会产生如下问题:
- 两个执行者碰撞越来越激烈,但始终谁也说服不了谁
- 决策者越听越迷茫,不知道该如何抉择
在我看来,这类决策者往往是偏管理,技术上的掌控力不足,导致在决策时没有足够的倾向性;同时,与执行者之间的信任也不足,就希望把决策这件事下移、尝试着走平衡之道。
我个人的想法是:先选择一个能力相对优秀的执行者,认真评估其方案,然后交由对方执行;最后哪怕失败了,也可以通过复盘改进,想想下次如何更好地决策,更好地把控方案;当然,如果你认为纯粹是执行者的问题,那就换个可信赖的人。
2022-01-07 CNCF-Kubernetes
今天,我们一起来看看CNCF中的最核心项目 - Kubernetes
。Kubernetes
相关内容非常庞大,我们依旧关注聚焦于核心能力。
Kubernetes
位于CNCF核心的 调度与编排 模块,也就是整个解决方案的基石。在CNCF上的介绍为:
Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications.
对这个定义,我们关注两个点:
automating deployment, scaling, and management
自动化的部署、扩缩容和管理,这是k8s核心能力;containerized applications
容器化应用,这是k8s操作的基本对象;
为了更好地介绍Kubernetes,我对官方首页描述中的关键特性再做一些更详细地说明:
Automated rollouts and rollbacks
自动化扩缩容和升级回滚。这个特性是k8s最核心的,也是大规模推广的根本原因。
看起来,这功能描述与CICD
流程差不多,但使用体验差距很大。在传统的模式下,我们执行的是一个具体的动作,比如扩1个机器、升级2个程序等;而在k8s里,使用者只要声明最终的预期状态,比如5台机器运行v1.0版本的程序,那么整个系统该扩容还是缩容、该升级还是回滚,都由k8s自行根据当前状态进行判断。
这个,就是云原生的一大特性:声明式API ,而不是传统上的命令式API。
声明式API不一定比命令式API好。在应用程序开发时,命令式API更容易理解。
Service discovery and load balancing
服务发现与负载均衡。这个功能很大程度上减少了分布式软件运行模式的复杂性。
服务发现,以前非常依赖zookeeper
/etcd
等这类注册中心,往往需要侵入到业务代码;而负载均衡,则很依赖nginx
这类软件,并在上面做复杂配置。
当然,k8s给出的只是通用解法,对一些具备很强业务属性的服务发现与负载均衡,仍需要程序自行实现。
Storage orchestration
存储编排。存储的编排是k8s重点演进的功能。
k8s抽象了存储概念,从传统的本地存储扩展为分布式云存储,对上层应用屏蔽了存储这块的复杂度。
Designed for extensibility
为扩展性而设计。
扩展性是k8s非常重视的点,无论是开放出容器、网络、存储等接口规范,还是像自定义资源(CRD)等插件的开放,都体现出了一种开放的精神,也是k8s如今能作为云原生标志性的软件的立足之本。
有一个点希望大家认识到:k8s的成功不是简单地因为开放性,更重要的是,它定义的这些开放性的规范与接口,都是Google
经过实践总结出来的经验,符合主流厂商的趋势与开发者的需求。
Github: https://github.com/Junedayday/code_reading
Blog: http://junes.tech/
Bilibili: https://space.bilibili.com/293775192
公众号: golangcoding