因项目部署环境改变成国产化环境,需要使用金蝶中间件,spring cloud
的每个Project 可以直接打成jar
包运行,里面自带了tomcat
容器,所以要对spring cloud
各个微服务模块进行改造。本文根据现有的项目架构,记录了怎么用最小的改动去完成适配,并且介绍怎么使用Apusic
,来保持Euraka
注册发现与负载均衡、服务的管理,保持原有的高可用。(本文只记录Linux
下Apusic
安装部署过程)
项目war包适配改造
下面是本文需要适配的spring cloud
项目目录结构,因业务需要模块划分比较详细。
下面是对项目的详细改造:
- 步骤一
为防止spring cloud
内置的servlet container(tomcat)
,在发布war
中不会与Apusic
金蝶中间件冲突,需要标记内置tomcat
依赖为provided
,把内嵌的tomcat
去掉。下面是两种移除方式,我使用的第二种方式。
方式一
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-tomcat
方式二
org.springframework.boot
spring-boot-starter-tomcat
provided
- 步骤二
为防止运行时,与金蝶中间件本身自带了servlet-api.jar
包发生冲突,所以打包阶段移除了servlet-api
javax.servlet
javax.servlet-api
3.0.1
provided
提醒:在上线测试中,本项目有个模块打成
war
包后,存在移除了servlet-api
会报错的情况,后来加上去就能正常运行,也不跟Apusic冲突,所以各位根据自己项目情况适当调整吧,也懒得去探究了说明 :因本项目中所有子项目会依赖于父的
pom.xml
文件,所以我们只需要在父pom.xml
中加入排除内置的tomcat 、servlet-api
依赖即可,也可以在子项目总pom.xml
中添加(如图二web下的pom),每个模块都要改,这种方式比较麻烦不推荐。
步骤三
我的项目模块比较多,所以就比较麻烦了,需要在每个模块启动类下的pom.xml
中添加
,修改打包类型,将默认的jar
方式改为war
- 步骤四
修改启动类,并重写初始化方法
public class WebApplication extends SpringBootServletInitializer {
1、修改启动类,继承 SpringBootServletInitializer 并重写 configure 方法
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
System.out.println("======WebApplication====start==========");
return builder.sources(new Class[]{WebApplication.class});
}
2、由于Spring boot默认使用Tomcat作为嵌入式Servlet容器,来启动SpringBoot的web应用,所以需要修改servlet容器的配置
@Bean
public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
return new ServletRegistrationBean(dispatcherServlet, "/*");
}
3、如果模块需要上传文件需要添加下面的代码,如果没有可以忽略
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
resolver.setResolveLazily(true);//resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常
resolver.setMaxInMemorySize(40960);
resolver.setMaxUploadSize(50 * 1024 * 1024);//上传文件大小 50M 50*1024*1024
return resolver;
}
}
需要上传文件的的服务,在加了上面代码3
的配置后,还需要添加一个依赖包,不然,没这个包访问的时候会报错,找不到一个类
commons-fileupload
commons-fileupload
1.4
- 步骤五
在每个模块的application.properties
中添加spring.jmx.default-domain=唯一名称
,否则无法在金蝶中间件中启动,原因:spring.jmx
是默认打开的每个jmx
名字必须是唯一的!!,详细原因自己去查吧,照着做就行,如图五,我是用的服务注册标识,与注册到注册中心服务名保持一致,你也可以随意指定别重复就行,两者没啥关系。
spring.jmx.default-domain=service-web
- 提示:金蝶中间件的某些版本存在了一个问题,如果你日志设置的info级别,启动后,控制台会疯狂刷屏,只能error才不刷屏。后来是换了版本,这个问题才好。
ok,到这儿基本的代码改动就算完成了,可以打war
包了,剩下就是在发版到金蝶中间件中会遇到各种乱七八糟的问题了。
安装金蝶
金蝶版本AAS-V9.0
,金蝶中间件需要jdk环境,所以需要先安装jdk,jdk
版本应同时高于金蝶、iServer
要求的版本。本文使用的金蝶要求jdk1.6
及以上、iServer 8.1.1
要求jre1.8
及以上,所以这里使用JDK1.8(64位)
。 解压 AAS-V9.0.zip
文件即可,本文解压到以下目录/data/Apusic
,解压缩即完成安装。license.xml为
授权文件,必须有才能Apusic
使用,window
详细安装步骤,可参考金蝶用户手册。
下面介绍时,用
APUSIC_HOME
描述Apusic
服务器的安装目录路径,即本文解压后的/data/Apusic
安装路径。
在APUSIC_HOME
路径下,有个domains
,此文件内是所有服务的所在,APUSIC_HOME/domains
目录下的 samples
内预部署了若干个示例应用,用以演示 JavaEE5
的新技术、新特性。samples
目录结构与 mydomain
基本一致,存放示例应用的源代码及构建脚本。前段话是从用户手册上拷贝过来的,这些都不重要,我们主要用到的就是mydomain
,这个目录,稍后再讲。
金蝶中间件可以允许在一个domain
中运行多个war
包,这样的话,就会出现多个服务一个端口的问题(金蝶中间件的默认端口为6888)
,并且会为每个服务默认一个上下文根路径为"/服务名"
,比如访问我部署的web
服务的接口地址就为:http://ip:6888/web
,这样的情况我们在使用feignclient
进行服务之间调用时,就会访问不到,feignclient
就会废了,正常我们访问注册中心的web
服务地址应该为:http://ip:自定端口
,不会后缀服务名。
为了是实现feignclient
正常使用就必须对domain
内服务进行拆分,实现一个服务一个domain
,这就是APUSIC_HOME/domains
目录中包含s
意义啦。开始干
步骤一
拷贝mydomain
整个文件夹,改为自己的服务名称,mydomain
内部的default
文件可以删除了,没啥用,sample
觉得碍眼也可删除,以下都以我自己的web
服务介绍。
cp -r mydomain 自己的服务名称(如图七)
步骤二
选择
web
服务目录进入,有四个重要目录需要关注,其他的不用管
目录 | 作用 |
---|---|
applications | war包服务放置目录 |
bin | 服务启动脚本 |
config | 服务配置目录,主要修改server.xml、apusic.conf这两个文件 |
logs | 控制台日志输出 |
1、 选择config
目录进入,修改server.xml
、apusic.conf
配置文件
1.1、 修改server.xml
,name
为服务名称,base
为applications
目录下war
包名称,如applications/web.war
,修改后保存并退出。
vim server.xml
1.2、 修改
apusic.conf
配置文件,查找Port
设置端口号,注意此处的端口必须与服务在Euraka
注册中心的端口号保持一致,不然服务之间无法使用feignclient
访问,修改后保存并退出。
vim apusic.conf
- 注意 :服务部署到
apusic
中间件启动后,各个服务模块会根据自生properties
中配置的端口,注册到Euraka
中,服务之间调用地址都是从Euraka
获取到的,所以在给每个domain
设置的端口要与注册到Euraka
中保持一致,不然是无法访问的。
2、 在bin
子目录中,提供了预设的启动脚本 startapusic
,可直接使用此脚本启动 apusic
应用服务器。startapusic
提供了多种启动参数,还可以配置 JVM 参数。修改startapusic
启动脚本,在这个脚本中可以设置spring
一些启动参数
本项目设置的启动使用
application-gmprd.properties
配置文件,只需要修改else
中即可,修改完成保存并退出。
vim startapusic
启动脚本有两种方式:
终端退出,服务会关闭
第一种:./startapusic
后台启动方式下,终端的退出不会导致 apusic 服务的退出
第一种:nohup ./startapusic &
步骤三
最后一步,也是最重要的一步,为防止金蝶中间件在服务启动后,会指定http
访问该应用时的上下文根路径(context-root)
(以服务名即上下文根路径,前面讲到过),需要手动配置服务上下文根路径。根据金蝶用户手册29.2.2
章节提供的方式,需要手动创建一个apusic-application.xml
文件,使服务可以找到这个文件,以下是我总结了做出两种方式。
1、在server.xml
中增加一个config
配置项,指定 apusic-application.xml
配置文件路径,如图十三,我把文件放在domains
下,这样在需要部署多个服务是都可以指向这个一个文件,可以共用。
2、 把
apusic-application.xml
文件放入打好的war
包中,直接用解压工具打开war
包,把文件拖入 META-INF
目录下,如下图十四:
apusic-application.xml配置内容,直接复制可用
/
- 友情提示 :最好还是选用第二种方式,因为在使用第一种方式时,虽然解决了上下文根路径问题,但是
Apusic
控制台会报错,apusic-application.xml
是不合法的java
文件,看着贼不舒服,不知道是Apusic
问题还是什么,所以我选用的第二种方式,虽然每次打包,都要往META-INF
拖入一遍,但是胜在不报错啊。噢,对了,如果用的第二中方式,就不要在配置config
项了,不然还是有路径问题,都是一步步被坑过来的。
ok,到这里基本上所有的配置说明都讲解完事了,上传war
到applications
中,然后运行启动脚本,如图十五,看到Context Root [/]
内没有服务名,就是设置成功了,可以部署你的多个服务测试下feignclient
之间调用了。
这种适配网上资料很少,希望能给你提供帮助!
金蝶还有个Web应用服务器监控管理平台,就不多介绍了,金蝶用户手册有介绍。
========================2020-7-7===============================
适配过程中又发现新问题:
弄了个注册中心,启动报错,这个包在tomcat下是没有问题的可以正常启动不报错,但是在金蝶中间件内启动就有问题了,Tomcat对不适用的类,不会进行加载,但是金蝶的会启动时候全局加载,导致对引用的代码比较严格。
根据报错问题排查,发现freemarker这个jar包内依赖org.apache.log.Hierarchy,但是在jar内并没有找到,如下图可以发现,无法找到,但是并不影响编译,最后解决方式是,引入org.apache.log解决:
log4j
log4j
1.2.15
javax.mail
mail
javax.jms
jms
com.sun.jdmk
jmxtools
com.sun.jmx
jmxri
compile
注意log4j的scope为compile
使用springboot的应用出现streamclose异常时,在vm.options加上这个参数apusic.webcontainer.close.after.forward=false,屏蔽streamclose异常,显示真实错误信息
在domains/mydomain/config/vm.options里面修改下
========================2020-10-27===============================
因为在 Apusic 应用服务器中部署的 Web 应用,提供多种策略指定 http 访问该应用时的上下文根路径(context-root)。
• 第一种:使用apusic-application.xml
参考 Apusic 的 default 应用的 apusic-application.xml 如下:
/
其中,
在domain目录下 config 目录中的 server.xml 文件中,可指定一个应用的 base-context,如下:
这种方式 服务启动报错的话,base-context可能会被自动去掉,也是很麻烦。所以我一直采用的第一种。
当 base-context 不为空时,如果应用没有配置 context-root,那么 base-context 即为该应用的 cont ext-root;如果该应用的 web 模块配置了 context-root,那么该应用所有 web 模块的 context-root 会以 b ase-context 为前缀。比如 app1 的 base-context 为 app1,app1 下有个 web 模块的 context-root 为 web1, 那么访问该 web 模块的路径为 http://hostname/app1/web1/。
• 应用名即上下文根路径
如果 base-context 和 context-root 都未配置,那么 apusic 会按照以下规则指定 web 应用的上下文 根路径:如果应用是ear模块,那么指定apusic-application.xml中该web module的uri值为根路径; 如果应用是 web 模块,那么 web 应用的根路径为 server.xml 中指定的应用名,即"name"属性的值。 如果上述值以".war"结尾,那么去除".war"后的值为 context-root。
第一种方式,因为部署的地方增多,每次都要手动放置apusic-application.xml很麻烦,所以做了调整,把apusic-application.xml放置在resource中
然后早pom.xml增加这个配置:
org.apache.maven.plugins
maven-war-plugin
src/main/resources
META-INF/
**/apusic-application.xml
这样打包出来的war就自动带有apusic-application.xml配置了
- 提示错误
Caused by: java.lang.NoClassDefFoundError: org/apache/catalina/servlet4preview/http/HttpServletRequest
或
Caused by: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]] - 错误原因
导错包了,HttpServletRequest类引入的包应该是javax.servlet.http.HttpServletRequest,而不应该是org.apache.catalina.servlet4preview.http.HttpServletRequest