Salesforce在生产中大规模采用OpenJDK 11的一年

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Salesforce是首批大规模采用OpenJDK 11的大型企业之一,在2018年底OpenJDK 11发布后不久,Salesforce就开始了OpenJDK 11的采用之旅。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"前沿吗? 当然是。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"安全吗? 绝对地。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"你可能还不知道,Salesforce在整合前沿、转型技术,并以安全、可靠、无缝的方式,同时在不损害其"},{"type":"link","attrs":{"href":"https:\/\/www.salesforce.com\/company\/our-story\/","title":null,"type":null},"content":[{"type":"text","text":"#1核心价值:信任"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"的前提下,将这些技术提供给客户方面一直处于行业的领先地位。从"},{"type":"link","attrs":{"href":"https:\/\/www.cncf.io\/case-studies\/salesforce\/","title":null,"type":null},"content":[{"type":"text","text":"gRPC"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"到"},{"type":"link","attrs":{"href":"https:\/\/engineering.salesforce.com\/adopting-kubernetes-46b6c13b204b","title":null,"type":null},"content":[{"type":"text","text":"Kubernetes"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":",Salesforce在新技术领域有着早期大胆探索的历史。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"在本文的案例中,将主要的Salesforce CRM应用程序升级到OpenJDK 11是一项庞大的跨组织工作。 把它做好,不仅能为我们带来几年的Java运行时创新红利,也能为我们的客户提供更好的体验,并为开源社区做出贡献。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"背景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"2018年末,OpenJDK 11作为Java最新的长期支持(LTS)版本面世。这开启了一个人们期待已久的机遇,推动了Salesforce应用程序的向前发展,并为我们的内部开发人员带来了巨大的新特性和创新。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"为什么我们认为我们可以安全地从OpenJDK 8(上一个最新的LTS版本)过渡到OpenJDK 11呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"首先,我们并不是一蹴而就的。对于OpenJDK 9和OpenJDK 10这两个版本,虽然我们只打算将它们作为垫脚石,而不在生产环境中使用,但一旦它们的版本可用,我们就会立即升级到对应版本。正如你所料,最困难的部分是从OpenJDK 8升级到OpenJDK 9,这需要对Salesforce应用程序进行重大的更改。从OpenJDK 9升级到OpenJDK 10,再从OpenJDK 10升级到OpenJDK 11,都只需做相对较小的改动。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"另外,Java的向后兼容性保证允许用旧版本Java开发编译的应用程序代码能运行在新的版本上,这一功能的威力不容小觑。向后兼容性为迁移提供了巨大的帮助,这样我们的大多数代码都不需要更改。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"Salesforce应用程序利用Java向后兼容性的方法之一是,将用于构建Salesforce应用程序的Java版本与用于启动它的Java版本分开。这使我们能够首先集中精力将过程的一端从OpenJDK 8升级到OpenJDK 11,而另一端仍保持在OpenJDK 8上不变,并将其升级到OpenJDK 11的时间往后推迟。我们内部开发人员的目标是,通过在初始化和启动Salesforce应用程序的脚本中隐藏所有的差异和复杂性的方式,让OpenJDK 8和OpenJDK 11运行时之间的切换尽可能的简单和无缝。因此,对于我们的开发人员来说,升级到OpenJDK 11运行时就像用OpenJDK 11版本的字符串覆盖配置属性一样简单。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"也就是说,我们面临的另一个挑战是,我们的OpenJDK 11迁移工作跨越了多个版本周期,我们必须确保任何支持OpenJDK 11的增量更改都不会打破我们的生产环境(生产环境仍然是基于OpenJDK 8部署的),也不能对客户的信任产生任何负面影响。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"平台的变更&挑战"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"当我们一个接一个地升级OpenJDK版本时,我们遇到了Java平台的许多显著变更。而我们的迁移之路漫长且需有条不紊地推进,这意味着这些变更会给我们带来了很多挑战,但在这里我们只讨论其中的几个。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"类路径与模块化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/en.wikipedia.org\/wiki\/Java_version_history#Java_SE_9","title":null,"type":null},"content":[{"type":"text","text":"Java SE 9"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"平台引入的重大变更之一就是Java平台模块系统(Java Platform Module System,JPMS)。JPMS将JDK划分为多个模块,每个模块都是一组命名唯一且可重用的相关包。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"好消息是,Java 9仍然支持传统的类路径,它能与模块路径一起工作,并映射到一个被称为未命名模块的特殊模块上。因此,构成Salesforce应用程序类路径的所有JAR文件都会自动加入模块系统,从而导致了传统类路径和模块路径的混合。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"实际上,Salesforce应用程序的整个类加载器层次结构都保留在Java 9及更高版本中。它由我们的Web服务器和Servlet容器锚定,委托给OSGi类加载器,而OSGi类加载器又委托给Java运行时的内置类加载器。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"然而,作为Jigsaw计划的一部分,Java 9带来了一个影响类加载的重大变更。这是对"},{"type":"link","attrs":{"href":"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/guides\/standards\/index.html","title":null,"type":null},"content":[{"type":"text","text":"授权标准覆盖机制"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"(Endorsed Standards Override Mechanism,用于支持加载包含授权标准和独立技术实现的JAR文件)和"},{"type":"link","attrs":{"href":"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/guides\/extensions\/index.html","title":null,"type":null},"content":[{"type":"text","text":"扩展机制"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"( Extension Mechanism,用于支持加载包含扩展或可选软件包的JAR文件)的移除。由于Salesforce应用程序过去依赖于这两种机制,因此必须使用 "},{"type":"codeinline","content":[{"type":"text","text":"-module-path"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" 、 "},{"type":"codeinline","content":[{"type":"text","text":"-upgrade-module-path"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" 和 "},{"type":"codeinline","content":[{"type":"text","text":"-patch-module"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" 标志的组合,将所有受影响的JAR文件迁移到Salesforce应用程序的模块路径下。不过,这些非模块化的JAR文件都无需转换为模块:它们作为依赖项被放置在Salesforce应用程序的模块路径上,从而自动成为模块化的。此功能被称为自动模块化,创建它是为了减轻将现有应用程序转换为新模块系统的负担。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"影响Salesforce应用程序的另一个变更是删除了Salesforce应用程序所依赖的Java Enterprise Edition(“Java EE”)API。Java 9开始将这些API分离到它们各自的模块中,这些模块被注解为不推荐使用,以便删除,这表明了在将来的版本中会删除它们的意图。这些模块包含在运行时镜像中,但默认情况下未启用。因而,它们必须通过 "},{"type":"codeinline","content":[{"type":"text","text":"--add modules"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" 标识显式“激活”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"从Java11开始,这些模块不再包含在运行时中("},{"type":"link","attrs":{"href":"https:\/\/openjdk.java.net\/jeps\/320","title":null,"type":null},"content":[{"type":"text","text":"参见JEP 320:删除Java EE和CORBA模块"}],"marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":")。相反,Java EE和CORBA技术的独立版本作为Maven构件发布,并可以从第三方网站(如Maven Central)上获取,我们从那里下载了它们并将它们添加到了Salesforce应用程序的模块路径中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"向后不兼容"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"在将Salesforce应用程序的Java运行时迁移到OpenJDK 11时,我们发现了许多向后不兼容的变更。其中大多数都是“设计使然”,并且是涵盖在版本说明中了的,正如下面所要讨论的那样。(有一个true的回归影响了布尔型bean属性的内省;这是由OpenJDK实现本身的一个bug引起的,我们报告了这个bug,并且它已经被修复了。)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":" "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#494949","name":"user"}}],"text":"设计上向后不兼容变更的例子很明显,因为它会导致JVM在启动时中断,并出现如下的错误:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Unrecognized VM option '
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章