Closed johnyannj closed 5 years ago
不会记录list,因为运行时同一个类智能委托到唯一的 ClassLoader 加载。如果存在多个 Plugin 导出相同的类,以 Plugin 的优先级为准。
Hi @QilongZhang 我说的不是导出类,是导出package, ark 不是还可以指定导出package吗?
Hi @QilongZhang 我说的不是导出类,是导出package, ark 不是还可以指定导出package吗?
和类是一样的,优先级高的 Plugin 加载.
@QilongZhang 可能我没表达清楚
PluginA 导出com.alipay.test 优先级高 PluginB 也导出com.alipay.test
类com.alipya.test.MyClass 在PluginB里。
com.alipay.sofa.ark.container.service.classloader.ClassLoaderServiceImpl#findExportClassLoader 可能找到的是PluginA的classLoader,而导致无法找到这个类。
@QilongZhang 可能我没表达清楚
PluginA 导出com.alipay.test 优先级高 PluginB 也导出com.alipay.test
类com.alipya.test.MyClass 在PluginB里。
com.alipay.sofa.ark.container.service.classloader.ClassLoaderServiceImpl#findExportClassLoader 可能找到的是PluginA的classLoader,而导致无法找到这个类。
这种情况下会报 CNF 错误,在 OSGi 规范实现的 Equinox 框架中,它会校验是否存在多个 Bundle 导出相同的 Package,存在就会报错。在 Ark 实现中,不会做这个校验,以优先级最高的 Plugin 导出为准,如果加载失败,就会报错。
hi @QilongZhang 我理解了这个设计原则。
但是,我觉得这种情况还是很常见的。 因为相同单位不同部门开发的插件,可能都会简单的设置 把“com.公司名” 下面的包导出,从而导致问题。
我想提一个建议:
我看到pandora的plugin目录下有一个export.index文件,里面好像列出了所有导出类的列表。
我想ark的plugin的打包maven插件,是否可以在打包的时候,就根据export的package,把所有package下面的class导出到一个文件中。 这样在运行过程中查找类就可以精确匹配。
不知道这是不是一个好主意。
hi @QilongZhang 我理解了这个设计原则。
但是,我觉得这种情况还是很常见的。 因为相同单位不同部门开发的插件,可能都会简单的设置 把“com.公司名” 下面的包导出,从而导致问题。
我想提一个建议:
我看到pandora的plugin目录下有一个export.index文件,里面好像列出了所有导出类的列表。
我想ark的plugin的打包maven插件,是否可以在打包的时候,就根据export的package,把所有package下面的class导出到一个文件中。 这样在运行过程中查找类就可以精确匹配。
不知道这是不是一个好主意。
之前 SOFAArk 借鉴了 Pandora 这个设计,有用户反馈 https://github.com/alipay/sofa-ark/issues/145 这个问题,这种方案并不适合 SOFAArk。 原因是 SOFAArk 沿用了 OSGi 的设计思路,所有类是动态懒加载的,而 Pandora 是提前加载好,index 方案不太适合 SOFAArk
但是,我觉得这种情况还是很常见的。 因为相同单位不同部门开发的插件,可能都会简单的设置 把“com.公司名” 下面的包导出,从而导致问题。
"简单的设置" 其实是偷懒的行为,如果每个插件都这样设计,每个应用的运行时类加载都必须one by one 排查,OSGi 的规范以及我们内部最佳实践,plugin的导出导入类尽可能的范围精确,或者像上面回复的运行时进行规则校验
谢谢 @QilongZhang 您的耐心回复。
原因是 SOFAArk 沿用了 OSGi 的设计思路,所有类是动态懒加载的,而 Pandora 是提前加载好,index 方案不太适合 SOFAArk
使用index方案,类也不一定预先加载。也可以动态加载的吧。
之前 SOFAArk 借鉴了 Pandora 这个设计,有用户反馈 #145 这个问题
"简单的设置" 其实是偷懒的行为,如果每个插件都这样设计,每个应用的运行时类加载都必须one by one 排查,OSGi 的规范以及我们内部最佳实践,plugin的导出导入类尽可能的范围精确,或者像上面回复的运行时进行规则校验
我是觉得指定一个包名,可以覆盖自己的插件内所有要导出的类,是符合常人思维和逻辑的。
是不是class index+ package匹配 两个机制结合,是不是可以避免#145 的同时也解决了问题呢?
使用单一的 package 匹配已经是可以解决这个问题的,index 对 sofaark 没有存在的价值了。
我是觉得指定一个包名,可以覆盖自己的插件内所有要导出的类,是符合常人思维和逻辑的。
没明白这句话的意思
我是觉得指定一个包名,可以覆盖自己的插件内所有要导出的类,是符合常人思维和逻辑的。
没描述准确,我的意思是,假设开发plugin的时候:
如果一个plugin要导出的类全部在 com.xxxx.a.b.c.d 下面。 他可以写 com.xxxx.a.b.c.d.*, 也可以写com.xxxx.* , 只要能覆盖自己plugin里要export的类就可以。都可以表示我这个plugin要导出哪些类。
这个已经是支持了。只是如果多个 Plugin 配置了相同的 package,只会委托给优先级高的 Plugin 加载。
我是觉得指定一个包名,可以覆盖自己的插件内所有要导出的类,是符合常人思维和逻辑的。
没描述准确,我的意思是,假设开发plugin的时候:
如果一个plugin要导出的类全部在 com.xxxx.a.b.c.d 下面。 他可以写 com.xxxx.a.b.c.d., 也可以写com.xxxx. , 只要能覆盖自己plugin里要export的类就可以。都可以表示我这个plugin要导出哪些类。
这个已经是支持了。只是如果多个 Plugin 配置了相同的 package,只会委托给优先级高的 Plugin 加载。
这个已经支持了,只是如果多个 Plugin 导出相同的 Package, 只会委托给优先级高的 Plugin 加载。
这个已经支持了,只是如果多个 Plugin 导出相同的 Package, 只会委托给优先级高的 Plugin 加载。
我的意思就是 “如果多个 Plugin 导出相同的 Package”, 可不可以不只考虑优先级,因为低优先级的plugin里可能存在这个类, 高优先级的反而没这个类。
我们的讨论可能有点车轱辘循环了^_^
这个已经支持了,只是如果多个 Plugin 导出相同的 Package, 只会委托给优先级高的 Plugin 加载。
我的意思就是 “如果多个 Plugin 导出相同的 Package”, 可不可以不只考虑优先级,因为低优先级的plugin里可能存在这个类, 高优先级的反而没这个类。
我们的讨论可能有点车轱辘循环了^_^
😄 这个应该不会支持,很有可能导致在一个package下面,一部分类由pluginA加载,一部分类由pluginB加载,对于排查问题是个灾难.. 这一点最好是遵循 OSGi 的规范。
很有可能导致在一个package下面,一部分类由pluginA加载,一部分类由pluginB加载,对于排查问题是个灾难
@QilongZhang 再次感谢您的耐心回复, 完全同意你说的这个问题。业务指定导出的包,确实不能重复。
此外,我还想提个另外的建议: 有关sofa-ark-plugin-maven-plugin的。 意思大体如下:
<exported>
<!-- configure package-level exported class-->
<packages>
<package>com.alipay.sofa.ark.sample.common</package>
</packages>
<!-- configure class-level exported class -->
<classes>
<class>com.alipay.sofa.ark.sample.facade.SamplePluginService</class>
**<package>com.alipay.sofa.www</package>**
</classes>
</exported>
导出类这个地方,是否可以指定包名,然后maven插件帮这个包下类都列出来。 这样开发者就不用一个个的把类写出来了。
导出类这个地方,是否可以指定包名,然后maven插件帮这个包下类都列出来。 这样开发者就不用一个个的把类写出来了。
额... 本身就支持包级别的导出
@QilongZhang 含义不一样,package导出是指运行的时候匹配用的。 我说这个是在打包的时候,把指定package下的类扫描出来,写到导出类列表里。
比如我有些类,因为第三方开源软件的限制,必须在org.springframework 下面。 但是org.springframework 这个包名又不能直接导出(和别人重复) 下面的类又很多,一个个的列出来又很麻烦。
@QilongZhang 含义不一样,package导出是指运行的时候匹配用的。 我说这个是在打包的时候,把指定package下的类扫描出来,写到导出类列表里。
比如我有些类,因为第三方开源软件的限制,必须在org.springframework 下面。 但是org.springframework 这个包名又不能直接导出(和别人重复) 下面的类又很多,一个个的列出来又很麻烦。
扫描也还是会扫描你依赖的二方包中的类,并不支持扫描特定jar下面的package. 可以尽可能精确你需要导出的包范围,比如 org.springframework.xx 不一定非要配置到一个大的包范围中。
Your question
我在阅读ark的源码,读到 com.alipay.sofa.ark.container.service.classloader.BizClassLoader 寻找类的过程。 第五步是寻找export的类 resolveExportClass(name)
他会调用com.alipay.sofa.ark.container.service.classloader.ClassLoaderServiceImpl#findExportClassLoader 找到一个classloader,
如果有两个相同export package的plugin。 pluginA 和pluginB。
如果要查找的类是在PluginB里面,而仅到PluginA里找不到就结束了,会不会就找不到这个类了?
Your scenes
因为Plugin是同一个公司开发的,导出的包名可能是一样的。
Your advice
com.alipay.sofa.ark.container.service.classloader.ClassLoaderServiceImpl#exportNodeAndClassLoaderMap 是不是应该记录 导出包名 和一个List的关系?
Environment
java -version
): 1.8uname -a
): windows 10