[Tistory] 230928

원글 페이지 : 바로가기

due on or before today
short mode
not done
🍒 오늘 공부한 내용 커넥션 풀링 (Connection Pooling) DataSource 객체를 통해 미리 커넥션을 만들어 두는 것 새로운 커넥션을 생성하는 것이 비용이 많이 들어서 미리 만들어두면 성능상 이점이 있다. (쓰레드 풀에 미리 쓰레드 만들어 놓는 것과 같은 이점) 리소스 관리 쓰레드 재사용 제어 가능한 병렬처리 부하 분산 커넥션 풀링에 미리 만들어둔 커넥션은 재사용 가능 Connection Pooling and Statement Pooling package connectionpool;

import com.mysql.cj.jdbc.MysqlDataSource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.util.ClockSource;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
* pooling을 사용한 경우와 사용하지 않은 경우 트래픽이 얼마나 차이나는지 확인해보자.
*
* network bandwidth capture
* 터미널에 iftop를 설치하고 아래 명령어를 실행한 상태에서 테스트를 실행하자.
* $ sudo iftop -i lo0 -nf “host localhost”
* windows 사용자라면 wsl2를 사용하거나 다른 모니터링 툴을 찾아보자.
*/
class PoolingVsNoPoolingTest {

private final Logger log = LoggerFactory.getLogger(PoolingVsNoPoolingTest.class);

private static final int COUNT = 1000;

private static MySQLContainer container;

@BeforeAll
static void beforeAll() throws SQLException {
// TestContainer로 임시 MySQL을 실행한다.
container = new MySQLContainer<>(DockerImageName.parse(“mysql:8.0.30”))
.withDatabaseName(“test”);
container.start();

final var dataSource = createMysqlDataSource();

// 테스트에 사용할 users 테이블을 생성하고 데이터를 추가한다.
try (Connection conn = dataSource.getConnection()) {
conn.setAutoCommit(true);
try (Statement stmt = conn.createStatement()) {
stmt.execute(“DROP TABLE IF EXISTS users;”);
stmt.execute(“CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(100) NOT NULL) ENGINE=INNODB;”);
stmt.executeUpdate(“INSERT INTO users (email) VALUES (‘hkkang@woowahan.com’)”);
conn.setAutoCommit(false);
}
}
}

@AfterAll
static void afterAll() {
container.stop();
}

@Test
void noPooling() throws SQLException {
final var dataSource = createMysqlDataSource();

long start = ClockSource.currentTime();
connect(dataSource);
long end = ClockSource.currentTime();

// 테스트 결과를 확인한다.
log.info(“Elapsed runtime: {}”, ClockSource.elapsedDisplayString(start, end));
}

@Test
void pooling() throws SQLException {
final var config = new HikariConfig();
config.setJdbcUrl(container.getJdbcUrl());
config.setUsername(container.getUsername());
config.setPassword(container.getPassword());
config.setMinimumIdle(1);
config.setMaximumPoolSize(1);
config.setConnectionTimeout(1000);
config.setAutoCommit(false);
config.setReadOnly(false);
final var hikariDataSource = new HikariDataSource(config);

long start = ClockSource.currentTime();
connect(hikariDataSource);
long end = ClockSource.currentTime();

// 테스트 결과를 확인한다.
log.info(“Elapsed runtime: {}”, ClockSource.elapsedDisplayString(start, end));
}

private static void connect(DataSource dataSource) throws SQLException {
// COUNT만큼 DB 연결을 수행한다.
for (int i = 0; i < COUNT; i++) { try (Connection connection = dataSource.getConnection()) { try (Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM users")) { if (rs.next()) { rs.getString(1).hashCode(); } } } } } private static MysqlDataSource createMysqlDataSource() throws SQLException { final var dataSource = new MysqlDataSource(); dataSource.setUrl(container.getJdbcUrl()); dataSource.setUser(container.getUsername()); dataSource.setPassword(container.getPassword()); dataSource.setConnectTimeout(1000); return dataSource; } } 커넥션 풀링 안 한 경우 -> peak 11.6Mb 커넥션 풀링 한 경우 -> peak 6.79Mb HikariCP Spring Boot 2.0 부터 HikariCP를 기본 데이터 소스로 채택 하고 있다. Supported Connection Pools We prefer HikariCP for its performance and concurrency. If HikariCP is available, we always choose it. HikariCP 공식 문서를 참고하여 HikariCP를 설정해보자. HikariCP 필수 설정 HikariCP의 pool size는 몇으로 설정하는게 좋을까? HikariCP를 사용할 때 적용하면 좋은 MySQL 설정 Spring Boot에서 설정 파일인 application.yml을 통해 DataSource설정 가능 하지만 데이터소스 여러 개 쓰거나 세부 설정 하려면 빈을 직접 생성함 DataSourceConfig 클래스 -> getInstance() 하면 DataSource 인스턴스 가져옴 설정한 커넥션 풀 최대값보다 더 많은 쓰레드 생성해서 동시에 디비 접근 시도해도 최대 풀 사이즈 유지함 쓰레드 10개, 커넥션 5개일 때 쓰레드 15개, 커넥션 5개일 때 쓰레드 15개, 커넥션 10개일 때 => ??? 다섯개나 10개씩만 들어가야하는거아닌가?? 쓰레드-커넥션 풀 실험 이유 찾기 🎶 느낀 점 & 배운 점 오늘 계획 한 것 : 미션 PR 날리기 추석 계획 세우기 – 강의 다시 듣기, 노트 정리, 이력서, 포트폴리오, 우테코에서 배운 것 정리 오픽 준비 어제 못 푼 이분탐색 문제 다시 이벤트 써야하는 거 => 감상 잇는 여행 삭제 안되는 거 해결 쿼리 튜닝 마무리 오늘 한 것 : 미션 PR 날리기 공부할 것 : 펼치기 API versioning

AsyncUncaughtExceptionHandler

TaskDecorator

ThreadPoolTaskExecutor

@ConfigurationProperties

톰캣 기본 8192개 어떻게 쓰이나?

ngrinder

locust
jmeter
k6

gradle로 빌드하면 q타입 읽는데 intellij로 하면 못읽는 문제

cqrs pattern

Modifier

쓰레드 풀 설정 <- 테코블 글 써보기?

native thread, green thread

process lifecycle

역정규화

파티션 프루닝

커버링 인덱스

스케쥴 프로그램, 배치 프로그램

TransactionTemplate

Event @Order
@RecordApplicationEvents

HAProxy

DB 장애 대처
레플리카
Binary Log 기반
GTID 기반

virtual stored

-> stored는 왜 칼럼 따로 안하고 버츄얼에 있지?

enum 사용하면 reflection을 통한 생성도 방지

싱크홀패턴

JVM의 쓰레드와 운영체제의 쓰레드

리플렉션 자세하게

라운드로빈

DNS

WeakHashMap

nslookup

포스트모뎀

NIO

completable future
Spring Web Flux

자바의 Synchronized -> monitor lock

@PostConstruct
@HandlebarsHelper

WebContentInterceptor

REST한 요청

DNS

CORS – Preflight 

CDN

CAS (Compare and Swap) 알고리즘

Configuration Property Scan

static field 언제 올라감?

Mozilla

ClassLoader가 어떻게 읽음?

spring boot project build package 생기는 이유랑 왜 거기서 클래스패스 찾는지

[https://velog.io/@ohzzi/F12%EC%9D%98-%EB%88%88%EB%AC%BC%EB%82%98%EB%8A%94-%EC%BF%BC%EB%A6%AC-%EA%B0%9C%EC%84%A0%EA%B8%B0-%EC%9D%B4%EB%A1%A0%ED%8E%B8](https://velog.io/@ohzzi/F12%EC%9D%98-%EB%88%88%EB%AC%BC%EB%82%98%EB%8A%94-%EC%BF%BC%EB%A6%AC-%EA%B0%9C%EC%84%A0%EA%B8%B0-%EC%9D%B4%EB%A1%A0%ED%8E%B8)오찌 쿼리 개선기

오찌 로깅

[https://velog.io/@saint6839/Controller%EC%97%90%EC%84%9C-HttpRequest-Body-%EA%B0%92%EC%9D%80-%EC%99%9C-%EB%B9%84%EC%9B%8C%EC%A0%B8-%EC%9E%88%EC%9D%84%EA%B9%8C](https://velog.io/@saint6839/Controller%EC%97%90%EC%84%9C-HttpRequest-Body-%EA%B0%92%EC%9D%80-%EC%99%9C-%EB%B9%84%EC%9B%8C%EC%A0%B8-%EC%9E%88%EC%9D%84%EA%B9%8C) getBody 왜 비워져있는지

필터 인터셉터 빈등록

StatementInspector

쿼리카운터 -> ThreadLocal

로그인 -> 인터셉터 or 필터

Join Column 공부

createdDate CreationTime

entity listener
MappedSuperClass

웹소켓

블루그린, 레드블랙, 롤링
flyway -> 롤백하는 경우 스키마 관리에 문제 생김

@Retention -> [https://jeong-pro.tistory.com/234](https://jeong-pro.tistory.com/234)

composite 패턴
decorate 패턴

검프 도커 테코톡 실습편

@Valid 에서 잡은 예외 허브가 해 놓은거 이해하기

ssh 설정

propagation, isolation 직접 설정 ([https://velog.io/@kdhyo/JavaTransactional-Annotation-%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-26her30h](https://velog.io/@kdhyo/JavaTransactional-Annotation-%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-26her30h)) -> 이거 보고 감 잡기
팬텀리드 예시 다시 보기
DB에서 B-Tree 쓰는 이유
복합키
Unique 동시에 걸기
인덱스 스킵 스캔

springfox, springdoc

CQRS

LAZY Loading (Transactional 사용하지 않으면 못 쓰는 이유)
Fetch Join

@ContextConfiguration(classes = TestSyncConfig.class)

나아가팀 배포 스크립트문제 -> 쉘 스크립트 프로세스 물고 있는 문제

동욱님 JPA Exists 쿼리 성능 개선 블로그
동욱님 예외레벨 블로그

나아가팀 AuthInterceptor에서 터지는 예외가 ControllerAdvice에서 처리도 되고, 콘솔에 에러라고 찍히기도 함 -> 해결못함

CD 할 때 도커 허브

토큰 암호화

self-join

certbot 

jpa bulk insert 할 때 auto increment 이면 안됨

토큰 세션 장단점

syncronized, 비관적 락 장단점

비동기와 트랜잭션

@AttributeOverride

레디스
메세지 큐
R-Tree

커버링인덱스

대칭키 암호화 비대칭키 암호화 복호화

모든 엔티티의 변수를 VO로

🌸 감정회고 집 내려가서 가족도 보고 로리도 봐야하는데… 후회없게 열심히 하자

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다