做网站资料准备,广州短视频内容营销平台,网站快速排名工具,建筑网片的用途有哪些有人可能会说上述标题可以简称为OSGi #xff0c;我想在一开始就放弃这种思考过程。 对于OSGi而言#xff0c;这不是一个冒犯#xff0c;这是一个很棒的规范#xff0c;在实现层或可用性层上都弄得一团糟#xff0c;这就是我对OSGi的信念。 当然#xff0c;您可以使用OS… 有人可能会说上述标题可以简称为OSGi 我想在一开始就放弃这种思考过程。 对于OSGi而言这不是一个冒犯这是一个很棒的规范在实现层或可用性层上都弄得一团糟这就是我对OSGi的信念。 当然您可以使用OSGi进行此操作但同时还要进行一些自定义工作。 使用OSGi解决此问题的缺点是在开发过程中引入了不必要的复杂性。 我们受到了JRebel的启发并且想了一会儿我们想要并很快意识到那条线上的东西我们不想在生产级运行时进行字节码注入。 因此让我们分析问题领域。 问题域 我们要解决的问题与UltraESB有关 具体来说就是实时更新功能 。 UltraESB支持以原子方式向正在运行的ESB更新/添加新的配置片段称为“ 部署单元 ”而不会造成停机时间最重要的是不会出现任何不一致的状态。 但是此功能的局限性之一是如果特定的Java类驻留在用户类空间中则需要对此部署单元的配置更新进行更改因此需要重新启动JVM。 尽管在集群部署中使用循环重启可以承受但是在单实例部署中这给整个系统带来了停机时间。 我们必须确保在解决这一问题时几乎没有任何保证 在更新部署单元时该单元已经接受的消息应使用所有资源包括现有单元的已加载类以及要加载的任何新类而任何新消息在完成单元更新后都必须使用被调度到新的部署单元配置和资源库我们称之为“ 一致性保证 ”。 为了确保这一点我们需要在同一JVM上管理同一类的2个或更多个相同类的版本以使各个部署单元以原子方式使用这些类。 让我们称其为部署单元的“ 原子性保证 ”。 部署单元配置可能包含Java片段这些Java片段在更新时进行即时编译其中可能包含对更新后的类的依赖关系从而使编译器能够找到该类的新版本以进行编译过程。 这就是“ 正确性保证 ” 更新过程必须对用户透明他们不必担心这一点无论是在开发时间上还是在部署时间上并且整个过程应该很简单。 让我们称之为“ 简单性保证 ” 现在您将理解这个问题不仅仅是OSGi因为编译是至少在我撰写此博客时OSGi无法自行解决的问题AFAIK。 如果我回到OSGi以确保它非常清晰为什么我们不走这条路呢让我们详细分析需求。 我们真正想要的不是完全模块化的JVM而是JVM内部可动态且原子可重新加载的特定空间。 将其映射到我们的实际用例中 可以确保用户写入并插入ESB的任何内容即包含代理服务序列和中介逻辑的部署单元都可以动态地自动重新加载可版本化但不能像在ESB核心中执行用户代码 。 这是用户向我们询问的内容而不是您如何在不重新启动的情况下如何在运行时向ESB添加其他功能。 我同意能够添加新功能很酷但是似乎没有人希望这样做以及与之相关的复杂性。 我们已经准备好进行任何复杂的工作但是还没有准备好将这种复杂性或任何复杂性传递给我们的用户。 拟议的解决方案 如果您想在Java中使用前2个保证“ Consistency / Atomicity ”能够在运行时加载同一个类的2个版本并在其中的正确任务中使用正确的类则除了编写之外别无他法一个新的类加载器它强制JVM执行子优先级加载 。 JVM标准类装入器都是“父优先”的。 典型应用程序容器的WebAppClassLoader与我们想要的非常接近但是在生产环境中具有动态重载功能。 旧类空间和新类空间应由该类加载器的2个实例管理以便能够安全地隔离这2个版本。 要了解上述事实重要的是要了解JVM如何识别类。 即使从Java语言的角度来看类也是由FQN唯一标识的即FQN即“包名类名”但是从JVM的角度来看除了上述概念外已经加载了该类的类加载器也是一个事实班级的独特性。 在类似OSGi的环境中这就是为什么即使您强制转换为正确的类型也看到ClassCastException的原因。 因此得出的结论是我们需要编写一个类加载器并为可重新加载的不同部署单元的不同版本保留该类加载器的单独实例。 为了确保即时编译器看到正确的类来编译序列片段从而保证“ 正确性 ”需要有一个JavaFileManager实现再次寻找更新的类空间。 Java编译器任务javac通过指定的文件管理器作为JavaFileObject实例而不是通过类加载器作为类对象来搜索依赖项以编译类这是为了确保编译器有效地解析类因为可能存在依赖项在正在编译的类中。 此外不应该要求用户将jar文件放在经过版本控制的文件结构中以免影响对“ 简单性 ”的保证而ESB本身必须管理该jar文件的版本控制以确保我们不会混合使用不同的版本类空间。 这对于在不同版本中正确执行编译器任务也很重要因为编译器使用“ 内存映射”文件读取文件管理器提供的类的输入流上的类定义从而强制维护每个文件的物理副本。 jar文件/类的版本。 执行执行 首先让我指出完整的变更集 在阅读实现时可以不时参考。 我们已经确定了3个要实现的关键空间其中第一个是提供用户类空间的类的类加载器。 我们将其命名为HotSwapClassLoader 我不会在博客中向您显示代码片段请记住该完整代码请牢记AGPL许可的条款因为该代码为AGPL 。 现在我们想将此类加载器与部署单元的版本相关联UltraESB固有地支持该版本加载器因为它将它们保持为单独的Spring子上下文。 因此任何新的部署单元配置创建包括现有部署单元的新版本都将实例化此类加载器的新实例并将其用作部署单元配置的资源/类加载器。 初始化时的类加载器计算用户类空间的规范化哈希值并检查当前版本的类空间是否存在现有副本并根据上述声明使用该副本或创建新副本。 这种散列和重用类空间的现有副本会阻止管理同一用户类空间版本的2个副本因为整个过程都是在静态最终锁上同步的。 然后它对用户类空间的该副本进行操作。 必须进行此复制以免让用户担心类的版本控制并确保在给定的配置中使用了正确的类集。 该类装入器还采取了广泛的措施以确保尽早清除类空间副本。 但是这只能保证最终清除。 执行的下一个主要项目是InMemoryFileManager哪个是哪个得到改性通过列表的方法的一个可迭代以支持另外的用户类的空间来在内存中的编译源代码片段现有类SwappableJavaFileObject实例。 文件管理器首先查询HotSwapClassLoader以查找与用户类空间相对应的SwappableJavaFileObject实例然后是系统类空间并以WrappedIterator的形式返回以确保用户空间类获得优先级。 在实现的最后一步中对核心JVM功能进行了调整/自定义之后只需使用此自定义类加载器来加载序列和代理服务的类并为片段编译任务提供自定义文件管理器即可。部署单元以完成解决方案。 我们还希望有一个开关在默认情况下将其禁用并建议在生产部署中将其禁用。 为了简化运行时环境并进行其他一些自定义UltraESB引入了环境概念该概念是从Grails环境功能中借用的。 最后成功实现了动态运行时即“一致”“原子”“正确”最重要的是“对用户简单”。 操作行为 现在我们已经实现了解决方案让我们看一下UltraESB的内部结构了解它在生产部署中如何工作。 发出配置添加或更新管理命令后将更新生产环境中的所有部署单元配置。 可以通过原始JMX或通过在JMX操作之上实现的任何管理工具例如UTerm 或通过UConsole发出此命令。 完成此实现后它不会对您进行更新的方式进行任何更改它通过添加/替换jar文件的功能进一步增强了功能并进行了修改从而将更新影响到UltraESB的lib / custom用户类空间中从而确保了在更新后发出每个所述管理命令后为新配置选择更新的jar文件/类。 您可以在UltraESB的夜间版本中尝试此操作甚至可以等待2.0.0版本的发布该版本计划在2013年1月中旬发布更多新的酷但可用的功能。 参考 Java内部的动态热交换环境 我们的JCG合作伙伴 Ruwan Linton在 Blind Vision –来自软件工程与生活博客。 翻译自: https://www.javacodegeeks.com/2012/12/dynamic-hot-swap-environment-inside-java-with-atomic-updates.html