diff --git a/server/docker-compose.yml b/server/docker-compose.yml index 88312a05..453ab1e5 100644 --- a/server/docker-compose.yml +++ b/server/docker-compose.yml @@ -14,6 +14,11 @@ services: command: [ "mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_general_ci" ] volumes: - db-data:/var/lib/mysql + # my.cnf의 server_id 값은 복제에 참여한 MySQL 서버들이 고유하게 가지고 있는 식별 값이다. + # 이 값은 바이너리 로그에 이벤트별로 이벤트가 최초로 발생한 MySQL을 식별하기 위해 사용되며, 기본값이 모두 1이다. + # 이 때문에 Master 서버와 Slave 서버를 구별할 수 있도록 Slave 서버의 server_id를 바꾸어 주기 위해 volume 매핑을 진행해야한다. + # my.cnf 파일이 존재해야한다. + - ./my.cnf:/etc/my.cnf volumes: db-data: diff --git a/server/src/main/java/com/project/yozmcafe/config/datasource/DataSourceConfig.java b/server/src/main/java/com/project/yozmcafe/config/datasource/DataSourceConfig.java new file mode 100644 index 00000000..5795c558 --- /dev/null +++ b/server/src/main/java/com/project/yozmcafe/config/datasource/DataSourceConfig.java @@ -0,0 +1,60 @@ +package com.project.yozmcafe.config.datasource; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; +import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy; + +import javax.sql.DataSource; +import java.util.Map; + +@Configuration +@Profile({"prod"}) +public class DataSourceConfig { + + public static final String MASTER_DATA_SOURCE = "master"; + private static final String MASTER_DATA_SOURCE_LOCATION = "spring.datasource.master"; + public static final String SLAVE_DATA_SOURCE = "slave"; + private static final String SLAVE_DATA_SOURCE_LOCATION = "spring.datasource.slave"; + private static final String ROUTING_DATA_SOURCE = "routingDataSource"; + + @Bean + @Qualifier(MASTER_DATA_SOURCE) + @ConfigurationProperties(prefix = MASTER_DATA_SOURCE_LOCATION) + public DataSource masterDataSource() { + return DataSourceBuilder.create() + .build(); + } + + @Bean + @Qualifier(SLAVE_DATA_SOURCE) + @ConfigurationProperties(prefix = SLAVE_DATA_SOURCE_LOCATION) + public DataSource slaveDataSource() { + return DataSourceBuilder.create() + .build(); + } + + @Bean + @Qualifier(ROUTING_DATA_SOURCE) + public DataSource routingDataSource(@Qualifier(MASTER_DATA_SOURCE) DataSource sourceDataSource, + @Qualifier(SLAVE_DATA_SOURCE) DataSource replicaDataSource) { + final RoutingDataSource routingDataSource = new RoutingDataSource(); + final Map dataSources = Map.of(MASTER_DATA_SOURCE, sourceDataSource, + SLAVE_DATA_SOURCE, replicaDataSource); + + routingDataSource.setDefaultTargetDataSource(dataSources.get(MASTER_DATA_SOURCE)); + routingDataSource.setTargetDataSources(dataSources); + + return routingDataSource; + } + + @Bean + @Primary + public DataSource dataSource(@Qualifier(ROUTING_DATA_SOURCE) DataSource routingDataSource) { + return new LazyConnectionDataSourceProxy(routingDataSource); + } +} diff --git a/server/src/main/java/com/project/yozmcafe/config/datasource/RoutingDataSource.java b/server/src/main/java/com/project/yozmcafe/config/datasource/RoutingDataSource.java new file mode 100644 index 00000000..b5979b16 --- /dev/null +++ b/server/src/main/java/com/project/yozmcafe/config/datasource/RoutingDataSource.java @@ -0,0 +1,18 @@ +package com.project.yozmcafe.config.datasource; + +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import static com.project.yozmcafe.config.datasource.DataSourceConfig.MASTER_DATA_SOURCE; +import static com.project.yozmcafe.config.datasource.DataSourceConfig.SLAVE_DATA_SOURCE; + +public class RoutingDataSource extends AbstractRoutingDataSource { + @Override + protected Object determineCurrentLookupKey() { + final boolean isReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly(); + if(isReadOnly){ + return SLAVE_DATA_SOURCE; + } + return MASTER_DATA_SOURCE; + } +} diff --git a/server/src/main/resources/application-test.properties b/server/src/main/resources/application-test.properties deleted file mode 100644 index ea37a068..00000000 --- a/server/src/main/resources/application-test.properties +++ /dev/null @@ -1,25 +0,0 @@ -spring.auth.key=testtesttesttesttesttesttesttesttesttesttesttesttesttesttest -spring.auth.accessTokenExpired=360000 -spring.auth.refreshTokenExpired=36000000 -spring.auth.google.tokenUri=testtesttesttesttesttest -spring.auth.google.authUri=testtesttesttesttesttest -spring.auth.google.clientId=testtesttesttesttesttest -spring.auth.google.clientSecret=testtesttesttesttesttest -spring.auth.google.redirectUri=testtesttesttesttesttest -spring.auth.google.scope=testtesttesttesttesttest -spring.auth.kakao.tokenUri=testtesttesttesttesttest -spring.auth.kakao.authUri=testtesttesttesttesttest -spring.auth.kakao.clientId=testtesttesttesttesttest -spring.auth.kakao.clientSecret=testtesttesttesttesttest -spring.auth.kakao.redirectUri=testtesttesttesttesttest -spring.auth.kakao.scope=testtesttesttesttesttest -s3.bucket=2023-team-project/2023-yozm-cafe/test -spring.servlet.multipart.max-file-size=11MB -spring.servlet.multipart.max-request-size=110MB -spring.jpa.show-sql=true -spring.jpa.properties.hibernate.format_sql=true -spring.flyway.enabled=true -spring.flyway.baseline-version=20230901153300 -spring.flyway.baseline-on-migrate=true -spring.flyway.out-of-order=true -spring.jpa.properties.hibernate.default_batch_fetch_size=1000 diff --git a/server/src/main/resources/application-test.yaml b/server/src/main/resources/application-test.yaml new file mode 100644 index 00000000..0bfd905e --- /dev/null +++ b/server/src/main/resources/application-test.yaml @@ -0,0 +1,40 @@ +spring: + auth: + key: testtesttesttesttesttesttesttesttesttesttesttesttesttesttest + accessTokenExpired: 360000 + refreshTokenExpired: 36000000 + google: + tokenUri: testtesttesttesttesttest + authUri: testtesttesttesttesttest + clientId: testtesttesttesttesttest + clientSecret: testtesttesttesttesttest + redirectUri: testtesttesttesttesttest + scope: testtesttesttesttesttest + kakao: + tokenUri: testtesttesttesttesttest + authUri: testtesttesttesttesttest + clientId: testtesttesttesttesttest + clientSecret: testtesttesttesttesttest + redirectUri: testtesttesttesttesttest + scope: testtesttesttesttesttest + + servlet: + multipart: + max-file-size: 11MB + max-request-size: 110MB + + flyway: + enabled: true + baseline-version: 20230901153300 + baseline-on-migrate: true + out-of-order: true + + jpa: + properties: + hibernate: + default_batch_fetch_size: 1000 + format_sql: true + show-sql: true + +s3: + bucket: 2023-team-project/2023-yozm-cafe/test/images diff --git a/server/src/main/resources/application.properties b/server/src/main/resources/application.properties deleted file mode 100644 index 745746e3..00000000 --- a/server/src/main/resources/application.properties +++ /dev/null @@ -1,32 +0,0 @@ -spring.datasource.url=jdbc:mysql://localhost:20000/yozm-cafe?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8&serverTimezone=UTC -spring.datasource.username=root -spring.datasource.password=root -spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.jpa.hibernate.ddl-auto=validate -spring.auth.key=testtesttesttesttesttesttesttesttesttesttesttesttesttesttest -spring.auth.accessTokenExpired=360000 -spring.auth.refreshTokenExpired=36000000 -spring.auth.google.tokenUri=testtesttesttesttesttest -spring.auth.google.authUri=testtesttesttesttesttest -spring.auth.google.clientId=testtesttesttesttesttest -spring.auth.google.clientSecret=testtesttesttesttesttest -spring.auth.google.redirectUri=testtesttesttesttesttest -spring.auth.google.scope=testtesttesttesttesttest -spring.auth.kakao.tokenUri=testtesttesttesttesttest -spring.auth.kakao.authUri=testtesttesttesttesttest -spring.auth.kakao.clientId=testtesttesttesttesttest -spring.auth.kakao.clientSecret=testtesttesttesttesttest -spring.auth.kakao.redirectUri=testtesttesttesttesttest -spring.auth.kakao.scope=testtesttesttesttesttest -s3.bucket=2023-team-project/2023-yozm-cafe/dev -spring.servlet.multipart.max-file-size=11MB -spring.servlet.multipart.max-request-size=110MB -management.endpoints.web.exposure.include=prometheus, logfile -management.endpoint.logfile.external-file=./logs/spring-boot-logger.log -spring.flyway.enabled=true -spring.flyway.baseline-version=20230901153300 -spring.flyway.baseline-on-migrate=true -spring.flyway.out-of-order=true -spring.jpa.properties.hibernate.default_batch_fetch_size=1000 -spring.jpa.open-in-view=false - diff --git a/server/src/main/resources/application.yaml b/server/src/main/resources/application.yaml new file mode 100644 index 00000000..a726a4d9 --- /dev/null +++ b/server/src/main/resources/application.yaml @@ -0,0 +1,54 @@ +spring: + datasource: + url: jdbc:mysql://localhost:20000/yozm-cafe?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8&serverTimezone=UTC + username: root + password: root + driver-class-name: com.mysql.cj.jdbc.Driver + + auth: + key: testtesttesttesttesttesttesttesttesttesttesttesttesttesttest + accessTokenExpired: 360000 + refreshTokenExpired: 36000000 + google: + tokenUri: testtesttesttesttesttest + authUri: testtesttesttesttesttest + clientId: testtesttesttesttesttest + clientSecret: testtesttesttesttesttest + redirectUri: testtesttesttesttesttest + scope: testtesttesttesttesttest + kakao: + tokenUri: testtesttesttesttesttest + authUri: testtesttesttesttesttest + clientId: testtesttesttesttesttest + clientSecret: testtesttesttesttesttest + redirectUri: testtesttesttesttesttest + scope: testtesttesttesttesttest + + servlet: + multipart: + max-file-size: 11MB + max-request-size: 110MB + + flyway: + enabled: true + baseline-version: 20230901153300 + baseline-on-migrate: true + out-of-order: true + + jpa: + properties: + hibernate: + default_batch_fetch_size: 1000 + +s3: + bucket: 2023-team-project/2023-yozm-cafe/dev/images + +management: + endpoints: + web: + exposure: + include: prometheus, logfile + + endpoint: + logfile: + external-file: ./logs/spring-boot-logger.log