基于两个数据库的 Spring Boot Batch-REST-api 的 Docker 问题

Posted

技术标签:

【中文标题】基于两个数据库的 Spring Boot Batch-REST-api 的 Docker 问题【英文标题】:Docker problem with Springboot Batch-REST-app based on two DBs 【发布时间】:2020-12-31 16:04:52 【问题描述】:

我是 Docker 新手,我将基于单个数据库的 Springboot REST 应用程序容器化,没有任何问题。但是当我尝试基于一个管理两个数据库的应用程序做一组类似的容器时,我遇到了麻烦。当我运行 Docker Compose 时,我得到一个错误,说它找不到 DB social_bank_db。有关详细信息,请参阅列出的错误块。

sociobankdbpostgres | 2020-09-12 19:58:09.404 UTC [32] FATAL:  database "socio_bank_db" does not exist
sociobank          | 2020-09-12 19:58:09,472 ERROR [main] com.zaxxer.hikari.pool.HikariPool: HikariPool-1 - Exception during pool initialization.
sociobank          | org.postgresql.util.PSQLException: FATAL: database "socio_bank_db" does not exist
sociobank          |    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2497)
sociobank          |    at org.postgresql.core.v3.QueryExecutorImpl.readStartupMessages(QueryExecutorImpl.java:2618)
sociobank          |    at org.postgresql.core.v3.QueryExecutorImpl.<init>(QueryExecutorImpl.java:135)
sociobank          |    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:250)
sociobank          |    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
sociobank          |    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
sociobank          |    at org.postgresql.Driver.makeConnection(Driver.java:458)
sociobank          |    at org.postgresql.Driver.connect(Driver.java:260)
sociobank          |    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
sociobank          |    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:353)
sociobank          |    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201)
sociobank          |    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:473)
sociobank          |    at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:562)
sociobank          |    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115)
sociobank          |    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112)

接下来找到 Docker 和 Compose 文件以及应用程序属性:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
EXPOSE 8082
RUN mkdir -p /app/
RUN mkdir -p /app/logs/
COPY /target/sociobank-1.0-SNAPSHOT.jar /app/app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=container", "-jar", "/app/app.jar"]


version: "3"
services:
  sociobankdb:
    image: postgres:latest
    network_mode: bridge
    container_name: sociobankpostgres
    restart: always
    volumes:
      - postgres-data:/var/lib/postgresql/data
    ports:
      - 5434:5432
    environment:
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_DB=socio_bank_db
# second DB***************************************** 
  sociobankmetadb:
    image: postgres:latest
    network_mode: bridge
    container_name: sociobankmetapostgres
    restart: always
    volumes:
      - postgres-data:/var/lib/postgresql/data
    ports:
      - 5433:5432
    environment:
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_DB=socio_bank_batch_meta_data_db
# APP*****************************************
  springbootapp:
    image: sociobank:latest
    network_mode: bridge
    container_name: sociobank
    expose:
      - 8082
    ports:
      - 8082:8082
    restart: unless-stopped
    depends_on:
      - sociobankdb
      - sociobankmetadb
    links:
      - sociobankdb
      - sociobankmetadb
volumes:
  postgres-data:


#Backend validation messages
spring.messages.basename=error-messages
spring.messages.cache-seconds=-1
spring.messages.encoding=UTF-8

spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false
spring.main.allow-bean-definition-overriding=true

#app.datasource.batch.url=jdbc:postgresql://localhost:5432/socio_bank_batch_meta_data_db
app.datasource.batch.url=jdbc:postgresql://sociobankmetadb:5432/socio_bank_batch_meta_data_db
app.datasource.batch.driverClassName=org.postgresql.Driver
app.datasource.batch.username=postgres
app.datasource.batch.password=postgres
app.datasource.batch.schema=classpath:metadata.sql

#app.datasource.db.url=jdbc:postgresql://localhost:5432/socio_bank_db
app.datasource.db.url=jdbc:postgresql://sociobankdb:5432/socio_bank_db
app.datasource.db.driverClassName=org.postgresql.Driver
app.datasource.db.username=postgres
app.datasource.db.password=postgres
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
spring.datasource.initialization-mode=always

spring.batch.initialize-schema=always
spring.batch.job.enabled=false

spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=false
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
server.port=8082

最后我列出了所有关于 Postres 中两个 DB 配置的类。

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.artsgard.sociobank.repository", "com.artsgard.sociobank.config" ,
                entityManagerFactoryRef = "dbEntityManagerFactory", 
                transactionManagerRef = "dbTransactionManager")
public class BatchDbRepoConfig 

    @Bean(name = "dbDataSourceProperties")
    @ConfigurationProperties("app.datasource.db")
    public DataSourceProperties dataSourceProperties() 
        return new DataSourceProperties();
    

    @Bean(name = "dbDataSource")
    @ConfigurationProperties("app.datasource.db.hikari")
    public DataSource dataSource(@Qualifier("dbDataSourceProperties") DataSourceProperties dataSourceProperties) 
        return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class)
                .build();
    

    

    @Bean(name = "dbEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder, @Qualifier("dbDataSource") DataSource dataSource) 
        return builder
                    .dataSource(dataSource)
                    .packages("com.artsgard.sociobank.model")
                    .persistenceUnit("db")
                    .build();
    

    @Bean(name = "dbTransactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("dbEntityManagerFactory") EntityManagerFactory entityManagerFactory)        
        return new JpaTransactionManager(entityManagerFactory);
    



@Configuration
public class BatchDbMetaDataRepoConfig 

    @Primary
    @Bean(name = "batchDataSourceProperties")
    @ConfigurationProperties("app.datasource.batch")
    public DataSourceProperties dataSourceProperties() 
        return new DataSourceProperties();
    

    @Primary
    @Bean(name = "batchDataSource")
    @ConfigurationProperties("app.datasource.batch.hikari")
    public DataSource dataSource(@Qualifier("batchDataSourceProperties") DataSourceProperties dataSourceProperties) 
        return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    


public class JobRepositoryConfig extends DefaultBatchConfigurer 

    @Autowired
    @Qualifier("transactionManager")
    private PlatformTransactionManager transactionManager;

    @Autowired
    @Qualifier("batchDataSource")
    private DataSource datasource;

    @Override
    protected JobRepository createJobRepository() throws Exception 
        JobRepositoryFactoryBean factoryBean = new JobRepositoryFactoryBean();
        factoryBean.setDatabaseType(DatabaseType.POSTGRES.getProductName());
        factoryBean.setTablePrefix("BATCH_");
        factoryBean.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
        factoryBean.setDataSource(datasource);
        factoryBean.setTransactionManager(transactionManager);
        factoryBean.afterPropertiesSet();
        return factoryBean.getObject();
    

该应用程序可以在 github 上找到

sociobank application

顺便说一句,在 Docker (localhost) 之外,一切正常!

【问题讨论】:

【参考方案1】:

您在两个 postgres 实例中使用相同的端口映射。更改它们以使用不同的端口。因此,也可以更改应用程序中的端口,并且事情应该可以正常工作。阅读有关 docker 网络的信息以获得更清晰的信息。

【讨论】:

感谢您的回复!但是我该怎么办: app.datasource.db.url=jdbc:postgresql://sociobankdb:5432/socio_bank_db app.datasource.batch.url=jdbc:postgresql://sociobankmetadb:5433/socio_bank_batch_meta_data_db 例如。但我不清楚 Compose 文件中的端口应该是什么:5432 中的一个应该映射到端口?:? 和4533端口之一?:?

以上是关于基于两个数据库的 Spring Boot Batch-REST-api 的 Docker 问题的主要内容,如果未能解决你的问题,请参考以下文章

217.Spring Boot+Spring Security:基于内存的角色授权

spring boot: spring boot+jdbctemplate+sql server

基于 Spring Boot 的 MySQL 实现读写分离,看这篇就够了!

spring cloud和spring boot两个完整项目

Spring Boot多数据源配置与使用

从 Spring Boot 应用程序中排除 @Configuration