데이터 수집, 저장, 검색, 시각화 및 분석을 위한 오픈 소스 플랫폼
Kibana
- ElasticSearch를 기반으로 데이터를 시각화하고 대시보드를 작성하는 데 사용되는 오픈 소스 시각화 도구Elasticsearch
- 검색 및 분석을 위한 오픈소스 검색엔진으로 Json 문서를 저장하고 쿼리할 수 있으며 대량의 데이터를 실시간으로 확인하고 검색할 수 있다.Logstash
- 애플리케이션의 로그를 수집하여 Elasticsearch 로 전송하는 역할을 담당하는 오픈소스 데이터 수집 도구Beats
- 경량 데이터 수집기로, 다양한 종류의 데이터를 수집하여 Elasticsearch 또는 Logstash로 전송Cluster
- 하나 이상의 노드(서버)가 모인것 으로 전체 데이터를 저장하고, 통합 색인화 및 검색 기능을 제공
Node
- 클러스터 내의 단일 인스턴스, 각 노드는 데이터를 저장하고 검색하는 역할을 한다.
Master Node
- 클러스터 구성 및 관리, 노드 추가 및 제거, 인덱스 생성 및 삭제 와 같은 관리 작업 수행
Data Node
- 클러스터에서 실제 데이터를 저장
Client Node
- 요청을 받고 응답을 클라이언트에 반환하는 역할 수행, 검색 및 질의를 처리하고 결과를 클라이언트에 전달하여 애플리케이션과 클러스터 간의 중개 역할을 수행
Index
- 데이터를 저장하는 단위, 고유의 이름을 가지며 매핑을 통해 데이터 형식을 정의할 수 있다.
Document
- 저장되는 데이터의 단위, Json 형식으로 표현되며 고유한 ID를 가진다.
Shard
- 데이터의 수평 분할 단위로 대용량 데이터를 처리하기 위해 인덱스를 여러개의 샤드로 분할, Primary Shard - 쓰기작업을 처리, Replica Shard - 데이터의 가용성을 향상
NoSQL 기반으로 REST API를 통한 데이터 조작을 지원
@Document(indexName = "person")
public class EsPerson {
private String name;
private Integer age;
@Id
private Long id;
}
@Document
- 스프링 과 엘라스틱서치 Document와 매핑되는 엔티티 클래스에 사용public interface EsRepository extends ElasticsearchRepository<EsPerson,Long>, CrudRepository<EsPerson,Long> {
}
ElasticsearchRepository
- Elastic 과 상호작용 하기 위한 고수준의 추상화 제공. 데이터를 쿼리하고 조작할 수 있는 메서드를 정의@EnableElasticsearchRepositories(basePackageClasses = {EsRepository.class})
public class MiddlewareConfig extends AbstractElasticsearchConfiguration {
@Override
public RestHighLevelClient elasticsearchClient() {
ClientConfiguration build = ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
return RestClients.create(build).rest();
}
@EnableElasticsearchRepositories
- Elasticsearch 리포지토리를 검색하고 스프링 애플리케이션 컨텍스트에 등록RestHighLevelClient
- Elasticsearch와 상호 작용하기 위한 고수준 REST 클라이언트ClientConfiguration
- Elasticsearch 클라이언트 구성을 설정하기 위해 사용@Service
@RequiredArgsConstructor
@Slf4j
public class EsService {
private final EsRepository repository;
private final ElasticsearchRestTemplate template;
public EsPerson save(EsPerson person) {
repository.save(person);
return person;
}
public List<EsPerson> search(EsPersonDto esPersonDto) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
if (!esPersonDto.getName().isEmpty()) {
queryBuilder.must(QueryBuilders.matchQuery("name", esPersonDto.getName()));
}
Integer minAge = esPersonDto.getMinAge();
Integer maxAge = esPersonDto.getMaxAge();
if ((minAge != null && minAge > 0) || (maxAge != null && maxAge > 0)) {
RangeQueryBuilder ageRangeQuery = QueryBuilders.rangeQuery("age");
if (minAge != null && minAge > 0) {
ageRangeQuery.gte(minAge);
}
if (maxAge != null && maxAge > 0) {
ageRangeQuery.lte(maxAge);
}
queryBuilder.must(ageRangeQuery);
}
if (esPersonDto.getName().isEmpty()&& minAge == null && maxAge == null) {
queryBuilder.must(QueryBuilders.matchAllQuery());
}
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.withPageable(PageRequest.of(0, 10))
.build();
SearchHits<EsPerson> searchHits = template.search(searchQuery, EsPerson.class);
List<EsPerson> esPeople = new ArrayList<>();
searchHits.forEach(searchHit -> esPeople.add(searchHit.getContent()));
log.info("search result = {}", esPeople);
return esPeople;
}
}
ElasticsearchRestTemplate
- 스프링 데이터 엘라스틱서치에서 제공하는 연동을 위한 템플릿, 인덱스 생성, 삭제, 데이터 삽입 등BoolQueryBuilder
- 엘라스틱서치의 논리적 조건식을 만들기 위해 사용되는 빌더must
- 반드시 일치해야하는 검색 조건matchQuery
- 텍스트 검색을 위한 쿼리로, 특정 필드에 대한 부분 문자열 검색을 수행RangeQueryBuilder
- 특정 필드 값의 범위를 지정gte
- 크거나 같은lte
- 작거나 같은 NativeSearchQueryBuilder
- 엘라스틱서치 에 대한 검색을 정의하기 위해 사용, 동적 쿼리를 구성 SearchHits
- 검색결과를 나타내는 객체http://localhost:9200/person/_search
미드필더는요?