1. Let's Build a
Serverless Architecture
in Scala!
Yoshitaka Fujii (@yoshiyoshifujii)
2017 ScalaMatsuri
Saturday, February 25th
16:30 - 17:10 Conference Room 1
2. Who am I ?
• Yoshitaka Fujii (@yoshiyoshifujii)
• Joined MOTEX in April, 2014
• Software Engineer
• Scala(19 months)
• Scala Kansai summit 2016 staff.
自己紹介。エムオーテックス株式会社。Scala歴19ヶ月。Scala関西サミット2016でスタッフさせていただきました。
5. Serverless Architecture
• using FaaS
• a significant reduction in costs
• scalability
• the lack of operating and maintaining infrastructure
サーバレスアーキテクチャとは、FaaSを活用したシステム。コストの大幅な削減。スケーラビリティ。 インフラの運用管理が不要。
6. Function as a Service
• AWS Lambda
• Google Cloud Function
• Microsoft Azure Functions
7. AWS Lambda
• AWS Lambda is a compute service that lets you run code without
provisioning or managing servers.
• executes your code only when needed.
• scales automatically, a few requests per day to thousands per second.
• Node.js, Java, C# and Python
AWS Lambda はサーバーをプロビジョニングしたり管理しなくてもコードを実行できるコンピューティングサービスです。必要な
ときにコードを実行し、自動的にスケールします。
9. Amazon API Gateway
• Amazon API Gateway is a fully managed service that makes it easy for
developers to create, publish, maintain, monitor, and secure APIs at any scale.
• Low-Cost and Efficient.
(only for calls made to your APIs and data transfer out)
• Performance at Any Scale
• Run Your APIs Without Servers
フルマネージドサービスで、開発者はどのようなスケールであっても、簡単に API の作成、配布、保守、監視、保護が行えます。
11. Amazon Kinesis Streams
• Use Amazon Kinesis Streams to collect and process large streams of data records in real
time.
• rapid and continuous data intake and aggregation.
• Accelerated log and data feed intake and processing.
• Real-time metrics and reporting.
• Real-time data analytics.
• Complex stream processing.
Amazon Kinesis Streams を使用して、データレコードの大量のストリームをリアルタイムで収集し、処理します。 高速かつ継続的
にデータの取り込みと集約を行うことができます。
15. Large scale system
• More functional requirements.
• AWS Lambda wants to be a simple function.
• 1 Lambda per method request.
GET:/hello => getHello
POST:/hello => postHello
• develop and deploy efficiently
大規模なシステムは、機能要件が多い。AWS LambdaはシンプルなFunctionを保ちたい。1メソッドリクエストにつきLambdaを1
つ。また効率良く開発とデプロイをしたい。
17. How to make simple AWS Lambda.
単純なAWS Lambdaの作り方を紹介します。
18. RequestStreamHandler.java
public interface RequestStreamHandler {
/**
* Handles a Lambda Function request
* @param input The Lambda Function input stream
* @param output The Lambda function output stream
* @param context The Lambda execution environment context object.
* @throws IOException
*/
public void handleRequest(InputStream input, OutputStream output, Context context)
throws IOException;
}
AWS Lambdaの公開インタフェースです。この中身を実装すると任意の処理が実行できます。
19. RequestHandler.java
public interface RequestHandler<I, O> {
/**
* Handles a Lambda Function request
* @param input The Lambda Function input
* @param context The Lambda execution environment context object.
* @return The Lambda Function output
*/
public O handleRequest(I input, Context context);
}
I/Oを任意の型で実装できますが、Java Beanなクラスもしくは、プリミティブな型のみになっており、Javaの制約を受けたりするの
で、あまりオススメしません。
20. build.sbt
lazy val root = (project in file(".")).
settings(
name := "aws-lambda-scala",
organization := "com.example",
scalaVersion := "2.12.1",
libraryDependencies ++= Seq(
"com.amazonaws" % "aws-lambda-java-core" % "1.1.0"
)
)
28. Labor …
• It is hard to run Lambda.
• I will `assembly` one by one and upload it.
• It is troublesome to configure the API Gateway on the console.
Lambdaで実行するまでが大変。assemblyしてアップロードしてを繰り返さないとうまく動くか分からない。コンソール上でAPI
Gatewayの設定を行うのは面倒。
29. sbt-aws-serverless plugin
• sbt plugin to deploy code to Amazon API Gateway and AWS
Lambda.
• https://github.com/yoshiyoshifujii/sbt-aws-serverless
自前で開発したsbt-pluginを使います。API GatewayやLambdaにデプロイするpluginです。
30. serverless framework
• To be honest this way is better.
• However, blue green deployment is difficult.
正直、serverless frameworkを使うのが良いと思います。ただ、ブルーグリーンデプロイができない印象です。
32. Amazon API
Gateway
Stage Stage Variables
test env : test
prod env : prod
Deployment Resources Lambda ARN
1 /hello hello:${stageVariables.env}_1
AWS
Lambda
Alias Publish Versions
dev $LATEST
test_1 1
prod_1 1
Blue-Green deployment - 1st release
Amazon
DynamoDB
Table
account-test
account-prod
33. Amazon API
Gateway
Stage Stage Variables
test env : test
prod env : prod
Deployment Resources Lambda ARN
1 /hello hello:${stageVariables.env}_1
2 /hello hello:${stageVariables.env}_2
AWS
Lambda
Alias Publish Versions
dev $LATEST
test_1 1
prod_1 1
test_2 2
Blue-Green deployment - 2nd release test
Amazon
DynamoDB
Table
account-test
account-prod
34. Amazon API
Gateway
Stage Stage Variables
test env : test
prod env : prod
Deployment Resources Lambda ARN
1 /hello hello:${stageVariables.env}_1
2 /hello hello:${stageVariables.env}_2
AWS
Lambda
Alias Publish Versions
dev $LATEST
test_1 1
prod_1 1
test_2 2
prod_2 2
Amazon
DynamoDB
Table
account-test
account-production
Blue-Green deployment - 2nd release
35. in this case
• Release the test environment as it is.
• Quickly return to the previous version.
• A/B Testing.
• Canary Release.
https://martinfowler.com/bliki/CanaryRelease.html
この方式なら、テストした環境をそのままリリースできる。すぐに前のバージョンに戻すことができる。A/Bテストや、カナリア・リ
リースに使える。
42. build.sbt - dependsOn
lazy val domain = (project in file("./modules/domain")).
lazy val infraDynamo = (project in file("./modules/infrastructure/dynamodb")).
dependsOn(domain).
lazy val infraKinesis = (project in file("./modules/infrastructure/kinesis")).
dependsOn(domain).
lazy val appHello = (project in file("./modules/application/hello")).
dependsOn(infraLambda, infraDynamo, infraKinesis).
マルチプロジェクトの依存関係を依存モデルの通りに設定。
43. Project tree
• Sources under modules.
• application is a module of Lambda.
• Make the Infrastructure as finely as
possible.
• Reduce module size.
プロジェクト構成。ソースはmodulesディレクトリの配下に置く。applicationがLambdaのモジュールになる。Infrastructureは限
りなく小さく作る。Lambdaのモジュールサイズを小さくするため。
44. domain
• POSO (Plain old Scala object)
• Do not specify anything for
libraryDependencies.
domain層。POSOで作る。libraryDependenciesに何も指定しない。
45. Account
case class AccountId(value: String) extends ValueObject[String]
case class Account(
id: AccountId,
version: Option[Version],
email: String,
password: String,
name: String) extends Entity[AccountId]
48. infrastructure
• implementation of Repository
or Domain Event.
• DI with Cake pattern.
• It has no direct inheritance
relation.
infrastructure層。RepositoryやDomainEventの実装を持つ。Cake patternでDIされる。直接の継承関係を持たない。
52. Base
trait Base extends BaseStreamHandler {
val accountRepository: AccountRepository
val accountEventPublisher: AccountEventPublisher
override def handle(input: Input): Try[String] = Try {
JsObject(
"message" -> JsString("hello world!!")
).compactPrint
}
}
53. App
class App extends Base {
override val accountRepository =
new AccountRepository with AccountRepositoryOnDynamoDB
override val accountEventPublisher =
new AccountEventPublisher with AccountEventPublisherOnKinesis
}
55. build.sbt - dependsOn
lazy val domain = (project in file("./modules/domain")).
lazy val infraDomain = (project in file("./modules/infrastructure/domain")).
dependsOn(domain).
lazy val appAccountModified = (project in file(“./modules/application/accountmodified”)).
dependsOn(infraLambdaConsumer, infraDomain).
依存関係は、API Gatewayとほぼ同じ。
66. Summary
• Scala is easy to combine DDD and Serverless.
• Easy to share processing with multiple projects.
• Cheap, scalable and easy to operate.
ScalaはDDDとServerlessを組み合わせるとやりやすい。マルチプロジェクトで処理を共通化しやすい。安くてスケーラブルで運用
が楽。