SlideShare a Scribd company logo
ビズリーチの新サービスを
Scalaで作ってみた
Naoki Takezoe
BizReach, Inc
About BizReach
今日は新しいサービスの
話をします
求人検索エンジン
スタンバイ
Available for PC Web, Mobile Web, iOS and Android
今日話すこと
• マイクロサービスアーキテクチャ
• Apache Spark
• Scalaで開発する上での課題
マイクロサービス
アーキテクチャ
マイクロサービスとは?
• サービスによるコンポーネント化:ライブラリではなく別プロセスで動作するサービスに
よってアプリケーションのコンポーネント化を実現している。
• ビジネスケイパビリティに基づく組織化:役割ごとにチームが構成されるのではなく、複
数の役割が混在したチームがひとつのサービスを構築する。(コンウェイの法則!)
• プロジェクトではなくプロダクト:コンポーネントは期限のあるプロジェクトとして開発
されるではなく、継続的なプロダクトとして提供される。
• スマートエンドポイント、ダムパイプ:サービス間のメッセージは、HTTP経由でAPI呼
び出しされるか、RabbitMQやZeroMQといった軽量メッセージングシステムによる通信
で交換される。
• 分散ガバナンス:サービスごとに言語やデータベースなどは統一されず、個別に適切なも
のが選択される。
• 分散データ管理:サービスごとにデータを持ち、統合されていない。
• インフラストラクチャ自動化:継続的デリバリが実現され、自動テスト、自動デプロイな
どが採用されている。
• 障害設計:構成されるサービスの障害に耐性を持つように設計されている。
• 進化的設計:各サービスごとに変更が行なわれ、漸進的に設計がされる。
疎結合な小さなサービスの
集合体としてシステムを構築する
マイクロサービス
マイクロサービス
マイクロサービス
HTTP
Messaging
HTTP
• 独立して開発・メンテナンスが可能
• 耐障害性の高いシステムを構築可能
なにがうれしいのか?
• 並列処理を記述するのが容易
• ノンブロッキングI/Oベースのミドルウェア、フ
レームワーク、ライブラリが豊富
• 巨大なシステムにおける静的型付けの安全性
なぜScalaなのか?
アーキテクチャ
PC Web Mobile Web iOS App Android App
Front API
Backend APIs Backend APIs Backend APIs
Elasticsearch MySQL Memcached
JSON over HTTP
JSON over HTTP
elasticsearch4s Slick ???
アーキテクチャ
PC Web Mobile Web iOS App Android App
Front API
Backend APIs Backend APIs Backend APIs
Elasticsearch MySQL Memcached
JSON over HTTP
JSON over HTTP
elasticsearch4s Slick ???
Webアプリもフロントエンドと
サーバサイドでレイヤリング
Webアプリもレイヤリング
play2-stub play2-handlebars
フロントサーバ(Play2)
APIサーバ(Play2)
JSON over HTTP
開発時は固定の
JSONを返す
JSONをテンプレートに
渡してHTMLをレンダリング
request response
ねらい
•サーバサイドとフロントエンドのライフサイクルは異な
るので別々にデプロイできるようにしたい
•フロントエンドの修正はフロントエンジニアだけで完結
したい
•サーバサイドはScalaで固く、フロントエンドは
JavaScriptやテンプレートエンジンで柔らかく作ること
で両者のメリットを活かせる
play2-stub
• リクエストを受け取り、routingやstubbingを行うフロントコントローラ
• フロントエンドとサーバサイドを分離して開発するためのもの
• リクエストやレスポンスを加工するフィルタを挟んだり、複雑な処理は別のコ
ントローラにデリゲートしたりすることもできる
play2stub {!
routes: [!
{!
"GET /author/~authorName/books" {!
template = "author-biology"!
data = "authors/:authorName.json"!
}!
}!
]!
}
https://github.com/bizreach/play2-stub
リモートAPIを呼び出す代わりに
静的なJSONでレンダリング
play2-handlebars
• Play2でHandlebarsを使うためのプラグイン
• コンパイルなしでテンプレートを修正可能
• デザイナにも扱いやすいテンプレート記法
• Play2のTwirlテンプレートはコンパイルが遅いし記法も複雑で、カッチリ作る
にはいいが、デザインを迅速に反映・修正するのには向いてない
https://github.com/bizreach/play2-stub
object Application extends Controller {!
!
def simple = Action {!
Ok(HBS("simple", "who" -> "World"))!
}!
!
}
現実は厳しい
•Handlebarsの自由度が低すぎるので大量にヘルパーを
作らなくてはいけない(ヘルパーの作成がボトルネック
になることも)
•結局画面の仕様に対応したAPIが必要になるケースが多
く、再利用可能なAPIにならない
•性能面・工数面などの理由で直接DBに接続せざるを得
ない、というような部分もあり、密結合になってしまっ
ている
複数のAPIの呼び出し
Web API
Web API
Web API
Web API
Controller
1つのコントローラから複数のWeb APIを呼び出す必要がある
シリアルに呼び出していてはAPIが増えるほど遅くなってしまう
Future
import scala.concurrent._!
import scala.concurrent.ExecutionContext.Implicits.global!
!
val fileNames = Seq("1.jpg", "2.jpg", "3.jpg", …)!
!
fileNames.foreach { fileName =>!
Future {!
resizeAndStore(fileName)!
}!
}
•FutureはScalaにおける非同期処理の基本的なインターフェース
•Play標準のWS APIはFutureを返す
•Dispatchなど他の通信系ライブラリもFutureを返すものが多い
PlayのWS API
// 戻り値としてFutureを返す!
val f: Future[WSResponse] = WS.url(requestUrl).get()!
!
// アクションの実行結果をFutureで返す!
def wsAction = Action.async {!
WS.url(requestUrl).get().map { res =>!
Ok(res.body)!
}!
}
Futureによる並列処理
// 1つ目のAPIを呼び出す!
val res1: WSResponse !
= Await.result(WS.url(url1).get(), Duration.Inf)!
// レスポンスを取得!
val body1: String = res1.body!
!
// 2つ目のAPIを呼び出す!
val res2: WSResponse !
= Await.result(WS.url(url2).get(), Duration.Inf)!
// レスポンスを取得!
val body2: String = res2.body
複数のWeb APIをシリアルに呼び出す
Futureによる並列処理
// 1つ目のAPIを呼び出す!
val res1: WSResponse !
= Await.result(WS.url(url1).get(), Duration.Inf)!
// レスポンスを取得!
val body1: String = res1.body!
!
// 2つ目のAPIを呼び出す!
val res2: WSResponse !
= Await.result(WS.url(url2).get(), Duration.Inf)!
// レスポンスを取得!
val body2: String = res2.body
複数のWeb APIをシリアルに呼び出す
Await.resultを使うとFutureから値を
取り出すことができるがブロックしてしまう
Futureによる並列処理
val f1 = WS.url(url1).get()!
val f2 = WS.url(url2).get()!
!
val f: Future[(String, String)] = for {!
res1 <- f1!
res2 <- f2!
} yield {!
(res1.body, res2.body)!
}
複数のWeb APIをパラレルに呼び出す
やってみて思ったこと
• 開発時のオーバーヘッドやサービス毎の冗長化によるコス
ト増など、短期的にはデメリットの方が大きい
• デバッグが難しくなる、並列プログラミングのスキルが必
要になる
• 最初はモノリシックに作り、大きくなってきたタイミング
でマイクロサービスにするのがよい
• 大きくなるタイミングはサービスとしては攻め時なので判
断としては難しい
Apache Spark
クローリング・インデキシング
データを加工 Elasticsearchクロール JSONHTML
DispatchでHTMLを取得する
アクターをスケジュール実行する
ことでサーバのリソースを活用
HTMLを解析したり、別のデータと
結合して検索用のインデックスを
生成する処理をSparkで実行
クローリング・インデキシング
データを加工 Elasticsearchクロール JSONHTML
DispatchでHTMLを取得する
アクターをスケジュール実行する
ことでサーバのリソースを活用
HTMLを解析したり、別のデータと
結合して検索用のインデックスを
生成する処理をSparkで実行
Apache Sparkとは?
• Scala製の高速バッチ処理フレームワーク
• 簡単なプログラムで分散処理を記述できる
• 機械学習のMLlib、SQLインターフェースを提供するSpark-SQL、
ストリーミング処理用のSpark-Streamingなど様々なサブプロ
ジェクトが存在する
• elastichadoop-sparkというアダプタを使うことでElasticsearch
への入出力が可能
並列分散処理を手軽に記述できる
def main(args: Array[String]) {!
val sc = new SparkContext("local", "Log Query", !
System.getenv("SPARK_HOME"), !
SparkContext.jarOfClass(this.getClass)) // ログファイルをロード!
!
val dataSet = sc.textFile("hdfs://...")!
// ERRORで始まるデータを抽出しキャッシュ!
val cached = dataSet.filter(_ startsWith "ERROR").cache()!
!
val counts1 = cached!
.flatMap(_ split " ") // スペースで分割しフラット化!
.map(_ -> 1) // 文字列とカウントのタプルに変換!
.reduceByKey(_ + _) // 集計!
!
// キャッシュしたデータを使って別の条件で集計する!
val counts2 = cached.filter・・・!
}
毎回ストレージにアクセス
しないようキャッシュ
通常のScalaプログラムと
同じ感覚でコードを書ける
複数のインデックスを結合
val conf = new SparkConf().setAll(Seq(!
ES_NODES -> "localhost",!
ES_PORT -> “9200",!
ES_RESOURCE -> "job",!
ES_QUERY -> "?q=*:*"!
))!
!
val spark = new SparkContext(conf)!
!
val rdd = spark.esRDD.leftOuterJoin(spark.esRDD(Map(!
ES_RESOURCE -> "geo",!
ES_QUERY -> "?q=*:*"!
))).flatMap { case (_id, (_source, geo)) =>!
geo.map { x =>!
_source ++ Map("location" -> x(“location"))!
}!
}
jobインデックスに
geoインデックスを外部結合
複数のインデックスを更新
// 加工したデータをキャッシュしておく!
val rdd = spark.esRDD.map { x=>!
…!
}.cache!
!
// 1台目のElasticsearchにデータを登録!
rdd.saveToEs(Map(!
ES_NODES -> "localhost",!
ES_PORT -> "9200"!
))!
!
// 2台目のElasticsearchにデータを登録!
rdd.saveToEs(Map(!
ES_NODES -> "localhost",!
ES_PORT -> "9201"!
)) 加工したデータをキャッシュしておくことで複数の
インデックスを高速に更新することができる
注意点
• I/Oが多いとCPUを使い切れずSparkの良さが出せない
• 細かいジョブを大量に投げると失敗することがある
• 処理の並列度がElasticsearchのシャード数に依存する
(elastichadoop-sparkの場合)
• 記述の仕方を少し変えただけで猛烈にパフォーマンス
が変わるので使いこなすのが難しい
Scalaを使う上での
一番の課題
一番の課題
• Scalaプログラマの教育・採用
• JavaよりもLLからのほうが入りやすい様子
• 長期的にはScalaをもっと普及させる
• 短期的には社内で育成していくしかない
長期的な取り組み
• 書籍・雑誌記事等の執筆
• イベントでの登壇・支援(スポンサー)
• 他社さんとの合同での勉強会
• OSS活動(足りない物を作る)
短期的な取り組み
• Daily Scala(毎朝30分Scalaの勉強会)
• GitHubでのプルリクレビュー
• ハンズオンコンテンツの作成
Play2ハンズオン
https://github.com/bizreach/play2-hands-on
まとめ
• マイクロサービスは良いことばかりではない
• Future大事
• Apache Sparkは便利だけど使いこなすのが難しい
• Scalaプログラマの教育・採用が一番の課題です
お知らせ
• 弊社オフィスのイベントスペースを使用して渋谷java、Swift
もくもく会などいろんな勉強会をやってます
• 会場提供も可能です
お問い合わせはhttp://dcube.ioまたは@takezoenまで!

More Related Content

PPTX
Spring Boot
Jiayun Zhou
 
PPTX
Introduction to Redis
Arnab Mitra
 
PDF
Introduction to MongoDB
Mike Dirolf
 
PPTX
Lambda Expressions in Java 8
icarter09
 
PPTX
Spring data jpa
Jeevesh Pandey
 
PDF
Hibernate Presentation
guest11106b
 
PDF
Spring Data JPA
Cheng Ta Yeh
 
PDF
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
onozaty
 
Spring Boot
Jiayun Zhou
 
Introduction to Redis
Arnab Mitra
 
Introduction to MongoDB
Mike Dirolf
 
Lambda Expressions in Java 8
icarter09
 
Spring data jpa
Jeevesh Pandey
 
Hibernate Presentation
guest11106b
 
Spring Data JPA
Cheng Ta Yeh
 
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
onozaty
 

What's hot (20)

PDF
JPA and Hibernate
elliando dias
 
PPTX
React Native
ASIMYILDIZ
 
PPTX
Blazor
Ed Charbeneau
 
PDF
ドメイン駆動設計 失敗したことと成功したこと
BIGLOBE Inc.
 
PDF
Real Life Clean Architecture
Mattia Battiston
 
PPTX
Spring Boot and REST API
07.pallav
 
PDF
3週連続DDDその1 ドメイン駆動設計の基本を理解する
増田 亨
 
PDF
REST APIs with Spring
Joshua Long
 
PDF
Introduction to Docker
Aditya Konarde
 
PDF
김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019
min woog kim
 
PDF
Asynchronous API in Java8, how to use CompletableFuture
José Paumard
 
PPTX
Micro Service Architecture의 이해
Terry Cho
 
PDF
Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...
Edureka!
 
PDF
Java 8 Workshop
Mario Fusco
 
PDF
Building RESTful applications using Spring MVC
IndicThreads
 
PPTX
예외처리가이드
도형 임
 
PPTX
Hibernate ppt
Aneega
 
PDF
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
Takuto Wada
 
PPTX
Introduction to laravel framework
Ahmad Fatoni
 
PPTX
Spring Security 5
Jesus Perez Franco
 
JPA and Hibernate
elliando dias
 
React Native
ASIMYILDIZ
 
ドメイン駆動設計 失敗したことと成功したこと
BIGLOBE Inc.
 
Real Life Clean Architecture
Mattia Battiston
 
Spring Boot and REST API
07.pallav
 
3週連続DDDその1 ドメイン駆動設計の基本を理解する
増田 亨
 
REST APIs with Spring
Joshua Long
 
Introduction to Docker
Aditya Konarde
 
김민욱, (달빛조각사) 엘릭서를 이용한 mmorpg 서버 개발, NDC2019
min woog kim
 
Asynchronous API in Java8, how to use CompletableFuture
José Paumard
 
Micro Service Architecture의 이해
Terry Cho
 
Node.js Tutorial for Beginners | Node.js Web Application Tutorial | Node.js T...
Edureka!
 
Java 8 Workshop
Mario Fusco
 
Building RESTful applications using Spring MVC
IndicThreads
 
예외처리가이드
도형 임
 
Hibernate ppt
Aneega
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
Takuto Wada
 
Introduction to laravel framework
Ahmad Fatoni
 
Spring Security 5
Jesus Perez Franco
 
Ad

Similar to ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala (20)

PPTX
【 ヒカ☆ラボ 】LIFULL Home's androidアプリの開発の裏側について
LIFULL Co., Ltd.
 
PDF
BPStudy20121221
Shinichiro Takezaki
 
PPTX
20170510 タウンwi fixlifull_スマホアプリ開発の実例 (1)
LIFULL Co., Ltd.
 
PDF
20200708サーバーレスでのAPI管理の考え方
Amazon Web Services Japan
 
PDF
アドテクを支える技術 〜1日40億リクエストを捌くには〜
MicroAd, Inc.(Engineer)
 
PDF
Java クライント実装におけるAPIスタイル頂上決戦! 野良REST vs GraphQL vs OData vs OpenAPI (Swagger)
Kazuya Sugimoto
 
PPTX
これからのOpenShiftの話をしよう
Kazuto Kusama
 
PPTX
JavaOne 2016 Report for Java EE
Yoshio Terada
 
PPTX
REST API、gRPC、GraphQL 触ってみた【2023年12月開催勉強会資料】
洵貴 佐川
 
PPTX
API Academy:マイクロサービス化へのファーストステップ
CA Technologies
 
PDF
ケーススタディ/実装 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第46回】
Tomoharu ASAMI
 
PPTX
Spring I/O 2015 報告
Takuya Iwatsuka
 
PDF
開発チームが安定したプロダクトマネジメントを実現するための7つのルール
LINE Corporation
 
PDF
20161111 java one2016-feedback
Takashi Ito
 
PDF
LambdaとMobileの美味しいかもしれない関係
Hiraku Komuro
 
PPTX
JSUG SpringOnePlatform 2016報告会 Case study2 - feed back - springoneplatform
Takahiro Fujii
 
PDF
実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】
Tomoharu ASAMI
 
PPTX
Talend StudioでAPIを開発 - SOAP/RESTのサービス開発手法
QlikPresalesJapan
 
PDF
ochacafe#6 人にもマシンにもやさしいAPIのエコシステム
オラクルエンジニア通信
 
PPTX
IoTと業務システムをつなぐgRPC/RESTサービスの開発と運用
DeNA
 
【 ヒカ☆ラボ 】LIFULL Home's androidアプリの開発の裏側について
LIFULL Co., Ltd.
 
BPStudy20121221
Shinichiro Takezaki
 
20170510 タウンwi fixlifull_スマホアプリ開発の実例 (1)
LIFULL Co., Ltd.
 
20200708サーバーレスでのAPI管理の考え方
Amazon Web Services Japan
 
アドテクを支える技術 〜1日40億リクエストを捌くには〜
MicroAd, Inc.(Engineer)
 
Java クライント実装におけるAPIスタイル頂上決戦! 野良REST vs GraphQL vs OData vs OpenAPI (Swagger)
Kazuya Sugimoto
 
これからのOpenShiftの話をしよう
Kazuto Kusama
 
JavaOne 2016 Report for Java EE
Yoshio Terada
 
REST API、gRPC、GraphQL 触ってみた【2023年12月開催勉強会資料】
洵貴 佐川
 
API Academy:マイクロサービス化へのファーストステップ
CA Technologies
 
ケーススタディ/実装 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第46回】
Tomoharu ASAMI
 
Spring I/O 2015 報告
Takuya Iwatsuka
 
開発チームが安定したプロダクトマネジメントを実現するための7つのルール
LINE Corporation
 
20161111 java one2016-feedback
Takashi Ito
 
LambdaとMobileの美味しいかもしれない関係
Hiraku Komuro
 
JSUG SpringOnePlatform 2016報告会 Case study2 - feed back - springoneplatform
Takahiro Fujii
 
実装(3) 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第32回】
Tomoharu ASAMI
 
Talend StudioでAPIを開発 - SOAP/RESTのサービス開発手法
QlikPresalesJapan
 
ochacafe#6 人にもマシンにもやさしいAPIのエコシステム
オラクルエンジニア通信
 
IoTと業務システムをつなぐgRPC/RESTサービスの開発と運用
DeNA
 
Ad

More from takezoe (20)

PDF
Journey of Migrating Millions of Queries on The Cloud
takezoe
 
PDF
GitBucket: Open source self-hosting Git server built by Scala
takezoe
 
PDF
Testing Distributed Query Engine as a Service
takezoe
 
PDF
Revisit Dependency Injection in scala
takezoe
 
PDF
How to keep maintainability of long life Scala applications
takezoe
 
PDF
頑張りすぎないScala
takezoe
 
PDF
GitBucket: Git Centric Software Development Platform by Scala
takezoe
 
PDF
Non-Functional Programming in Scala
takezoe
 
PDF
Scala警察のすすめ
takezoe
 
PDF
Scala製機械学習サーバ「Apache PredictionIO」
takezoe
 
PDF
The best of AltJava is Xtend
takezoe
 
PDF
Scala Warrior and type-safe front-end development with Scala.js
takezoe
 
PDF
Tracing Microservices with Zipkin
takezoe
 
PDF
Type-safe front-end development with Scala
takezoe
 
PDF
Scala Frameworks for Web Application 2016
takezoe
 
PDF
Macro in Scala
takezoe
 
PDF
Java9 and Project Jigsaw
takezoe
 
PDF
Reactive database access with Slick3
takezoe
 
PDF
markedj: The best of markdown processor on JVM
takezoe
 
PDF
ネタじゃないScala.js
takezoe
 
Journey of Migrating Millions of Queries on The Cloud
takezoe
 
GitBucket: Open source self-hosting Git server built by Scala
takezoe
 
Testing Distributed Query Engine as a Service
takezoe
 
Revisit Dependency Injection in scala
takezoe
 
How to keep maintainability of long life Scala applications
takezoe
 
頑張りすぎないScala
takezoe
 
GitBucket: Git Centric Software Development Platform by Scala
takezoe
 
Non-Functional Programming in Scala
takezoe
 
Scala警察のすすめ
takezoe
 
Scala製機械学習サーバ「Apache PredictionIO」
takezoe
 
The best of AltJava is Xtend
takezoe
 
Scala Warrior and type-safe front-end development with Scala.js
takezoe
 
Tracing Microservices with Zipkin
takezoe
 
Type-safe front-end development with Scala
takezoe
 
Scala Frameworks for Web Application 2016
takezoe
 
Macro in Scala
takezoe
 
Java9 and Project Jigsaw
takezoe
 
Reactive database access with Slick3
takezoe
 
markedj: The best of markdown processor on JVM
takezoe
 
ネタじゃないScala.js
takezoe
 

ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala