Journal17 DB서버 병목 장애 해결기: 5시간 배치를 5분으로 만들기 *보안을 준수하기 위해 각종 명칭은 모두 디저트 명으로 대체했다문제 상황맡은지 한 달이 된 서비스에서 daily batch 작업 실행 중 심각한 DB 서버 병목 현상이 발생해 서비스 장애로 이어졌다.증상특정 쿼리가 5시간 동안 실행되며 결과를 반환하지 않음후속 작업들이 대기 상태로 멈춰 batch 프로세스 전체가 중단해당 프로세스 이후의 데이터 처리 파이프라인 진행 모두 중단쿼리 자체는 기존과 동일했으나, 서버 재구축 이후 성능이 급격히 저하pid | usename | application_name | client_addr | duration | state | query_preview-------+------------+------------------.. 2025. 10. 26. 웹소켓 Subscribe시에 Interceptor에서 채팅방 권한을 조회하도록 함 지난번에 이렇게 해서 웹소켓 연결을 했는데 Spring과 STOMP를 이용해서 웹소켓 연결하기Gradle에 필요한 설정 import // WebSocket implementation("org.springframework.boot:spring-boot-starter-websocket") implementation("com.fasterxml.jackson.core:jackson-databind") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implegreedydeveloper.tistory.com연결해두고 보니 아무나 특정 채팅방이나 서버를 Subscribe할 수 있는 구조라 보안 이슈가 있을 것 같았다 그래서 Intercep.. 2024. 11. 5. Spring과 STOMP를 이용해서 웹소켓 연결하기 Gradle에 필요한 설정 import // WebSocket implementation("org.springframework.boot:spring-boot-starter-websocket") implementation("com.fasterxml.jackson.core:jackson-databind") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") // Web Security implementation("org.spr.. 2024. 9. 26. Spring에서 MongoDB 이용할때의 Pagination : MongoTemplate 으로 List<Model> , Page<Model> 리턴 Pageable pageable = new PageRequests(page, size);Query query = new Query().with(pageable);List list = mongoTemplate.find(query, XXX.class);return PageableExecutionUtils.getPage( list, pageable, () -> mongoTemplate.count(Query.of(query).limit(-1).skip(-1), XXX.class));이렇게 하면 mongoTemplate이 Page를 지원하지 않는다고 해도 PageableExecutionUtils을.. 2024. 9. 22. QueryDSL로 검색 기능 구현 + 쿼리 빌드 단계적으로 하기 + LocalDateTime을 Controller의 Parameter로 받을 때 주의할 점 QueryDSL 설정법은 여기로 QueryDSL 설정일단 gradle에 관련 설정들을 추가해준다plugins { id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'}configurations { compileOnly { extendsFrom annotationProcessor }}repositories { mavenCentral()}dependencies { implementation 'org.springfrgreedydeveloper.tistory.com 오늘 여러 조건에 따라서 검색을 해야하는 쿼리를 작성해야 했는데검색할때 쿼리가 null인 경우를 모두 메서드로 분리해서 하지 않고 null이거나 비어있으면 제외하고 쿼리를 빌드하는 코드를 작성해 보았다 .. 2024. 9. 5. @EnableJpaAuditing 이 한 곳에서만 정의되어야 하는 이유 습관처럼 QueryDsl을 사용하기 위해 JPAConfig를 만들려고 했다@Configuration@EnableJpaAuditingpublic class JPAConfig { @PersistenceContext private EntityManager entityManager; @Bean public JPAQueryFactory queryFactory() { return new JPAQueryFactory(entityManager); }} 그랬더니 다른 곳에서 이미 JPAAuditoing이 되고 있어서 안 된다는 에러가 떴다 overriding = true로 바꾸라는 제안도 있었지만 위험할 것 같아서 하지 않았다 찾아보니 동일한 모듈에 이게 있었다@Configura.. 2024. 9. 5. QueryDSL 설정 일단 gradle에 관련 설정들을 추가해준다plugins { id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'}configurations { compileOnly { extendsFrom annotationProcessor }}repositories { mavenCentral()}dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.mysql:mysql-connector-j' implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' .. 2024. 9. 5. Spatial Index 전환기 프로젝트에서 거리순 정렬이 필요했는데 기존에는 그냥 QueryDSL로 Order By 유클리드 거리를 하고 있었다.너무 비효율적이라는 생각이 들어서 더 좋은 방법이 없나 찾아보다가 공간 인덱스를 발견했다.https://www.baeldung.com/hibernate-spatial 결론부터 말하자면 적용 후 성능이 151ms 에서 63ms 으로 58.28% 개선되었다Hibernate-Spatial 개념 정리 → 링크 나에게 필요한 것은 특정한 좌표들을 비교하는 일이니까 Point를 선택해서 썼다우선 관련된 설정을 해준다 latitude와 longitude를 Point로 바꿔줬다⚠️주의⚠️경도 longitude → x위도 latitude → y @Column private Double lati.. 2024. 8. 1. 한 시간 후 만료되는 초대 링크 개발기 : DB 구성에 대한 고민 디스코드 클론코딩 서비스를 개발하면서채팅방 입장 링크를 발급해준 후 한시간 후 만료시키고만료되지 않은 코드라면 참여가 가능하게 해야하는 기능을 개발해야했다 Key:Value 형태로 간단하게 저장할 수 있을 것 같고 만료되는 기능도 TTL로 하기 쉬운 Redis를 쓰기로 했는데, 코드 발급 시에는 채팅방id, userId -> 코드 이렇게 접근해야 했고코드로 참여 시에는 코드 -> 채팅방 id 이렇게 접근해야 했다 그러나 Redis는 Key로 Value를 찾는 것은 효율적인 반면, Value로 Key를 찾는 것은 효율적이지 않아서처음에는 채팅방id, userId -> 코드, 코드 -> 채팅방 id 이렇게 DB를 두개로 나눠서 저장했다 @Serviceclass ChatRoomService( private.. 2024. 6. 20. 이전 1 2 다음