共识算法、服务发现、流量治理、网络通信、监控预警共同构成了分布式的基石。
可以说如果是一个分布式的服务,都能找到上面的这些关键词的影子。
有些是应用系统自己做的。
有些是开源框架就帮你搞定了,你甚至不知道它们的存在。
但是上面的诸如流量治理和监控预警(可观察性)不是一个分布式服务一开始搭建时所必须的。
大多数情况下,刚刚搭建好的分布式都处于一个蛮荒状态。
随着时间推进和业务的发展,会慢慢补充上流量治理和监控预警。
也就是说如果想要分布式服务发展的监控可控,那么这些东西都是应该有的。
“基石”一词,像是手术刀一样精准。
来到了第四部分,不可变基础设施:
到这里我们就要从微服务走向云原生了。
在这一章,周佬以容器、编排系统和服务网格的发展为主线,介绍虚拟化容器与服务网格是如何模糊掉软件与硬件之间的界限,如何在基础设施与通讯层面上帮助微服务隐藏复杂性,解决原本只能由程序员通过软件编程来解决的分布式问题。
接下来的“技术方法论”属于微服务避坑指南,从目的、前提、边界、治理四个角度去阐述如何更好的使用微服务。
最后一部分是“随笔文章”:
其中的《云原生时代,Java 的危与机》和《程序员之路》这两篇文章,建议大家反复观看。
前者是技术方向的,后者是软技能方向的。
读完《Java 的危与机》,我感受到的是一场关于 Java 的自我革命已经悄然开始了。
Java 并不是一个优秀的开发语言,这一点我是非常承认且确定的。但是 Java 有一个庞大的用户群体和异常丰富的生态,这是它的护城河。所以短时间内还倒不下来。
但是大风起于青萍之末。风雨欲来,而包括我在内的很多人都浑然不知。
在文章里面,周佬有这样的一段话:
Java 支持提前编译最大的困难在于它是一门动态链接的语言,它假设程序的代码空间是开放的(Open World),允许在程序的任何时候通过类加载器去加载新的类,作为程序的一部分运行。要进行提前编译,就必须放弃这部分动态性,假设程序的代码空间是封闭的(Closed World),所有要运行的代码都必须在编译期全部可知。这一点不仅仅影响到了类加载器的正常运作,除了无法再动态加载外,反射(通过反射可以调用在编译期不可知的方法)、动态代理、字节码生成库(如 CGLib)等一切会运行时产生新代码的功能都不再可用,如果将这些基础能力直接抽离掉,Helloworld 还是能跑起来,但 Spring 肯定跑不起来,Hibernate 也跑不起来,大部分的生产力工具都跑不起来,整个 Java 生态中绝大多数上层建筑都会轰然崩塌。
“整个 Java 生态中绝大多数上层建筑都会轰然崩塌。”
所以,Java 的这次变革属于要釜底抽薪。
读完《Java 的危与机》之后,你再去看《Graal VM》一文,你就明白了:为什么说 Graal VM 的成功与否,与 Java 的前途命运息息相关。
而这场变革已然悄悄开始,比如说一个小点:
大多数运行期对字节码的生成和修改操作,在 Graal VM 看来都是无法接受的。
但是比如 CGLIB 就是通过运行时产生字节码(生成代理类的子类)来做动态代理的。
这是目前的主流形式。
现在因为Graal VM 支持不了,所以必须由和框架一起来共同解决。
因此自 Spring Framework 5.2 起,@Configuration 注解中加入了一个新的 proxyBeanMethods 参数,设置为 false 则可避免 Spring 对与非接口类型的 Bean 进行代理。
同样地,对应在 Spring Boot 2.2 中,@SpringBootApplication 注解也增加了 proxyBeanMethods 参数,通常采用 Graal VM 去构建的 Spring Boot 本地应用都需要设置该参数。
我最喜欢的还是技术演示工程部分,直接把项目 Demo 都给你准备好了,开箱即用:
而且周佬写的这个开源项目有个特点,引用的部分会给出具体的官方的地址。严谨又权威,比如写到项目中用到的技术组件的时候:
一个问答
在项目里面,我还发现了一个问答。
问题和回答都非常的好,搬运过来给大家看看。
评论区:https://icyfenix.cn/methodology/forward-msa/prerequest.html
问题如下:
周大哥,看到了您说的马太效应。再联想到之前您讲的软件涅槃,而完善的微服务体系允许服务有涅槃的过程,有强大的容错能力。微服务发展又如此迅猛,觉得马太效应真的不远。
我不禁对最需要掌握的技能进行了思考,并产生了更强的焦虑感。
我是一名有七年工作经验的java开发工程师,28岁,目前在一家北京的传统信息软件技术公司,工资相对计算机行业偏低。
局限在java语言来说,jvm调优与并发编程等比较高阶的能力,是不是就很不关键了?
jvm我读了您写的《深入理解Java虚拟机:JVM高级特性与最佳实践》的第二版与第三版,由于工作中鲜有机会实践,只停留在一些理论理解,而缺失实践,理论知识也会淡忘。
并发编程读过《Java并发编程实战》,对并发编程有些了解,也有一些实践,一般水平。
微服务公司并没有用起来,实践经验也缺少。远程调用、分布式事务、注册中心、配置中心、熔断、限流等知识,通过看视频跟您的这个文档有一些了解。
java基础知识,经过这些年的磨练,是挺扎实了,spring能熟练使用。
常用设计模式有了解,也理解的比较到位。
我不想沦为螺丝钉。
我应该提升自己的哪些能力呢?
这些年只是做到了胜任分配给自己的工作。
现在发现自己缺少前瞻性思考,缺少对自己职业生涯的把控。
我现在想把握自己的职业生涯,请周大哥给一些指导。
我会通过招聘市场去挖掘市场需求,做整理,进行思考。
但是迫不及待的想跟您述说一下,请您不吝赐教,希望我的请求不是很唐突。
这个问题其实是很具有普遍性的:学了没地方实践,慢慢就忘记了。理论学了一大堆,聊起来可以谈笑风生,但是就是没有实际使用过。自己就是一颗螺丝钉。
周佬的回复如下:
写这文章不是为了贩卖焦虑,我也没有能力指导别人的职业生涯,但针对“应该提升自己的哪些能力”这类问题,我以前被问过很多次,这里可以重复一下。
我的建议就两个:
- 不要轻视不直接产生实践价值的知识;
- 不要对陷入已经被你熟练掌握的技术中不能自拔。
为了便于你理解,我做一个很土的比喻,把程序员提升自己类比成武侠中的练功,软件中的技能其实有很明显的“内力”和“武功”之分,譬如你提到的Java虚拟机,这类知识不仅是你在工作中鲜有机会实践,我也是差不多的。
大学计算机课程中,以“原理”二字结尾的课程,譬如计算机原理、操作系统原理、编译原理、数据库原理,等等,对绝大多数人而言,都不太会去设计处理器逻辑电路、设计程序语言和编译器,开发操作系统内核。
这些都有很经典的书:编译原理的龙书,计算机体系结构和程序运行的CSAPP,分布式与数据库原理的DDIA、操作系统原理的MOS,等等。这些书系统严谨全面,但可读性并不优秀,在B站/Coursera刷这些书作者们的公开课翻译视频也许是更好的方法。
这些技能能够辅助你去思考和分析问题,但是很难直接为你解决生产中的问题,以实践价值,就是以工作中是否有机会用到来衡量它们的作用是不合适的。
但这些课程之所以会是必修,是因为学习它们,能够为一名程序员的知识框架构筑好基础。
这话听起来很教条,可是当你一旦建立了相对完备稳固的知识框架,发现遇到的新知识、新技术,能够很自然地安放在已有知识体系的某个位置上,能够清楚感知到语言、技术、框架的设计意图和目标,甚至能共鸣到设计者当时所想,就会产生一种理所当然的感觉。
这样你接受新知识的认知负荷就会比别人更低,掌握起来更快速,理解起来更深刻。
我在这文档开篇中所说的,写这部文档是以整理自己的知识框架为目的,并非场面话,这点的确就是程序员如何学习新知识的关键,在知识快速迭代IT业界,这也是决定一名程序员能力上限有多高的根本因素。
相对的,那些具体的、用来解决生产中问题的技术和方法,譬如你提到的Spring、设计模式,我将其类比为“武功”。
这当然也是重要的,只有内力没有武功无法行走江湖,空有一身理论,但写不出代码来(包括那些只定大方向的架构师、设计者),我认为不肯定是合格的程序员,也很难指望能成为一名出色的技术领导(难以服众)。
但是具体的“武功”应该是能够快速捡起的,也能快速“忘掉”的,就是避免将一件事情做熟了,就一直陷在这件事情里面,避免拿到一把好的锤子,就看着一切问题都像是钉子。
很多程序员都抱怨,自己是CRUD Boy,自己在业务逻辑中打滚,没有机会接触底层的或者前瞻性的技术,所以自己技术难以提升。
这里当然有客观原因的存在,但往往也是受到了主观原因放大。
程序员其实与旧时代的手工技艺者差不多,骨子里就有天生的技术崇拜,你写的代码比别人的优雅健壮高性能,你杀BUG比别人快速干净利索,就会受到大家的认可。
很自然地,更多偏向技术偏向深层次的工作就会落到你这里,至少你会有话语权,有选择做哪些事情的权利,是否要一直在围绕着你最熟悉的业务去打滚是由你决定的。
学习武艺成为“武林高手”,是成为大BOSS之后才不必长期面对虾兵蟹将的纠缠。
学习一门具体的技术,也是为了用它解决好问题,然后把它忘掉,去掌握那些更深层次的、更前沿,而且自己还不会的技术。
最后还有个追问和回答如下:
不知道大家看到这个回答后的感受是怎么样的。
至少对我而言,振聋发聩。特别是这两点:
- 不要轻视不直接产生实践价值的知识;
- 不要对陷入已经被你熟练掌握的技术中不能自拔。
已经放入手机标签中,时常提醒自己。
与君共勉。