복붙노트

[HADOOP] MapRe에서 조회를 위해 XML 파일을 읽도록 허용하는 방법

HADOOP

MapRe에서 조회를 위해 XML 파일을 읽도록 허용하는 방법

내 MapReduce 작업에서 제품 이름을 문자열 인수로 Mapper에 전달합니다. Mapper.py 스크립트는 제품 이름으로 무언가를 수행하고 일부 방출 문자열을 Mapper에 반환하는 Process.py라는 보조 스크립트를 가져옵니다. 그런 다음 매퍼는 해당 문자열을 Hadoop 프레임 워크로 내 보내서 Reducer에서 선택할 수 있습니다. 다음을 제외한 모든 것이 잘 작동합니다.

Process.py 스크립트에는 업데이트하기 쉽도록 스크립트 내부에서 xml 파일로 이동하려는 조회 값 사전이 포함되어 있습니다. 나는 이것을 로컬에서 테스트했으며 Process.py 스크립트에 xml 파일의 Windows 경로를 포함하면 정상적으로 작동합니다. 그러나 Hadoop MapReduce 환경에서이 테스트는 어떤 이유로 작동하지 않습니다.

Process.py 스크립트 내에서 xml 문서에 대한 HDFS 경로를 지정하려고했지만 MapReduce 작업 명령에서 xml 문서의 이름을 -file 인수로 추가하려고 시도했지만 둘 다 작동하지 않았습니다.

예를 들어 Process.py 내부에서 다음을 시도했습니다. xml_file = r'appers@hdfs.network.com : /nfs_home/appers/cnielsen/product_lookups.xml ' 과 xml_file = r '/ nfs_home / appers / cnielsen / product_lookups.xml'

MapReduce 명령에서 xml 파일의 이름을 -file 인수로 포함했습니다. 예를 들면 다음과 같습니다. ... -file product_lookups.xml -reducer ...

질문 : MapReduce 환경에서 Process.py 스크립트가 HDFS에 저장된이 xml 문서를 읽도록하려면 어떻게해야합니까?

해결법

  1. ==============================

    1.다음은이 이전 질문에서 언급 된 기술을 귀하의 질문에보다 가깝게 맞추는 엔드 투 엔드 예제입니다.

    다음은이 이전 질문에서 언급 된 기술을 귀하의 질문에보다 가깝게 맞추는 엔드 투 엔드 예제입니다.

    파이썬은 파일을 HDFS에서 스트림으로 읽습니다.

    키-값 쌍을 읽고 HDFS에 저장된 XML 구성 파일과 키를 확인한 다음 키가 구성과 일치하는 경우에만 값을 내보내는 작은 Python Hadoop 스트리밍 응용 프로그램입니다. 일치하는 논리는 별도의 Process.py 모듈로 오프로드되며 hdfs dfs -cat에 대한 외부 호출을 사용하여 HDFS에서 XML 구성 파일을 읽습니다.

    먼저, 구현을위한 Python 소스 파일을 포함하는 pythonapp라는 디렉토리를 만듭니다. 나중에 스트리밍 작업을 제출할 때이 디렉토리를 -files 인수로 전달할 것입니다.

    파일을 -files 인수에 개별적으로 나열하는 대신 파일을 중간 디렉토리에 넣는 이유는 무엇입니까? YARN이 컨테이너에서 실행할 파일을 지역화 할 때 심볼릭 링크 간접 레이어를 도입하기 때문입니다. 그러면 파이썬은 심볼릭 링크를 통해 모듈을 올바르게로드 할 수 없습니다. 해결책은 두 파일을 동일한 디렉토리에 패키지하는 것입니다. 그런 다음 YARN이 파일을 지역화 할 때 개별 파일 대신 디렉토리 수준에서 심볼릭 링크를 수행합니다. 메인 스크립트와 모듈은 물리적으로 같은 디렉토리에 있기 때문에 파이썬은 모듈을 올바르게로드 할 수 있습니다. 이 질문은 문제를보다 자세하게 설명합니다.

    MapReduce 작업에서 사용자 정의 모듈을 가져 오는 방법은 무엇입니까?

    import subprocess
    import sys
    from Process import match
    
    for line in sys.stdin:
        key, value = line.split()
        if match(key):
            print value
    
    import subprocess
    import xml.etree.ElementTree as ElementTree
    
    hdfsCatProcess = subprocess.Popen(
            ['hdfs', 'dfs', '-cat', '/pythonAppConf.xml'],
            stdout=subprocess.PIPE)
    pythonAppConfXmlTree = ElementTree.parse(hdfsCatProcess.stdout)
    matchString = pythonAppConfXmlTree.find('./matchString').text.strip()
    
    def match(key):
        return key == matchString
    

    다음으로 2 개의 파일을 HDFS에 넣습니다. / testData는 탭으로 구분 된 키-값 쌍을 포함하는 입력 파일입니다. /pythonAppConf.xml은 특정 키를 구성 할 수있는 XML 파일입니다.

    foo 1
    bar 2
    baz 3
    
    <pythonAppConf>
        <matchString>foo</matchString>
    </pythonAppConf>
    

    matchString을 foo로 설정하고 입력 파일에 키가 foo로 설정된 단일 레코드 만 포함되므로 작업 실행 결과는 키 foo에 해당하는 값을 포함하는 단일 행 (1)이 될 것으로 예상합니다. 테스트 실행의 경우 예상 결과를 얻습니다.

    > hadoop jar share/hadoop/tools/lib/hadoop-streaming-*.jar \
          -D mapreduce.job.reduces=0 \
          -files pythonapp \
          -input /testData \
          -output /streamingOut \
          -mapper 'python pythonapp/Mapper.py'
    
    > hdfs dfs -cat /streamingOut/part*
    1   
    

    이를 수행하는 다른 방법은 -files 인수에 HDFS 파일을 지정하는 것입니다. 이런 식으로 YARN은 Python 스크립트가 시작되기 전에 XML 파일을 현지화 된 리소스로 컨테이너를 실행하는 개별 노드에 가져옵니다. 그런 다음 Python 코드는 작업 디렉토리의 로컬 파일 인 것처럼 XML 파일을 열 수 있습니다. 여러 작업 / 컨테이너를 실행하는 매우 큰 작업의 경우이 기술은 각 작업에서 hdfs dfs -cat 호출보다 성능이 우수합니다.

    이 기술을 테스트하기 위해 다른 버전의 Process.py 모듈을 사용해 볼 수 있습니다.

    import xml.etree.ElementTree as ElementTree
    
    pythonAppConfXmlTree = ElementTree.parse('pythonAppConf.xml')
    matchString = pythonAppConfXmlTree.find('./matchString').text.strip()
    
    def match(key):
        return key == matchString
    

    명령 행 호출이 -files에 HDFS 경로를 지정하도록 변경되고 다시 한 번 예상 된 결과가 표시됩니다.

    > hadoop jar share/hadoop/tools/lib/hadoop-streaming-*.jar \
          -D mapreduce.job.reduces=0 \
          -files pythonapp,hdfs:///pythonAppConf.xml \
          -input /testData \
          -output /streamingOut \
          -mapper 'python pythonapp/Mapper.py'
    
    > hdfs dfs -cat /streamingOut/part*
    1   
    

    Apache Hadoop 문서는 HDFS 파일을 로컬로 가져 오기위한 -files 옵션 사용법에 대해 설명합니다.

    http://hadoop.apache.org/docs/r2.7.1/hadoop-streaming/HadoopStreaming.html#Working_with_Large_Files_and_Archives

  2. ==============================

    2.위에서 제공 한 답변에 대해 Chris Nauroth에게 감사드립니다. 이 게시물을 통해 내 문제를 해결 한 것이 정확히 무엇인지 요약하고 싶습니다.

    위에서 제공 한 답변에 대해 Chris Nauroth에게 감사드립니다. 이 게시물을 통해 내 문제를 해결 한 것이 정확히 무엇인지 요약하고 싶습니다.

    그가 제공 한 두 번째 대답은 내가 원래하려고했던 것에 매우 가깝습니다. 내가 알게 된 것은 몇 가지 작은 변화가 내가 그것을 작동시키는 데 필요한 전부라는 것입니다. 예를 들어 Process.py 스크립트에서 이전에 다음과 같이 작은 조회 XML에 대한 전체 경로를 포함하려고했습니다.

    xml_file = r'appers@hdfs.network.com : /nfs_home/appers/cnielsen/product_lookups.xml ' 과 xml_file = r '/ nfs_home / appers / cnielsen / product_lookups.xml'

    내가해야 할 일은 경로없이 내 Process.py 스크립트에 파일 이름을 제공하는 것입니다. 예를 들면 다음과 같습니다. xml_file = 'product_lookups.xml'

    그런 다음 실제 Hadoop 명령에서 이전 에이 작업을 성공적으로 시도하지 못했습니다. (-mapper 목록 뒤에 -file product_lookups.xml 사용)

      > hadoop jar /share/hadoop/tools/lib/hadoop-streaming.jar \
      -file /nfs_home/appers/cnielsen/Mapper.py \
      -file /nfs_home/appers/cnielsen/Reducer.py \
      -mapper '/usr/lib/python_2.7.3/bin/python Mapper.py ProductName' \
      -file Process.py \
      -file product_lookups.xml \
      -reducer '/usr/lib/python_2.7.3/bin/python Reducer.py' \
      -input /nfs_home/appers/extracts/*/*.xml \
      -output /user/lcmsprod/output/cnielsen/test47
    

    Hadoop 명령을 구성하는 올바른 방법은 -files를 사용하고이 조회 파일을 다른 파일 목록보다 먼저 나열하는 것입니다. 예를 들어 다음과 같이 작동했습니다.

      > hadoop jar /share/hadoop/tools/lib/hadoop-streaming.jar \
      -files /nfs_home/appers/cnielsen/product_lookups.xml \
      -file /nfs_home/appers/cnielsen/Mapper.py \
      -file /nfs_home/appers/cnielsen/Reducer.py \
      -mapper '/usr/lib/python_2.7.3/bin/python Mapper.py ProductName' \
      -file Process.py \
      -reducer '/usr/lib/python_2.7.3/bin/python Reducer.py' \
      -input /nfs_home/appers/extracts/*/*.xml \
      -output /user/lcmsprod/output/cnielsen/test47
    

    참고 :이 페이지에 -files 명령을 구성한다고 표시되어 있지만

    -files hdfs : // host : fs_port / user / testfile.txt

    위에 나열된 실제 명령에서 볼 수 있듯이 hdfs : // 또는 host : 부분을 포함하면 작동하지 않습니다.

  3. from https://stackoverflow.com/questions/34362331/mapreduce-how-to-allow-mapper-to-read-an-xml-file-for-lookup by cc-by-sa and MIT license