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
FRESH LIVEにおけるServer Side Kotlinと Microservices...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
soushi
October 05, 2018
Technology
1.4k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
FRESH LIVEにおけるServer Side Kotlinと Microservicesの今 / Logmi Tech Live #1
ログミーTech Live #1
https://logmitechlive.connpass.com/event/100619/
soushi
October 05, 2018
More Decks by soushi
See All by soushi
FRESH!プロジェクト/Server Side Kotlin 活用事例 / CA.kt #3
soushi
3
2.1k
Other Decks in Technology
See All in Technology
go-sqletch
moznion
0
130
メルペイ 会計システム概要と歴史
mewuto
0
210
大型犬好きによるPugの紹介
yamanoku
1
130
Kiro Crewをはじめよう
kizawa2020
1
140
生成AIを使って「人が」考える技術 ― AI時代の人機共想と実践ノウハウ|UNITT AC2026
ishiirikie
0
580
初対面のメンバーがチームを組み、Claude Codeでゼロからサービスをリリース
mkdev10
1
120
OpenSharing について熱く語る〜AI アセットの共有について〜
kameitomohiro
0
260
SDDの運用にめげずに向き合った話
sansantech
PRO
1
140
予測不能な実行エージェントを安全にサクッと試せるサンドボックス環境の話
sansantech
PRO
1
150
味覇で作るパスタが美味い - 20261001_yabaubuki.dev
livesense
PRO
0
120
AI駆動開発の時代になったのでトヨタ生産方式から見直す
terurou
7
5.8k
今さら理解するウェブフォントver.2026
takanorip
3
670
Featured
See All Featured
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
Darren the Foodie - Storyboard
khoart
PRO
4
4k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Producing Creativity
orderedlist
PRO
348
41k
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
860
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
480
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
42k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
33
5.2k
Are puppies a ranking factor?
jonoalderson
2
4k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
20k
Transcript
'3&4)-*7&ʹ͓͚Δ 4FSWFS4JEF,PUMJOͱ.JDSPTFSWJDFTͷࠓ ϩάϛʔ5FDI-JWF ᖒ૱࢙!TPVTIJ@OP[BXB
BCPVUNF w αʔόαΠυΤϯδχΞ w ͍·"OESPJEΤϯδχΞͬͯ·͢! w ʙ'3&4)-*7&ॴଐLUྺ @soushi_nozawa @soushin blog.soushi.me
ੜ์ૹಈըϓϥοτϑΥʔϜ .JDSPTFSWJDFT"SDIJUFDUVSF'VMM%PDLFSOJ[FE"NB[PO8FC4FSWJDFT,VCFSOFUFT
ʮͣΌͪΌΜͶΔ'3&4)ʯ ήʔϜঁࢠͣΤͱ࣮گ͕͑ΔΌʹ͑ʹΑΔ࣮ گϢχοτ IUUQTGSFTIMJWFUWNID IUUQTUXJUUFSDPNZPVTFJ@IBZBOJF ࢲͷਪ͠νϟϯωϧͰ͢"
"HFOEB '3&4)-*7&ͱαʔόαΠυͱ,PUMJO '3&4)-*7&ͷϚΠΫϩαʔϏεࣄྫ 4QSJOH#PPUͱ,PUMJO ίϯςφͱϚΠΫϩαʔϏε
H31$ͱϚΠΫϩαʔϏε ·ͱΊ
ʮ'3&4)-*7&ʹ͓͚ΔαʔόαΠυ,PUMJO Λத৺ͱͨ͠पลٕज़ͷίϯςφͱH31$ ʹ৮ΕϚΠΫϩαʔϏε։ൃͷݟΛڞ༗ʯ
'3&4)-*7&ͱαʔόαΠυͱ,PUMJO w ༷ʑͳϚΠΫϩαʔϏεʹ,PUMJOΛಋೖ w ܾࡁूܭɺΞφϦςΟΫεɺϓογϡ௨ɺϩάऩूɺ"1* ήʔτΣΠͳͲ w ࠷৽՝ۚج൫ͷϚΠΫϩαʔϏε w ༷ʑͳγεςϜཁ݅ʹॊೈʹରԠͰ͖͍ͯΔ
ϚΠΫϩαʔϏεͷར w ୯ҰোͰཹ·ΓશମΕͳ͍ w ϚΠΫϩαʔϏεೝূɺϩά ɺ՝ۚͳͲͷ୯ҐͰಈ͍͍ͯΔ w ՝͕ۚͰ͖ͳͯ͘ࢹௌͰ͖Δ w εέʔϧઓཱུ͕͍ͯ͢
w αʔϏεઓུͱڞʹεέʔϧͤ͞ΔϚΠΫϩαʔϏε͕໌֬ʹͳΔ w ٕज़తνϟϯϨϯδͷෑډΛԼ͛Δ w ʮνϟϯϨϯδ͍ͨ͠ݴޠͰϚΠΫϩαʔϏεΛ࡞ͬͯΈΑ͏!ʯ w ʮখ͍͞αʔϏε͔ͩΒޙͰ࡞Γͦ͏ʯʢΤϯδχΞͷϞνϕʔγϣϯ⬆
ΞʔΩςΫνϟ w ̍ͭͷϚΠΫϩαʔϏεʹ̍ͭͷϨϙδτϦɺ̍ͭͷϦιʔεʢ%#ʣ͕ίϯηϓτ w ̍ͭͷϚΠΫϩαʔϏε%PDLFSpMFΛͪίϯςφԽ͢Δ w %PDLFSOJ[FE͞ΕͨϚΠΫϩαʔϏε,VCFSOFUFTͰΦʔέετϨʔγϣϯ
ݱࡏͷ'3&4)-*7& w (PMBOHͱ,PUMJOͷϋΠϒϦουߏ w ৴γεςϜɺϨΠϠʔܥ(PMBOH w ৽نͷ"1*جຊ,PUMJOͰ w "1*Λ(PMBOHͰ͍ͬͺ͍ॻ͘ͷπϥΠʢ(Pے௧ʣ w
+BWBࢿ࢈Λ׆༻͢Εૣ͘࡞ΕΔͱ͜Ζ͋Δ w ϚΠΫϩαʔϏε։ൃͷརΛ׆͔ͯ͠ݴޠʹറΒΕͣϑϥοτʹ
,PUMJOͷ͖ͳͱ͜Ζ w /VMMTBGFUZ w ߴ֊ؔ w ֦ுؔ w %BUBDMBTT w
είʔϓؔ 3FJpFEUZQFQBSBNFUFST ʜFUD w "OESPJEΤϯδχΞͱྑ͘ͳΕΔ w ,PUMJOΛѪͰͨ͘ͳΔͱ͜Ζ͕͍ͬͺ͍
4QSJOH#PPU w ओʹ࠾༻͍ͯ͠ΔϑϨʔϜϫʔΫ w WY3&-&"4&Λಋೖ w ,PUMJOTVQQPSU w ίʔυΛγϯϓϧʹݟ௨͠Α͘*EJPNBUJD ,PUMJO$PEFΛॻ͘͜ͱΛ৺͕͚Δ
IUUQTEPDTTQSJOHJPTQSJOHEPDTDVSSFOUTQSJOH GSBNFXPSLSFGFSFODFLPUMJOIUNM
*EJPNBUJD,PUMJO$PEF 1 val context = GenericApplicationContext().apply { 2 registerBean<Foo>() 3
registerBean { Bar(it.getBean<Foo>()) } 4 } w είʔϓ֦ؔுؔΛͬͯ,PUMJOΒ͍͠ίʔυΛॻ͘ w SFHJTUFS#FBO HFU#FBO֦ுؔ 1 GenericApplicationContext context=new GenericApplicationContext(); 2 context.registerBean(Foo.class); 3 context.registerBean(Bar.class,()->new 4 Bar(context.getBean(Foo.class)) 5 ); w +BWB w ,PUMJO
,PUMJOTVQQPSU w 4QSJOH'SBNFXPSLͷ,PUMJOαϙʔτ w 3FJpFEUZQFQBSBNFUFSͰίʔυதͷܕʹΞΫηεͰ͖Δ 1 inline fun <reified T
: Any> BeanFactory.getBean(): T = 2 getBean(T::class.java) 3 4 inline fun <reified T : Any> GenericApplicationContext.registerBean( 5 vararg customizers: BeanDefinitionCustomizer) { 6 registerBean(T::class.java, *customizers) 7 } 8 9 inline fun <reified T : Any> GenericApplicationContext.registerBean( 10 vararg customizers: BeanDefinitionCustomizer, 11 crossinline function: (ApplicationContext) -> T) { 12 registerBean(T::class.java, 13 Supplier { function.invoke(this) }, *customizers) 14 }
3PVUFS'VODUJPO%4- 1 @Configuration 2 class TaskRoutes(private val taskHandler: TaskHandler, 3
private val authFilter: AuthFilter) { 4 5 @Bean 6 fun taskRouter() = router { 7 "/api".nest { 8 accept(APPLICATION_JSON).nest { 9 POST("/task", taskHandler::create) 10 GET("/task/{id}", taskHandler::fetchByTaskId) 11 } 12 } 13 }.filter(authFilter) 14 } w 4QSJOH'SBNFXPSL͔Βͷ৽ػೳͰ"1*ϧʔςΟϯάͷ%4-
3PVUFS'VODUJPO%4- w 5BTL"1*ͷ5BTL)BOEMFSΫϥε w SFR4FSWFS3FRVFTU ΛҾʹ.POP4FSWFS3FTQPOTFΛฦ͕ؔ͢ฒͿ 1 @Component 2 class
TaskHandler(private val taskRepository: TaskRepository) { 3 4 fun fetchByTaskId(req: ServerRequest): Mono<ServerResponse> = 5 (req.pathVariable("id").toLongOrNull() 6 ?: throw WebAppException.BadRequestException("required id")).let { 7 ServerResponse.ok().json().body(Mono.just(taskRepository.getTaskById(it))) 8 } 9 10 fun create(req: ServerRequest): Mono<ServerResponse> = 11 Validator.validBody<RequestCreateTask>(req).let { 12 taskRepository.createTask(it.title, it.description).let { 13 ServerResponse.ok().json().body(Mono.just(it)) 14 } 15 } 16 }
4QSJOH8FC'MVY w͔ΒՃ͞Εͨίϯϙʔωϯτ w3FBDUJWF1SPHSBNNJOHΛαϙʔτ wαʔό1VTIܕͷ"1*͕ͭ͘ΕΔ w4FSWFS4FOU&WFOUTͰఏڙ w4QSJOHXFCqVYͱXFCNWDڞଘՄ ೳ
4QSJOH8FC'MVY 1 @Configuration 2 class TaskRoutes(private val taskHandler: TaskHandler, 3
private val authFilter: AuthFilter) { 4 @Bean 5 fun taskRouter() = router { 6 "/api".nest { 7 accept(TEXT_EVENT_STREAM).nest { 8 GET("/task/count", taskHandler::fetchTaskCount) 9 } 10 } 11 }.filter(authFilter) 12 } 13 14 @Component 15 class TaskHandler(private val taskService: TaskService) { 16 fun fetchTaskCount(req: ServerRequest): Mono<ServerResponse> { 17 return ok().json().bodyToServerSentEvents( 18 taskService.subscribeTaskCount().map { TaskCount(it) } 19 ) 20 } 21 } w 4USFBNͳ"1*Λ࣮Ͱ͖Δ؆ศͳΈ͕͋Δ
IUUQTTQFBLFSEFDLDPNTPVTIJDBEPULUOVNCFS w ,PUMJOݴޠͷ׆༻ࣄྫΛத৺ʹͨ͠εϥΠυ
·ͱΊ4QSJOH#PPUͱ,PUMJO w ,PUMJOαϙʔτͰ,PUMJOΒ͍͠ίʔυΛॻ͘ w 3PVUFS'VODUJPO%4- w "1*։ൃʹมԽ w 4QSJOH8FC'MVY w
ϦΞϧλΠϜͳίϯςϯπఏڙ͕Մೳʹ
ίϯςφͱϚΠΫϩαʔϏε w ϚΠΫϩαʔϏεͷϧʔϧ w %PDLFSpMFΛ࣋ͪίϯςφԽ͢Δ͜ͱ w ڥมΛίϯςφʹ%* w LTͷ4FDSFUϦιʔεΛ׆༻ w
LTͷ%BNFO4FUʹΑΔαʔϏεϩάऩूͷมԽ
ڥมΛίϯςφʹ%* 1 // src/main/resources/application.properties 2 3 auth.env=${AUTH_ENV:local} 1 // src/main/kotlin/app/config/AppProperties.kt
2 3 @ConfigurationProperties("auth") 4 class AppProperties { 5 var env: String = “local" // localσϑΥϧτม 6 } w %#ઃఆͳͲҟͳΔίϯςφͷڥมʹηοτ w 4QSJOHͷ$POpHVSBUJPO1SPQFSUJFTͰBQQMJDBUJPOQSPQFSUJFTΛϚοϐϯά w ֤ڥͷڥมूͨ͠ϨϙδτϦͰཧ w 4QSJOHʹίϯςφͱੑΛ࣋ͭΈ͕͋Δ"
LTͷ4FDSFUϦιʔε 1 apiVersion: v1 2 kind: Secret 3 metadata: 4
name: mysecret 5 type: Opaque 6 data: 7 username: YWRtaW4= 8 password: MWYyZDFlMmU2N2Rm w ڥຖʹҟͳΔɺओʹػີใΛѻ͏Ϧιʔε w /BNFTQBDFຖʹϦιʔεԽ
4FDSFUΛڥมͰ͔ͭ͏ 1 apiVersion: v1 2 kind: Pod 3 metadata: 4
name: secret-env-pod 5 spec: 6 containers: 7 - name: mycontainer 8 image: redis 9 env: 10 - name: SECRET_USERNAME 11 valueFrom: 12 secretKeyRef: 13 name: mysecret 14 key: username 15 - name: SECRET_PASSWORD 16 valueFrom: 17 secretKeyRef: 18 name: mysecret 19 key: password 20 restartPolicy: Never w ίϯςφͷڥมʹηοτ w ϚΠΫϩαʔϏεͰԣஅతʹڞ௨ͷϦιʔεΛࢀরͰ͖Δ
αʔϏεϩάऩूͷมԽ w ͜Ε·ͰͷFDTͰϚΠΫϩαʔϏε୯ҐͰΫϥελΛΜͰ͍ͨ w ϚΠΫϩαʔϏεͱηοτͰαΠυΧʔίϯςφΛஔʢqVFOUʣ w LTͷ%BFNPO4FUͰqVFOUEΛ/PEFʹஔʢ/PEFQPEͷू߹ମʣ w /PEFͷίϯςφͷϩάΛऩू w
αΠυΧʔίϯςφͷఫഇ( w ΞϓϦͷϩάग़ྗઌΛඪ४ग़ྗͷΈͱ͢Δ w MPHCBDLͷઃఆ͕؆ૉʹ(
TUFSO wQPEͷϩάΛUBJMͯ͘͠ΕΔ wDMVTUFS OBNFTQBDF DPOUBJOFS TFMFDUPSFUDͰϑΟϧλϦϯά wKRͱ߹Θͤͯϩά֬ೝ wೝূ͕௨ΕϩʔΧϧ͔Βར༻Մೳ w։ൃͷ͓ڙʹ"
IUUQTHJUIVCDPNXFSDLFSTUFSO
ίϯςφͱϚΠΫϩαʔϏεਤղ wίϯςφͷڥใڥมͰ %* wڞ௨Խ͍ͨ͠มLTͷ4FDSFU ϦιʔεΛར༻ wίϯςφͷϩάLTͷ %BFNPO4FUΛ/PEFʹஔͯ͠ qVFUEͰऩू
%PDLFS,VCFSOFUFT࣮ફ։ൃೖ w '3&4)-*7&5FDI-FBEͷࢁా໌ݑʢஶʣ w ग़൛ɿٕज़ධࣾ ଓ͖ςΩετͰ"
·ͱΊίϯςφͱϚΠΫϩαʔϏε w ίϯςφͱͷੑ͕େࣄ w ڥมͷϚοϐϯά w LTϦιʔεʹΑΓίϯςφߏʹมԽ w 4FDSFU %BFNPO4FU
w TUFSOศར(
H31$ w (PPHMF͕։ൃͨ͠31$ϑϨʔϜϫʔΫ w )551ͱͷޮతͳଓ w ํετϦʔϛϯάͷ௨৴ํࣜ w 1SPUPCVGʹΑΓσʔλγϦΞϥΠζ w
๛ͳݴޠαϙʔτ w $ɺ+BWBɺ(Pɺ/PEFKTɺ1ZUIPOɺ1)1ɺ3VCZ w ϚΠΫϩαʔϏε։ൃͱ߹கͨ͠ଓσʔλసૹ
ετϦʔϛϯά w ༷ʑͳ௨৴ํࣜ w 6OBSZ31$ʗ୯Ұ௨৴ w 4FSWFSTUSFBNJOH31$ʗ4FSWFS1VTIܕ w $MJFOUTUSFBNJOH31$ʗ$MJFOU1VTIܕ w
#JEJSFDUJPOBMTUSFBNJOHʗํ௨৴ w ࢹௌɺίϝϯτɺ৴ঢ়گͳͲͷϦιʔ εΛετϦʔϛϯάͰྲྀ͢ 4FWFSTUSFBNJOH31$
ϚΠΫϩαʔϏεͱH31$ w 1VCMJDͱ*OUFSOBM͚ͷH31$4FSWFSͷఏڙ w 1PSUΛ͚ͯ̎ͭͷ4FSWFSΛىಈ w 4QSJOHGSBNFXPSL w $PNNBOE-JOF3VOOFS w
%JTQPTBCMF#FBO
H31$4FWFS3VOOFS 1 @Configuration 2 class GrpcGlobalServerRunner(private val appProperties: AppProperties, private
val authInterceptor: AuthInterceptor, 3 private val balanceServer: BalanceServer) : CommandLineRunner, DisposableBean { 4 5 lateinit var server: Server 6 7 override fun run(args: Array<String>) { 8 NettyServerBuilder.forPort(appProperties.grpc.global.port) 9 .addService(ProtoReflectionService.newInstance()) 10 .apply { 11 balanceServer.let { 12 ServerInterceptors.intercept(it, authInterceptor) 13 addService(it) 14 } 15 } 16 .build().start() 17 .also { server = it } 18 } 19 20 override fun destroy() { 21 Optional.ofNullable(server).ifPresent { 22 it.shutdown() 23 } 24 } 25 }
4QSJOH'SBNFXPSLͱH31$ w 4QSJOHGSBNFXPSLͷFDPTZTUFNͱHSQDKBWBͷڞଘ( w 4FSWFSىಈɺ*OUFSDFQUPSͳͲͳ͘ߏஙՄೳ w ೖ೦ͳΫϥΠΞϯτૄ௨֬ೝʢಛʹ"OESPJEʣ w ఆظతͳपลϥΠϒϥϦͷΞοϓσʔτ
·ͱΊH31$ͱϚΠΫϩαʔϏε w ޮతͳ௨৴ w ϚΠΫϩαʔϏεʹ߹கͨ͠։ൃ w 4QSJOH'SBNFXPSLͰH31$4FWFSͷߏங w 1PSUͷ׆༻ w
̍ͭͷKBSʹ1VCMJD *OUFSOBMͷ4FSWFSΛىಈ
·ͱΊ w ϚΠΫϩαʔϏε։ൃͰकΓ߈ΊՌʹ w αʔόαΠυ,PUMJO։ൃʹ4QSJOH#PPUYΛΦεεϝ" w ,PUMJOαϙʔτ ॆ࣮ͨ͠4QSJOH'SBNFXPSLͷίϯϙʔωϯτ w ίϯςφͱͷੑ
w LTͷಋೖʹΑΓίϯςφஔઓུʹมԽ w ϦΞϧλΠϜͳίϯςϯπఏڙʹ࠷దͳ௨৴ํࣜͷબ w 44& )551 w 4QSJOH8FC'MVY H31$
খ͞ͳϚΠΫϩαʔϏε͔Β ,PUMJOͰ4FSWFS4JEF։ൃΛ"
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ɻ