Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e72c534
[Fix]Test 코드 수정
hykim02 Mar 24, 2025
1dbbc56
[Fix]public 접근지정자 private으로 변경(캡슐화)
hykim02 Mar 26, 2025
b91f4a7
[Refactor]CafeteriaServiceV2 단일 책임 원칙 적용하여 클래스 분리
hykim02 Mar 27, 2025
f19aa3d
Update Java CI-CD.yml
hykim02 Mar 27, 2025
7f9a50e
merge conflict 해결
hykim02 Mar 27, 2025
0c7cd50
merge conflict 해결 중
hykim02 Mar 27, 2025
dd851d2
[Refactor]CampusServiceV2 클래스 분리
hykim02 Mar 27, 2025
c098a0c
merge conflict
hykim02 Mar 27, 2025
2a7290c
Merge branch 'main' of https://github.com/GNU-connect/Server-JavaSpring
hykim02 Mar 27, 2025
fbca9f3
[Refactor]DietServiceV2 서비스 클래스 분리
hykim02 Mar 27, 2025
4e67e9e
merge
hykim02 Apr 16, 2025
a4eb0a9
[fix]caheable 주석 처리 - 잠깐 보류
hykim02 Apr 17, 2025
e70e82b
[fix]Cafeteria Cacheable 주석처리
hykim02 Apr 17, 2025
9b7b803
Merge branch 'main' into main
hykim02 Apr 17, 2025
00f3532
[Refactor]캐시 적용 및 중복로직 최적화
hykim02 Apr 17, 2025
6f829d9
[Refactor]캐시 적용 및 중복 로직 최적화
hykim02 Apr 17, 2025
931b37c
Merge remote-tracking branch 'origin/main'
hykim02 Apr 17, 2025
cbd71ef
[fix]userService에서 발생한 hikariCP connection error 찾는 중
hykim02 Apr 21, 2025
bd75fde
Merge branch 'main' into main
hykim02 Apr 21, 2025
0165d50
[Test]HikariCP 멀티스레드 환경 테슽
hykim02 Apr 21, 2025
14c8c57
[Fix]conflict 해결
hykim02 Apr 21, 2025
f5d6eea
Merge branch 'GNU-connect:main' into main
hykim02 Apr 21, 2025
17ab978
merge 충돌
hykim02 Apr 21, 2025
a5704cb
[Fix]파일명 수정
hykim02 May 7, 2025
c1f0134
[Fix]파일명 수정
hykim02 May 7, 2025
e1916ba
Merge branch 'GNU-connect:main' into main
hykim02 May 9, 2025
4797300
[Feat]hikari, tomcat monitoring code
hykim02 May 9, 2025
95b7613
[Fix]redis db 수정 위해 cacheable 주석처리
hykim02 May 9, 2025
eef3202
[Fix]code rabbit 반영
hykim02 May 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ dependencies {

// actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-core'
implementation 'io.micrometer:micrometer-registry-prometheus'

implementation 'io.sentry:sentry-spring-boot-starter-jakarta:8.3.0'
implementation 'javax.enterprise:cdi-api:2.0'
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/com/example/Jinus/controller/DietController.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RestController
@RequestMapping("/api/spring")
@RequiredArgsConstructor
public class DietController {
private final DietService dietServiceV2;
private final DietService dietService;
private static final Logger logger = LoggerFactory.getLogger(DietController.class);

@PostMapping("/v2/dish")
public String handleRequest(@RequestBody RequestDto requestDto) {
return dietServiceV2.requestHandler(requestDto);
String threadName = Thread.currentThread().getName();
logger.info("[식단 요청] 스레드 이름: {}", threadName);

return dietService.requestHandler(requestDto);
}

}
35 changes: 35 additions & 0 deletions src/main/java/com/example/Jinus/monitor/HikariCPMonitor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.example.Jinus.monitor;

import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.HikariPoolMXBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class HikariCPMonitor {

private final HikariDataSource dataSource;

@Autowired
public HikariCPMonitor(HikariDataSource dataSource) {
this.dataSource = dataSource;
}

@Scheduled(fixedRateString = "${monitor.pool.status.rate.ms:60000}") // 상태 출력 주기 (기본 1분)
public void logHikariStatus() {
if (dataSource != null) {
HikariPoolMXBean poolMXBean = dataSource.getHikariPoolMXBean();

Comment on lines +23 to +25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null check for poolMXBean

While there's a null check for the dataSource, there's no check for poolMXBean before accessing its methods, which could lead to a NullPointerException.

         if (dataSource != null) {
             HikariPoolMXBean poolMXBean = dataSource.getHikariPoolMXBean();
+            
+            if (poolMXBean == null) {
+                log.warn("HikariPoolMXBean is null, cannot monitor connection pool");
+                return;
+            }

int total = poolMXBean.getTotalConnections();
int active = poolMXBean.getActiveConnections();
int idle = poolMXBean.getIdleConnections();
int waiting = poolMXBean.getThreadsAwaitingConnection();

log.info("[HikariCP 상태] 전체: {} / 사용 중: {} / 유휴: {} / 대기 중: {}",
+ total, active, idle, waiting);
}
}
}
47 changes: 47 additions & 0 deletions src/main/java/com/example/Jinus/monitor/TomcatThreadMonitor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.example.Jinus.monitor;

import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Connector;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.AbstractProtocol;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.concurrent.Executor;

@Component
@Slf4j
public class TomcatThreadMonitor {

private final ServletWebServerApplicationContext context;

public TomcatThreadMonitor(ServletWebServerApplicationContext context) {
this.context = context;
}

@Scheduled(fixedRateString = "${monitor.pool.status.rate.ms:60000}") // 상태 출력 주기 (기본 1분)
public void logTomcatThreadPoolStatus() {
if (context.getWebServer() instanceof TomcatWebServer tomcatWebServer) {
Connector connector = tomcatWebServer.getTomcat().getConnector();
ProtocolHandler handler = connector.getProtocolHandler();

if (handler instanceof AbstractProtocol<?> protocol) {
Executor executor = protocol.getExecutor();

if (executor instanceof ThreadPoolExecutor threadPoolExecutor) {
int max = threadPoolExecutor.getMaximumPoolSize();
int poolSize = threadPoolExecutor.getPoolSize();
int active = threadPoolExecutor.getActiveCount();
long taskCount = threadPoolExecutor.getTaskCount();
long completedTaskCount = threadPoolExecutor.getCompletedTaskCount();

log.info("[Tomcat 스레드] MaxPoolSize: {}, PoolSize: {}, 활성: {}, TaskCount: {}, 완료: {}",
+ max, poolSize, active, taskCount, completedTaskCount);
}
Comment on lines +41 to +43
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove the unexpected '+' character in the logging statement

There's an unexpected '+' character at the beginning of line 42 that will cause a compilation error.

log.info("[Tomcat 스레드] MaxPoolSize: {}, PoolSize: {}, 활성: {}, TaskCount: {}, 완료: {}",
-        + max, poolSize, active, taskCount, completedTaskCount);
+        max, poolSize, active, taskCount, completedTaskCount);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
log.info("[Tomcat 스레드] MaxPoolSize: {}, PoolSize: {}, 활성: {}, TaskCount: {}, 완료: {}",
+ max, poolSize, active, taskCount, completedTaskCount);
}
log.info("[Tomcat 스레드] MaxPoolSize: {}, PoolSize: {}, 활성: {}, TaskCount: {}, 완료: {}",
max, poolSize, active, taskCount, completedTaskCount);

}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ private long calculateTtlUntilNextMidnight(Date dietDate) {


// Redis에서 조회 (없으면 DB에서 가져옴)
@Cacheable(
value = "cafeteriaList",
key = "#p0",
cacheManager = "contentCacheManager")
// @Cacheable(
// value = "cafeteriaList",
// key = "#p0",
// cacheManager = "contentCacheManager")
public List<CafeteriaDto> getCafeteriaList(int campusId) {
return cafeteriaRepositoryV2.findCafeteriaListByCampusId(campusId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@
public class CafeteriaQueryService {
private final CafeteriaRepository cafeteriaRepositoryV2;

@Cacheable(
value = "cafeteriaId",
key = "#p0 + '::' + #p1",
unless = "#result == -1",
cacheManager = "contentCacheManager")
// @Cacheable(
// value = "cafeteriaId",
// key = "#p0 + '::' + #p1",
// unless = "#result == -1",
// cacheManager = "contentCacheManager")
public int getCafeteriaId(String cafeteriaName, int campusId) {
return cafeteriaRepositoryV2.findCafeteriaId(cafeteriaName, campusId).orElse(-1);
}

@Cacheable(
value = "cafeteriaUrl",
key = "#p0",
cacheManager = "contentCacheManager")
// @Cacheable(
// value = "cafeteriaUrl",
// key = "#p0",
// cacheManager = "contentCacheManager")
public String getImgUrl(int cafeteriaId) {
return cafeteriaRepositoryV2.findImgUrlByCafeteriaId(cafeteriaId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
public class CampusService {
private final CampusRepository campusRepositoryV2;

@Cacheable(
value = "campusId",
key = "#p0",
cacheManager = "contentCacheManager")
// @Cacheable(
// value = "campusId",
// key = "#p0",
// cacheManager = "contentCacheManager")
// 사용자의 campusId 받아 캠퍼스 이름 찾기
public String getUserCampusName(int campusId) {
return campusRepositoryV2.findCampusNameByCampusId(campusId);
Expand All @@ -29,10 +29,10 @@ public List<CampusEntity> getCampusList() {
return campusRepositoryV2.findCampusList();
}

@Cacheable(
value = "campusName",
key = "#p0",
cacheManager = "contentCacheManager")
// @Cacheable(
// value = "campusName",
// key = "#p0",
// cacheManager = "contentCacheManager")
// 캠퍼스 이름으로 id 찾기
public int getCampusId(String campusName) {
return campusRepositoryV2.findCampusIdByName(campusName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
public class DietQueryService {

private final CacheService cacheServiceV2;
private final DietRepository dietRepositoryV2;

// 메뉴 존재 여부에 따른 반환값 처리 로직
public String getDietResponse(HandleRequestDto parameters, int cafeteriaId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,16 @@
package com.example.Jinus.service.userInfo;

import com.example.Jinus.entity.userInfo.CollegeEntity;
import com.example.Jinus.repository.userInfo.CollegeRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class CollegeService {
private static final Logger logger = LoggerFactory.getLogger(CollegeService.class);
private final CollegeRepository collegeRepository;

public CollegeService(CollegeRepository collegeRepository) {
this.collegeRepository = collegeRepository;
// logger.info("CollegeService 실행");
}

public String getCollegeName(int collegeId) {
// logger.info("getCollegeName 실행");
CollegeEntity collegeEntity = collegeRepository.findById(collegeId).orElse(null);
// logger.info("collegeEntity: {}", collegeEntity);

if (collegeEntity != null) {
// logger.info("collegeEng: {}", collegeEntity.getCollegeEng());
return collegeEntity.getCollegeEng(); // 학과 영어 이름 리턴(테이블 찾기 위함)
} else {
logger.debug("CollegeService: collge를 찾을 수 없습니다.");
return null;
}
}

public boolean checkEtcValue(int collegeId) {
CollegeEntity collegeEntity = collegeRepository.findById(collegeId).orElse(null);
return collegeEntity.isEtcValue();
}

// collegeId에 해당하는 campusId 찾기
public int getCampusId(int collegeId) {
// logger.info("getCampusId 실행");
int campusId = collegeRepository.findCampusId(collegeId);
// logger.info("campusId: {}", campusId);

return campusId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ public int getUserDepartmentId(String userId) {
}

// hikariCP test
@Transactional
public void selectCampusIdTest(String userId) throws InterruptedException {
log.info("selectCampusIdTest 시작 - userId: {}", userId);
Thread.sleep(2500); // 커넥션을 5초간 점유 (풀 점유 시 타임아웃 유도)
userRepositoryV2.findCampusIdById(userId);
log.info("selectCampusIdTest 종료 - userId: {}", userId);
}
// @Transactional
// public void selectCampusIdTest(String userId) throws InterruptedException {
// log.info("selectCampusIdTest 시작 - userId: {}", userId);
// Thread.sleep(2500); // 커넥션을 5초간 점유 (풀 점유 시 타임아웃 유도)
// userRepositoryV2.findCampusIdById(userId);
// log.info("selectCampusIdTest 종료 - userId: {}", userId);
// }
}
Loading