- 기술 블로그들 검색 사이트 만들기
- 회사 상관 없이 제목으로 검색 가능하도록 DB구성, 검색 웹사이트 구축
- crawler
- RSS feed 파일 바탕으로 게시물 크롤링
- gRPC client. gRPC로 db(handler)의 insert 함수 호출
- db(handler)
- gRPC server. 게시물 정보 받아 db에 insert
- 웹 사이트 운영
- later
- 최소 기능 동작-rss feed를 DB에 저장 (완료)
- 학교 과제
- docker compose로 mysql, 크롤러 2개 서비스 구성.
- gRPC로 crawler에서 db(handler)의 함수 호출. 4가지 방식 이용
- kubernetes 이용해서 crawler pod과 db pod 만들어 통신
- crawler/db/mysql pod 만듦
- grpc_health_probe와 mysql health check 이용
- crawler는 cronjob으로. 매번 설정 파일 읽어 동작
- 성능 개선
- 전체적으로 goroutine 적용해서 비동기처리
- 운영 측면 기능 추가
- 하루 단위로 프로그램 실행. 기술 블로그 업데이트 확인 및 반영 (linux crontab 적용 or k8s cronjob)
- 설정 파일로 크롤러 정보 받아 프로그램 수행
- 서비스 완전성(방학때 웹 공부용)
- rss feed가 제공하지 않는 예전 post 정보 크롤링. db 저장.
- 크롤링한 정보를 웹에 게시판 형식으로 게시. 원하는 내용 검색해서 볼 수 있도록.
- db 계정, 비번 정보 환경변수로 따로 관리
- git pull 없이 docker hub 이미지와 최소 파일 만으로 실행
- docker/distribute 폴더 다운, config-crawler.yaml 에서 crawler 정보 수정 후 docker compose up
- git pull 후 직접 이미지 빌드하여 실행(에러 발생 시 db/data 폴더 삭제)
docker build -t db-handler:1.0 -f docker/Dockerfile_dbhandler .
docker build -t crawler:1.0 -f docker/Dockerfile_crawler .
docker compose -f ./docker/docker-compose-on-hand.yml up
- 결과
- mysql 컨테이너, db-handler(grpc server), crawler(grpc client) 순으로 실행됨. mysql health check, grpc health check 때문에 시간 좀 걸림.
- CronJob 이용하여 crawler가 일정 주기마다 실행되도록 함.
- k8s 폴더 내 3개 yaml 파일 hostPath 부분 수정 후 crawler.yaml의 hostPath위치에 config-crawler.yaml 파일 둠.
- 해당 폴더에서 k8s 실행
kubectl apply -f mysql.yaml kubectl apply -f db-handler.yaml kubectl apply -f crawler.yaml
- 종료
kubectl delete -f crawler.yaml kubectl delete -f db-handler.yaml kubectl delete -f mysql.yaml
- 각 블로그 별 크롤러 동작 비동기 처리
- crawler/client.go/main
- DB에 새로 반영해야 할 게시물 확인. 확인해야 할 영역 나누어 비동기 처리
- crawler/utils/xmlHandler.go/CheckUpdatedPost
- gRPC streaming 함수들. 여러 개 보내는 동작, 받는 동작 비동기 처리.
- crawler/client.go/ db/server.go/
- 스키마
- url 중복도메인 - 한 회사의 기술 블로그 게시물 많음
- 방법 1 : url varchar(큰 값) 혹은 text 타입으로 한 테이블에 넣기
- 메모리 낭비 생기지만 링크 보여줄 때 조인 안해도 됨.
- 방법 2 : id를 크롤러별로 만들고, url 중복도메인 지우고, 크롤러-중복도메인 매핑 테이블 따로 만들기
- 메모리 효율적.
- 게시물 특성 상 한 번 넣으면 수정도 변경도 안되는 상황 -> 캐싱
- 방법 1 : url varchar(큰 값) 혹은 text 타입으로 한 테이블에 넣기
- primary key 무엇으로 할 것인가
- 방법 1 : id 만들고 AUTO_INCREMENT
- DB 수준에서 중복 처리 못함. 코드 레벨에서 처리 -> goroutine 동기화 처리해야. 병목 예상됨
- 방법 2 : 크롤러id, pubDate(unix time)을 composite primary key로.
- DB 기능 활용 가능
- 방법 1 : id 만들고 AUTO_INCREMENT
- 최종 스키마
- domain(crawler_id(PK), domain_url)
- post(crawler_id(PK, FK), url(PK), title, pubDate(nullable) )
- pubDate nullable인 이유 : RSS 파일에서 optional임 [참고]https://www.rssboard.org/rss-specification
- 트랜잭션 적용
- 하나씩 insert만 하니까 트랜잭션 적용 시 db 성능 저하 우려되어 적용 안함