본문 바로가기

내가 당면한 문제와 해결방안

logstash postgres to elasticsearch

stackoverflow.com/a/61672243/10194999

 

Missing Converter handling for full class name=org.postgresql.util.PGobject, simple name=PGobject

There is a column of geometry type in my postgres table. I checked that the rest of the columns worked fine postgres-> logstash-> elasticsearch. However, I am not sure how to cast the geometry type...

stackoverflow.com

결국 해결.

geometry는 geojson으로 받아 json으로 한번 더 casting 해줘야하는거같고..

jsonb는 text로 받아서 json으로 parse 해주기

 

그런데 이제 jsonb  나 geometry 타입 전송을 해결해야함 

pgobject를 적재하기위해선 converter가 필요한가봐요 .. ㅠ ㅅㅄㅂㅋㅋㅋㅋㅋ

왜 이러냐면은  아마도...

One of the columns returned by the query has a data type that Logstash doesn't know how to handle. You can type cast that column to a recognized data type (e.g. VARCHAR) in the query's SELECT statement.

 

이렇기 때문인 것 같아요. 그래서 type cating을 직접 해줘야 할 것같아요.

그래도 로그스태시 써야하는 사람이 아쉬운사람이니까 다시 찾아보고오겠습니다...

 

 

돌아왔습니다.

 

cast 예시는 이런식인 것 같네요. 이것도 성공 예시는 아닌 것 같지만~ statement를 이런식으로 써줘야 jdbc가 그거보고 고대로 pgobject를 담아오는듯... ! 힌트를 얻었습니다 ! 후후 

 

-> statement 에 type cast 해주면 되는것같은데, prestatement 와 statement 차이가 뭔지도 갑자기 궁금해짐. 대체로 뭐 전자는 캐시가 되는 장점ㅇ ㅣ있다는 것같은데 솔직히 캐시? 모름.

 

-> 캐시에 대해 속시원하게 설명하지 못하는 나를 위해서 관련 글 링크를 담아본다.

 

윗 글에 대해 내 나름대로 이해한 바는,

 

- 데이터베이스 성능을 향상 시키기위하여 -> 질의가 줄어들면 좋다.

- 애플리케이션 입장에서 데이터베이스의 데이터를 정적메모리에 보관 해두었다 필요 시에 메모리에서 꺼내 사용

- 자주 사용되면서도 && 변경은 자주 일어나지 않는 데이터가 이에 적합.

 

------> 이럴 시에 캐시 사용이 적합하다는 것.

 

cast에 대해서는 우리의 친절한 스택오버플로우 친구가 

이렇게 말함.

 

위의 답변에서와 같이 참고 링크는 여기구요 여기도 참고.

 

-> 음 그런데... geometry 를 뭘로 cast 하지???? string 으로 해야하나..? 

 

 

아마도

-> 이걸로 (https://stackoverflow.com/questions/57340648/problem-with-postgresql-json-object-pgobject-to-logstash-type-cast-problem) 해결가능한 것 같아 확인중

 

 

 

너무 오래 쉬다 와서 

컬럼이 뭐였는데 로그스태시가 안받아주노 하는 상황까지 가서 다시 ;;

봤는데

geometry 맞음

run psql -E  and then  \d 테이블이름

맞네... geometry

 

 

--> 일단 postgis 함수써서 보내라도 놓음 ST_AsText로 

https://stackoverflow.com/questions/61669916/missing-converter-handling-for-full-class-name-org-postgresql-util-pgobject-sim

영어를 못해서 그런건지 ㅠㅠ 아무도 대답안해주고 만날 자문자답함.. 


 

인코딩 해결하였다 ㅎ 

 

TL;DR / 실행되지만 인코딩 문제 해결못한 튜토리얼 입니다...

 

 

0 logstash & elasticsearch / java -version 과 jdbc 드라이버 버전 맞춰 설치하즈아

https://discuss.elastic.co/t/error-org-postgresql-driver-not-loaded/155850)

 

  • If you are using Java 8 or newer then you should use the JDBC 4.2 version.
  • If you are using Java 7 then you should use the JDBC 4.1 version.
  • If you are using Java 6 then you should use the JDBC 4.0 version.
  • If you are using a Java version older than 6 then you will need to use a JDBC3 version of the driver, which will by necessity not be current, found in Other Versions.

jdbc driver download 페이지에 이렇게 되어있습니다... 저는 안읽었었지만... 운이 좋았어요... https://jdbc.postgresql.org/download.html)

 

 

1 다운로드 받은 jar 파일을 logstash의 path에 넣어주자.

난 여기였음... /usr/share/logstash

 

 

2 conf 파일을 설정하자.

하단 참고.

 

3 별것도 아님 잘 실행됨... 그러나 문서는 읽기 싫음 ㅇㅇ 

 

 

 

 

 

0 logstash & elasticsearch install

: centos install

https://www.elastic.co/guide/en/elasticsearch/reference/current/rpm.html)

https://www.elastic.co/guide/en/logstash/current/installing-logstash.html)

: configuration

https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-elasticsearch-on-centos-7)
https://www.digitalocean.com/community/tutorials/how-to-install-elasticsearch-logstash-and-kibana-elastic-stack-on-centos-7)

 

 

 

1 INSERT INTO LOGSTASH SELECT DATA FROM DATABASE

: https://www.elastic.co/kr/blog/logstash-jdbc-input-plugin)

플러그인 목록

: https://www.elastic.co/guide/en/logstash/current/index.html)

인풋 

: https://www.elastic.co/guide/en/logstash/current/plugins-inputs-jdbc.html)

아웃풋

: https://www.elastic.co/guide/en/logstash/current/output-plugins.html)

 

https://www.elastic.co/kr/blog/logstash-jdbc-input-plugin) 공식 홈페이지의 튜토리얼인데 졸라 짜증남; ㅋㅎ

 

그래서 logstash jdbc plugin  설치를 어디서 하라는건지? 내가 못찾은건가...? .....

암튼 누가 물어봤네

https://discuss.elastic.co/t/how-to-install-logstash-jdbc-plugin/157842)

답변 : https://discuss.elastic.co/t/how-to-install-logstash-jdbc-plugin/157842/2)

$ cd /usr/share/logstash
And after the above command run the following command:
bin/logstash-plugin install logstash-input-jdbc

So after this we have successfully installed logstash jdbc plugin. You will see on screen successful message.
This plugin does not come packaged with JDBC driver libraries. The desired jdbc driver library must be explicitly passed in to the plugin using the jdbc_driver_library configuration option.

 

 

원하는대로 쓰고자 하면 conf 수정 해줘야되는것같은데.

그것두 좀 자세하지 않네. 커맨드를 써놓기만 하면 뭐하나 어느 경로에서실행할지 정도는 알려줘야하는거 아닌가..? ㅠ;;

 

/usr/share/logstash

에서 

 

bin/logstash -f logstash-simple.conf

이런식으로 실행하면 될것같고 실행 파일은 자기가 원하는 곳에 위치해야겠지...

 

 

input { stdin { } }
output {
  elasticsearch { hosts => ["localhost:9200"] }
  stdout { codec => rubydebug }
}

난 이것을 참고했으나, 더 자세한 예는 따로 찾아봐야겠지

https://www.elastic.co/guide/en/logstash/current/config-examples.html)

 

 

다행히 아까 날 신경질나게 했던 포스팅에 input output 설정이 조금 쓰여있어 참고할만 하겠네.

(https://www.elastic.co/kr/blog/logstash-jdbc-input-plugin)

 

 

logstash input postgres conf example

을 검색해봐야겠네.

https://discuss.elastic.co/t/trying-to-send-postgresql-query-from-logstash-to-elasticsearch/106113)

누가 이렇게 고맙게 써놨네. 

 

 

# file: contacts-index-logstash.conf
input {
    jdbc {
        jdbc_connection_string => "jdbc:postgresql://localhost:5432/mydb"
        jdbc_user => "postgres"
        jdbc_validate_connection => true
        jdbc_driver_library => "/path/to/postgresql-9.4-1201.jdbc41.jar"
        jdbc_driver_class => "org.postgresql.Driver"
        statement => "SELECT * from contacts"
    }
}
output {
    elasticsearch {
        protocol => http
        index => "contacts"
        document_type => "contact"
        document_id => "%{uid}"
        host => "ES_NODE_HOST"
    }
}

https://www.elastic.co/kr/blog/logstash-jdbc-input-plugin)

 

 

 

 

input {
jdbc {
# Postgres jdbc connection string to our database, mydb
jdbc_connection_string => "jdbc:postgresql://:5432/"
# The user we wish to execute our statement as
jdbc_user => ""
jdbc_password => ""
# The path to our downloaded jdbc driver
jdbc_driver_library => "///postgresql-42.1.4.jar"
# The name of the driver class for Postgresql
jdbc_driver_class => "org.postgresql.Driver"
# our query
statement => "SELECT * from contact where money < 80000"
}
}
output {
elasticsearch {
index => "contact"
document_type => "appr"
document_id => "%{app_id}"
hosts => ["localhost:9200"]
}
}

https://discuss.elastic.co/t/trying-to-send-postgresql-query-from-logstash-to-elasticsearch/106113)

설정에 실패한 예시인듯하나 일단 참고...

 

 

이걸 따라하려고 보니 내가 jdbc_driver를 다운로드 받아야한다는 사실을 알게되었네...

그런데 그게 뭔지 뭐를받아야하는지는 모르겠네

 

https://sesang06.tistory.com/129) 이블로그에서 그걸 알게되었네... 

https://discuss.elastic.co/t/postgresql-integration/8316/4) 여기서는 아래 링크에서 다운받으라고 하네...

https://jdbc.postgresql.org/

 

https://stackoverflow.com/questions/23260586/elasticsearch-creating-jdbc-river)

https://stackoverflow.com/a/23261180/10194999 위의 답변 중...

여기도 참고. 커넥터 같은듯한데 뭐랑 뭐의 버전을 맞추면 좋은지 팁같은건 잘 없네 

 

 

 

 

 

 

일단 드라이버 파일은 버전과 딱 맞는지 모르겠지만

postgresql-42.2.12.jar
0.89MB

이것을 

/lib/파일이름

이렇게 위치 시켰고.

 

logstash conf file은

 

input {
    jdbc {
        jdbc_connection_string => "jdbc:postgresql://localhost:5432/atlasdb"
        jdbc_user => "atlas"
        jdbc_password => "atlas"
        jdbc_validate_connection => true
        jdbc_driver_library => "/lib/postgresql-42.2.12.jar" 
        jdbc_driver_class => "org.postgresql.Driver"
        statement => "SELECT * from naver_city"
    }
}
output {
    elasticsearch {
        hosts => [ "localhost:9200" ]
        index => "인덱스이름"
    }
}

이렇게... 아 근데 안되네 잠만 

 

잘 기동된 것 같은데

 

 pipeline - Pipeline has terminated 

 

이렇게 됨. 왜일까? 

 

logstash는 잘 실행 되었고 postgres의 컬럼명도 잘 읽어오나, elasticsearch에 output이 안되는것 같다.

 

 

 

 

output 을 그냥 비워보니

잘 실행된다. ㅠ ㅠ

 

 

input {
    jdbc {
        jdbc_connection_string => "jdbc:postgresql://localhost:5432/atlasdb"
        jdbc_user => "atlas"
        jdbc_password => "atlas"
        jdbc_validate_connection => true
        jdbc_driver_library => "/lib/postgresql-42.2.12.jar"
        jdbc_driver_class => "org.postgresql.Driver"
        schedule => "* * * * *"
        statement => "SELECT * from naver_city"
    }
}
output {
  stdout { codec => rubydebug }
}

 그냥 이렇게 하니까 잘 되네. 변경사항있을때마다 logstash가 출력하는 모습.

 

 

 

 

결국 output을 elasticsearch에서 확인하였는데

 

내 경우에는 

https://discuss.elastic.co/t/error-logstash-inputs-jdbc-unable-to-connect-to-database/177091/4?u=ohoroyoi)

이것으로 해결...

timezone 으로

 

elasticsearch index에서 확인할 수 있었다.

 

적용에 성공한 conf file

input {
    jdbc {
        jdbc_connection_string => "jdbc:postgresql://localhost:5432/atlasdb?useTimezone=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf8"
        jdbc_user => "atlas"
        jdbc_password => "atlas"
        jdbc_validate_connection => true
        jdbc_driver_library => "/lib/postgresql-42.2.12.jar"
        jdbc_driver_class => "org.postgresql.Driver"
        schedule => "* * * * *"
        statement => "SELECT * from naver_city"
   }
}
output {
 elasticsearch {
        hosts => [ "localhost:9200" ]
        index => "인덱스이름이쥬"
    }
 stdout { codec => rubydebug }
}

 

 

 

아직 해결해야하는 부분은

1) 인코딩

2) document_id를 내가 원하는 id 로 && document를 내가 원하는 document형태 로 적재시킬 것  -> 성공

3) 사내 테스트 망 적용이므로 운영망에 적용할 것.

 

 

그리고 이 인스턴스를 다시 실행하려니까 안되어서...

https://stackoverflow.com/questions/51086824/logstash-could-not-be-started-when-running-multiple-instances-path-data-settin) 이거 보고 

 

명령어에다가 data2 이런식으로 path를 따로줬음

uuid 삭제해도 안되더라. --path.data 이 인자를 그냥 새 디렉토리에 줘야함 

LOGSTASH_HOME 에서 (내경우에는 /usr/share/logstash)

bin/logstash -f /home/경로/logstash-postgres-naver-city.conf --path.data ./data2

로 실행하니까 잘 된다...

 

 

 

그런데 내가 원하는 테이블은 타입을 support 하는 것 같지 않기도 한데... 아마도 json_b 때문에? 

https://discuss.elastic.co/t/missing-converter-handling-for-full-class-error/113630/2)
얘네들이 다 해보면서 찾아보라네. 뻔하지 뭐 json_b 때문에 안되는 테이블일듯. 

 

 

 

그런데 다른건 문제없는데 스케쥴링 돌때마다 데이터를 증식시킨다.

upsert를 설정해주지 않았기 때문일것이다. 

 

일케 잘 되긴 함

 

 

 

https://discuss.elastic.co/t/upsert-update-if-exist-create-if-not/194681/2) 참고해서 일단 바꿔보는중...

 

 

input {
    jdbc {
        jdbc_connection_string => "jdbc:postgresql://localhost:5432/atlasdb?useTimezone=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf8"
        jdbc_user => "atlas"
        jdbc_password => "atlas"
        jdbc_validate_connection => true
        jdbc_driver_library => "/lib/postgresql-42.2.12.jar"
        jdbc_driver_class => "org.postgresql.Driver"
        schedule => "* * * * *"
        statement => "SELECT region_id, region_name_full from expedia_region_union_copy_jpa_test order by region_id asc limit 100"
   }
}
output {
 elasticsearch {
        hosts => [ "localhost:9200" ]
        index => "인덱스이름예시-test"
        doc_as_upsert => true
        action => "update"
        document_id => "%{region_id}"
        }
 stdout { codec => rubydebug }
}

 이대로 하니까 

postgres에 update 있을때마다, elasticsearch 해당 index내의 document에서도 변경된 것을 조회가능한데? ^ ~ ^ 성공~

 

 

 

오스트레일리아-테스트에서 오스트레일리아로 바뀐 모습.

 

 

 

 

utf-8 하려고 하고있는데 어휴 ㅅㅂ 영어권으로 태어나서 잔잔한 서비스 만들었으면 좋았을걸.

 

utf-8 처리하려고 하니 왜인지 driver 가 not loaded란다.

왜지? 왜 이런오류가 뜨지? ㅠ 

 

https://github.com/logstash-plugins/logstash-filter-jdbc_static/issues/47#issuecomment-496606449)

 

이거 대로 함 시도 해본다. 

 

하라는대로 했어 형...

이게 될까...?

 

인코딩은 아직 해결못한 상태!

 

 

nput {
    jdbc {
        jdbc_connection_string => "jdbc:postgresql://localhost:5432/atlasdb?useTimezone=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf8"
        jdbc_user => "atlas"
        jdbc_password => "atlas"
        jdbc_validate_connection => true
        jdbc_driver_library => "/lib/postgres-42-test.jar"
        jdbc_driver_class => "org.postgresql.Driver"
        schedule => "* * * * *"
        statement => "SELECT * from naver_city"
   }
   stdin {
        codec => plain { charset => "UTF-8"}
   }
}
output {
 elasticsearch {
        hosts => [ "localhost:9200" ]
        index => "2020-04-23-1"
        doc_as_upsert => true
        action => "update"
        document_id => "%{code}"
        }
 stdout { codec => rubydebug }
}

 저

stdin {

   codec => plain { charset => "UTF-8"}

}

블록 추가하니까 실행되었음 

 

 

name 값이 한글로 잘 출력되는 모습


https://stackoverflow.com/questions/50655931/importing-data-from-mysql-error-pipeline-has-terminated)

이거는 다른 답변인것같은데. terminated 되는 다른 이유 -> 스케쥴링 해줘라.

 

https://www.golinuxcloud.com/configure-logstash-ssl-elasticsearch-pipeline/)

자세한 튜토리얼

 

https://discuss.elastic.co/t/error-org-postgresql-driver-not-loaded/155850)

버전... 자바랑 jdbc 드라이버 간에 이렇게 맞추시란다. 

 

 

https://discuss.elastic.co/t/jdbc-input-put-data-in-all-indexes/80446/5)

이 링크는 여러 인덱스에 적용할 수 있는 example 소개

 

https://medium.com/@erangadulshan.14/pushing-relational-data-to-elasticsearch-using-logstash-jdbc-input-plugin-48af81ed1000)

windows에서 디렉토리 지정하는 것만 빼면, 옵션같은거 친절하게 설명되어있는 tutorial

 

'내가 당면한 문제와 해결방안' 카테고리의 다른 글

postgresql get column_name with data_type  (0) 2020.05.19
logstash postgres to elasticsearch  (0) 2020.05.15
python 환경 관리  (0) 2020.04.16
postgres ilike  (0) 2020.04.02
elastiesearch doc upsert  (0) 2020.02.25