CloudNative Days Tokyo 2020 の発表資料です。Wantedly での gRPC 導入の取り組みについて話しました。
gRPC という通信技術についての詳細な説明から、gPRC を利用することによるメリット、gRPC を利用することで実際に得られたパフォーマンス改善、gRPC への移行を行うための実践的な Tips について話しました。移行の際にはツールやライブラリの開発や開発フローの整備など技術的、組織的な挑戦を行なっており、その詳細についても話しました。
https://event.cloudnativedays.jp/cndt2020/talks/14
©2020 Wantedly, Inc.Real World Migrationfrom HTTP to gRPC08.Sep.2020 - Nao Minami (@south37) Wantedly, Inc.CloudNative Days Tokyo 2020
View Slide
©2019 Wantedly, Inc./BP.JOBNJ*OGSBTUSVDUVSF5FBN 8BOUFEMZ *OD(JU)VCTPVUI5XJUUFSTPVUIϚΠΫϩαʔϏεؒ௨৴ͷH31$ಋೖʹऔΓΉ 43&ͱͯ͠ͷׂʢαʔϏεͷ৴པੑʹʣ ։ൃج൫ͱͯ͠ͷׂʢΤϯδχΞͷੜ࢈ੑʹʣ
©2020 Wantedly, Inc.1. gRPC Λͳͥར༻͢Δͷ͔2. gRPC ΛͲ͏ར༻࢝͠Ί͔ͨ3. gRPC ΛࣾʹͲ͏Ί͔ͨAgenda
©2020 Wantedly, Inc.gRPC ͱ
©2020 Wantedly, Inc.gRPC ͱGoogle ͷ high performance ͳ RPC frameworkw 3FNPUF1SPDFEVSF$BMM 31$w DMJFOU͕ؔݺͼग़͠SFNPUFTFSWFS্Ͱؔݺͼग़͕͠ॲཧ͞Εͯ݁Ռ͕ฦ͞ΕΔw )551Λ௨৴ϓϩτίϧͱͯ͠ར༻w 1SPUPDPM#V⒎FSTΛαʔϏεఆٛʢTFSWFSͰ࣮͞Εͨؔͷܕʣͷهड़ʹར༻H31$ͷެࣜEPDVNFOUΑΓҾ༻
©2020 Wantedly, Inc.HTTP/2 ͱޮతͳ Hypertext Transfer Protocol (HTTP)w (PPHMF41%:QSPUPDPM͕ݩʹͳͬͯඪ४Խw 5SBOTQPSUΛޮԽ͢Δ͍ͭ͘ͷ༏ΕͨػೳଟॏԽɺϔομѹॖɺFUDH31$ͷIJHIQFSGPSNBODFʹߩݙIUUQTEFWFMPQFSTHPPHMFDPNXFCGVOEBNFOUBMTQFSGPSNBODFIUUQΑΓҾ༻
©2020 Wantedly, Inc.Protocol Buffers ͱGoogle IDL + ίϯύΠϥ + serialization libraryw *OUFSGBDF%FpOJUJPO-BOHVBHF *%-αʔϏεఆٛΛهड़͢ΔͨΊͷಠࣗݴޠw *%-ͰαʔϏεఆٛΛهड़͢Δͱɺ1SPUPDPM#V⒎FSTίϯύΠϥʢQSPUPDʣ͕ޮతͳTFSJBMJ[BUJPOͷҝͷίʔυΛࣗಈੜw αʔϏεఆٛ"1*4DIFNBͱͯ͠ͷׂΛՌͨ͢4DIFNB%SJWFO%FWFMPQNFOUͰߴ͍ੜ࢈ੑΛ࣮ݱՄೳAPI Schema = proto ϑΝΠϧ4FSWFS։ൃ$MJFOU։ൃ
©2020 Wantedly, Inc.gRPC HTTP/2 ͱ Protocol Buffers Λར༻͢Δ༏Εͨ RPC framework
©2020 Wantedly, Inc.gRPC Λͳͥར༻͢Δͷ͔
©2018 Wantedly, Inc.8BOUFEMZͰ8BOUFEMZ7JTJUɺ8BOUFEMZ1FPQMFΛϚΠΫϩαʔϏεͰ։ൃ
©2018 Wantedly, Inc.ͨΒ͘Λ໘ന͘༗໊اۀϕϯνϟʔɺελʔτΞοϓاۀɺؾʹͳΔΦϑΟεʹΛฉ͖ʹ͍͜͏ɻ ΩϥͬͱޫΔγΰτϓϩδΣΫτɺձࣾΛݟ͚ͭͯΤϯτϦʔ͠·͠ΐ͏ɻΓ߹͍ͷͭͳ͕Γ͕͔ͬͯ҆৺Ͱ͢ɻ
©2018 Wantedly, Inc.ड͚औ໊ͬͨશͯΛɺճͷࡱӨͰಉ࣌ʹಡΈࠐΈɻ ಡΈࠐΜ໊ͩਓೳ͕ଈ࣌σʔλԽ͠ɺ࿈བྷாʹՃ͞Ε·͢ɻݡ໊͘ཧ
©2020 Wantedly, Inc.എܠ: Wantedly Visit ͱ Wantedly People ͷΞʔΩςΫνϟ 100 ͷϚΠΫϩαʔϏεΛΈ߹ΘͤͨΞʔΩςΫνϟw 3VCZ (P 1ZUIPO /PEFKTͳͲ༷ʑͳݴޠͰϚΠΫϩαʔϏεΛ࣮w ݩʑϚΠΫϩαʔϏεؒ௨৴ʹ)551Λར༻LTDMVTUFS$PSF4FSWJDFT
©2018 Wantedly, Inc.ϚΠΫϩαʔϏε։ൃΛਐΊΔ্Ͱ͍͔ͭ͘՝͕ଘࡏͨ͠
©2020 Wantedly, Inc.HTTP/1.1 Λར༻͢ΔࣄͰੜ͡Δ௨৴ latency ͕w ,FFQBMJWFແ͠ͷૉͳ)551༷ʑͳཁҼͰ͘ͳΔw FH%/4MPPLVQ 5$1XBZIBOETIBLF 5$1TMPXTUBSU FUD՝1ϚΠΫϩαʔϏε-BUFODZDBVTFECZVTJOH)551
©2020 Wantedly, Inc.ϚΠΫϩαʔϏεͰ௨৴ latency ͷӨڹ͕େ͖͍w ௨৴૬ख͕૿͑Δ΄Ͳɺ௨৴MBUFODZʢಛʹUBJMMBUFODZʣͷӨڹΛड͚͘͢ͳΔw ྫϚΠΫϩαʔϏεؒ௨৴͕ͷ֬Ͱ͘ͳΔέʔεΛߟ͑Δw ݸͷϚΠΫϩαʔϏεͱ௨৴͢Δ߹શମͱͯ͠ͷ֬Ͱ͍w ݸͷϚΠΫϩαʔϏεͱ௨৴͢Δ߹શମͱͯ͠ͷ֬Ͱ͍w ࣮ࡍʹUBJMMBUFODZͷد༩Ͱ͘ͳͬͯΔϚΠΫϩαʔϏε͕ଘࡏͨ͠w ྫଞͷϚΠΫϩαʔϏεͱͷ௨৴MBUFODZ͕ࢧతͳϚΠΫϩαʔϏεͰBWFSBHFSFTQPOTFUJNFNTʹରͯ͠UJMFSFTQPOTFUJNF͕ NTϚΠΫϩαʔϏεؒ௨৴ͷUBJMMBUFODZվળ͕ඞཁͱ͞Ε͍ͯͨϚΠΫϩαʔϏεʹ͓͚Δ௨৴ latency ͷ
©2020 Wantedly, Inc.Protocol Buffers ͷԸܙΛҰ෦ͷνʔϜͷΈ͕ڗडw ݩʑɺҰ෦νʔϜͰ1SPUPDPM#V⒎FSTΛϚΠΫϩαʔϏεͷ"1*4DIFNBͱͯ͠ར༻4DIFNB%SJWFO%FWFMPQNFOUͰߴ͍ੜ࢈ੑΛ࣮ݱ՝2CVJMEFSTDPOUPLZPl8FC"1*ʹடংΛ༩͑Δ1SPUPDPM#V⒎FSTlw ͔͠͠ɺ1SPUPDPM#V⒎FSTPWFS)551ͰʮQBZMPBEΛMJCSBSZ͔Βར༻ͮ͠Β͍ʯͳͲ͍͔ͭ͋͘Γࣾશମʹ1SPUPDPM#V⒎FSTΛ͛ͮΒ͍ঢ়گͩͬͨ
©2020 Wantedly, Inc.
©2020 Wantedly, Inc.gRPC ʹظͨ͜͠ͱ1. ϚΠΫϩαʔϏεͷύϑΥʔϚϯεվળ2. Protocol Buffers ͷࣾશମͰͷར༻ʹΑΔɹɹɹ։ൃੜ࢈ੑ্
©2020 Wantedly, Inc.gRPC ͕՝Λղܾͯ͘͠ΕΔ͜ͱΛظͯ͠ಋೖΛܾΊͨ
©2020 Wantedly, Inc.2-1. ݕূ2-2. Πϯϑϥඋ2-3. খ͘͞ಋೖ & ޮՌଌఆ2. gRPC ΛͲ͏ར༻࢝͠Ί͔ͨ
©2020 Wantedly, Inc.gRPC ͷύϑΥʔϚϯεΛ։ൃ༻ k8s cluster Ͱݕূw ݩʑɺຊ൪LTDMVTUFSͱ΄΅ಉ͡ߏͷLTDMVTUFS͕։ൃ༻్ͱͯ͠ଘࡏw ϚΠΫϩαʔϏεͷίʔυΛH31$Λར༻͢Δͷͱॻ͖͑ͯ-BUFODZΛܭଌ2-1. ݕূຊ൪LTDMVTUFS)551ϚΠΫϩαʔϏε)551H31$ϚΠΫϩαʔϏε։ൃ༻LTDMVTUFS5SZH31$
©2020 Wantedly, Inc.gRPC ͷݕূ݁Ռʁ
©2020 Wantedly, Inc.௨৴෦ͷ latency ͷܶతͳվળΛ؍ଌ w "WFSBHFMBUFODZഒߴԽ NTNTw 5BJMMBUFODZ UJMFഒߴԽ NTNTLatency [ms]percentilegRPC։ൃ༻ k8s cluster Ͱͷ Benchmark ݁ՌHTTP/1.120 40 60 80 100100150500
©2020 Wantedly, Inc.ݕূ݁ՌΛड͚ͯgRPC ͷظ͕ߴ·ͬͨ
©2020 Wantedly, Inc.gRPC Λ Production Ͱར༻͢ΔͨΊͷΠϯϑϥw -PBE#BMBODJOHɺ.POJUPSJOHͳͲͷΠϯϑϥඋ͕ඞཁ2-2. Πϯϑϥඋ
©2020 Wantedly, Inc.gRPC Λ Production Ͱར༻͢ΔͨΊͷΠϯϑϥw-PBE#BMBODJOHw .POJUPSJOH2-2. Πϯϑϥඋ
©2020 Wantedly, Inc.gRPC ʹ͓͍ͯɺL4 load-balancer ෆదw H31$)551Λ׆༻ͯ͠ʮҰཱ֬ͨ͠MPOHMJWFEͳ5$1DPOOFDUJPOΛԿSFRVFTUʹར༻͢Δʯલఏͷઃܭw -MPBECBMBODFS5$1DPOOFDUJPOཱ֬ͷෛՙࢄ͔͠ߦΘͳ͍ͨΊɺH31$ͰUSB⒏Dͷෛՙࢄ͕͏·͘ߦΘΕͳ͍Load Balancing௨৴૬ख͕ݻఆ͞ΕΔ
©2020 Wantedly, Inc.ղܾࡦ: Istio Λ L7 load-balancing ʹར༻w *TUJPɺ,VCFSOFUFTͳͲͰར༻Ͱ͖ΔαʔϏεϝογϡɾϓϥοτϑΥʔϜw *TUJPʹΑͬͯDPOpHVSF͞Εͨ&OWPZΛTJEFDBSQSPYZͱͯ͠JOKFDUͯ͠ɺ-MPBECBMBODJOHʹར༻ͨ͠Load Balancing&OWPZ
©2020 Wantedly, Inc.gRPC Λ Production Ͱར༻͢ΔͨΊͷΠϯϑϥw -PBE#BMBODJOHw.POJUPSJOH2-2. Πϯϑϥඋ
©2020 Wantedly, Inc.ຊ൪ڥͷΞϓϦέʔγϣϯϞχλϦϯά͕ඞཁw ͷݕύϑΥʔϚϯεͷܭଌͳͲ༷ʑͳతͰϞχλϦϯάΛߦ͏w )551ͰͲͷϚΠΫϩαʔϏε%BUBEPH /FX3FMJD )POFZCBEHFSͳͲͰSFRVFTU͝ͱͷNFUSJDTΛϞχλϦϯάಉ͡ঢ়گΛH31$Ͱ࡞Γ͍ͨMonitoring
©2020 Wantedly, Inc.MonitoringgRPC server ͷϞχλϦϯάΛͲ͏࣮ݱ͢Δ͔ʁ=> gRPC interceptor Λར༻w H31$JOUFSDFQUPSΛར༻͢ΔࣄͰɺʮH31$SFRVFTUSFTQPOTFͷϥΠϑαΠΫϧʹNFUSJDTૹ৴ͳͲͷҙͷॲཧΛࠩ͠ࠐΉʯ͜ͱ͕Մೳ$MJFOUH31$JOUFSDFQUPST$MJFOU4FSWFSH31$JOUFSDFQUPST4FSWFS3FRVFTU3FTQPOTF
©2020 Wantedly, Inc.MonitoringgRPC interceptor Λ༻ҙw ֤छ4BB4͚ͷH31$JOUFSDFQUPSΛ࣮ͨ͠w 3VCZ࣮ͷҰ෦044ͱͯ͠ެ։
©2020 Wantedly, Inc.Ұ෦ͷϚΠΫϩαʔϏεͰ gRPC Λಋೖw H31$ಋೖΛૉૣ͘ਐΊΔͨΊʹɺ࠷ॳҰ෦ͷϚΠΫϩαʔϏεͰಋೖw ରͱͯ͠lϢʔβʔαʔϏεzΛબΜͩ2-3. খ͘͞ಋೖ & ޮՌଌఆLTDMVTUFS$PSF4FSWJDFTϢʔβʔαʔϏε
©2020 Wantedly, Inc.ͳͥϢʔβʔαʔϏεΛબΜͩͷ͔ʁಛ: traffic ͕ଟ͘ low latency ͕ඞཁw ଟ͘ͷϚΠΫϩαʔϏε͔Βར༻͍ͯ͠ΔͨΊUSB⒏D͕ଟ͍w Ϣʔβʔ͔ΒͷSFRVFTUॲཧͰಉظతʹSFRVFTU͞ΕΔέʔεଟMPXMBUFODZ͕ඞཁH31$ಋೖʹΑΔΠϯύΫτ͕ݦஶʹݱΕΔ͜ͱ͕ظग़དྷΔϢʔβʔαʔϏεϢʔβʔͷઃఆϓϩϑΟʔϧͷऔಘɾߋ৽
©2020 Wantedly, Inc.gRPC ಋೖΛͲ͏ਐΊ͔ͨʁ
©2020 Wantedly, Inc.k8s objects Λ 2 ηοτ༻ҙw ύϑΥʔϚϯεಛੑͳͲ͕ҧ͏ͷͰɺ%FQMPZNFOUͱ)1"Λݸผʹ༻ҙw )5513VCZPO3BJMTTFSWFS͕ىಈ͢Δ%FQMPZNFOU)1"4FSWJDFw H31$H31$TFSWFS͕ىಈ͢Δ%FQMPZNFOU)1"4FSWJDFw $MJFOUଆͰ௨৴ઌIPTU໊ LT4FSWJDFΛΓସ͑ͯ௨৴खஈΛ੍ޚgRPC ಋೖͷਐΊํH31$H31$TFSWFS$MJFOUϚΠΫϩαʔϏε)5513VCZPO3BJMT
©2020 Wantedly, Inc.Client ϚΠΫϩαʔϏεͰ gRPC ͷར༻Λ૿͢w Ұ෦ϦΫΤετʹH31$Λಋೖ༷ͯ͠ࢠΛݟͳ͕Βɺঃʑʹׂ߹Λ૿ՃશʹҠߦgRPC ಋೖͷਐΊํϢʔβʔαʔϏε ϢʔβʔαʔϏε)551H31$H31$ͷׂ߹Λ૿Ճ)551H31$$MJFOU $MJFOU
©2020 Wantedly, Inc.gRPC Λಋೖͨ݁͠Ռʁ
©2020 Wantedly, Inc.ϚΠΫϩαʔϏεؒ௨৴ͷύϑΥʔϚϯε͕ܶతʹվળͨ͠
©2020 Wantedly, Inc.gRPC ΛҰ෦ϚΠΫϩαʔϏεʹಋೖͨ݁͠Ռ௨৴෦ͷ Latency ͕ܶతʹվળ w ϢʔβʔαʔϏεͱͷ௨৴ͷBWFSBHFMBUFODZ͕SFRVFTU͋ͨΓNTվળw ͷSFRVFTUॲཧͷதͰϢʔβʔαʔϏεԿSFRVFTU͢Δέʔε͕ଘࡏ௨৴ͷBWFSBHFMBUFODZ͕ेඦͷܶతվળe.g. ϢʔβʔαʔϏε௨৴෦ͷ average latency ͕ 153ms ͔Β 45ms ʹ 240% վળͨ͠ྫHTTP/1.1 gRPC
©2020 Wantedly, Inc.gRPC ΛҰ෦ϚΠΫϩαʔϏεʹಋೖͨ݁͠ՌશͯͷॲཧΛؚΉ response time ݦஶʹվળ w ϢʔβʔαʔϏεͱͷ௨৴͕ଟ͍FOEQPJOUɺશମͷSFTQPOTFUJNFܶతʹվળw શମͱͯ͠ૣ͘ͳ͚ͬͨͩͰͳ͘ɺʮۃʹ͘ͳΔέʔεʯ͕ܹݮͨ͠5BJMMBUFODZվળͷޮՌΛ࣮ײUJMFSFTQPOTFUJNFHTTP/1.1 gRPCe.g. 99%tile response time ͷϐʔΫ͕ 5,000ms ͔Β 1,900ms ʹ 3,000ms Ҏ্վળͨ͠ྫ
©2020 Wantedly, Inc.gRPC Λຊ൪ k8s cluster ʹಋೖͯ͠ύϑΥʔϚϯεվળ͕ग़དྷΔͱ֬ೝͰ͖ͨ
©2020 Wantedly, Inc.՝: gRPC ͷར༻͕Ұ෦ʹݶΒΕ͍ͯͨw H31$͕Ұ෦Ͱ͔͠ར༻͞Εͯͳ͍ͱɺԸܙΛड͚ΒΕΔͷҰ෦ͷFOEQPJOUͱҰ෦ͷ։ൃऀʹݶΒΕͯ͠·͏3. gRPC ΛࣾʹͲ͏Ί͔ͨҰ෦ͷH31$ϚΠΫϩαʔϏεଟ͘ͷ)551ϚΠΫϩαʔϏε
©2020 Wantedly, Inc.ΰʔϧ: gRPC ͷར༻Λ͛ͯԸܙΛ͘ड͚Δw ଟ͘ͷFOEQPJOUͰH31$Λར༻༏ΕͨύϑΥʔϚϯεʹΑͬͯϢʔβʔମݧΛվળw ଟ͘ͷ։ൃऀ͕H31$Λར༻1SPUPDPM#V⒎FSTʹΑΓ։ൃੜ࢈ੑΛ্3. gRPC ΛࣾʹͲ͏Ί͔ͨଟ͘ͷH31$ϚΠΫϩαʔϏεҰ෦ͷ)551ϚΠΫϩαʔϏε
©2020 Wantedly, Inc.gRPC Λར༻ͨ͠։ൃΛ͛Δ͜ͱΛࢦͨ͠
©2020 Wantedly, Inc.3-1. ։ൃڥඋ3-2. ࣾએ͍ͯ͛ͯ͘͠3. gRPC ΛࣾʹͲ͏Ί͔ͨ
©2020 Wantedly, Inc.ੜ࢈ੑͷߴ͍։ൃڥΛߏஙw εΩʔϚཧϫʔΫϑϩʔɺϥΠϒϥϦඋʹΑͬͯ։ൃڥΛ͑Δ3-1. ։ൃڥඋ
©2020 Wantedly, Inc.ੜ࢈ੑͷߴ͍։ൃڥΛߏஙwεΩʔϚཧw ϥΠϒϥϦඋ3-1. ։ൃڥඋ
©2020 Wantedly, Inc.Monorepo Λ࠾༻͠ͳ͍߹ɺͲ͏ͬͯಉ͡proto ϑΝΠϧΛڞ༗͢Δ͔ߟ͑Δඞཁ͕͋Δಉ͡QSPUPϑΝΠϧ3FQPTJUPSZ" 3FQPTJUPSZ# 3FQPTJUPSZ$εΩʔϚཧ = proto ϑΝΠϧཧ
©2020 Wantedly, Inc.Ͳ͏ͬͯ proto ϑΝΠϧΛڞ༗͢Δ͔ʁw खಈ$PQZ1BTUFʁෳSFQPTJUPSZΛ߹ੑΛอͬͯߋ৽͠ଓ͚Δͷ͕͍͠w QSPUPϑΝΠϧΛࣗಈμϯϩʔυ͢ΔػߏΛ༻ҙ͢Δʁ֤ϨϙδτϦͷ։ൃऀ͕ίʔυੜΛߦ͏ඞཁ͕͋ΓɺQSPUPDWFSTJPOQMVHJOͷ༗ແͳͲɺ։ൃऀؒͷڥͷҧ͍ʹۤ͠Ήͦ͜Ͱɺcentral repository Λ༻ҙͨ͠εΩʔϚཧ = proto ϑΝΠϧཧ
©2020 Wantedly, Inc.apis: εΩʔϚཧͷͨΊͷ central repositoryw lBQJTz8BOUFEMZͷͯ͢ͷQSPUPϑΝΠϧΛཧεΩʔϚཧ = proto ϑΝΠϧཧ
©2020 Wantedly, Inc.“apis” repository ΛͲ͏ར༻͢Δͷ͔ʁ“apis” ͷ CI ύΠϓϥΠϯͰίʔυੜ͕ߦΘΕΔw 3VCZ (P 1ZUIPO /PEFKTͦΕͧΕͷݴޠ͚ͷίʔυΛQSPUPϑΝΠϧ͔Βੜw ੜ͞Εͨίʔυ֤ݴޠͷ1BDLBHF.BOBHFSͰ৴ FH#VOEMFS (P.PEVMFT FUDw ։ൃऀ͕ࣗͰίʔυੜΛߦ͏ඞཁ͕ͳ͍ঢ়ଶΛ࣮ݱ
©2020 Wantedly, Inc.# Gemfilegem 'apis', git: '[email protected]:wantedly/apis-ruby.git', tag: 'xxx.yyy.zzz'3VCZXJUI#VOEMFS
©2020 Wantedly, Inc.ੜ࢈ੑͷߴ͍։ൃڥΛߏஙw εΩʔϚཧwϥΠϒϥϦඋ3-1. ։ൃڥඋ
©2020 Wantedly, Inc.֤ݴޠ͚ʹϥΠϒϥϦͰ֤छػೳΛఏڙw ݴޠw 3VCZ (P 1ZUIPO /PEFKTw ػೳw H31$4FSWFS $MJFOU։ൃ༻VUJMJUZw H31$JOUFSDFQUPSTw 1SPUPDPM#V⒎FSTར༻ͷͨΊͷVUJMJUZϥΠϒϥϦඋ
©2020 Wantedly, Inc.ϥΠϒϥϦͲ͏͍ͬͨܗͰඋͨ͠ͷ͔ʁ
©2020 Wantedly, Inc.“servicex” ͱݺΕΔࣾڞ௨ library Λར༻w ݩʑɺ)551ͷ͔࣌ΒʮͲͷϚΠΫϩαʔϏε͔Βڞ௨ͰΘΕΔػೳʯΛTFSWJDFYͰఏڙ͖ͯͨ͠H31$։ൃΛศརʹ͢ΔMJCSBSZTFSWJDFYͰఏڙw TFSWJDFY֤ݴޠ͚ʹଘࡏw 3VCZ (P 1ZUIPOϥΠϒϥϦͲ͏͍ͬͨܗͰඋͨ͠ͷ͔ʁϚΠΫϩαʔϏε" ϚΠΫϩαʔϏε# ϚΠΫϩαʔϏε$lTFSWJDFYz
©2020 Wantedly, Inc.servicex-ruby Ͱ࣮ͨ͠ػೳΛҰ෦հ
©2020 Wantedly, Inc.gRPC server ։ൃͷͨΊͷ grpc-server ίϚϯυw H31$TFSWJDFDMBTTࣗಈͰIBOEMFSͱͯ͠ొw H31$JOUFSDFQUPSඞཁͳͷࣗಈͰઃఆw 3VCZPO3BJMTͷΑ͏ͳ)PUSFMPBEJOHػೳΛఏڙw ։ൃऀɺH31$TFSWJDFDMBTTͷ࣮ʹूதߴ͍ੜ࢈ੑΛ࣮ݱ“servicex-ruby” ͷػೳ$ bundle exec grpc-serverhandling /grpc.health.v1.Health/Check with #handling /grpc.health.v1.Health/Watch with #Grpc::Health::Checker(Grpc::Health::V1::Health::Service)#watch>handling /wantedly.users.UserService/ListUsers with #...gRPC server starting...* Listening on tcp://0.0.0.0:6046* Environment: development
©2020 Wantedly, Inc.gRPC client ͷͨΊͷ Servicex::Grpc.stub_forw H31$JOUFSDFQUPSͱͯ͠ඞཁͳͷࣗಈͰઃఆw 6TFS"HFOUࣗಈͰઃఆw ։ൃऀʮH31$ͷ͍ํʯΛؾʹ͢Δࣄͳ͘ɺϩδοΫͷ࣮ʹूதߴ͍ੜ࢈ੑ# NOTE: Load UsersPb::UserService from apisrequire "wantedly/users/users_services_pb"grpc_server_url = “xxx”client = Servicex::Grpc.stub_for(UsersPb::UserService,grpc_server_url,)client.get_user(UsersPb::GetUserRequest.new(…))“servicex-ruby” ͷػೳ
©2020 Wantedly, Inc.Pb: Protocol Buffers ͷར༻Λ؆୯ʹ͢Δ utilityw 1CΛར༻͢ΔࣄͰQSPUPCVGPCKFDUΛ؆୯ʹ࡞Մೳw ྫ͑ɺ4USJOH͔ΒUJNFTUBNQΦϒδΣΫτΛ࡞͢Δ͜ͱ͕Մೳ[1] pry(main)> Pb.to_timestamp("2019-05-15T00:00:00+09:00")=> 8JUIl1Cz[1] pry(main)> Google::Protobuf::Timestamp.new([1] pry(main)* seconds: Time.parse("2019-05-15T00:00:00+09:00").to_i[1] pry(main)* )=> 8JUIPVUl1Cz“servicex-ruby” ͷػೳ
©2020 Wantedly, Inc.servicex-ruby ͷػೳͷҰ෦ OSS Խw 044ԽΛ௨ͯ͠ɺH31$ͷΤίγεςϜख़ʹߩݙ“servicex-ruby” ͱ OSS
©2020 Wantedly, Inc.Ruby Ͱͷ gRPC ։ൃΛखް͘αϙʔτͨ͠
©2020 Wantedly, Inc.Go, Python, Node.js ͳͲଞͷݴޠͰʁ
©2020 Wantedly, Inc.“grapi” + “servicex-go” Λར༻w HSBQJH31$HSQDHBUFXBZߏͷ"1*TFSWFS͚DPEFHFOFSBUPSMJCSBSZ 044w H31$TFSWFS୯ಠར༻Մೳw TFSWJDFYHPHSBQJͷਪઃఆH31$JOUFSDFQUPSΛఏڙ͢Δࣾڞ௨MJCSBSZGo ͷ gRPC ։ൃڥ(P$POGFSFODF4QSJOHlHSBQJ#VMEJOH+40/"1*TFSWFSXJUIHSQDHBUFXBZGPSNJDSPTFSWJDFTz
©2020 Wantedly, Inc.Go ͷ gRPC ։ൃڥpackage mainimport (..."github.com/izumin5210/grapi/pkg/grapiserver""github.com/wantedly/servicex-go/v2/pkg/servicex""github.com/wantedly/servicex-go/v2/pkg/grpcx""github.com/wantedly/spath/to/server")func InitializeGrapiServerEngine(ctx context.Context) (*grapiserver.Engine, error) {userServiceServer := server.NewUserServiceServer(ctx)engine := grapiserver.New(grpcx.WithDefault(),grapiserver.WithServers(userServiceServer),)return engine, nil}func run() error {ctx := context.Background()defer servicex.Close()s, err := InitializeGrapiServerEngine(ctx)if err != nil {return fail.Wrap(err)}return s.ServeContext(ctx)}
©2020 Wantedly, Inc.“grapi” ͱ “servicex-go” ͕ࣾڞ௨ͷػೳఏڙw ։ൃऀH31$TFSWFSͷϩδοΫ࣮ʹूதͰ͖Δߴ͍ੜ࢈ੑΛ࣮ݱGo ͷ gRPC ։ൃڥ
©2020 Wantedly, Inc.Python ͷ gRPC ։ൃڥ
©2020 Wantedly, Inc.“servicex-python” ͱ͍͏ࣾڞ௨ library Λར༻w lHSQDYzQBDLBHFͱͯ͠HSQDY4FSWFSDMBTTͳͲͷVUJMJUZΛ༻ҙw ։ൃऀɺH31$TFSWJDFDMBTTͷ࣮ʹूதߴ͍ੜ࢈ੑΛ࣮ݱPython ͷ gRPC ։ൃڥimport servicex.grpcx as grpcxclass UserService(users_pb2_grpc.UserServiceServicer):...server = grpcx.Server(port=os.getenv("APP_GRPC_PORT", "3000"),max_workers=10,grpc_services=[grpcx.ServiceInfo(name=users_pb2.DESCRIPTOR.services_by_name['UserService'].full_name,adder=users_pb2_grpc.add_UserServiceServicer_to_server,servicer=UserService(),)])server.run()
©2020 Wantedly, Inc.gRPC client ։ൃʹ grpc package Λར༻w 1ZUIPO.-ϚΠΫϩαʔϏεͱͯ͠Ͱͷར༻͕ଟ͍H31$DMJFOUར༻গͳ͘VUJMJUZͷχʔζগͳ͍w χʔζ͕૿͑ͨλΠϛϯάͰࣾڞ௨MJCSBSZԽͷ༧ఆPython ͷ gRPC ։ൃڥfrom grpc.experimental import aioclass UsersService:def __init__(self) -> None:self.base_url = ...async def get(self, user_id: int) -> users_pb2.User:async with aio.insecure_channel(target=self.base_url) as channel:stub = users_pb2_grpc.UserServiceStub(channel)req = users_pb2.GetUserRequest(...)res = await stub.GetUser(req, timeout=2)return res.user#SPXTFSH31$1ZUIPO.-ϚΠΫϩαʔϏε
©2020 Wantedly, Inc.Node.js ͷ gRPC ։ൃڥ
©2020 Wantedly, Inc.Node.js Backend for Frontend (BFF) Ͱ gRPCclient Λར༻w 6UJMJUZMJCSBSZΛར༻͢ΔࣄͰɺH31$DMJFOUΛར༻ͨ͠։ൃΛޮԽw lBQJTOPEFzͰܕఆٛϑΝΠϧΛੜͯ͠5ZQF4DSJQUͷ੩తܕݕࠪʹ׆༻Node.js ͷ gRPC ։ൃڥ/PEFKT#''(SBQI2-H31$)551#SPXTFS import {UserServiceClient,IUserServiceClient,} from "@wantedly_private/apis-node/path/to/users_pb";import { serviceClientCreator } from "../../utils/grpc/";export class UserService extends serviceClientCreator(UserServiceClient,“127.0.0.1:3000”,) {}
©2020 Wantedly, Inc.֤ݴޠͰ gRPC ։ൃڥΛ͑ͨ
©2020 Wantedly, Inc.લఏ: ։ൃνʔϜʹ gRPC ͷར༻Λڧ੍ग़དྷͳ͍w ։ൃνʔϜͦΕͧΕ͕ʮࣗͨͪͷ࠾༻͢Δٕज़ελοΫʯΛબఆ3-2. ࣾએ͍ͯ͛ͯ͘͠Infra (k8s, gRPC, etc.)։ൃνʔϜ Aw ج൫ΛUPPMMJCSBSZͱͯ͠ఏڙw LTͷ֦ுʢFHDVTUPNDPOUSPMMFSʣw ϓϩμΫτΛ։ൃw ࣗͨͪͰٕज़બఆ։ൃνʔϜ B։ൃνʔϜ C
©2020 Wantedly, Inc.Ξϓϩʔν: ϝϦοτΛૌٻͭͭࣾ͠ษڧձw ʮH31$ͰύϑΥʔϚϯεվળͨ͠ྫʯΛఆظతʹࣾͰએͯ͠ϝϦοτΛૌٻw ʮࣾษڧձʯΛ։࠵ͯ͠ɺH31$TFSWFSDMJFOU։ൃͷࣝΛਁಁ3-2. ࣾએ͍ͯ͛ͯ͘͠
©2020 Wantedly, Inc.ΞϓϦέʔγϣϯίʔυॻ͖͑Λੵۃతʹࢧԉw H31$ͷར༻ྫΛ૿͍ͯ͘͜͠ͱͰɺH31$ར༻ͷٕज़త৺ཧతϋʔυϧΛԼ͛Δ3-2. ࣾએ͍ͯ͛ͯ͘͠
©2020 Wantedly, Inc.ϝϦοτૌٻɺࣾษڧձɺಓͳίʔυมߋΛ௨ͯ͠ঃʑʹࣾʹ gRPC Λ͍͛ͯͬͨ
©2020 Wantedly, Inc.gRPC ΛࣾʹΊΔऔΓΈͷ݁Ռʁ
©2020 Wantedly, Inc.gRPC ͕ࣾͰ͘ར༻͞ΕΔΑ͏ʹͳͬͨ w ΞΫςΟϒʹ։ൃ͞Ε͍ͯΔओཁͳϚΠΫϩαʔϏε͕H31$Խw ৽نͷϚΠΫϩαʔϏε։ൃʹ΄΅H31$Λར༻w όοΫΤϯυ։ൃऀͷׂ͕H31$Λར༻ͨ͠։ൃΛܦݧgRPC ΛࣾʹΊΔऔΓΈͷ݁Ռ)551H31$ϢʔβʔαʔϏε$PSF4FSWJDFT
©2020 Wantedly, Inc.ࣾͷ։ൃऀ͔Βتͼͷฉ͍ͨw lH31$͔ͳΓ։ൃମݧ͕ྑ͔ͬͨzͱ͍͏͕ಧ͍ͨgRPC ΛࣾʹΊΔऔΓΈͷ݁Ռ
©2020 Wantedly, Inc.gRPC ͕ࣾελϯμʔυͱݴ͑Δͱ͜Ζ·Ͱ·ͬͨ
©2020 Wantedly, Inc.ͦͷ݁Ռ͞Βʹɻɻɻ
©2020 Wantedly, Inc.ϚΠΫϩαʔϏεͷύϑΥʔϚϯε͕վળग़དྷͨw H31$͕͘ར༻͞ΕΔΑ͏ʹͳͬͨࣄͰɺଟ͘ͷFOEQPJOUͰԸܙΛड͚ΔΑ͏ʹͳͬͨProtocol Buffers Λར༻ͨ͠։ൃ͕͕ͬͨw H31$͕·ͬͨ݁Ռɺଟ͘ͷ։ൃऀ͕1SPUPDPM#V⒎FSTΛར༻͢ΔΑ͏ʹͳͬͨεΩʔϚۦಈ։ൃͷԸܙΛड͚ΒΕΔػձ͕૿͑ͨgRPC ͕·ͬͨ݁Ռ
©2020 Wantedly, Inc.৫શମͱͯ͠ gRPC ͷԸܙΛड͚ΒΕΔΑ͏ʹͳͬͨ
©2020 Wantedly, Inc.·ͱΊ
©2020 Wantedly, Inc.ύϑΥʔϚϯε։ൃੜ࢈ੑͷ؍Ͱ gRPC ʹணw ՝)551ͷ௨৴MBUFODZw ՝1SPUPDPM#V⒎FSTʹΑΔ։ൃੜ࢈ੑ্ͷԸܙ͕Ұ෦νʔϜʹݶఆૉૣ͘ಋೖ͠։ൃڥඋΛߦ্ͬͨͰར༻Λ͛ͨw Ұ෦ͷϚΠΫϩαʔϏεͰH31$Λૉૣ͘ݕূɾಋೖw ϝϦοτૌٻࣾษڧձͱͱʹಓʹίʔυΛมߋ͠ɺࣾʹΊͨͦͷ݁Ռ gRPC ͘ΘΕΔΑ͏ʹͳͬͨw ଟͷϚΠΫϩαʔϏεͰH31$͕ར༻͞ΕͯύϑΥʔϚϯε͕վળw ଟͷ։ൃऀ͕H31$Λར༻͢ΔࣄͰɺ৫શମͱͯ͠։ൃੜ࢈ੑ্͕·ͱΊ
©2020 Wantedly, Inc.• Chris Briggs https://unsplash.com/photos/V72Hk6LjjjIPhoto Credit