Clojure를 사용하여 Hive JDBC를 통해 AWS EMR 조회

11557 단어 awsemrjdbcclojure

배경.


올해 1월에 나는 이전 프로젝트를 위해 Amazon Elastic Map/Reduce(EMR) 집단을 가동했다.그 이후로 나는 줄곧 조정과 설정의 속도를 늦추고 있다(도움말에서).
  • 데이터 호수
  • 의 외부 벌집 메모리 사용
  • Hive JDBC
  • 를 통한 클러스터 조회 활성화
  • SimbaJDBC(Spark Thrift)를 통한 쿼리 클러스터 활성화
  • 안전이 제한된 환경에서 이 총알들은 시간이 걸려야만 실현될 수 있다.copasetic이 발표된 후 몇 주 내에, 나는 Hive JDBC 접근을 테스트하기 시작했다.
    첫 번째 성공적인 테스트는 비Active Record 모델(PORO)이 Rails 4.2에 있는 JRuby 9.1.15.0을 사용하는 것과 관련이 있다.본고는 Clojure를 사용하여 나의 두 번째 테스트를 보여 주었다.

    선결 조건


    이는 Hive 등이 활성화된 상태에서 AWS EMR 클러스터를 실행한 경우를 가정합니다.

    Hive JDBC 드라이버 다운로드


    첫 번째 단계는 아마존에서 제공하는 Hive JDBC 드라이버를 다운로드하는 것이다.링크가 시간의 추이에 따라 바뀌었기 때문에 찾기가 매우 어렵다.이 2014blog postSimba Technologies에서 왔고AWS Big Data Blogdrivers에 포함된 링크입니다.비록 나는 구글fu를 사용하지만, 업데이트된 버전의 드라이버를 찾을 수 없다.
    저는 AmazonHiveJDBC/AMAzonHiveJDBC41-1.0.9.1060 디렉터리에 있는 JDBC4.1 드라이버를 사용합니다.

    새 항목 만들기


    Leiningen를 사용하여 새 Clojure 항목을 만들려면 다음과 같이 하십시오.
    lein new app emr-hive-jdbc-example
    

    종속성 추가


    항목을 편집합니다.clj 파일, 로그 및 Java JDBC에 종속성 추가
    :dependencies [[org.clojure/clojure "1.8.0"]
                   [org.clojure/tools.logging "0.4.1"]
                   [org.clojure/java.jdbc "0.7.8"]]
    

    JAR 파일 추가


    나는 이 예시 코드에서 사용하고 싶지 않다Maven.나는 JAR 파일을 resources directory에 넣는 방법을 취했다.항목에 해당 항목을 추가합니다.clj 파일.
    :resource-paths ["resources/HiveJDBC41.jar"
                     "resources/commons-codec-1.3.jar"
                     "resources/commons-logging-1.1.1.jar"
                     "resources/hive_metastore.jar"
                     "resources/hive_service.jar"
                     "resources/httpclient-4.1.3.jar"
                     "resources/httpcore-4.1.3.jar"
                     "resources/libfb303-0.9.0.jar"
                     "resources/libthrift-0.9.0.jar"
                     "resources/log4j-1.2.14.jar"
                     "resources/ql.jar"
                     "resources/slf4j-api-1.5.11.jar"
                     "resources/slf4j-log4j12-1.5.11.jar"
                     "resources/TCLIServiceClient.jar"
                     "resources/zookeeper-3.4.6.jar"]
    
    다음은 전체 project.clj 파일의 모양입니다.
    (defproject emr-hive-jdbc-example "0.1.0-SNAPSHOT"
      :description "Example of how to connect to AWS EMR via Hive JDBC"
      :url "https://gitlab.com/ejstembler/emr-hive-jdbc-example"
      :license {:name "MIT"
                :url "https://mit-license.org"}
      :dependencies [[org.clojure/clojure "1.8.0"]
                     [org.clojure/tools.logging "0.4.1"]
                     [org.clojure/java.jdbc "0.7.8"]]
      :resource-paths ["resources/HiveJDBC41.jar"
                       "resources/commons-codec-1.3.jar"
                       "resources/commons-logging-1.1.1.jar"
                       "resources/hive_metastore.jar"
                       "resources/hive_service.jar"
                       "resources/httpclient-4.1.3.jar"
                       "resources/httpcore-4.1.3.jar"
                       "resources/libfb303-0.9.0.jar"
                       "resources/libthrift-0.9.0.jar"
                       "resources/log4j-1.2.14.jar"
                       "resources/ql.jar"
                       "resources/slf4j-api-1.5.11.jar"
                       "resources/slf4j-log4j12-1.5.11.jar"
                       "resources/TCLIServiceClient.jar"
                       "resources/zookeeper-3.4.6.jar"]
      :main ^:skip-aot emr-hive-jdbc-example.core
      :target-path "target/%s"
      :profiles {:uberjar {:aot :all}})
    

    log4j를 추가합니다.속성 파일


    src 디렉터리에 새 log4j.properties 파일을 만듭니다.log4j에 기본 로그 설정을 추가합니다.
    log4j.rootLogger=INFO, console
    log4j.logger.example=DEBUG
    log4j.appender.console=org.apache.log4j.ConsoleAppender
    log4j.appender.console.layout=org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=%-5p %c: %m%n
    

    핵심 소스 편집


    핵심clj 파일은 이 예의 주요하고 유일한 원본 파일입니다.

    네임스페이스에 요구 사항 추가


    파일의 맨 위에 로그 기록과 JDBC에 사용할 Requires 문장을 추가해야 합니다.나는 간결하지만 논리에 맞는 별명을 즐겨 쓴다.
    (ns emr-hive-jdbc-example.core
      (:require [clojure.tools.logging :as log])
      (:require [clojure.java.jdbc :as jdbc])
      (:gen-class))
    
    어떤 예들은 j를 JDBC의 별명으로 사용한다.이것은 너무 간단해서 묘사성이 없다.

    환경 변수에서 민감한 값 읽기


    다음에 나는 environment variables에서 민감한 값을 읽었다.너는 원본 코드에서, 심지어는 설정 파일에서 하드코딩 민감한 값을 영원히 원하지 않는다!별도: The Twelve-Factor App: III. Config.
    ;; Define the user/password/subname from ENV variables
    (def user (System/getenv "EMR_HIVE_JDBC_USER"))
    (def password (System/getenv "EMR_HIVE_JDBC_PASSWORD"))
    (def subname (System/getenv "EMR_HIVE_JDBC_SUBNAME"))
    
    다른 JVM 언어에서 JDBC를 처리할 때 URL을 사용합니다.그러나 Clojure JDBC는 하위 이름을 사용하는 것을 더 좋아하는 것 같습니다.이것은 하위 이름을 포함한 모든 부분에 따라 URL을 만들 수 있습니다.어쨌든 하위 이름은 URL의 일부분입니다.

    사전 요구 사항: 필요한 값 확인


    저는 Betrand MeyerPreconditions콘셉트의 팬입니다.나는 코드를 작성하는 대부분의 언어에서 그것을 사용해 보려고 한다.일부 언어는 내장 지원이나 제3자 라이브러리를 가지고 있다.간단하게 보기 위해서는, 때때로 수동으로 코드를 작성하는 것이 가장 좋다.별도: Design by contract.
    ;; Preconditions
    (when (nil? user)
      (throw (RuntimeException. "user is nil")))
    (when (nil? password)
      (throw (RuntimeException. "password is nil")))
    (when (nil? subname)
      (throw (RuntimeException. "subname is nil")))
    
    user/password/subname의 유효한 값이 없기 때문에 코드를 계속할 수 없습니다. 따라서 이 값이 부족하면 오류가 발생하는 것은 의미가 있습니다.이렇게 하면 최종 사용자에게 표시되는 메시지를 제어할 수 있습니다.

    연결 사양 정의


    연결 규범을 정의하는 것은 매우 간단하다.이것은 단지 하나Map일 뿐이다.
    ;; Define the connection specification
    (def hive-spec {:classname "com.amazon.hive.jdbc41.HS2Driver"
                   :subprotocol "hive2"
                   :subname subname
                   :user user
                   :password password})
    
    JDBC 4.1 HS2 드라이버를 hive2 서브루틴과 함께 사용합니다.

    SQL 문 정의


    이것도 매우 간단명료하다.그러나 나는 Clojure JDBC 조회 함수가 왜 Vector의 SQL 문구가 필요한지 곤혹스러웠다.왜 안 써요String?
    ;; Define the SQL statement to execute
    (def sql ["SELECT
                   COUNT(*) AS row_count
               FROM
                   my_table"]) ; TODO: Change to your desired SQL statement
    

    주요 접점


    다음은 다음 작업을 수행하는 이 예제의 주요 엔트리 포인트입니다.
  • 수행할 SQL 문서화
  • SQL
  • 실행
  • 첫 번째 행의 행 계수값 반환
  • ;; The main entry-point
    ;; 1. Logs the SQL to execute
    ;; 2. Executes the SQL
    ;; 3. Returns the row_count value of the first row
    (defn -main
      [& args]
      (log/info "Executing SQL:\n" (first sql))
      (println (jdbc/query hive-spec sql {:row-fn :row_count :result-set-fn first})))
    
    나는 이곳의 명령행 매개 변수를 무시했다.나는 그것을 보기 위해 SQL 문장을 기록했다.쿼리 함수를 호출하여 사양명세, sql 및 옵션 매핑을 전달합니다. 여기서 다음을 지정합니다.
  • 첫 줄만 되돌려주는 결과 집합 함수
  • row 함수, SQL 문장에 별명을 사용한 row count열만 되돌려줍니다
    열 앨리어스를 사용하지 않고 COUNT(*)를 사용하는 경우 Hive는 이를 c0과 같은 모호한 값으로 정의합니다.조금도 우호적이지 않다.
  • 다음은 전체 core.clj 파일입니다.
    (ns emr-hive-jdbc-example.core
      (:require [clojure.tools.logging :as log])
      (:require [clojure.java.jdbc :as jdbc])
      (:gen-class))
    
    ;; Define the user/password/subname from ENV variables
    (def user (System/getenv "EMR_HIVE_JDBC_USER"))
    (def password (System/getenv "EMR_HIVE_JDBC_PASSWORD"))
    (def subname (System/getenv "EMR_HIVE_JDBC_SUBNAME"))
    
    ;; Preconditions
    (when (nil? user)
      (throw (RuntimeException. "user is nil")))
    (when (nil? password)
      (throw (RuntimeException. "password is nil")))
    (when (nil? subname)
      (throw (RuntimeException. "subname is nil")))
    
    ;; Define the connection specification
    (def hive-spec {:classname "com.amazon.hive.jdbc41.HS2Driver"
                   :subprotocol "hive2"
                   :subname subname
                   :user user
                   :password password})
    
    ;; Define the SQL statement to execute
    (def sql ["SELECT
                   COUNT(*) AS row_count
               FROM
                   my_table"]) ; TODO: Change to your desired SQL statement
    
    ;; The main entry-point
    ;; 1. Logs the SQL to execute
    ;; 2. Executes the SQL
    ;; 3. Returns the row_count value of the first row
    (defn -main
      [& args]
      (log/info "Executing SQL:\n" (first sql))
      (println (jdbc/query hive-spec sql {:row-fn :row_count :result-set-fn first})))
    

    프로젝트 관리


    내가 이 프로젝트를 테스트할 때, 나는lein으로 그것을 운행한다.
    lein run
    
    나중에 JAR을 컴파일한 후 Java를 통해 실행할 수 있습니다.
    java -jar emr-hive-jdbc-example-0.1.0-standalone.jar
    

    결론


    어쨌든 나는 내가 성공할 수 있어서 매우 기쁘다.나는 Clojure + JDBC 코드의 기능성을 좋아한다.
    누군가도 이게 유용하다고 생각했으면 좋겠어요.

    전체 소스 코드


    ejstembler/emr-hive-jdbc-example

    좋은 웹페이지 즐겨찾기