Upload
koichi-sakata
View
10.232
Download
0
Embed Size (px)
Citation preview
Seasar2からSpringへ移行した
俺たちのアプリケーションがマイクロサービス
アーキテクチャへ歩み始めた
フリュー株式会社 /関西Javaエンジニアの会
阪田浩一 @jyukutyo
#ccc_f5
サービスの変容を連載中
• 2015 Spring• クリスマスを支える俺たちとJava
• 2016 Spring• Seasar2で作った俺たちのサービスの今
• 2016 Fall• 10年運用している画像サービスでのJavaの活用と今後の展望
• 2017 Spring <- now• Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めた
Application (WAR)
S2Servlet DispatcherServlet
DIコンテナ DIコンテナ
Cubby Action
Service / Logic
S2Dao DAO
Interceptor
MVC Controller
Service / Logic
S2Dao DAO
Interceptor
Doma2 DAO
同一のJS/CSS/テンプレートファイル
対象アプリケーション
サービス名 ピクトリンク
開始
2011年(前身サービスはもっと以前から)
利用者数1,000万人超
(有料会員数は秘密)
主な機能
プリントシール機で撮影した画像を取得する + SNS的な
あるある
• RDBMSが巨大になってきた• Oracle EE RACを今年購入した
• 13億行のテーブル...
• 負荷増大に対してフルスペックのサーバを追加する• お高い
• オンプレミスです
Application (WAR)
S2Servlet DispatcherServlet
DIコンテナ DIコンテナ
Cubby Action
Service / Logic
S2Dao DAO
Interceptor
MVC Controller
Service / Logic
S2Dao DAO
Interceptor
Doma2 DAO
同一のJS/CSS/テンプレートファイル
何が必要か
クライアント
サービスインスタンスA
サービスインスタンスB
サービスインスタンスC
10.5.83.126
10.5.83.127
10.5.83.128ロードバランスはどうする?
インスタンス数は動的に変更できる?
?
何が必要か
クライアント
サービスインスタンスA
サービスインスタンスB
サービスインスタンスC
10.5.83.126
10.5.83.127
サービスディスカバリ
ディスカバリを認識する
HTTPクライアント
126,127,128
10.5.83.128
@ResourceLoadBalancingHttpClient<ByteBuf, ByteBuf>
ribbonClient;
...
HttpClientRequest<ByteBuf> request =
HttpClientRequest.createPost(url)
.withContent(“...”)
.withHeader("Content-type",
"application/json");
HttpClientResponse<ByteBuf> httpClientResponse =
ribbonClient
.submit(request)
.toBlocking()
.first();
HttpResponseStatus status =
httpClientResponse.getStatus();
org.springframework.cloud.contract.spec.Contract.make {
request { method 'POST' url '/example' body([ "id": 12345 ])
} response {
status 201 body([ "name": "john" ]) headers {
contentType('application/json;charset=UTF-8’)
} }
}
$ curl -D- -X post -H 'Content-Type:application/json' -d "{"id":12345}" http://localhost:14161/example
HTTP/1.1 201 CreatedContent-Type: application/json;
charset=utf-8Transfer-Encoding: chunkedServer: Jetty(9.3.16.v20170120)
{"name":"john"}
org.springframework.cloud.contract.spec.Contract.make {
request { method 'POST' url '/example' body([ "id": 12345 ])
} response {
status 201 body([ "name": "john" ]) headers {
contentType('application/json;charset=UTF-8’)
} }
}
Spring Cloud Contract
• コンシューマ駆動契約(CDC)フレームワークの1つ
• APIを使う側がほしい仕様(契約)を書き、提供側は契約を常に満たす• 使う側: コンシューマ
• 提供側: プロデューサ
Spring Cloud Contract
• 契約をGroovy DSLで書ける
• DSLからスタブを生成できる
• WireMockを使ってスタブをアプリケーションとして起動する• Spring Cloud Contract WireMock
Spring Cloud ContractStub Runner
• スタブをJARにして、Mavenリポジトリに置いておく• ローカル、インハウスでも
• Stub Runnerはリポジトリからスタブをダウンロードし適当なポートで起動する
Spring Cloud ContractStub Runner
• 複数のスタブも1つのStub Runner から起動できる
• スタブをサービスディスカバリ(Eureka)に登録もできる
https://github.com/spring-cloud/spring-cloud-contract/tree/master/spring-cloud-contract-stub-runner
org.springframework.cloud.contract.spec.Contract.make {
request { method 'POST' url '/example' body([ "id": 12345 ])
} response {
status 201 body([ "name": "john" ]) headers {
contentType('application/json;charset=UTF-8’)
} }
}
{"uuid" : "91053c7f-106d-4441-9dd0-
b2b0fccb3388","request" : {"url" : "/example","method" : "POST","bodyPatterns" : [ {"matchesJsonPath" : "$[?(@.id ==
12345)]"} ]
},"response" : {"status" : 201,"body" : "{\"name\":\"john\"}","headers" : {"Content-Type" : "application/
json;charset=UTF-8”
WireMockのJSON
$ java -jar -Dstubrunner.ids=[groupId]:
[artifactId],(略)
-Dstubrunner.idsToServiceIds.[スタブ1のartifactId]=hoge
-Dstubrunner.idsToServiceIds.[スタブ2のartifactId]=fuga
stub-runner.jarEurekaへの登録名
@RunWith(SpringRunner.class)@SpringBootTest(
webEnvironment=WebEnvironment.NONE)@AutoConfigureStubRunner(
ids = {"com.example:http-server-dsl:+:stubs:6565"},
workOffline = true)@DirtiesContextpublic class LoanApplicationServiceTests {
参考: InfoQ記事
Spring Cloud Contractについて
Marcin Grzejszczak氏とのQ&A https://www.infoq.com/jp/news/2017/05/spring-cloud-contract
(公式翻訳: 私)