sofastack / sofa-ark

SOFAArk is a light-weight,java based classloader isolation framework.
https://www.sofastack.tech/projects/sofa-boot/sofa-ark-readme/
Apache License 2.0
1.56k stars 497 forks source link

sofaark问题:模块biz引入springboot依赖导致启动ark包时报factory already defined #674

Closed zkitcast closed 1 year ago

zkitcast commented 1 year ago

我下载了这个案例https://github.com/sofastack-guides/sofa-ark-spring-guides#41, 按照文档操作,主biz静态引入模块biz,单host模式,成功打包ark包并启动。但是我现在需要在模块biz中引入springboot的依赖,

`

org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-logging

` 并且把declaredMode置为false

<declaredMode>false</declaredMode>

打完包后,启动ark包,却报这个错误 ` 2023-06-29 21:37:24.556 INFO 25066 --- [ main] c.a.s.s.SpringBootArkBizApplication : Starting SpringBootArkBizApplication v0.0.1-SNAPSHOT using Java 1.8.0_291 on localhost with PID 25066 (/Volumes/ExtremeSSD/mavenRepo/repository/com/alipay/sofa/spring-boot-ark-biz/0.0.1-SNAPSHOT/spring-boot-ark-biz-0.0.1-SNAPSHOT-ark-biz.jar started by zhaokan in /Volumes/ExtremeSSD/IdeaProjects/sofa-ark-spring-guides) 2023-06-29 21:37:24.563 INFO 25066 --- [ main] c.a.s.s.SpringBootArkBizApplication : No active profile set, falling back to default profiles: default 2023-06-29 21:37:26.183 INFO 25066 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8090 (http) 2023-06-29 21:37:26.202 INFO 25066 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2023-06-29 21:37:26.202 INFO 25066 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.46] 2023-06-29 21:37:26.229 ERROR 25066 --- [ main] org.apache.catalina.core.ContainerBase : A child container failed during start

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@6c6333cd] at java.util.concurrent.FutureTask.report(FutureTask.java:122) [na:1.8.0_291] at java.util.concurrent.FutureTask.get(FutureTask.java:192) [na:1.8.0_291] at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:916) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:829) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374) [tomcat-embed-core-9.0.46.jar!/:na] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_291] at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-embed-core-9.0.46.jar!/:na] at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) [na:1.8.0_291] at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.StandardService.startInternal(StandardService.java:433) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486) [tomcat-embed-core-9.0.46.jar!/:na] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.(TomcatWebServer.java:104) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:450) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:199) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:182) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) [spring-context-5.3.7.jar!/:5.3.7] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:337) [spring-boot-2.5.0.jar!/:2.5.0] at com.alipay.sofa.springbootarkbiz.SpringBootArkBizApplication.main(SpringBootArkBizApplication.java:23) [spring-boot-ark-biz-0.0.1-SNAPSHOT-ark-biz.jar!/:0.0.1-SNAPSHOT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_291] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_291] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_291] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_291] at com.alipay.sofa.ark.bootstrap.MainMethodRunner.run(MainMethodRunner.java:48) [sofa-ark-archive-2.1.2.jar!/:na] at com.alipay.sofa.ark.container.model.BizModel.start(BizModel.java:287) [sofa-ark-container-2.1.2.jar!/:na] at com.alipay.sofa.ark.container.service.biz.DefaultBizDeployer.deploy(DefaultBizDeployer.java:57) [sofa-ark-container-2.1.2.jar!/:na] at com.alipay.sofa.ark.container.service.biz.BizDeployServiceImpl.deploy(BizDeployServiceImpl.java:55) [sofa-ark-container-2.1.2.jar!/:na] at com.alipay.sofa.ark.container.pipeline.DeployBizStage.processStaticBiz(DeployBizStage.java:56) [sofa-ark-container-2.1.2.jar!/:na] at com.alipay.sofa.ark.container.ArkContainer.deployBizAfterMasterBizReady(ArkContainer.java:168) [sofa-ark-container-2.1.2.jar!/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_291] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_291] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_291] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_291] at com.alipay.sofa.ark.support.startup.EmbedSofaArkBootstrap.deployStaticBizAfterEmbedMasterBizStarted(EmbedSofaArkBootstrap.java:103) [sofa-ark-support-starter-2.1.2.jar:na] at com.alipay.sofa.ark.springboot.listener.ArkDeployStaticBizListener.onApplicationEvent(ArkDeployStaticBizListener.java:38) [sofa-ark-springboot-starter-2.1.2.jar:na] at com.alipay.sofa.ark.springboot.listener.ArkDeployStaticBizListener.onApplicationEvent(ArkDeployStaticBizListener.java:26) [sofa-ark-springboot-starter-2.1.2.jar:na] at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176) [spring-context-5.3.18.jar:5.3.18] at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169) [spring-context-5.3.18.jar:5.3.18] at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143) [spring-context-5.3.18.jar:5.3.18] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421) [spring-context-5.3.7.jar!/:5.3.7] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378) [spring-context-5.3.7.jar!/:5.3.7] at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:938) [spring-context-5.3.7.jar!/:5.3.7] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) [spring-context-5.3.7.jar!/:5.3.7] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) [spring-boot-2.5.0.jar!/:2.5.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) [spring-boot-2.5.0.jar!/:2.5.0] at com.alipay.sofa.sofaarkspringguides.SofaArkSpringGuidesApplication.main(SofaArkSpringGuidesApplication.java:15) [classes/:na] Caused by: org.apache.catalina.LifecycleException: Failed to initialize component [org.apache.catalina.webresources.StandardRoot@6c6333cd] at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:139) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:173) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.StandardContext.resourcesStart(StandardContext.java:4830) ~[tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4966) ~[tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384) [tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374) [tomcat-embed-core-9.0.46.jar!/:na] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_291] at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-embed-core-9.0.46.jar!/:na] at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) [na:1.8.0_291] at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909) [tomcat-embed-core-9.0.46.jar!/:na] ... 58 common frames omitted Caused by: java.lang.Error: factory already defined at java.net.URL.setURLStreamHandlerFactory(URL.java:1159) ~[na:1.8.0_291] at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.(TomcatURLStreamHandlerFactory.java:130) ~[tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.getInstanceInternal(TomcatURLStreamHandlerFactory.java:53) ~[tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.webresources.TomcatURLStreamHandlerFactory.register(TomcatURLStreamHandlerFactory.java:77) ~[tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.webresources.StandardRoot.registerURLStreamHandlerFactory(StandardRoot.java:700) ~[tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.webresources.StandardRoot.initInternal(StandardRoot.java:682) ~[tomcat-embed-core-9.0.46.jar!/:na] at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136) [tomcat-embed-core-9.0.46.jar!/:na] ... 68 common frames omitted `

无论是多host还是单host都有这个问题,难道只能把模块biz的springboot相关依赖都provided掉才可以吗

Environment

gaosaroma commented 1 year ago

是的,因为基座提供了springboot相关依赖,模块使用的时候要设置provided,否则可能会出现springboot启动时 classloader 不一致,或者找不到类的情况。

zkitcast commented 1 year ago

我希望模块biz能使用自己的springboot依赖,而不要使用基座的,应该如何配置呢

gaosaroma commented 1 year ago

sofaark 不支持这种使用方式,也不建议用这种使用方式。对于启动框架版本,建议ark模块和基座保持一致。

zkitcast commented 1 year ago

那用sofa-ark-maven-plugin打包模块biz时,declaredMode置为true和false是不是没有区别了,最后都得使用基座的依赖

      <!-- declaredMode 开启后,业务应用可以使用自己声明过的、且宿主应用拥有的通用依赖-->
      <declaredMode>false</declaredMode> <!-- 使用宿主应用的通用依赖-->
lvjing2 commented 1 year ago

declaredMode 设置为 true 的作用是,让模块能使用到的依赖,只能是模块里声明过的依赖,而不是整个基座的所有依赖都能用。

zkitcast commented 1 year ago

我设置declaredMode为true。模块biz中声明的所有spring依赖都设置了provided。然后模块biz除了spring依赖外还声明了5个第三方依赖,恰巧基座里也有这5个依赖且版本不同,模块biz是不是依然可能出现类冲突?是不是只要模块biz和基座同时声明的依赖,都要在模块biz里provided掉?

gaosaroma commented 1 year ago

然后模块biz除了spring依赖外还声明了5个第三方依赖,恰巧基座里也有这5个依赖且版本不同,模块biz是不是依然可能出现类冲突?

不会出现类的冲突,因为模块和基座的类是可以隔离的,但初始化时可能会因为 classloader 不一致而失败。

是不是只要模块biz和基座同时声明的依赖,都要在模块biz里provided掉?

如果模块biz可以使用和基座相同版本的依赖,建议在模块biz里provided掉。

lvjing2 commented 1 year ago

当前什么依赖放基座,什么依赖放模块,没有固定的标准,只有最佳实践,最佳实践是模块瘦身掉,让相同类只在一个 classsLoader 里导入,是能尽可能避免 java的 linkage error。

lylingzhen commented 1 year ago

Issue 先关闭,后续可以重开继续讨论哈

lvjing2 commented 4 months ago

same with https://github.com/sofastack/sofa-ark/issues/674,https://github.com/spring-projects/spring-boot/issues/10529,代码方式禁掉 TomcatURLStreamHandlerFactory.disable(),该开关只影响 war 部署模式