Spark 2.0의 데이터 셋(dataset)은 다음과 같이 정의되어 있다.



type DataFrame = Dataset[Row]



Dataset은 스키마를 갖고 있다. 


(spark 1.5) DataFrame에 encoder를 추가한 것이 Dataset이라 할 수 있다.  


(spark 2.0) DataFrame은 특별한 encoder 없이 Dataset[Row]의 앨리어스로 쓸 수 있게 되었다.





데이터 셋을 고도로 최적화한 바이너리(binary)로 표현하는 RDD의 효율적인 테이블로 생각할 수 있다.


바이너리 표현은 인코더(encoder)를 사용해 이루어 진다.


인코더는 RDD 표현보다 성능이 더 좋은 다양한 오브젝트를 바이너리 구조로 직렬화한다.


데이터 프레임은 내부적으로 RDD를 내부적으로 사용하고 데이터 프레임/데이터 셋은 RDD와 동일하게 배포되므로 분산 데이터 집합이기도 하다.


분명 데이터 셋은 불변임을 의미한다.

Posted by '김용환'
,


Play2와 webjar를 이용해 React를 개발하고 있다.


react-infinite.js를 사용하다가 다음과 같은 에러가 발생되었다. 



org.webjars.MultipleMatchesException: Multiple matches found for react-infinite.js. 

Please provide a more specific path, for example by including a version number.




디버깅 버전으로 테스트해보니..(https://github.com/knight76/webjars-locator-core)


build와 dist 디렉토리에 동일한 파일이 있음을 확인했다. 



react-infinite.js/build/0.11.0/react-infinite/webjars/resources/META-INF/=META-INF/resources/webjars/react-infinite/0.11.0/build/react-infinite.js, 

react-infinite.js/dist/0.11.0/react-infinite/webjars/resources/META-INF/=META-INF/resources/webjars/react-infinite/0.11.0/dist/react-infinite.js, 



다음과 같이 build.sbt를 수정하면 된다. 

excludeDependencies ++= Seq(
"org.webjars.npm" % "react-infinite"
)



unmanagedJars in Compile += file("lib/react-infinite-without-conflict-0.11.0.jar")



ivy2에서 캐싱된 내용때문에 그냥 실행하면 기존 파일이 남아 있을 수 있다. 

그리고 새롭게 변경된 lib을 사용할 때마다 다음 커맨드를 실행한다. 


# sbt clean

# sbt clean-files






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 '김용환'
,


scala 2.6에 react 16 연동 작업을 진행하다가 sbt-reactjs에서 사용 중인 graceful-readlink와 minimatch 라이브러리가 사라졌다. (scala-react 연동은 아주 작은 프로젝트만 사용가능하다..)


다음과 같이 수정하니 잘 동작한다. 



resolvers += "Typesafe Releases Repository" at "http://repo.typesafe.com/typesafe/releases/" resolvers += "Central Maven Repository" at "http://repo.maven.apache.org/maven2" resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/" addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.6") addSbtPlugin("com.github.ddispaltro" % "sbt-reactjs" % "0.6.8") dependencyOverrides += "org.webjars.npm" % "minimatch" % "3.0.4" dependencyOverrides += "org.webjars.npm" % "graceful-readlink" % "1.0.1"

https://raw.githubusercontent.com/knight76/play26-scala-reactjs-example/master/project/plugins.sbt

Posted by '김용환'
,


npm을 설치하지 않고 play 2.6에 reactjs를 사용해봤다.


 http://ticofab.io/react-js-tutorial-with-play_scala_webjars/ 링크를 기반으로 


https://github.com/knight76/play26-scala-reactjs-example 예제를 추가했다.


(jquery, bootstrap 연동은 확실히 쉽다)





배운 점(고마운 점)


1. java 커뮤니티에서 web framework를 jar로 묶어둔 webjars 때문에 개발이 엄청 편해졌다. !!


java8의 ScriptEngine, JShell이 엄청 좋아진 것 같다.




2. scala(play) 세계는 reactjs 레퍼런스가 많이 없지만 해볼만한다. 



3. play2의 twirl template engine은 엄청 쓸만하다. 




단점


reactjs의 속도를 따라잡을 수 없다.


아주 작은 프로젝트에만 쓸만하다. 

Posted by '김용환'
,


play framework(scala)에 reactjs를 실행시킬려면 sbt-reactjs를 사용해야 한다.

addSbtPlugin("com.github.ddispaltro" % "sbt-reactjs" % "0.6.8")


이 때 sbt version 은 1.0을 사용할 수 없다. 즉 sbt-reactjs를 못찾는다는 문구가 나온다. 


sbt.version=0.13.15



그래서 sbt.version을 1.0에서 0.13으로 내리니. 다음과 같은 에러가 많이 발생한다.



Error wrapping InputStream in GZIPInputStream: java.util.zip.ZipException: Not in GZIP format

at sbt.ErrorHandling$.translate(ErrorHandling.scala:10)

at sbt.WrapUsing.open(Using.scala:34)

at sbt.Using.apply(Using.scala:23)

at sbt.IO$$anonfun$gzipFileIn$1.apply(IO.scala:877)

at sbt.IO$$anonfun$gzipFileIn$1.apply(IO.scala:876)

at sbt.Using.apply(Using.scala:24)

at sbt.IO$.gzipFileIn(IO.scala:876)

at sbt.Sync$.readUncaught(Sync.scala:88)

at sbt.Sync$.readInfo(Sync.scala:84)

at sbt.Sync$$anonfun$apply$1.apply(Sync.scala:28)

at sbt.Sync$$anonfun$apply$1.apply(Sync.scala:22)

at sbt.Defaults$$anonfun$copyResourcesTask$1.apply(Defaults.scala:948)

at sbt.Defaults$$anonfun$copyResourcesTask$1.apply(Defaults.scala:944)

at scala.Function4$$anonfun$tupled$1.apply(Function4.scala:35)

at scala.Function4$$anonfun$tupled$1.apply(Function4.scala:34)

at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)

at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)

at sbt.std.Transform$$anon$4.work(System.scala:63)

at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)

at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)

at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)

at sbt.Execute.work(Execute.scala:237)

at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)

at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)

at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)

at sbt.CompletionService$$anon$2.call(CompletionService.scala:28)

at java.util.concurrent.FutureTask.run(FutureTask.java:266)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

at java.util.concurrent.FutureTask.run(FutureTask.java:266)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

at java.lang.Thread.run(Thread.java:745)

Caused by: java.util.zip.ZipException: Not in GZIP format

at java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:165)

at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:79)

at sbt.Using$$anonfun$gzipInputStream$1.apply(Using.scala:84)

at sbt.Using$$anonfun$gzipInputStream$1.apply(Using.scala:84)

at sbt.Using$$anon$1.openImpl(Using.scala:51)

at sbt.WrapUsing$$anonfun$open$2.apply(Using.scala:34)

at sbt.ErrorHandling$.translate(ErrorHandling.scala:10)

at sbt.WrapUsing.open(Using.scala:34)

at sbt.Using.apply(Using.scala:23)

at sbt.IO$$anonfun$gzipFileIn$1.apply(IO.scala:877)

at sbt.IO$$anonfun$gzipFileIn$1.apply(IO.scala:876)

at sbt.Using.apply(Using.scala:24)

at sbt.IO$.gzipFileIn(IO.scala:876)

at sbt.Sync$.readUncaught(Sync.scala:88)

at sbt.Sync$.readInfo(Sync.scala:84)

at sbt.Sync$$anonfun$apply$1.apply(Sync.scala:28)

at sbt.Sync$$anonfun$apply$1.apply(Sync.scala:22)

at sbt.Defaults$$anonfun$copyResourcesTask$1.apply(Defaults.scala:948)

at sbt.Defaults$$anonfun$copyResourcesTask$1.apply(Defaults.scala:944)

at scala.Function4$$anonfun$tupled$1.apply(Function4.scala:35)

at scala.Function4$$anonfun$tupled$1.apply(Function4.scala:34)

at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)

at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)

at sbt.std.Transform$$anon$4.work(System.scala:63)

at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)

at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)

at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)

at sbt.Execute.work(Execute.scala:237)

at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)

at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)

at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)

at sbt.CompletionService$$anon$2.call(CompletionService.scala:28)

at java.util.concurrent.FutureTask.run(FutureTask.java:266)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

at java.util.concurrent.FutureTask.run(FutureTask.java:266)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

at java.lang.Thread.run(Thread.java:745)

[error] (compile:copyResources) Error wrapping InputStream in GZIPInputStream: java.util.zip.ZipException: Not in GZIP format





그래서 프로젝트 홈에서 다음 커맨드로 target 디렉토리의 모든 소스를 삭제하니. 잘 동작한다. 


find . -name target -exec rm -r "{}" \;




그런데. org.webjars.npm#minimatch 버전을 다운을 받을 수 없다고 나온다. 



plugin.sbt 파일에 다음을 추가해서 컴파일 제외시키고.. 

addSbtPlugin("com.github.ddispaltro" % "sbt-reactjs" % "0.6.8" 
                        exclude ("org.webjars.npm", "minimatch"))



build.sbt에 minimatch 라이브러리 3.0.0를 강제로 의존성을 갖게 한다.

dependencyOverrides += "org.webjars.npm" % "minimatch" % "3.0.0"


잘 동작한다...





Posted by '김용환'
,


play에 webjars를 포함시켜 보니. 이거 물건이다. 

Java의 jars와 JShell을 최대한 활용하니. npm 설치가 필요없다. 


https://github.com/webjars/webjars-play를 참고하길 바란다.


https://github.com/webjars/webjars-play/tree/master/test-project 프로젝트에 다음 sbt를 사용하니 잘 동작한다. 

"org.webjars" %% "webjars-play" % "2.6.2",
"org.webjars" % "bootstrap" % "3.1.1-1" exclude("org.webjars", "jquery"),
"org.webjars" % "jquery" % "3.2.1",
"org.webjars" % "webjars-locator" % "0.32-1",
"org.webjars" % "requirejs" % "2.3.5",
"org.webjars" % "marked" % "0.3.2-1",


Posted by '김용환'
,

[play2] template 예시

scala 2017. 11. 23. 16:59


play2의 template(twirl template engine)을 사용하는 예제는 다음 링크에 있지만.. 조금 잘 눈에 안 들어온다.


https://www.playframework.com/documentation/2.6.x/ScalaTemplates




코드로 간단히 표현하면 다음과 같다. 


Controller는 다음과 같다. 

def index= Action { implicit request =>
val seq = Seq("Samuel", "Hardy", "Dennis", "Issac")
Ok(views.html.update(new java.util.Date, seq)) }


update.scala.html은 다음 과 같다. (template paramter, template content로 나뉘어져 있다)

@(date: java.util.Date, seq: Seq[String])

<html>
<body>
<h1>Today : @date.toString!</h1>
<ul>
<li><code>List</code>: @List(1,2,3)</li>
<li><code>Seq</code>: @Seq("a", "b", "c")</li>
<li><code>Some</code>: @Some("foo")</li>
<li><code>None</code>: @None</li>
<li><code>Left</code>: @Left("foo")</li>
<li><code>Right</code>: @Right("bar")</li>
</ul>
<ul>
@seq.map { order =>
<li>@order.toLowerCase</li>
}
</ul>
</body>
</html>


결과는 깔끔하게 잘 나온다. 



Today : Thu Nov 23 19:52:04 KST 2017!

  • List: 123
  • Seq: abc
  • Some: foo
  • None:
  • Left: Left(foo)
  • Right: Right(bar)
  • samuel
  • hardy
  • dennis
  • issac






이번엔 주석과 @display 이다. 이것은 현재 template안에서 어떻게 표현하고 싶은지 보여줄 기능이라 하겠다.


@**************************
* import *
***************************@
@display(date: java.util.Date) = {
@date.toString (@date.hashCode())
}
<ul>
<li>@display(date)</li>
</ul>


결과는 다음과 같다.


  • Thu Nov 23 19:15:33 KST 2017 (-403555210)



변수의 값이 정의되어 있다면 다음을 출력한다.
@defining(seq) { name =>
<ul><li>Hello @name </li></ul>
}

결과는 다음과 같다.
  • Hello SamuelHardyDennisIssac



일반 변수를 정의하는 방식은 다음과 같다.
@name = {samuel}
@name

@{val name = "samuel"; name}


결과는 다음과 같다.


samuel






Posted by '김용환'
,


scala에서 elatic4s에서 복합 쿼리(compound query)를 실행하는 예제이다. 

should 다음에 바로 뒤에 query를 사용하면 문제가 생긴다.



쿼리가 하나 손실되는 예제


shoud {

 matchQuery

 rangeQuery

}




appendShould 예제를 잘 사용하는 것을 추천한다. 


search(searchData.serviceTag / DEFAULT_TYPE).
query {
bool {
must {
matchQuery("message", searchData.grep)
} appendMust {
rangeQuery("@timestamp").gte(searchData.startDateTime).lte(searchData.endDateTime)
}
}
}.size(searchData.size).sortByFieldDesc("@timestamp")


요청 json은 다음과 같다. 



 
   "query": 
      "bool": 
         "should": 
             
               "match": 
                  "message": 
                     "query":"*HTTP*"
                  }
               }
            },
             
               "range": 
                  "@timestamp": 
                     "gte":"2017-11-14T14:00:00+09:00",
                     "lte":"2017-11-14T15:00:00+09:00"
                  }
               }
            }
         ]
      }
   },
   "size":10,
   "sort": 
       
         "@timestamp": 
            "order":"desc"
         }
      }
   ]
}


이 두개의 짝을 잘 맞춰 개발할 필요가 있다. 

should->appendShould

must->mustShould

Posted by '김용환'
,