본문 바로가기

작업일지/안동버스 API 연동

#2) 엘라스틱서치(Elasticsearch)로 원문 데이터를 저장하기

엘라스틱서치는 JSON구조를 사용해 스키마가 동적으로 변화할 수 있는 특징을 가진다

그렇기 때문에 필요없는 데이터 컬럼은 빼서 저장할 수 있으므로 데이터 공간을 절약할 수 있다.

 

그리고 기본적으로 검색엔진이므로 검색 기능에 빠르고 강력한 기능이 탑재되어있다.

또한 다양한 프로그램 언어를 지원하고 REST API를 제공해 HTTP 형식으로 사용할 수 있다.

 

RDBMS와 비교해보면 다음과 같다.

RDBMS Elasticsearch
Database Index
Table type
Row Document

키바나(Kibana)는 ELK에서 K를 맡고있는 솔루션이다.

엘라스틱서치와 연계하며 유저 인터페이스를 제공한다.

즉, 엘라스틱서치의 GUI툴이라고 쉽게 생각하면 될것같다.

 


Elasticsearch와 springBoot 연동

 

1. pom.xml에 엘라스틱서치 dependency 추가

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            <version>2.1.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.1.4.RELEASE</version>
        </dependency>

 

2. application.yml 혹은 properties에 셋팅값 입력

spring:
  profiles:
    active:
    - dblocal
    - redislocal
    - tomcatlocal
    - elasticlocal
    - kafkaLocal
    - mysqllocal
    
    .
    .
    .
    .
    .

spring:
  profiles: elasticlocal
  elasticsearch:
    clusterName: luna-lms
    host: 127.0.0.1
    port: 9300
    resthost: 127.0.0.1
    restport: 9200

 

3. Elasticsearch와 연동하는 방법은 총 3가지가 있는데 나는 ElasticsearchTemplate를 사용했다.

   ElasticSearchConfig.java파일 생성 후 다음과 같이 작성

@EnableElasticsearchRepositories
@Configuration
@Slf4j
public class ElasticSearchConfig implements AutoCloseable {

	@Value("${spring.elasticsearch.clusterName}")
	private String clusterName;

	@Value("${spring.elasticsearch.host}")
	private String host;

	@Value("${spring.elasticsearch.port}")
	private int port;

	@Value("${spring.elasticsearch.resthost}")
	private String resthost;

	@Value("${spring.elasticsearch.restport}")
	private int restport;

	RestClient restClient;

	TransportClient client;

	@PostConstruct
	void init() {
		System.setProperty("es.set.netty.runtime.available.processors", "false");
	}

	@Bean(name = "lunaElasticsearchClient")
	public Client client() throws Exception {
		Settings settings = Settings.builder().put("cluster.name", clusterName).build();

		client = new PreBuiltTransportClient(settings);
		client.addTransportAddress(new TransportAddress(InetAddress.getByName(host), port));
		return client;
	}

	@Bean(name = "elasticsearchTemplate")
	public ElasticsearchOperations elasticsearchTemplate() throws Exception {
		log.info("elasticsearchTemplate");
		return new ElasticsearchTemplate(client());
	}

	@Bean(name = "lunaElasticsearchRestClient")
	public RestClient restClient() {
		restClient = RestClient.builder(new HttpHost(resthost, restport)).build();
		log.info("restClient");
		return restClient;
	}

	@Override
	public void close() throws Exception {
//		log.info("elasticClose()");
		client.close();
		restClient.close();
	}

}

port 9300은 template로 데이터를 처리하고, port 9200은 REST API 통신을 통해 데이터를 처리하는 용이다.

두개 나눈이유는 insert할땐 template를 사용하고 조회 및 수정, 삭제는 REST API로 하기위함이다.

 

4. vo를 작성합니다.

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Builder
@Document(indexName = "rawdata", type = "rawdata", createIndex = false)

public class RawData {
    // ID
    @Id
    private String id;
    
    //등록시간
    @Field(type = FieldType.Date)
    private String regiTime;

    //호출 URL
	@Field(type = FieldType.Text, index = false)
    private String apiUrl;

	//파라미터
    @Field(type = FieldType.Text, index = false)
    private String parameters;

	//원문
    @Field(type = FieldType.Text, index = false)
    private String rawData;
}

 

5. controller를 만들어서 호출 후 kibana를 통해 데이터를 확인해서 연동이 잘 되었는지 확인한다.

@Slf4j
@RestController
@RequestMapping(value="/es")
public class ElasticSearchContoller {

	@Resource
	private ElasticSearchRepository elasticSearchRepository;

	@RequestMapping( value="/save" )
	public void elasticSearchSave() {
		log.info("Elasticsearch Save Start");

		RawData rawData = new RawData();
		rawData.setId(UUID.randomUUID().toString());
		rawData.setApiUrl("apiurl");
		rawData.setRawData("fdfdf");

		elasticSearchRepository.save(rawData);
	}
}

 


연동이 잘 되었다면 ElasticsearchService.java를 생성해서 다음과 같이 작성 후 원문데이터를 저장할때

서비스 내부 메소드를 호출하면 된다~

package co.kr.smartplusteam.luna.study.service;

import co.kr.smartplusteam.luna.study.vo.RawData;
import co.kr.smartplusteam.luna.study.Repository.ElasticSearchRepository;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Slf4j
@AllArgsConstructor
@NoArgsConstructor
@Service
public class ElasticSearchService {

	@Resource
	private ElasticSearchRepository elasticSearchRepository;

	//ElasticSearch 저장
	public void elasticSearchSave(String apiurl, Map<String, Object> parameters, String rawdata) {
		log.info("Elasticsearch Save Start [{}],[{}],[{}]", apiurl, parameters, rawdata);

		RawData rawData = new RawData();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
		rawData.setId(UUID.randomUUID().toString());
		rawData.setApiUrl(apiurl);
		rawData.setParameters(parameters.toString());
		rawData.setRegiTime(sdf.format(new Date()));
		rawData.setRawData(rawdata);

		log.info("Elasticsearch Save Success!!");
		elasticSearchRepository.save(rawData);
	}
}

 

아주 잘 연동되었습니다.

 

반응형