아파치 NIFI를 처음 써보려면 약간 당혹스러울 수 있다.


보통 NIFI에 KAFKA나 HADOOP을 연동할 터인데요. 초반에 애를 먹는다.



아래 블로그를 참조하면 어떻게 KAFKA, HDFS, CASSANDRA를 사용하는 예를 참고하면 좋을 것 같다.


https://blog.autsoft.hu/beginners-guide-to-apache-nifi-flows/









Posted by 김용환 '김용환'



HadoopRDD는 하둡 1.x 라이브러리의 맵리듀스 API를 사용해 HDFS에 저장된 데이터를 읽는 핵심 기능을 제공한다. 

그러나 일반 파일 시스템에서 읽을 때도 HadoopRDD가 사용된다. 


HadoopRDD는 기본적으로 사용되며 모든 파일 시스템의 데이터를 RDD로 로드할 때 HadoopRDD를 살펴볼 수 있다.




scala> val statesPopulationRDD = sc.textFile("test.csv")

statesPopulationRDD: org.apache.spark.rdd.RDD[String] = test.csv MapPartitionsRDD[27] at textFile at <console>:24


scala>  statesPopulationRDD.toDebugString

res22: String =

(2) test.csv MapPartitionsRDD[27] at textFile at <console>:24 []

 |  test.csv HadoopRDD[26] at textFile at <console>:24 []







NewHadoopRDD는 Hadoop 2.x 라이브러리의 새로운 맵리듀스 API를 사용해 HDFS, HBase 테이블, 아마존 S3에 저장된 데이터를 읽는 핵심 기능을 제공한다. NewHadoopRDD는 다양한 포맷으로 읽을 수 있기 때문에 여러 외부 시스템과 상호 작용하기 위해 사용된다.


스파크 컨텍스트의 wholeTextFiles 함수를 사용하여 WholeTextFileRDD를 생성하는 것이다. 실제로 WholeTextFileRDD는 다음 코드처럼 NewHadoopRDD를 상속한다.

scala> val rdd_whole = sc.wholeTextFiles("test.txt")

rdd_whole: org.apache.spark.rdd.RDD[(String, String)] = wiki1.txt MapPartitionsRDD[29] at wholeTextFiles at <console>:24


scala> rdd_whole.toDebugString

res23: String =

(1) test.txt MapPartitionsRDD[29] at wholeTextFiles at <console>:24 []

 |  WholeTextFileRDD[28] at wholeTextFiles at <console>:24 []




직접적으로 스파크 컨텍스트의 newAPIHadoopFile을 사용할 수 있다. 




import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat


import org.apache.hadoop.io.Text


val newHadoopRDD = sc.newAPIHadoopFile("test.txt", classOf[KeyValueTextInputFormat], classOf[Text],classOf[Text])






Posted by 김용환 '김용환'


scala를 webjars-play와 연동하다가 종종 중복 이슈가 발견이 되어서 자세히 중복 확인을 하고 싶었다.


자실 webjars-play 뿐 아니라 일반 scala 프로젝트를 사용할 때도 많은 도움이 된다. 




https://github.com/sbt/sbt-duplicates-finder를 사용해.. 자세히 확인할 수 있다. 



addSbtPlugin("org.scala-sbt" % "sbt-duplicates-finder" % "0.7.0")



$ sbt


[project name] $ checkDuplicates


[warn] Detected classes conflicts:

[warn]

[warn] - io/netty/handler/codec/string/LineSeparator.class: content differ

[warn] - /Users/samuel.kim/.ivy2/cache/io.netty/netty-codec/jars/netty-codec-4.1.9.Final.jar

[warn] - /Users/samuel.kim/.ivy2/cache/io.netty/netty-all/jars/netty-all-4.1.10.Final.jar

[warn]

[warn] - io/netty/util/internal/logging/InternalLoggerFactory.class: content differ

[warn] - /Users/samuel.kim/.ivy2/cache/io.netty/netty-common/jars/netty-common-4.1.9.Final.jar

[warn] - /Users/samuel.kim/.ivy2/cache/io.netty/netty-all/jars/netty-all-4.1.10.Final.jar

[warn]

[warn] - javax/servlet/SingleThreadModel.class: content differ

[warn] - /Users/samuel.kim/.ivy2/cache/org.mortbay.jetty/servlet-api-2.5/jars/servlet-api-2.5-6.1.14.jar

[warn] - /Users/samuel.kim/.ivy2/cache/javax.servlet/servlet-api/jars/servlet-api-2.5.jar

[warn]



하지만, https://github.com/coursier/coursier는 훨씬 자세히 보여준다.




$ sbt compile

[warn] Executing in batch mode.

[warn]   For better performance, hit [ENTER] to switch to interactive mode, or

[warn]   consider launching sbt without any commands, or explicitly passing 'shell'

[info] Loading project definition from /Users/samuel.kim/dev/ccc/kemi-logview/project

[info] Set current project to kemi-logview (in build file:/Users/samuel.kim/dev/ccc/kemi-logview/)

coursier.ResolutionException: Conflict(s) in dependency resolution:

  org.webjars.npm:object-assign:3.0.0:default(compile)

org.webjars.npm:object-assign:4.0.1:default(compile)

org.webjars.npm:object-assign:4.1.1:default(compile)

[error] (*:coursierResolutions) coursier.ResolutionException: Conflict(s) in dependency resolution:

[error]   org.webjars.npm:object-assign:3.0.0:default(compile)

[error] org.webjars.npm:object-assign:4.0.1:default(compile)

[error] org.webjars.npm:object-assign:4.1.1:default(compile)

[error] Total time: 8 s, completed 2017. 12. 22 오후 6:45:36


Posted by 김용환 '김용환'

개발자라면 이미 변수의 데이터가 존재하느냐 라는 함수/메소드를 정의해야 할 때가 있다. 


그냥 생각나는 대로 isExistedData, isExistData 란 함수/메소스를 쓰는 경우가 있다. 


이는 Konglish이다. hasData라는 함수/메소드를 사용하는 것이 좋다.



출처 


https://forum.wordreference.com/threads/is-existed-vs-exists.1773199/



is existed data

is exist data

-> has data






Posted by 김용환 '김용환'

React를 이해하고 Redux를 사용해야 할 때 


React 컴포넌트를 개발하고 처음으로 Redux 를 사용하려 하는 개발자를 위한 참조 문서


개념에 대한 이해도를 높이고 Provider를 활용할 수 있는 가이드

(기본 소스로 얘를 이용)

https://www.kirupa.com/react/using_redux_with_react.htm



custom 이벤트 데이터를 payload로 전달할 수 있고 connect에 대한 이해를 높이는 가이드

https://lorenstewart.me/2016/11/27/a-practical-guide-to-redux/



mapStateToProps을 이해하는데 도움되는 가이드

https://www.zerocho.com/category/React/post/57b60e7fcfbef617003bf456










Posted by 김용환 '김용환'



superagent(https://github.com/visionmedia/superagent)는 동기 콜이 없다. 


무조건 비동기 콜이다.


따라서 아래처럼 superagent가 동기콜인양 쓰면 state/props 간의 동기 이슈가 발생할 수 있다. 


즉, superagent에서 end 내부가 동작되기 전에 handleResult가 먼저 실행된다. 


superagent.get('/search_log')
.
query(..)
.
retry(2)
.
end((err, res) => {
if (res.ok) { //..
}
else {
//
..
}

}); {this.handleResult()}




따라서. end() 밑에 성공하고 난 이후에 handleResult()를 호출하는 형태로 진행하면 동기 콜과 같은 효과를 얻을 수 있을 것이다. 


superagent.get('/search_log')
.
query(..)
.
retry(2)
.
end((err, res) => {
if (res.ok) { //..
{this.handleResult()}
}
else {
//
..
}

});




Posted by 김용환 '김용환'



react 컴포넌트 안에서 다음처럼 내부 함수끼리 호출할 때 에러가 발생할 수 있다. 

(handleMouseDown은 bind()되어 있다)


handleMouseDown(e) {

   _handleLog()

}


_handleLog() {

..

}






아래와 같이 _handleLog()를 호출할 때 {와 }를 추가하면 문제가 해결된다. 




handleMouseDown(e) {

   {_handleLog()}

}


_handleLog() {

..

}






render() 함수 내에서도 동일하게 사용할 수 있다.

Posted by 김용환 '김용환'

react 컴포넌트간의 통신을 위해 redux 처음 공부할 때 


매우 도움되는 싸이트는 www.kirupa.com이다. 



이 중 연동 부분은 다음과 같다. 


https://www.kirupa.com/react/using_redux_with_react.htm



javascript 프로젝트를 처음을 해보니 react-redux 개발을 끝내고 나니, 저 싸이트가 최고더라는 생각이 들었다. 

Posted by 김용환 '김용환'



디스크 볼륨을 추가한 뒤


 재부팅되더라도 계속 디바이스에 잘 연결되도록 하려면.. /etc/fstab을 사용해야 한다. 





먼저 특정 디바이스를 xfs로 파일 시스템을 구축하고 mount 한다. 그리고 잘 붙는지 확인한다.


$ mkfs.xfs -f /dev/sdc 

$ mount -t xfs /dev/sdc /home/file3

$ df

/dev/sdc       2928835792     32944 2928802848   1% /home/file3

 



block id를 구한다.


$ sudo blkid -pi /dev/sdc

DEVNAME=/dev/sdc

UUID=df556bd3-da08-4642-a2cd-179f34c603a6

TYPE=xfs

USAGE=filesystem

MINIMUM_IO_SIZE=512

PHYSICAL_SECTOR_SIZE=512

LOGICAL_SECTOR_SIZE=512






재부팅되더라도 df 커맨드를 사용하면 항상 운영체제와 연결될 수 있도록 /etc/fstab에 추가한다.


UUID=df556bd3-da08-4642-a2cd-179f34c603a6    /               xfs    errors=remount-ro 0       1









만약 아래와 같이 uuid가 나오지 않는 다면 디스크 볼륨이 없거나 문제가 있는 것이다.


# sudo blkid -ip /dev/sdc

DEVNAME=/dev/sdc

MINIMUM_IO_SIZE=512

PHYSICAL_SECTOR_SIZE=512

LOGICAL_SECTOR_SIZE=512



참고


http://faq.hostway.co.kr/Linux_ETC/7437

http://nan1004au.tistory.com/entry/Linux-%EB%94%94%EC%8A%A4%ED%81%AC%EC%9D%98-UUID%EB%A5%BC-%EC%95%8C%EC%95%84%EC%98%A4%EA%B8%B0-ntfs-ext3-%EB%A7%88%EC%9A%B4%ED%8A%B8


Posted by 김용환 '김용환'


React, Redux 디버깅할 때 유용한 툴을 소개한다.


이것 없으면 진짜 힘들다..





1. 개발자 도구


크롬의 개발자 도구이다. 이번에 자세히 써보니. 크롬 개발자 도구에 대한 기본 지식이 없어서 쉽지 않았다.

아래 내용을 참고 한다. 


http://shiren.github.io/2016-03-23-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%ED%81%AC%EB%A1%AC-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EB%8F%84%EA%B5%AC/





2. Chrome React DevTools



설치

https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi





3. Chrom Redux DevTools


설치 

https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ko






사용하려면 아래 createStore에 아래 정보를 추가해야 한다.

const store = createStore( reducer, /* preloadedState, */ + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() );



Posted by 김용환 '김용환'