Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

검색을 위한 ElasticSearch 설정 및 장소 검색 성능 개선 #149

Merged
merged 27 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1552683
feat: elasticsearch 모듈 설치 #138
koomchang Nov 16, 2024
bb64b5c
config: elasticsearch에서의 place index 구성 #138
koomchang Nov 16, 2024
7c9e52d
config: 로컬에서 elasticsearch와 kibana를 인증 없이 사용할 수 있도록 설정 #138
koomchang Nov 16, 2024
cf4b020
feat: search 모듈에서 ElasticSearch에 검색할 수 있는 쿼리 구현 #138
koomchang Nov 16, 2024
43c2d2d
config: es에 nori analyzer 설치한 이미지 이용하도록 변경 #138
koomchang Nov 18, 2024
a5a35d8
config: 대한민국 지역 동음이의어 설정 추가 #138
koomchang Nov 18, 2024
517156c
feat: es가 적용 된 장소 검색 api #138
koomchang Nov 18, 2024
2cee713
config: production 환경 es 서버 설정 #138
koomchang Nov 19, 2024
69195a2
fix: es docker compose context 수정 #138
koomchang Nov 19, 2024
3a91e97
config: kibana 세팅 전에 es password 설정 #138
koomchang Nov 19, 2024
afeb6eb
fix: es kibana 비밀번호 설정 경로 오류 수정 #138
koomchang Nov 19, 2024
297360c
fix: es health 체크 이후 kibana 동작 하도록 설정 수정 #138
koomchang Nov 19, 2024
a24df3f
fix: prod 환경 sh 스크립트 수정 #138
koomchang Nov 19, 2024
70654a9
fix: elastic 및 Kibana에 사용할 계정 권한 수정 #138
koomchang Nov 19, 2024
5986886
refactor: es 검색할 때 dto 적용하여 반환하도록 변경 #138
koomchang Nov 19, 2024
2dfb6ca
config: 배포환경에서 권한 부여를 위해 root 유저 설정 #138
koomchang Nov 19, 2024
88a2156
docs: es 설정 관련 리드미 추가 #138
koomchang Nov 19, 2024
a31c131
refactor: ES index 등 설정 상수 분리 #138
koomchang Nov 20, 2024
8de59fc
refactor: ES 검색 쿼리를 service에서 다른 클래스로 분리 #138
koomchang Nov 20, 2024
95d0d52
fix: ESQuery 클래스를 injectable로 두어 모듈에 추가 #138
koomchang Nov 20, 2024
5006896
docs: ELK 설정 스크립트 수정
Miensoap Nov 20, 2024
9c257eb
refactor: es 관련 문서 경로 변경 #138
koomchang Nov 20, 2024
0ff0ce8
refactor: 경로를 나타내는 lon을 long으로 네이밍 변경 #138
koomchang Nov 20, 2024
2bcc48d
refactor: es에서 사용하는 match 쿼리를 분리 #138
koomchang Nov 20, 2024
605ade4
refactor: es에서 사용하는 gauss 쿼리 분리 #138
koomchang Nov 20, 2024
1de007e
refactor: es 에서 사용하는 filter 쿼리 분리 #138
koomchang Nov 20, 2024
10b536c
refactor: es에서 사용하는 prefix 쿼리 분리 #138
koomchang Nov 20, 2024
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
4 changes: 3 additions & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
"nestjs-pino": "^4.1.0",
"pino-http": "^10.3.0",
"rxjs": "^7.8.1",
"typeorm": "^0.3.20"
"typeorm": "^0.3.20",
"@nestjs/elasticsearch": "^10.0.2",
"@elastic/elasticsearch": "^8.16.0"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
Expand Down
3 changes: 3 additions & 0 deletions backend/resources/elasticsearch/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM docker.elastic.co/elasticsearch/elasticsearch:8.16.0

RUN elasticsearch-plugin install --batch analysis-nori
82 changes: 82 additions & 0 deletions backend/resources/elasticsearch/docker-compose.production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
services:
setup:
profiles:
- setup
build:
context: .
init: true
user: root
volumes:
- ./index/place-index.json:/usr/share/elasticsearch/place-index.json
- ./index/synonyms.txt:/usr/share/elasticsearch/config/synonyms.txt
- ./init-es.prod.sh:/usr/share/elasticsearch/init-es.prod.sh
command: >
/bin/bash -c '
until curl -s -XGET "http://elasticsearch:9200/_cluster/health" -u "elastic:${ELASTIC_PASSWORD}" | grep "\"status\":\"green\"" > /dev/null; do
echo "Waiting for Elasticsearch to be ready..."
sleep 5
done &&
curl -X POST "http://elasticsearch:9200/_security/role/custom_role" -H "Content-Type: application/json" -u elastic:${ELASTIC_PASSWORD} -d "{
\"cluster\": [\"all\"],
\"indices\": [
{
\"names\": [\"*\"],
\"privileges\": [\"all\"]
}
],
\"applications\": [
{
\"application\": \"kibana-.kibana\",
\"privileges\": [\"all\"],
\"resources\": [\"*\"]
}
],
\"run_as\": [\"*\"]
}" &&

curl -X POST "http://elasticsearch:9200/_security/user/${CUSTOM_USERNAME}" -H "Content-Type: application/json" -u elastic:${ELASTIC_PASSWORD} -d "{\"password\": \"${ELASTIC_PASSWORD}\", \"roles\": [\"custom_role\", \"kibana_system\"]}" &&
chmod +x /usr/share/elasticsearch/init-es.prod.sh &&
/usr/share/elasticsearch/init-es.prod.sh
'
environment:
- CUSTOM_USERNAME=${CUSTOM_USERNAME}
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
depends_on:
- elasticsearch

elasticsearch:
build:
context: .
dockerfile: Dockerfile
container_name: elasticsearch
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata:/usr/share/elasticsearch/data
- ./index/synonyms.txt:/usr/share/elasticsearch/config/synonyms.txt
ports:
- "9200:9200"

kibana:
image: docker.elastic.co/kibana/kibana:8.16.0
container_name: kibana
depends_on:
- elasticsearch
environment:
- SERVER_NAME=kibana
- ELASTICSEARCH_USERNAME=${CUSTOM_USERNAME}
- ELASTICSEARCH_PASSWORD=${ELASTIC_PASSWORD}
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"

volumes:
esdata:
driver: local
42 changes: 42 additions & 0 deletions backend/resources/elasticsearch/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
services:
elasticsearch:
build:
context: .
dockerfile: Dockerfile
container_name: elasticsearch
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- xpack.security.enabled=false
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata:/usr/share/elasticsearch/data
- ./index/place-index.json:/usr/share/elasticsearch/place-index.json
- ./index/synonyms.txt:/usr/share/elasticsearch/config/synonyms.txt
- ./init-es.local.sh:/usr/share/elasticsearch/init-es.local.sh
ports:
- "9200:9200"
command: >
/bin/bash -c "
chmod +x /usr/share/elasticsearch/init-es.local &&
/usr/share/elasticsearch/init-es.local &
exec /usr/local/bin/docker-entrypoint.sh
"

kibana:
image: docker.elastic.co/kibana/kibana:8.16.0
container_name: kibana
depends_on:
- elasticsearch
environment:
- SERVER_NAME=kibana
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"

volumes:
esdata:
driver: local
83 changes: 83 additions & 0 deletions backend/resources/elasticsearch/index/place-index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0,
"analysis": {
"analyzer": {
"nori_with_synonym": {
"type": "custom",
"tokenizer": "nori_tokenizer",
"filter": [
"lowercase",
"nori_readingform",
"synonym_filter"
]
}
},
"filter": {
"synonym_filter": {
"type": "synonym",
"synonyms_path": "synonyms.txt"
}
}
}
},
"mappings": {
"properties": {
"id": {
"type": "integer"
},
"googlePlaceId": {
"type": "keyword"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
},
"analyzer": "nori_with_synonym"
},
"thumbnailUrl": {
"type": "text",
"index": false
},
"rating": {
"type": "scaled_float",
"scaling_factor": 100
},
"location": {
"type": "geo_point"
},
"formattedAddress": {
"type": "text",
"analyzer": "nori_with_synonym"
},
"category": {
"type": "keyword",
"index": true
},
"description": {
"type": "text"
},
"detailPageUrl": {
"type": "text",
"index": false
},
"createdAt": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"updatedAt": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"deletedAt": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis",
"null_value": null
}
}
}
}
17 changes: 17 additions & 0 deletions backend/resources/elasticsearch/index/synonyms.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
서울특별시, 서울, 서울시
부산광역시, 부산, 부산시
대구광역시, 대구, 대구시
인천광역시, 인천, 인천시
광주광역시, 광주, 광주시
대전광역시, 대전, 대전시
울산광역시, 울산, 울산시
세종특별자치시, 세종, 세종시
경기도, 경기, 경기도청
강원도, 강원, 강원도청
충청북도, 충북, 충청북도청
충청남도, 충남, 충청남도청
전라북도, 전북, 전북특별자치도, 전라북도청
전라남도, 전남, 전라남도청
경상북도, 경북, 경상북도청
경상남도, 경남, 경상남도청
제주특별자치도, 제주, 제주도
19 changes: 19 additions & 0 deletions backend/resources/elasticsearch/init-es.local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash
until curl -s -XGET "http://localhost:9200/_cluster/health" | grep '"status":"green"' > /dev/null; do
echo "Waiting for Elasticsearch to be ready..."
sleep 5
done
# Place 인덱스 확인 및 생성
echo "Checking if 'place' index exists..."
response=$(curl -s -o /dev/null -w "%{http_code}" -XGET "http://localhost:9200/place")
if [ "$response" -eq 404 ]; then
echo "Index 'place' does not exist. Creating it..."
curl -X PUT "http://localhost:9200/place" \
-H "Content-Type: application/json" \
--data-binary @/usr/share/elasticsearch/place-index.json
echo "'place' index created successfully."
elif [ "$response" -eq 200 ]; then
echo "Index 'place' already exists."
else
echo "Unexpected response while checking for 'place' index: HTTP $response"
fi
15 changes: 15 additions & 0 deletions backend/resources/elasticsearch/init-es.prod.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
echo "Checking if 'place' index exists..."
response=$(curl -s -o /dev/null -w "%{http_code}" -XGET "http://elasticsearch:9200/place" -u "elastic:${ELASTIC_PASSWORD}")
if [ "$response" -eq 404 ]; then
echo "Index 'place' does not exist. Creating it..."
curl -X PUT "http://elasticsearch:9200/place" \
-H "Content-Type: application/json" \
-u "elastic:${ELASTIC_PASSWORD}" \
--data-binary @/usr/share/elasticsearch/place-index.json
echo "'place' index created successfully."
elif [ "$response" -eq 200 ]; then
echo "Index 'place' already exists."
else
echo "Unexpected response while checking for 'place' index: HTTP $response"
fi
2 changes: 2 additions & 0 deletions backend/resources/elasticsearch/sample_env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CUSTOM_USERNAME=
ELASTIC_PASSWORD=
22 changes: 22 additions & 0 deletions backend/resources/nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,26 @@ http {
include /etc/nginx/proxy_headers.conf;
}
}

# Elasticsearch 서브도메인
server {
listen 443 ssl;
server_name es.dailyroad.site;

location / {
proxy_pass http://<SEARCH_PRIVATE_IP>:9200;
include /etc/nginx/proxy_headers.conf;
}
}

# Search(Kibana) 서브도메인
server {
listen 443 ssl;
server_name search.dailyroad.site;

location / {
proxy_pass http://<SEARCH_PRIVATE_IP>:5601;
include /etc/nginx/proxy_headers.conf;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"index_patterns": [
"dailyroad-*"
],
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
},
"log_level": {
"type": "keyword"
},
"log_message": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"req": {
"properties": {
"id": {
"type": "integer"
},
"method": {
"type": "keyword"
},
"url": {
"type": "keyword"
},
"headers": {
"type": "object",
"enabled": false
}
}
}
}
}
}
}
34 changes: 34 additions & 0 deletions backend/resources/scripts/elk/logstash/logstash.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
input {
beats {
port => 5044
}

tcp {
port => 50000
codec => json_lines # JSON 형태의 데이터를 처리
}
}

filter {
json {
source => "message"
target => "parsed_message"
}

mutate {
rename => { "[parsed_message][level]" => "log_level" }
rename => { "[parsed_message][msg]" => "log_message" }
rename => { "[parsed_message][time]" => "@timestamp" }

remove_field => ["message", "parsed_message"]
}
}

output {
elasticsearch {
index => "%{[@metadata][service_name]}-%{+YYYY.MM.dd}"
hosts => "elasticsearch:9200"
user => "logstash_internal"
password => "${LOGSTASH_INTERNAL_PASSWORD}"
}
}
Loading
Loading