【问题标题】:How to deploy multiple Spring boot applications with external configurations on the same Tomcat?如何在同一个 Tomcat 上部署多个带有外部配置的 Spring Boot 应用程序?
【发布时间】:2019-07-28 10:06:16
【问题描述】:

当我想在同一个 tomcat 上部署多个 Spring-Boot 应用程序时,我面临着多个问题。

1) 两个应用程序必须独立运行,同时共享同一个 tomcat。在同一个 tomcat 上部署两个 Spring-Boot 应用程序时,出现以下异常:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-03-06 17:31:01 ERROR o.s.boot.SpringApplication - Application run failed
org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [HikariDataSource (HikariPool-2)] with key 'dataSource'; nested exception is javax.management.InstanceAlreadyExistsException: com.zaxxer.hikari:name=dataSource,type=HikariDataSource
    at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:625)
    at org.springframework.jmx.export.MBeanExporter.lambda$registerBeans$2(MBeanExporter.java:551)
    at java.util.HashMap.forEach(HashMap.java:1289)
    at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:551)
    at org.springframework.jmx.export.MBeanExporter.afterSingletonsInstantiated(MBeanExporter.java:434)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:863)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:157)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:137)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:171)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5267)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:754)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:629)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1839)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
    at java.util.concurrent.FutureTask.run(FutureTask.java)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: javax.management.InstanceAlreadyExistsException: com.zaxxer.hikari:name=dataSource,type=HikariDataSource
    at com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:437)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerWithRepository(DefaultMBeanServerInterceptor.java:1898)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:966)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:900)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:324)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522)
    at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:137)
    at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:671)
    at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:615)
    ... 28 common frames omitted

2) 我需要为两个应用程序提供外部配置,并且需要明确每个应用程序使用正确的配置。

【问题讨论】:

    标签: java spring spring-boot tomcat


    【解决方案1】:

    1) 当两个 Spring-Boot 应用程序在同一个 tomcat 上运行时,通常会遇到数据源的实例化可能失败的问题,因为已经存在同名的实例。这是您在问题中描述的例外情况。

    这可以通过为每个 Spring-Boot 应用程序添加一个唯一的名称来解决,例如在

    application.yml

    spring:
      application:
        name: application-name-1
      jmx:
        default-domain: application-name-1
    

    2) 为每个 Spring-Boot 应用程序提供外部配置可以通过每个应用程序单独的 tomcat 上下文配置来完成。假设所有应用程序都部署为.war,例如app1.war, app2.war 我们需要为这两个应用程序配置上下文如下:

    创建以下文件(如果缺少,则创建目录)

    tomcat-base-dir
      /conf
        /catalina
          /localhost #must be the same as specified in the Host tag in the server.xml
            app1.xml #must have the same name as the .war application file
            app2.xml
    

    app1.xml 的内容

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- docBase must contain be the name of the application to be configured -->
    <Context docBase="app1.war"> 
        <Parameter name="spring.config.location" value="${catalina.base}/conf/app1.yml" />
    </Context>
    

    这将配置应用程序app1.war 使用文件app1.yml 进行配置。对 app2 执行相同的操作。实际配置文件app1.yml可以位于值中指定的任意路径。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-27
      • 1970-01-01
      • 2019-07-28
      • 1970-01-01
      • 1970-01-01
      • 2018-08-29
      • 1970-01-01
      • 2016-03-28
      相关资源
      最近更新 更多