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

Biz包存在的问题与几点疑问 #633

Closed 343585776 closed 1 year ago

343585776 commented 1 year ago

Your question

参照的demo: https://github.com/sofastack-guides/sofa-ark-spring-guides https://github.com/sofastack-guides/spring-boot-ark-bizhttps://github.com/sofastack-guides/sofa-ark-dynamic-guides

1.是否ark-biz包中必须存在如下依赖,我们实际场景中,宿主应用作为请求入口,Controller层实现在宿主应用中,biz包只是接口的实现(可变逻辑部分动态升级),并不需要用到web相关内容

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <scope>provided</scope>
</dependency>

如果移除上述依赖,动态安装biz包时会报如下异常:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-03-25 10:42:37.869 ERROR 65426 --- [et-command-1-T1] o.s.boot.SpringApplication               : Application run failed

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:163) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[spring-context-5.3.18.jar:5.3.18]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-2.6.6.jar:2.6.6]
    at com.alipay.sofa.springbootarkbiz.SpringBootArkBizApplication.main(SpringBootArkBizApplication.java:16) [null-null-20230325104237650-unpack/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_331]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_331]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_331]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_331]
    at com.alipay.sofa.ark.bootstrap.MainMethodRunner.run(MainMethodRunner.java:48) [sofa-ark-archive-2.1.1.jar!/:na]
    at com.alipay.sofa.ark.container.model.BizModel.start(BizModel.java:287) [sofa-ark-container-2.1.1.jar!/:na]
    at com.alipay.sofa.ark.api.ArkClient.installBiz(ArkClient.java:171) [sofa-ark-api-2.1.1.jar:na]
    at com.alipay.sofa.ark.api.ArkClient.installOperation(ArkClient.java:346) [sofa-ark-api-2.1.1.jar:na]
    at com.alipay.sofa.ark.api.ArkClient.installOperation(ArkClient.java:331) [sofa-ark-api-2.1.1.jar:na]
    at com.alipay.sofa.ark.container.service.biz.BizCommandProvider$BizCommand$1.run(BizCommandProvider.java:249) [sofa-ark-container-2.1.1.jar!/:na]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_331]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_331]
    at java.lang.Thread.run(Thread.java:750) [na:1.8.0_331]
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:210) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:180) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160) ~[spring-boot-2.6.6.jar:2.6.6]
    ... 19 common frames omitted

2.如果ark包中使用了web的相关依赖,并设置webContextPath,则在进行动态升级时会提示如下异常,需要先将原先biz版本卸载后再安装新版本,无法使用switch方法进行切换了。对于这一块目前有好的办法处理吗?

org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is java.lang.IllegalArgumentException: Child name [biz] is not unique
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:163) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[spring-context-5.3.18.jar:5.3.18]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-2.6.6.jar:2.6.6]
    at com.alipay.sofa.springbootarkbiz.SpringBootArkBizApplication.main(SpringBootArkBizApplication.java:16) [null-null-20230325113308478-unpack/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_331]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_331]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_331]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_331]
    at com.alipay.sofa.ark.bootstrap.MainMethodRunner.run(MainMethodRunner.java:48) [sofa-ark-archive-2.1.1.jar!/:na]
    at com.alipay.sofa.ark.container.model.BizModel.start(BizModel.java:287) [sofa-ark-container-2.1.1.jar!/:na]
    at com.alipay.sofa.ark.api.ArkClient.installBiz(ArkClient.java:171) [sofa-ark-api-2.1.1.jar:na]
    at com.alipay.sofa.ark.api.ArkClient.installOperation(ArkClient.java:346) [sofa-ark-api-2.1.1.jar:na]
    at com.alipay.sofa.ark.api.ArkClient.installOperation(ArkClient.java:331) [sofa-ark-api-2.1.1.jar:na]
    at com.alipay.sofa.ark.container.service.biz.BizCommandProvider$BizCommand$1.run(BizCommandProvider.java:249) [sofa-ark-container-2.1.1.jar!/:na]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_331]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_331]
    at java.lang.Thread.run(Thread.java:750) [na:1.8.0_331]
Caused by: java.lang.IllegalArgumentException: Child name [biz] is not unique
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:711) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:698) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:696) ~[tomcat-embed-core-9.0.60.jar:9.0.60]
    at com.alipay.sofa.ark.springboot.web.ArkTomcatServletWebServerFactory.prepareContext(ArkTomcatServletWebServerFactory.java:204) ~[sofa-ark-springboot-starter-2.1.1.jar:na]
    at com.alipay.sofa.ark.springboot.web.ArkTomcatServletWebServerFactory.getWebServer(ArkTomcatServletWebServerFactory.java:93) ~[sofa-ark-springboot-starter-2.1.1.jar:na]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:182) ~[spring-boot-2.6.6.jar:2.6.6]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160) ~[spring-boot-2.6.6.jar:2.6.6]
    ... 19 common frames omitted

3.biz业务模块有些时候也需要使用到数据库操作,宿主中一般都进行了数据库相关配置与使用,如果在biz模块中需要使用,有什么好的办法使得在宿主中进行统一管理而不需要在各自biz中再单独配置数据库相关的了。 是否biz业务中使用宿主配置的数据库,也需要使用@SofaService/@SofaReference方式,有没有更好的方法或者思路提供。

阿里网站查询到一些内容,表示基座的能力更应该体现在RPC、数据库、缓存、通用方法、通用类等的基础能力上,但是具体业务模块如何直接使用宿主模块中的能力这块还是有点疑问

image

Your scenes

使用ark的动态加载能力,将业务中逻辑易变或场景易变部分的代码进行单独维护

Your advice

1.对于非web的biz模块是否可以去除相关web依赖 2.是否可以同时存在多个版本,通过switch方法进行切换 3.能否提供biz访问master模块中通用代码、缓存或数据库的的便捷方法或者思路,或者提供相关的示例demo进行参考

Environment

lylingzhen commented 1 year ago

参考一下这篇源码解析: https://www.sofastack.tech/projects/sofa-boot/sofa-ark-multi-web-component-deploy/

343585776 commented 1 year ago

多谢答复,这篇源码解析已经认真看过,但是还是没有解决我的问题

1和2提到的问题与 #464 是一样的

我们的场景中一个业务功能的biz包会存在多个版本,这些版本需要预先安装进宿主,然后根据实际使用时情况,经常使用switch方法进行版本切换生效,目前的动态加载方式导致同一个biz包的不同版本无法同时存在,必须卸载掉旧有版本再安装新版本才行。因为会提示webContextPath重复不唯一,这算不算是一个bug?

所以我才试验了在第1个问题中提到的,能否删掉web依赖,使biz业务包变成非web形式,这样就不需要去设置webContextPath,但是实际测试结果却不行

对于问题3,是想了解除了@SofaService/@SofaReference方式引用基座中的方法外,是否有其余方式与思路实现数据源统一在基座中,各业务biz内也能使用Dao的能力去跟数据库交互,而不用各自biz业务包内再单独去配置数据库相关

lylingzhen commented 1 year ago

”必须卸载掉旧有版本再安装新版本才行“ 是的,需要自己实现一个卸载回调,清理必要的资源。

lylingzhen commented 1 year ago

"对于问题3,xxx" 可以在基座把 datasource 发布成 sofaservice,模块引用,然后在模块使用 mybatis 开发 mapper 并用 sofareference 引用基座 datasource 服务即可。

343585776 commented 1 year ago

感谢指导,看来我们的场景得转换一下思路去实现了...

lylingzhen commented 1 year ago

好的,Issue 先 Close,有问题再 Reopen。