0 前言
容器(docker、k8s)的兴起是否意味着 Java 在跨服务器优势上不再明显?Java 虚拟机的存在是否会放大 Java 的运行性能问题?这颗在后端领域常青树的 Java 是否真的要走下坡路了?
1 真的为了跨平台吗?
实际上,在后端并没有太多的应用场景需要 Java 跨平台,大多数的 Java 后端服务都运行在 x64 Linux 环境上。真正需要关注跨平台的是客户端编程,但这个领域中 Java 的份额相对较小,而且也不会经常用到 Docker。
Docker 和 Kubernetes(k8s)的兴起实际上更多是为了方便管理和部署,Docker 只是在 Linux 核心之上添加了一层薄薄的映射,它主要省去的是配置环境的时间,而不是减少代码在运行时跨平台的问题。Docker 并不是专门用来处理跨平台问题的工具,它更多是用来解决环境依赖的问题。
而 Kubernetes 则更侧重于集群资源管理,这对于所有支持微服务的语言都是有益的,当然也包括 Java。
2 脱离场景讨论语言都是耍流氓!
在高并发或大数据吞吐量的情况下,各种后端语言,包括 C/C++,都会遇到各种问题。但在大多数后端应用场景下,Java 是最成熟的解决方案,同时也遇到的问题(包括性能问题)相对较少。这可以很容易理解,经过长时间的实践,一条被走得多的路往往更平坦。虽然也有人会提到 C/C++,但在相同复杂度的逻辑下,C/C++ 编程对程序员的负担更重,就像攀登珠峰的道路,再多的人也难以将其变得平坦。
当然,Java 的成功也得益于高质量的 JVM 和 Java 程序员对常用框架和库的持续优化。Java 的内存模型和运行效率实际上是很高的。只是有一些“爱用”某些框架的 Java 程序员可能会遇到低效的情况,或者有些框架被滥用。另外,有时候问题并不在语言本身,而是在所处理的问题规模上,比如一个运行了几天的 Hadoop 作业,用 C++ 重写可能会引入更多问题并且运行更慢。此时,更应该考虑的是调整算法,而不是仅仅改变编程语言。因此,关于性能问题,实际上并不存在“锅”,即使存在也不能完全归咎于 Java。
Java 当然也面临了许多其他语言的竞争,特别是现在的后端更加强调多语言协作,微服务架构也允许在同一个分布式系统中使用多种编程语言。许多新兴的互联网公司在新项目中可能会全面或部分地采用 Golang 等来取代 Java。但我们无需过于片面地认为 Java 就此不行了,整个后端领域的发展趋势是在扩大,而不是缩小。例如,在新兴的大数据平台中,Java 仍然是最广泛采用的编程语言之一。
3 问题有问题吗?
问题本身是否正确就是一个问题,容器是基础设施,从理论上讲,基础设施应该是透明的,与编程语言无关。至于 Docker,它只是目前容器化的一个优秀实现或最成熟的解决方案之一。而 Kubernetes 正在逐渐与 Docker 解耦,未来 Kubernetes 将支持更多类型的容器。
4 JVM 内存占用太大?
事实上,实际测试结果表明,使用 GraalVM 对 Web 程序进行静态编译后,启动只需要 30MB 内存,而同样的代码在 JVM 下需要 300MB 内存。虽然 Golang 没有实际测试数据,但估计其内存占用量也在 30MB 左右。
换句话说,启动一个实例时的额外内存消耗为 270MB。然而,这只是实例启动的一次性开销,后续的内存占用主要取决于业务数据。无论使用哪种编程语言,后续内存占用基本相当。举例来说,如果你的服务有 100 个实例,使用 Golang 编写服务可能会节省 100 x 270 = 27000 MB 的内存。以阿里云为例,1GB 内存一年大约需要 300 元,27 x 300 = 8100 元。一年的节省成本仅相当于不到一个高级程序员半个月的工资。从经济角度来看,节省的收益相对较低,因此内存占用并不是阻碍 Java 的理由。