Skip to content

Perf: BE 성능 최적화 - #4

Open
zaewc wants to merge 7 commits into
mainfrom
perf/backend-optimization
Open

Perf: BE 성능 최적화#4
zaewc wants to merge 7 commits into
mainfrom
perf/backend-optimization

Conversation

@zaewc

@zaewc zaewc commented Jun 7, 2026

Copy link
Copy Markdown
Member

No description provided.

@zaewc zaewc self-assigned this Jun 7, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request optimizes performance by converting multiple asynchronous endpoints to synchronous ones, resolving N+1 query issues using SQLAlchemy's joinedload, and introducing parallel Proxmox node querying via a global thread pool. It also configures connection pooling for PostgreSQL and adds a composite index on notifications. The review feedback highlights a potential thread pool exhaustion risk in services/proxmox_client.py if Proxmox nodes are unresponsive, and suggests initializing default values for VM metrics in api/routes/vmcontrol.py to avoid missing keys in the API response if a node query fails.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

# 여러 노드(서버)의 Proxmox 상태를 동시에 조회하기 위한 공용 스레드풀.
# 각 서버는 서로 다른 Proxmox 연결(requests.Session)을 쓰므로 "서버 단위" 병렬은 안전하다.
# (동일 서버 내 호출은 세션을 공유하므로 각 작업 함수 내부에서는 순차 처리한다.)
_node_executor = ThreadPoolExecutor(max_workers=12, thread_name_prefix="pmox-node")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

위험 (High): _node_executor는 전역적으로 공유되는 고정 크기(max_workers=12)의 스레드풀입니다. 만약 특정 Proxmox 노드가 다운되거나 네트워크 장애로 인해 응답하지 않는 경우, get_proxmox_for_server에 설정된 180초(3분)의 긴 타임아웃 동안 해당 스레드가 완전히 블로킹됩니다.
여러 노드가 동시에 장애 상태이거나 동시 요청이 몰릴 경우, 12개의 스레드가 모두 타임아웃 대기로 고갈(Exhaustion)되어 정상 작동 중인 다른 노드의 상태 조회 요청까지 모두 무한 대기하게 되는 장애(Cascading Failure)가 발생할 수 있습니다.

권장 조치:

  1. get_proxmox_for_server 내부의 ProxmoxAPI 타임아웃 설정을 웹 API 환경에 맞게 대폭 줄여야 합니다 (예: 5~10초). (현재 diff 범위 외이므로 별도 수정 필요)
  2. 스레드풀의 max_workers 크기를 노드 수 및 예상 동시 요청 수에 맞춰 더 여유 있게 늘려두는 것이 안전합니다.
Suggested change
_node_executor = ThreadPoolExecutor(max_workers=12, thread_name_prefix="pmox-node")
_node_executor = ThreadPoolExecutor(max_workers=20, thread_name_prefix="pmox-node")

Comment thread api/routes/vmcontrol.py
Comment on lines +129 to +138
info_by_server.setdefault(vm.server_id, []).append({
"vmid": vm.hypervisor_vmid,
"name": vm.display_name or vm.name,
"node": None, # 아래에서 서버명으로 채움
"status": "unknown",
"owner_email": vm.owner.email if vm.owner else None,
"internal_ip": vm.internal_ip,
"created_at": str(vm.created_at) if vm.created_at else None,
"expires_at": str(vm.expires_at) if vm.expires_at else None,
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

개선 사항 (Medium): Proxmox API 호출이 실패하거나 특정 노드가 오프라인 상태일 때, fetch 함수 내의 try-except 블록에서 예외가 무시되어 cpu_usage, maxmem, mem_usage, maxdisk, uptime 등의 키가 딕셔너리에 추가되지 않은 채 반환될 수 있습니다.
이로 인해 API 응답 스키마가 일관되지 않게 되어 프론트엔드에서 해당 필드에 접근할 때 KeyErrorundefined 관련 런타임 에러가 발생할 위험이 있습니다.

따라서 기본 딕셔너리를 생성할 때 Proxmox 관련 실시간 메트릭 필드들을 기본값(0)으로 미리 초기화해 두는 것이 안전합니다.

Suggested change
info_by_server.setdefault(vm.server_id, []).append({
"vmid": vm.hypervisor_vmid,
"name": vm.display_name or vm.name,
"node": None, # 아래에서 서버명으로 채움
"status": "unknown",
"owner_email": vm.owner.email if vm.owner else None,
"internal_ip": vm.internal_ip,
"created_at": str(vm.created_at) if vm.created_at else None,
"expires_at": str(vm.expires_at) if vm.expires_at else None,
})
info_by_server.setdefault(vm.server_id, []).append({
"vmid": vm.hypervisor_vmid,
"name": vm.display_name or vm.name,
"node": None, # 아래에서 서버명으로 채움
"status": "unknown",
"cpu_usage": 0,
"maxmem": 0,
"mem_usage": 0,
"maxdisk": 0,
"uptime": 0,
"owner_email": vm.owner.email if vm.owner else None,
"internal_ip": vm.internal_ip,
"created_at": str(vm.created_at) if vm.created_at else None,
"expires_at": str(vm.expires_at) if vm.expires_at else None,
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant