路漫漫其修远兮,吾将上下而求索。
为什么学习go
我并不算一个极度喜新厌旧的人,AI时代 Python 的崛起并没有让我抛弃 java。但云原生时代 java 确实面临着巨大的挑战,所以才有了学习 go 语言的想法。 我想切身体会一下原生语言的与众不同,至于 java 能否在后续的语言之争中仍然保持”世界第一”的位置并不是我关心的重点。
java面临哪些挑战
这里推荐大家可以去读一读周志明老师的《云原生时代,Java 的危与机》文章。
我并不能更好的描述java将要面临哪些挑战,所以对上面文章中内容进行了摘录:
将程序连同它的运行环境一起封装到稳定的镜像里,现已是一种主流的应用程序分发方式。Docker 同样提出过“一次构建,到处运行”(Build Once, Run Anywhere)的口号,尽管它只能提供环境兼容性和有局限的平台无关性(指系统内核功能以上的 ABI 兼容),且完全不可能支撑架构中立性,所以将“一次构建,到处运行”与“一次编写,到处运行”对立起来并不严谨恰当,但是无可否认,今天 Java 技术“一次编译,到处运行”的优势,已经被容器大幅度地削弱,不再是大多数服务端开发者技术选型的主要考虑因素了。
如果仅仅是优势的削弱,并不足以成为 Java 的直接威胁,充其量只是一个潜在的不利因素,但更加迫在眉睫的风险来自于那些与技术潮流直接冲突的假设。譬如,Java 总体上是面向大规模、长时间的服务端应用而设计的,严(luō)谨(suō)的语法利于约束所有人写出较一致的代码;静态类型动态链接的语言结构,利于多人协作开发,让软件触及更大规模;即时编译器、性能制导优化、垃圾收集子系统等 Java 最具代表性的技术特征,都是为了便于长时间运行的程序能享受到硬件规模发展的红利。
另一方面,在微服务的背景下,提倡服务围绕业务能力而非技术来构建应用,不再追求实现上的一致,一个系统由不同语言,不同技术框架所实现的服务来组成是完全合理的;服务化拆分后,很可能单个微服务不再需要再面对数十、数百 GB 乃至 TB 的内存;有了高可用的服务集群,也无须追求单个服务要 7×24 小时不可间断地运行,它们随时可以中断和更新。
同时,微服务又对应用的容器化亲和性,譬如镜像体积、内存消耗、启动速度,以及达到最高性能的时间等方面提出了新的要求。这两年的网红概念 Serverless 也进一步增加这些因素的考虑权重,而这些却正好都是 Java 的弱项:哪怕再小的 Java 程序也要带着完整的虚拟机和标准类库,使得镜像拉取和容器创建效率降低,进而使整个容器生命周期拉长。基于 Java 虚拟机的执行机制,使得任何 Java 的程序都会有固定的基础内存开销,以及固定的启动时间,而且 Java 生态中广泛采用的依赖注入进一步将启动时间拉长,使得容器的冷启动时间很难缩短。
软件工业中已经出现过不止一起因 Java 这些弱点而导致失败的案例,如 JRuby 编写的Logstash,原本是同时承担部署在节点上的收集端(Shipper)和专门转换处理的服务端(Master)的职责,后来因为资源占用的原因,被Elstaic.co用 Golang 的Filebeat代替了 Shipper 部分的职能;又如 Scala 语言编写的边车代理Linkerd,作为服务网格概念的提出者,却最终被Envoy所取代,其主要弱点之一也是由于 Java 虚拟机的资源消耗所带来的劣势。
个人观点
Kubernetes 的应用在工作中已经随处可见,应用能够灵活地扩容缩容、不再畏惧单个服务的崩溃消亡、立足应用系统更高层来管理和编排各服务之间的版本、交互。 但 Kubernetes 难以做到精细化的服务治理,譬如熔断、流控、观测,等等;现国内主流的做法还是依托于 java 的生态体系来完成这些工作。
但新的架构体系已经悄然而生,基于 Kubernetes 之上构筑的服务网格(Service Mesh)可以说是目前最先进的架构风格。
服务网格架构体系:Kubernetes、Istio、Golang、gRPC