반응형

스프링부트에서 mysql 연동시 다음과 같은 에러를 본적이 있을 것이다.

java.sql.SQLException: The server time zone value 'KST' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

 mysql-connector-java 버전 5.1.X 이후 버전부터 KST 타임존을 인식하지 못하는 이슈로

application.properties의 datasource.url부분을 수정해준다.

spring.datasource.url에 'serverTimezone=UTC'를 추가해준다.

이후 어플리케이션 시작시 에러가 깔끔하게 사라진것을 확인할 수 있을 것이다.

반응형
반응형

Mac에서 디렉토리별 사이즈를 쉽게 확인 할 수 있는 유틸리티 프로그램을 소개합니다.

 

Disk Innvenntory X

설치를 하시고 실행을 하게 되면 다음과 같이 디렉토리별 용량을 보여줍니다.

 

해당 앱을 사용하여 예상치 못한곳에서 디스크를 공간을 많이 차지하고 있는 불필요한 데이터를 삭제해주면 

 

좀 더 쾌적하게 Mac을 사용하실 수 있을 것 같습니다.

반응형
반응형

스프링부트에 actuactor적용하다가 다음과 같은 에러메시지가 발생했다.

해당 프로젝트에서는 스프링부트 버전 2.1.0.REALSE를 사용하고 있다.

org.apache.solr.client.solrj.SolrServerException: Server refused connection at: http://127.0.0.1:8983/solr at org.apache.solr.client.solrj.impl.HttpSolrClient.executeMethod(HttpSolrClient.java:650) at 
.
.
.
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to 127.0.0.1:8983 [/127.0.0.1] failed: Connection refused (Connection refused) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:159) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:373) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:394) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)

해당 프로젝트에서는 spring-boot-starter-data-solr를 사용하고 있었고 spring-boot-starter-actuator dependency를 추가하고

application.properties에 다음과 같이 추가해주었다. actuator사용을 위해서!

management.endpoint.metrics.enabled=true
management.endpoints.web.exposure.include=*
management.endpoint.prometheus.enabled=true
management.metrics.export.prometheus.enabled=true

 

 

문제해결은 다음과 같이 했다.

management.health.solr.enabled=false 한줄을 application.properties에 추가해주어 처리해주었다. 뭔가 actuator내부적으로 solr를 사용하고 있어 포트가 충돌나지 않았나 싶다. 이에 actuator설정에서 저렇게 false로 명시해주니 정상적으로 동작하는 것을 확인하였다.

반응형
반응형

스프링부트의 기본 컨테이너는 톰캣임을 알고 있었는데 이를 제외하고

다른 컨테이너를 사용하기 위한 방법에 대해 간단히 포스팅해본다. 

 

spring-boot-starter-web을 사용하게 되면 내부에 spring-boot-starter-tomcat을 포함하게 된다.

의존성 관계를 보면 알 수 있다.

따라서 다른 컨테이너를 사용하고 싶다면 spring-boot-starter-web의존성에서 tomcat을 exclusion시켜주어야 한다.

참조 : https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html

위와 같이 tomcat을 exclusion시켜주고 jetty의존성을 주입하게 되면 컨테이너로 jetty를 사용할 수 있다.

 

자세한 내용은 spring docs를 참고하자!

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html

반응형
반응형

가끔 사이즈 문제인지 binary형태로 저장된 데이터들을 본다,,.,,,,

이걸 읽으려면 파일을 읽기전에 다음과 같이 conf를 설정해준다.

sqlContext.setConf("spark.sql.parquet.binaryAsString","true")

 

그 이후 sqlContext.read.format("parquet").load("hdfs://path")로 읽어주면 된다.

 

spark 2.0대 이후 버전에서는 다음과 같이 입력해주자.

spark.conf.set("spark.sql.parquet.binaryAsString","true")

 

반응형
반응형

Spark datafrmae에서 데이터 정렬할 떄

 

dataframe.orderBy(desc("columnName"))

dafaframe.sort(desc("columnName"))

 

두 개 차이점이 뭘까???

OrderBy는 단순히 sort function의 alias라는점!!!...결국 동일하다는 얘기

[ Spark documentation ]
/**
* Returns a new Dataset sorted by the given expressions.
* This is an alias of the `sort` function.
*
* @group typedrel
* @since 2.0.0
*/
@scala.annotation.varargs
def orderBy(sortCol: String, sortCols: String*): Dataset[T] = sort(sortCol, sortCols : _*)
반응형
반응형

이번에 hadoop mapreduce작업을 진행하는겸 reducer개수 설정에 따라 처리속도가 어떻게 달라지는지 간단히 확인해보았다.

(물론 cluster의 환경 작업의 데이터처리 사이즈 및 작업의 종류에 따라 달라질 수 있다.)

 

작업내용

- parquet형태의 데이터를 읽는다.

- 컬럼별 특정 rule에 의해 match가 되지 않는 데이터에 대해 counting을 한다.

- MisMatch된 데이터에 대해 최종적으로 hdfs에 write한다. (MultipleOutput)

- 컬럼별 데이터 분포도를 counting해서 컬럼별로 결과 file로 남긴다. (local)

- 컬럼별 나올 수 있는 모든 조합들의 집합의 데이터 분포도도 hdfs파일에 write한다. (MultipleOutput)

 

데이터 사이즈/데이터 라인수

362.5 M / 22,766,706

 

컬럼개수 

6개

 

Reducer 1 개일 때 : 2 34

19/06/27 14:28:18 INFO client.RMProxy: Connecting to ResourceManager at acenmd-dmp001.svr.toastmaker.net/10.160.231.113:8032

19/06/27 14:28:19 INFO input.FileInputFormat: Total input paths to process : 50

19/06/27 14:28:19 INFO mapreduce.JobSubmitter: number of splits:50

19/06/27 14:28:19 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1559692026802_4638

19/06/27 14:28:19 INFO impl.YarnClientImpl: Submitted application application_1559692026802_4638

19/06/27 14:28:19 INFO mapreduce.Job: The url to track the job: http://acenmd-dmp001.svr.toastmaker.net:8088/proxy/application_1559692026802_4638/

19/06/27 14:28:19 INFO mapreduce.Job: Running job: job_1559692026802_4638

19/06/27 14:28:26 INFO mapreduce.Job: Job job_1559692026802_4638 running in uber mode : false

19/06/27 14:28:26 INFO mapreduce.Job:  map 0% reduce 0%

19/06/27 14:28:40 INFO mapreduce.Job:  map 2% reduce 0%

(생 략)

19/06/27 14:30:48 INFO mapreduce.Job:  map 100% reduce 99%

19/06/27 14:30:52 INFO mapreduce.Job:  map 100% reduce 100%

19/06/27 14:30:52 INFO mapreduce.Job: Job job_1559692026802_4638 completed successfully

 

Reducer 5개일 때 : 1 9

19/06/27 18:32:26 INFO client.RMProxy: Connecting to ResourceManager at acenmd-dmp001.svr.toastmaker.net/10.160.231.113:8032

19/06/27 18:32:27 INFO input.FileInputFormat: Total input paths to process : 50

19/06/27 18:32:27 INFO mapreduce.JobSubmitter: number of splits:50

19/06/27 18:32:27 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1559692026802_4692

19/06/27 18:32:27 INFO impl.YarnClientImpl: Submitted application application_1559692026802_4692

19/06/27 18:32:28 INFO mapreduce.Job: The url to track the job: http://acenmd-dmp001.svr.toastmaker.net:8088/proxy/application_1559692026802_4692/

19/06/27 18:32:28 INFO mapreduce.Job: Running job: job_1559692026802_4692

19/06/27 18:32:35 INFO mapreduce.Job: Job job_1559692026802_4692 running in uber mode : false

19/06/27 18:32:35 INFO mapreduce.Job:  map 0% reduce 0%

19/06/27 18:32:50 INFO mapreduce.Job:  map 8% reduce 0

(생 략)

19/06/27 18:33:32 INFO mapreduce.Job:  map 100% reduce 99%

19/06/27 18:33:35 INFO mapreduce.Job:  map 100% reduce 100%

19/06/27 18:33:35 INFO mapreduce.Job: Job job_1559692026802_4692 completed successfully

 

Reducer 10개 일 때 : 1분 2초

19/06/27 18:18:08 INFO client.RMProxy: Connecting to ResourceManager at acenmd-dmp001.svr.toastmaker.net/10.160.231.113:8032

19/06/27 18:18:09 INFO input.FileInputFormat: Total input paths to process : 50

19/06/27 18:18:09 INFO mapreduce.JobSubmitter: number of splits:50

19/06/27 18:18:09 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1559692026802_4688

19/06/27 18:18:10 INFO impl.YarnClientImpl: Submitted application application_1559692026802_4688

19/06/27 18:18:10 INFO mapreduce.Job: The url to track the job: http://acenmd-dmp001.svr.toastmaker.net:8088/proxy/application_1559692026802_4688/

19/06/27 18:18:10 INFO mapreduce.Job: Running job: job_1559692026802_4688

19/06/27 18:18:17 INFO mapreduce.Job: Job job_1559692026802_4688 running in uber mode : false

19/06/27 18:18:17 INFO mapreduce.Job:  map 0% reduce 0%

19/06/27 18:18:31 INFO mapreduce.Job:  map 2% reduce 0%

(생 략)

19/06/27 18:19:07 INFO mapreduce.Job:  map 100% reduce 99%

19/06/27 18:19:10 INFO mapreduce.Job:  map 100% reduce 100%

19/06/27 18:19:10 INFO mapreduce.Job: Job job_1559692026802_4688 completed successfully

 

Reducer 20개 일때 : 1분 1초

19/06/27 18:27:45 INFO client.RMProxy: Connecting to ResourceManager at acenmd-dmp001.svr.toastmaker.net/10.160.231.113:8032

19/06/27 18:27:46 INFO input.FileInputFormat: Total input paths to process : 50

19/06/27 18:27:47 INFO mapreduce.JobSubmitter: number of splits:50

19/06/27 18:27:47 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1559692026802_4689

19/06/27 18:27:47 INFO impl.YarnClientImpl: Submitted application application_1559692026802_4689

19/06/27 18:27:47 INFO mapreduce.Job: The url to track the job: http://acenmd-dmp001.svr.toastmaker.net:8088/proxy/application_1559692026802_4689/

19/06/27 18:27:47 INFO mapreduce.Job: Running job: job_1559692026802_4689

19/06/27 18:27:56 INFO mapreduce.Job: Job job_1559692026802_4689 running in uber mode : false

19/06/27 18:27:56 INFO mapreduce.Job:  map 0% reduce 0%

19/06/27 18:28:14 INFO mapreduce.Job:  map 19% reduce 0%

19/06/27 18:28:15 INFO mapreduce.Job:  map 39% reduce 0%

(생 략)

19/06/27 18:28:42 INFO mapreduce.Job:  map 100% reduce 99%

19/06/27 18:28:43 INFO mapreduce.Job:  map 100% reduce 100%

19/06/27 18:28:46 INFO mapreduce.Job: Job job_1559692026802_4689 completed successfully

 

결 론

Reducer를 많이 늘린다고해서 처리 속도가 비례해서 향상되는 것은 아니다. 해당 작업의 유형을 고려하고 Reducer개수를 조절해가며 최적의 개수를 찾는게 중요하다. Reducer개수에 따라 결과 데이터가 hdfs에 쓰여진다.(Reducer10개면 10개의 파티션으로, 5개이면 5개의 파티션으로)

 

마지막으로 하둡 완벽가이드(4판)의 내용을 첨부한다.

리듀서를 하나만 두는 것(기본값)은 하둡 초보자가 자주 범하는 실수다. 실제로 대부분의 잡은 리듀서 수를 기본값인 1보다 크게 설정하는 것이 좋다. 그렇지 않으면 모든 중간 데이터가 하나의 리듀스 태스크로 모여들기 때문에 잡이 굉장히 느려진다. 사실 잡의 리듀서 수를 결정하는 것은 과학보다는 예술에 가깝다. 보통 리듀서 수를 늘리면 병렬 처리 개수도 늘어나서 리듀스 단계에서 걸리는 시간을 줄일 수 있다. 그러나 너무 많이 늘리면 작은 파일이 너무 많이 생성되는 준최적화(suboptimal)에 빠지게 된다. 경험적으로 리듀서의 실행 시간은 5분 내외, 출력 파일의 HDFS 블록 수는 최소 1개로 잡는 것이 좋다.

 

반응형
반응형

하둡 MR작업 중 다음과 같은 에러를 만났다.

19/06/19 11:16:49 INFO mapreduce.Job: Task Id : attempt_1559692026802_2824_m_000031_2, Status : FAILED
Error: Found interface org.apache.hadoop.mapreduce.Counter, but class was expected
19/06/19 11:16:49 INFO mapreduce.Job: Task Id : attempt_1559692026802_2824_m_000047_2, Status : FAILED
Error: Found interface org.apache.hadoop.mapreduce.Counter, but class was expected
19/06/19 11:16:49 INFO mapreduce.Job: Task Id : attempt_1559692026802_2824_m_000011_2, Status : FAILED
Error: Found interface org.apache.hadoop.mapreduce.Counter, but class was expected
19/06/19 11:16:49 INFO mapreduce.Job: Task Id : attempt_1559692026802_2824_m_000034_2, Status : FAILED
Error: Found interface org.apache.hadoop.mapreduce.Counter, but class was expected

위와 같은 에러로 인해 map작업이 계속해서 실패하며 다음과 같은 에러를 내며 죽어버린다. 

Exception in thread "main" java.lang.NoSuchMethodError: org.apache.hadoop.mapreduce.Counters.getGroup(Ljava/lang/String;)Lorg/apache/hadoop/mapreduce/CounterGroup;

문제의 원인은 하둡 MR작업 중 Counter를 사용하는데 해당 라이브러리를 잘못 가져다 써서 문제가 발생한 것이였다.

maven pom.xml

위와 같은 hadoop-core, hadoop-common 버전의 라이브러리를 사용해 작업을 했었다. 하지만 실제 하둡 MR을 구동하는 환경은 CDH 5.11.1에 설치된 하둡 패키지를 사용하고 있었기에 Counter메소드를 찾지 못해 NoSuchMethodError를 뱉는 것이었다.

 

따라서 pom.xml에 repository와 depency 수정으로 해결하였다.

cloudera repository추가

cdh5.11.1에서 동작하도록 수정해주었다.

 

끝~~~~신기한건 똑같은 기능을 spark, mr둘다 만들어서 테스트해보았는데 단순히 데이터 읽어가면서 filterling하고 간단한 통계자료 뽑고하는 로직만 있어서 그런지 하둡MR이 훨씬 빨랐다는거....

반응형
반응형

스파크 작업 중 다음과 같은 에러를 만났다.

19/06/11 17:44:14 INFO scheduler.DAGScheduler: ResultStage 9 (saveAsTextFile at MainHanhwa.scala:51) failed in 31.631 s due to Job aborted due to stage failure: Task 108 in stage 9.0 failed 1 times, most recent failure: Lost task 108.0 in stage 9.0 (TID 529, localhost, executor driver): java.lang.OutOfMemoryError: error while calling spill() on org.apache.spark.util.collection.unsafe.sort.UnsafeExternalSorter@33e9c68d : 장치에 남은 공간이 없음
    at org.apache.spark.memory.TaskMemoryManager.acquireExecutionMemory(TaskMemoryManager.java:183)
    at org.apache.spark.memory.TaskMemoryManager.allocatePage(TaskMemoryManager.java:249)
    at org.apache.spark.memory.MemoryConsumer.allocatePage(MemoryConsumer.java:112)
    at org.apache.spark.util.collection.unsafe.sort.UnsafeExternalSorter.acquireNewPageIfNecessary(UnsafeExternalSorter.java:332)
    at org.apache.spark.util.collection.unsafe.sort.UnsafeExternalSorter.insertRecord(UnsafeExternalSorter.java:347)
    at org.apache.spark.sql.execution.UnsafeExternalRowSorter.insertRow(UnsafeExternalRowSorter.java:91)
    at org.apache.spark.sql.execution.UnsafeExternalRowSorter.sort(UnsafeExternalRowSorter.java:168)
    at org.apache.spark.sql.execution.Sort$$anonfun$1.apply(Sort.scala:90)
    at org.apache.spark.sql.execution.Sort$$anonfun$1.apply(Sort.scala:64)
    at org.apache.spark.rdd.RDD$$anonfun$mapPartitionsInternal$1$$anonfun$apply$21.apply(RDD.scala:728)
    at org.apache.spark.rdd.RDD$$anonfun$mapPartitionsInternal$1$$anonfun$apply$21.apply(RDD.scala:728)
    at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
    at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:306)

이 때 스파크 설정은 다음과 같았다. 

spark-submit \
    --name "hanhwa-job" \
    --master yarn \
    --driver-memory 2g \
    --executor-memory 4g \
    --class spark.datatech.MainHanhwa \
    /home1/irteam/dbkim/hanhwa/spark-gradle-1.6.x-0.1.jar

 

원인을 찾아본 결과 다음과 같은 스택오버플로우 내용이 있었다.

Questions : 

When performing a shuffle my Spark job fails and says "no space left on device", but when I run df -h it says I have free space left! Why does this happen, and how can I fix it?

 

Answers 1: 

By default Spark uses the /tmp directory to store intermediate data. If you actually do have space left on some device -- you can alter this by creating the file SPARK_HOME/conf/spark-defaults.confand adding the line. Here SPARK_HOME is wherever you root directory for the spark install is.

spark.local.dir SOME/DIR/WHERE/YOU/HAVE/SPACE

출처 : https://stackoverflow.com/questions/25707784/why-does-a-job-fail-with-no-space-left-on-device-but-df-says-otherwise

 

Answer2: 

This is because Spark create some temp shuffle files under /tmp directory of you local system.You can avoid this issue by setting below properties in your spark conf files.

Set this property in spark-evn.sh.

 

SPARK_JAVA_OPTS+=" -Dspark.local.dir=/mnt/spark,/mnt2/spark -Dhadoop.tmp.dir=/mnt/ephemeral-hdfs" export SPARK_JAVA_OPTS

출처 : https://stackoverflow.com/questions/30162845/spark-java-io-ioexception-no-space-left-on-device

 

뭐 스파크 작업중 중간 과정에서 셔플링 데이터가 쌓이는데 해당 공간이 부족해서 그렇다며 스파크 디렉토리 데이터를 수정해주면 된다는~!

하지만 난 그냥 뭔가 spark-submit시 설정만 변경하기로 하고 설정을 다시 봤더니 executor-cores와 num-executor를 설정해주지 않은 걸 보고 default로 잡혀서 너무 작게 잡혀서 그런가 하고 추가로 넣어서 다시 spark-submit결과 정상동작하였다.

 

Spark-submit 옵션은 다음과 같았다. 

num-executors와 executor-cores가 추가되었다.

spark-submit \
    --name "hanhwa-job" \
    --master yarn \
    --driver-memory 2g \
    --num-executors 10 \
    --executor-cores 12 \
    --executor-memory 4g \
    --class spark.datatech.MainHanhwa \
    /home1/irteam/dbkim/hanhwa/spark-gradle-1.6.x-0.1.jar 

 

문제는 이렇게 해결되긴 했지만 spark설정들의 default값을 좀 더 알아보고 클러스터, 서비스에 맞는 적절한 설정을 할 수 있도록 더 알아보고 학습해야 겠다.

반응형

+ Recent posts