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
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
AIによるクリエイティブ生成を行う上での試行錯誤
plaidtech
PRO
0
160
Azure Serverless 2026:Production-ready な AI エージェント基盤 / Azure Serverless 2026: Production-Ready AI Agent Platform
miyake
2
180
beyond jj: config & tools ecosystem
indirect
0
3.2k
AI de Idea
kawaguti
PRO
2
120
AIを活用するために決めた "やらないこと" - 価値に注目する / Not betting on AI
soudai
PRO
2
550
TinyGo 開発サイクルを高速化する:Go で作るエミュレータ入門
zozotech
PRO
1
750
OpenTelemetryのメトリクスをCloudWatchに送ってPromQLで見てみた
ota1022
0
150
10Xに技術的負債をもたらした「2つの境界の歪み」その構造と解消への営み
10xinc
0
2.1k
AIエージェントの自己改善をどう設計するか / How to Design Self-Improvement for AI Agents
22mi
25
16k
山手線を徒歩で一周してわかった、 位置情報アプリは「足」が最強のデバッガー
hinakko
0
160
What the customer really needed
kawaguti
PRO
3
210
絵ではじめるKubernetesセキュリティ
aoi1
4
660
Featured
See All Featured
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
750
The World Runs on Bad Software
bkeepers
PRO
72
12k
Fireside Chat
paigeccino
43
4k
[SF Ruby Conf 2025] Rails X
palkan
3
1.4k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
It's Worth the Effort
3n
188
29k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.3k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
240
Raft: Consensus for Rubyists
vanstee
142
7.7k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
810
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.9k
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։ൃΛ"
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ɻ