크롤 쉼에 동시 렌더링 상한·페이지 캐시를 두고 텍스트 모드로 돌린다 - #31
Merged
Merged
Conversation
/tools/fetch 는 인증 없이 닿고 쉼은 LiteLLM·데이터베이스·다른 도구 서비스와 같은 사설 네트워크에 있어, 넘겨받은 URL 로 내부 서비스를 더듬을 수 있었다 (SSRF). file:// 같은 스킴도 그대로 브라우저에 넘어갔다. - netguard.refusal: http(s) 만 허용하고, 호스트를 IP 로 풀어 하나라도 공개 주소가 아니면(루프백·사설·링크로컬·CGNAT·메타데이터 이름·점 없는 서비스 이름·.local/.internal) 거절한다. - 브라우저가 리다이렉트를 따라간 뒤 도착한 주소도 같은 기준으로 다시 본다. - 시험 22건, CI 의 pytest 대상에 추가.
2026-09-08 이 네트워크에서 임시 인스턴스로 엔진을 하나씩 다시 쟀다. 한국어 생활 질의 6개(약 병용, 최저임금, 장학금 신청 기간, 소아과, 모델 이름, 열차 요금)와 영어 개발 질의 4개를 질의어가 실린 결과 수로 채점했다. yandex 한국어 6/6, 영어 4/4 — 네이버 블로그, 지식iN, 아하, 언론사 bing 한국어 1/6, 영어 0/4 — 첫 화면, 사전, 바이두 잡음 yahoo Suspended: HTTP protocol error google/naver/duckduckgo/startpage/brave/mojeek/qwant/presearch 막힘 운영에서 34개 페르소나 질의의 상위 5건 중 질의어를 절반 이상 실은 결과가 166건 중 2건(1%)이었고, 바꾼 뒤 170건 중 87건(51%), 첫 화면은 39→17. bing 은 예비로 weight 0.5 에 남긴다: KloudChat 이 질의어 겹침으로 다시 정렬하므로 둘 다 답하면 bing 의 엉뚱한 결과가 아래로 내려간다.
Chromium 한 대가 모든 요청을 받는데 동시 수 제한이 없어, 몰리면 탭이 서로 CPU 를 뺏다가 30초 타임아웃에 함께 걸렸다(32 병렬에서 중앙값 20.6초, 최대 26.5초). `gate.py` 의 두 장치를 앞에 둔다. - Gate: 동시에 MAX_CONCURRENT_PAGES(8)장만 렌더링하고, 나머지는 QUEUE_TIMEOUT_MS(15초)까지 기다린 뒤 「busy」로 거절한다. 부르는 쪽 (KloudChat)은 읽지 못한 페이지처럼 요약문으로 물러난다. - PageCache: 성공한 스크랩을 URL·formats·본문 플래그로 CACHE_TTL_S (15분) 동안 메모리에 둔다. 같은 시간대에 같은 것을 묻는 사용자들은 같은 상위 결과를 읽는다. /health 가 렌더링 중·대기 중·캐시 항목 수를 보인다. 운영 측정(8코어): 16 병렬 콜드 p50 7.6→2.2초, 32 병렬 콜드 p50 20.6→15.5초·최대 26.5→19.8초(전부 성공), 캐시 적중 시 0.3초. Dockerfile 이 파일을 하나씩 복사하므로 gate.py 를 목록에 넣었다 — 처음 배포에서 빠뜨려 쉼이 재시작 루프에 들어갔었다. 확인: tests/test_gate.py 5건(상한·대기·거절, TTL, 키, 축출), ruff 통과.
이미지·글꼴·미디어는 모델에 전달되지 않는다 — 쉼은 마크다운 본문만 돌려주고 KloudChat 은 그 텍스트만 검색 결과에 붙인다. 그러니 브라우저가 내려받을 이유가 없다(`text_mode=True`, 스크립트는 그대로 돈다). 운영에서 같은 12쪽을 전후로 읽어 비교: 본문 길이는 동일(위키백과 463,355→463,455자, 파이썬 71,202→71,202자 등, 12쪽 모두 본문 있음), 합계 시간 64.4→59.2초, 무거운 쪽은 10.5→8.0초·11.4→8.4초.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#29 머지 뒤 base 브랜치 삭제로 #30이 닫혀 같은 내용을 main 기준으로 다시 연 PR입니다.
변경
services/crawl4ai-shim/gate.py:Gate(동시 렌더링 상한 + 바운드된 대기)와PageCache(TTL·LRU).app.py: 캐시 적중이면 브라우저를 열지 않고 답한다. 상한을 넘어QUEUE_TIMEOUT_MS안에 자리가 안 나면{"success": false, "error": "busy…"}. 성공한 스크랩은 캐시에 넣는다./health에pages{active,waiting,limit}·cache{entries,ttl_s}.docker-compose.yml:MAX_CONCURRENT_PAGES=8,QUEUE_TIMEOUT_MS=15000,CACHE_TTL_S=900.gate.py복사 추가.docs/tools.md문단.측정 (운영, 8코어, KloudChat api 컨테이너에서 병렬 호출)
모두 성공. 32 병렬에서는 8장씩 네 차례로 나뉘어 도는 모양이라 최대값은 대기 시간이 대부분이다. 더 늘리려면 쉼 복제(브라우저 여러 대)가 다음 단계다.
확인
tests/test_gate.py5건, ruff 통과. 운영에 배포해 위 표를 쟀다.추가: 텍스트 모드
이미지·글꼴·미디어는 모델에 전달되지 않으므로(쉼은 마크다운만 돌려준다) 브라우저가 내려받지 않게
text_mode=True를 켰다. 스크립트는 그대로 돈다. 같은 12쪽 전후 비교: 본문 길이 동일(12쪽 모두 본문 있음), 합계 64.4→59.2초, 무거운 쪽 10.5→8.0초·11.4→8.4초.