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.2k
Other Decks in Technology
See All in Technology
Context Ontology Accelerator 入門 (業務データの意味を、AI エージェントに渡す)
inariku
PRO
3
540
コードレビューをなくして見えたもの
henteko
0
140
[dbts2026]数十PBの超巨大データ×AI活用を支えるSnowflakeの実力〜大規模環境におけるアーキテクチャと運用のリアル〜
y_matsubara
0
120
GCASアップデート(202607-202610)
techniczna
1
230
Gifu WordPress Meetup #200 に向けて、私たちには何ができるだろうか?/ 2026-11-07 Gifu WordPress Meetup
torounit
0
230
登壇はいいぞ! 〜Kaigi on Railsに登壇して起きた3つの変化〜
occhi
0
110
The Author Pays
hiccupps
0
120
分析作業をどこまで任せるか自分で決められる AIネイティブBI『Golden Analytics』が 良さげな話 /golden-analytics-is-ai-native-bi
shinyaa31
0
130
Lint の層を組み直した話
bengo4com
3
330
慶應義塾大学 AI実践05 論文執筆の仕組み化
keio_smilab
PRO
7
3.8k
AWSを利用する上で知っておきたい名前解決の話 2026
nagisa53
5
3.2k
顧客合意を取りながら進めるAWSコスト削減の実践
optim
0
140
Featured
See All Featured
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
23k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
480
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
3k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
300
Intergalactic Javascript Robots from Outer Space
tanoku
273
28k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
The SEO identity crisis: Don't let AI make you average
varn
0
630
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.7k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
470
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
520
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։ൃΛ"
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ɻ