Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Spark Streaming Snippets
Search
AGAWA Koji
March 14, 2016
Programming
1.1k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Spark Streaming Snippets
AGAWA Koji
March 14, 2016
More Decks by AGAWA Koji
See All by AGAWA Koji
Software Architecture in an AI-Driven World
atty303
79
50k
PipeCDプラグインへの期待 / Anticipating PipeCD Plugins
atty303
0
140
EmscriptenでC/C++アプリをWASM化してブラウザで動かしてみた
atty303
0
710
良いソフトウェアとコードレビュー / Good software and code review
atty303
38
19k
Scala + Caliban で作るGraphQL バックエンド / Making GraphQL Backend with Scala + Caliban
atty303
0
620
Scala.jsとAndroidでドメイン層を共有しよう / Scala.js and Android
atty303
0
840
もう一つのビルドツール mill で作る Docker イメージ / Build docker image with mill the yet another build tool
atty303
2
2.6k
Case of Ad Delivery System is Implemented by Scala and DDD
atty303
4
3.7k
ログのメトリックを取ってみる話
atty303
0
1.1k
Other Decks in Programming
See All in Programming
Event is what happens
moro
2
2.1k
flutter_test のその先へ — Flutter アプリの LLM 機能に「評価」という品質保証を
kosukesaigusa
0
140
[2026-10-14](C)Re:ゼロから始める異世界生活〜始まりの終わりと終わりの始まり〜
tosite
0
180
R8 の設定見直しでアプリサイズ削減
andpad
0
240
個人開発者よ、Honoを使え(おじさんver)
tanahiro2010
2
290
HTML-in-Canvasで作る未来のWeb UI表現
clockmaker
5
6k
[2026-10-09]一枚の布で作らなくてもいい。 信頼性は「パッチワーク」で紡がれる~既存の運用と新しい可能性をつなぎ合わせてきたCREの話~
tosite
0
120
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
1.6k
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
220
Railsバージョンを4倍にした話
optim
0
840
GraphQL の onError と Nullability のこれから
quramy
0
200
パスワード再設定メールのURLについて知っておこう
uyuki234
0
200
Featured
See All Featured
Reflections from 52 weeks, 52 projects
jeffersonlam
356
22k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.7k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
610
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.5k
Embracing the Ebb and Flow
colly
88
5.2k
Prompt Engineering for Job Search
mfonobong
0
560
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
490
Test your architecture with Archunit
thirion
2
2.5k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
300
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Rails Girls Zürich Keynote
gr2m
96
14k
My Coaching Mixtape
mlcsv
0
370
Transcript
Spark Streaming Snippets @a#y303
ࠓ·Ͱ࡞ͬͨ Spark Streaming ΞϓϦ • rtg -- ϦΞϧλΠϜϦλή༻σʔλੜ • pixelwriter
-- Dynamic Crea4ve ༻ϚʔΫσʔλॻ͖ࠐΈ • feedsync -- ϑΟʔυಉظ • segment:elas4c -- ϦΞϧλΠϜηάϝϯτԽ • (logblend -- ҟͳΔΠϕϯτϩάͷ Join)
͜ΕΒͷΞϓϦ͔Βదʹڞ༗͢Δͱخͦ͠͏ͳͱ͜ ΖΛൈ͍ͯΈͨ • SparkBoot • Cron • UpdatableBroadcast • Connector
• SparkStreamingSpec
SparkBoot h"ps:/ /gist.github.com/a"y303/c83f3c8cb8a930951be0 • Spark ΞϓϦͷ main ࣮ • SparkContext
/ StreamingContext Λఏڙ͢Δ • Configura4on ཧ • spark-submit ͷ --files Ͱ applica4on.conf ΛૹͬͯΧελ ϚΠζ
όονͷ߹ object TrainingBatchApp extends SparkBatchBoot { val appName = "TrainingBatchApp"
override def mkApp(sc: SparkContext, args: Array[String]): SparkApp = new TrainingBatchApp(sc, appConfig) } class TrainingBatchApp( sc: SparkContext, appConfig: Config) extends SparkApp { def run(): Try[Int] = Try { 0 } }
ετϦʔϛϯάͷ߹ object PredictStreamingApp extends SparkStreamingBoot { val appName = "PredictStreamingApp"
override val checkpointPath: String = "app.training.streaming.checkpoint-path" override val batchDurationPath: String = "app.training.streaming.batch-duration" override def mkApp(sc: SparkContext, ssc: StreamingContext, args: Array[String]): SparkApp = new PredictStreamingApp(ssc, batchDuration, appConfig) } class PredictStreamingApp( ssc: StreamingContext, appConfig: Config) extends SparkApp { val sparkContext = ssc.sparkContext def run(): Try[Int] = Try { 0 } }
Cron తͳ͜ͱΛΔ • batch-dura+on ΑΓִ͍ؒͰఆظ࣮ߦ͍ͨ͠ॲཧ͕͋Δ • ֎෦σʔλετΞ͔ΒಡΜͰ͍ΔϚελσʔλͷϦϑϨογϡ ͳͲ
def repeatedly(streamingContext: StreamingContext, interval: Duration) (f: (SparkContext, Time) => Unit):
Unit = { // τϦΨʔΛੜ͢Δ DStream val s = streamingContext.queueStream( mutable.Queue.empty[RDD[Unit]], oneAtATime = true, defaultRDD = streamingContext.sparkContext.makeRDD(Seq(()))) .repartition(1) s.window(s.slideDuration, interval) .foreachRDD { (rdd, time) => f(rdd.context, time) rdd.foreach(_ => ()) } }
͍ํ repetedly(streamingContext, Durations.seconds(300)) { (sc, time) => // @driver: 5
ຖʹ࣮ߦ͢Δॲཧ }
ߋ৽Մೳͳ Broadcast • Streaming ͕ಈ͖࢝Ίͨޙʹ Broadcast Λߋ৽͍ͨ͠ • ୯ͳΔ Broadcast
Λอ࣋͢Δϥούʔ
/** * ͷߋ৽(࠶ϒϩʔυΩϟετ)͕Մೳͳ Broadcast * * https://gist.github.com/Reinvigorate/040a362ca8100347e1a6 * @author Reinvigorate
*/ case class UpdatableBroadcast[T: ClassTag]( @transient private val ssc: StreamingContext, @transient private val _v: T) { @transient private var v = ssc.sparkContext.broadcast(_v) def update(newValue: T, blocking: Boolean = false): Unit = { v.unpersist(blocking) v = ssc.sparkContext.broadcast(newValue) } def value: T = v.value private def writeObject(out: ObjectOutputStream): Unit = { out.writeObject(v) } private def readObject(in: ObjectInputStream): Unit = { v = in.readObject().asInstanceOf[Broadcast[T]] } }
͍ํ def loadModel(): Model = ??? val ub: UpdatableBroadcast[Model] =
UpdatableBroadcast(streamingContext, loadModel()) StreamingUtil.repeatedly(streamingContext, refreshInterval) { (_, _) => ub.update(loadModel()) } dstream.foreachRDD { rdd => val model = ub.value // use model }
֎෦ଓͷநԽ • Spark Ͱ֎෦ϦιʔεʹΞΫηε͢Δͱ͖ɺݸʑͷ Executor ͕ ଓΛҡ࣋͢Δඞཁ͕͋Δ • Driver ͔Β
Executor ʹʮଓͦͷͷʯΛૹ৴͢Δ͜ͱͰ͖ ͳ͍ • ʮଓ͢Δํ๏ʯΛ Connector trait ͱͯ͠நԽ͍ͯ͠Δ
trait Connector[A] extends java.io.Closeable with Serializable { def get: A
def close(): Unit def using[B](f: A => B): B = f(get) }
case class PoolAerospikeConnector(name: Symbol, config: AerospikeConfig) extends Connector[AerospikeClient] { def
get: AerospikeClient = PoolAerospikeConnector.defaultHolder.getOrCreate(name, mkClient) def close(): Unit = PoolAerospikeConnector.defaultHolder.remove(name)( AerospikeConnector.aerospikeClientClosable) private val mkClient: () => AerospikeClient = () => new AerospikeClient(config.clientPolicy.underlying, config.asHosts:_*) } object PoolAerospikeConnector { private val defaultHolder = new DefaultResourceHolder[AerospikeClient] }
case class ScalikeJdbcConnector(name: Symbol, config: Config) extends Connector[Unit] { def
get: Unit = { if (!ConnectionPool.isInitialized(name)) { // Load MySQL JDBC driver class Class.forName("com.mysql.jdbc.Driver") ConnectionPool.add(name, config.getString("url"), config.getString("user"), config.getString("password")) } } def close(): Unit = ConnectionPool.close(name) }
case class KafkaProducerConnector[K :ClassTag, V :ClassTag]( name: Symbol, config: java.util.Map[String,
AnyRef]) extends Connector[ScalaKafkaProducer[K, V]] { def get: ScalaKafkaProducer[K, V] = KafkaProducerConnector.defaultHolder.getOrCreate(name, mkResource) .asInstanceOf[ScalaKafkaProducer[K, V]] def close(): Unit = KafkaProducerConnector.defaultHolder.remove(name)( KafkaProducerConnector.kafkaProducerClosable) private val mkResource = () => { val keySer = mkDefaultSerializer[K](ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG) val valueSer = mkDefaultSerializer[V](ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG) new ScalaKafkaProducer[K, V]( new KafkaProducer[K, V](config, keySer.orNull, valueSer.orNull)) } private def mkDefaultSerializer[A :ClassTag](configKey: String): Option[Serializer[A]] = { if (!config.containsKey(configKey)) { implicitly[ClassTag[A]].runtimeClass match { case c if c == classOf[Array[Byte]] => Some(new ByteArraySerializer().asInstanceOf[Serializer[A]]) case c if c == classOf[String] => Some(new StringSerializer().asInstanceOf[Serializer[A]]) case _ => None } } else None } }
Spark Streaming ͷςετ h"ps:/ /gist.github.com/a"y303/18e64e718f0cf3261c0e
class CountProductSpec extends SpecWithJUnit with SparkStreamingSpec { val batchDuration: Duration
= Duration(1000) "Count" >> { val (sourceQueue, resultQueue) = startQueueStream[Product, (Product, Long)] { inStream => // ςετରͷ Streaming ॲཧ CountProduct(inStream).run(sc) } // ೖྗΩϡʔʹςετσʔλΛೖ͢Δ sourceQueue += sc.parallelize(Seq( Product(1, "id"), Product(1, "id"), Product(2, "id"))) // ࣌ؒΛਐΊΔ advance() // ग़ྗ͞ΕΔσʔλΛςετ͢Δ resultQueue.dequeue must eventually(contain(exactly( Product(1, "id") -> 2L, Product(2, "id") -> 1L ))) } }