ããã«ã¡ã¯ãéçºæ¬éšã®é«äºã§ããã¡ãã¬ãŒéçºæ¬éšã§è¡ãããŠããå匷äŒãTechLunchãã§ React Native ã«ã€ããŠçºè¡šããŸããã ç§ã¯æ®æ®µã¯ SwiftãKotlin/Java ã䜿ã£ãŠãã€ãã£ãã¢ããªãéçºããŠãããReact Native ã«è§Šãã®ã¯åããŠã§ãããããã§ä»åã¯ãã¢ããªãšã³ãžãã¢ã®èŠç¹ãããå®è£
ããããã®åºæ¬çãªç¥èãšåŒç€Ÿã®å®éã®éçºã§äœ¿ãããããæ€èšããçµæã«ã€ããŠã玹ä»ããŸãã ãªã React Native ãè§Šã£ãŠã¿ãããšæã£ãã ãªã³ã©ã€ã³èšºçã¢ããªã CLINICS ãã®éçºã§ã¯ãiOS/Android ã¢ããªãããããã®ãã€ãã£ãèšèªã§å¥ã
ã«éçºããŠãããããå®è£
ãã¬ãã¥ãŒã®éã«ã¯ãã©ãããã©ãŒã éã®ä»æ§ã®éããçè§£ããå¿
èŠãããããªããªã倧å€ã ãšæããŠããŸããã ãããã®èª²é¡ã«å¯Ÿã㊠ãã¡ã ã®ããã°ã§ã玹ä»ãããããªæœçãè¡ã£ãŠæ¹åãè¡ã£ãŠããŸãããããœãŒã¹ãå
±éåããããšã§ããéçºå¹çãåäžã§ããªãããšæããã¯ãã¹ãã©ãããã©ãŒã éçºã«ã€ããŠã調ã¹ãŠã¿ãããšã«ããŸããã ãã®äžã§ã以äžã®çç±ãããä»å㯠React Native ã«ã€ããŠèª¿ã¹ãŠã¿ãããšã«ããŸããã JavaScriptïŒä»¥äž JSïŒã» React ã®ãããWeb ãšã³ãžãã¢ããã€ãã£ãã¢ããªéçºãè¡ãéã®ããŒãã«ãäœãããããšãã§ããã UI ã®å®è£
ã«ãã€ãã£ã UI ã䜿çšããŠããã®ã§èªç¶ãªãã¶ã€ã³ãã€ã³ã¿ã©ã¯ã·ã§ã³ãäœããããã ããçšåºŠãªãªãŒã¹ããæéãçµã£ãŠæ
å ±ãè±å¯ã«ãã ç¹ã«åŒç€Ÿã§ã¯ããã€ãã£ãã¢ããªãã Web éçºãã¡ã€ã³ã«è¡ã£ãŠãããšã³ãžãã¢ã®æ¹ãå€ãããŸã Web ããã³ãã« React ã䜿ãããŠãããããã¯ããããã€ãããã®ã§ãReact Native ãæ¡çšããããšã§ããŒã ã®éçºå¹çã®åäžã ãã§ãªããéçºæ¬éšå
šäœã§ããã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäœããªãã®ã§ã¯ãªãããšèããŸããã ããã§ã以éã§ã¯ãã€ãã£ãã¢ããªãšã³ãžãã¢ãš Web ãšã³ãžãã¢ããããã«ãšã£ãŠãéçºãããããã©ãããšãã芳ç¹ã§ React Native ã®éçºæ¹æ³ãèŠãŠãããããšæããŸãã åæèšå®ã«ã€ã㊠ã€ã³ã¹ããŒã«ãã¢ããªå®è¡ ã€ã³ã¹ããŒã«ã¯å
¬åŒã® Getting Started ã«ããããŸããã以äžã®ã³ãã³ãã§å®äºã§ãã $ brew install node $ brew install watchman $ npm install -g react-native-cli ä»åãç§ãè§Šãã«ããã£ãŠã¯ Xcode ãš Android Studio ã®ã·ãã¥ã¬ãŒã¿ïŒãšãã¥ã¬ãŒã¿ïŒã§å®è¡ããªããéçºããŸããããReact Native 㯠Xcode ã Android Studio ãã€ã³ã¹ããŒã«ãããŠããªããŠãã Expo ãšããã¯ã©ã€ã¢ã³ãã¢ããªã宿©ã«ã€ã³ã¹ããŒã«ããããšã§ç»é¢ããã¬ãã¥ãŒããªããéçºããããšãã§ããŸãã ãããªããXcode ã®ããŠã³ããŒããåŸ
ã€å¿
èŠããããŸããïŒïŒiOS ãšã³ãžãã¢ã§ãã¢ããã°ã¬ãŒãã®ãã³ã« Xcode ã®ããŠã³ããŒããåŸ
ã€ã®ã¯ã€ã©ã€ã©ããŸãïŒ æ¬¡ã«ããããžã§ã¯ãäœæãã·ãã¥ã¬ãŒã¿ã§ã®ã¢ããªå®è¡ã¯ä»¥äžã®ã³ãã³ãã§å®è¡ã§ããŸãã ãã ããã·ãã¥ã¬ãŒã¿å®è¡åã« Xcode Command Line Tools ã®ã€ã³ã¹ããŒã«ãš Android Studio ã§ããã€ãã®èšå®ïŒSDK ã®ã€ã³ã¹ããŒã«ãAVD ã®äœæãç°å¢å€æ°ã®èšå®ïŒãå¿
èŠã§ãã # ãããžã§ã¯ãäœæ $ react-native init AwesomeProject  # ã¢ããªå®è¡ïŒã·ãã¥ã¬ãŒã¿ïŒ $ cd AwesomeProject $ react-native run-ios or react-native run-android # Android ã®å Žåãemulator ãå¥éèµ·åããŠããã§ãªããšå®è¡ã§ããªã å®è£
ããŠã¿ãææ³ UI ã®å®è£
æ¹æ³ React Native ã§ã¯ React åæ§ UI ã®åããŒããã³ã³ããŒãã³ããšåŒã³ãããããé
眮ããããšã§ UI ãå®è£
ããŠãããŸããéã㯠Web ã® HTML ã®ä»£ããã« Native ã® UI ãæç»ããããã®ã³ã³ããŒãã³ããšããŠäœ¿ãç¹ã§ãã èŠãç®ãã¬ã€ã¢ãŠã㯠CSS ãšäŒŒããããªåœ¢åŒã§èšè¿°ããŸããReact Native ã§äœ¿ããã¹ã¿ã€ã«ã®ããããã£ã¯åã³ã³ããŒãã³ãã§ç°ãªããŸãããäŸãã°ãView ã³ã³ããŒãã³ãã«èšå®ã§ããããããã£ã«ã¯ä»¥äžã®ãããªãã®ããããŸãã View Style Props Layout Props Web ã§äœ¿ãããŠãããã®ãšå
šãåããšããããã§ã¯ãªãã§ãããflexãmarginãborder ãªã©ã®äœ¿ãæ
£ããŠãã CSS ã®ããããã£åã§èšå®ã§ããã®ã§ãWeb ãšã³ãžãã¢ã«ãšã£ãŠã¯å®è£
ã®ããŒãã«ãäžããã®ã§ã¯ãªãããšæããŸããããã ãæ®æ®µ CSS ãè§Šã£ãŠããªããã€ãã£ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯åŠç¿ã³ã¹ããããããšæããŸãã ãŸãäžåºŠãã«ãããã°ãJS ã«ããä¿®æ£å
容ããã«ããªãã§ã·ãã¥ã¬ãŒã¿ã«åæ ããããšãã§ããã®ã§ãView åšãã®èª¿æŽã¯å¹ççã«ã§ãããã§ããã // js/components/home.js const renderItem = ({ item , index }) => ( < View style = { styles . row } > < Text style = { styles . title } >        { parseInt ( index , 10 ) + 1 }        { ". " }        { item . title } </ Text >      < Text style = { styles . description } > { item . description } </ Text > </ View > ); const styles = StyleSheet . create ({ row: { borderBottomWidth: 1 , borderColor: "#ccc" , padding: 10 , }, title: { fontSize: 15 , fontWeight: "600" , }, description: { marginTop: 5 , fontSize: 14 , }, }); ãã ãOS ããšã«ãããµãã€ã³ãåãããæ¹éã«ããªãéãã¯ãã³ãŒããå¥ã
ã«ãªããšããããããšå€ããªãããã ãšæããŸããã äŸãã°ãTabBar(iOS)ãš DrawerLayout(Android)ãDatePicker(iOS)ãš TimePicker(Android)ãProgressView(iOS)ãš ProgressBar(Android)ãªã©ã¯ React Native ã§ã¯å¥ã³ã³ããŒãã³ããšããŠæäŸãããŠããŠãAPI ãéã£ãŠããŸããã ç»é¢é·ç§» ç»é¢é·ç§»ïŒããã·ã¥ãã¢ãŒãã«ãã¿ãé·ç§»ãªã©ïŒã®ããã« API ãšããŠå
¬åŒã§æäŸãããŠããã®ã¯ iOS ã®ã¿ã§ Android ã¯å¥éãå®è£
ãããããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿çšããå¿
èŠããããŸãã ãããã䜿ã£ãŠã¿ã react-native-navigation ã¯ã¢ãŒãã«ãããã·ã¥ãªã©ã®é·ç§»ããã€ãã£ã API ããŒã¹ã§å®è£
ãããŠããã®ã§ããã€ãã£ãèšèªã§å®è£
ããå Žåãšæ¯ã¹ãŠéåæãªãå®è£
ããããšãã§ããŸããã äžèšã®ãããªåœ¢ã§ããã·ã¥ãã¢ãŒãã«è¡šç€ºã§ã®é·ç§»ãã§ããŸããç¹å®ã®ç»é¢ã«æ»ãæ©èœã«ã€ããŠã¯éçºäžã§ãã£ãããæ©èœçãªå¶çŽã¯å°ãããããã§ãããããã现ãããšããã¯ãã€ãã£ãèšèªã§ãã£ãæ¹ãèªç±ãå¹ãã®ã§ãè¯ããªãšæããŸãã ããã§ããiOS ãš Android ã§ã¯è€æ°ç»é¢ã®ç®¡çãé·ç§»ã«ã€ããŠã®èãæ¹ãéããAndroid ãåããŠéçºããæã«åãããšãå®çŸããã®ãé£ããã£ãèŠããããã®ã§ãå
±éã®æ¹æ³ã§å®çŸã§ããã®ã¯äŸ¿å©ã§ãããç¹ã« Web ã ãšããŸãç»é¢éã®é·ç§»ã«ã€ããŠèããããšã¯ãªããšæãã®ã§ãå
±éåãããŠãããšãã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäžãããšæããŸãã this . props . navigator . push ({ // ããã·ã¥ screen: "example.PushedScreen" , title: "Pushed Screen" , }); this . props . navigator . pop ({ // åã®ç»é¢ã«æ»ã animated: true , animationType: "fade" , }); this . props . navigator . showModal ({ // ã¢ãŒãã« screen: "example.ModalScreen" , title: "Modal" , animationType: "slide-up" , }); ãããã¯ãŒã¯åšã ãããã¯ãŒã¯çµç±ã§ããŒã¿ãååŸããŠãã¢ãã«ã«å€æããã¢ããªå
ã§äœ¿ããšããããããæäœãè¡ãã«ã¯ Fetch API ãå©çšããŸãã Fetch API 㯠JS ã§æäŸãããŠãã Promise ããŒã¹ã® API ã§ããäŸãã°ã以äžã®ãããªåœ¢ã§ JSON ãè¿ã API ããããŒã¿ãååŸãã receiveHelthNews 颿°ã«ãªããžã§ã¯ãã«å€æããé
åãæž¡ãããšãã§ããŸããJS ã® API ãªã®ã§ Web ãšã³ãžãã¢ã«ãšã£ãŠã¯äœ¿ããããã®ã§ã¯ãªãããšæããŸãã ãã€ãã£ãèšèªã§ããããå®è£
ããå Žåã¯ãURLSession(iOS)ãš HttpURLConnection(Android)ããããã¯åãã©ãããã©ãŒã åãã«æäŸãããŠãããµãŒãããŒãã£ã®ã©ã€ãã©ãªãªã©ã䜿ããšæããŸãããåœç¶ãAPI ã¯ç°ãªãã®ã§ããããã®å®è£
æ¹æ³ãææ¡ããªããšãããªããªããŸããããã«æ¯ã¹ããšåŠç¿ã³ã¹ãã¯äœããªãããã§ãã // js/actions/index.js export function fetchHelthNews () { return ( dispatch ) => fetch ( constructHealthNewsUrl ()) . then (( response ) => response . json ()) . then (( json ) => dispatch ( receiveHelthNews ( json . articles ))) . catch (( error ) => { console . log ( error ); }); } ãã€ãã£ãã¢ããªç¹æã®æ©èœã«ã€ã㊠ãã®ä»ã®ã¢ããªéçºã§ãã䜿ããã€ãã£ãã¢ããªç¹æã®æ©èœãå®è£
ããæ¹æ³ã¯ä»¥äžã®ããã«ãªããŸããå€ãã®æ©èœããµãŒãããŒãã£ã®ã©ã€ãã©ãªã«äŸåããŠããã®ã§ãåèšèªã®ããŒãžã§ã³ã¢ããæã®å¯Ÿå¿ãå°ãå¿é
ã§ã¯ãããŸãããããäœ¿ãæ©èœã«ã€ããŠã¯å®çŸããããšãã§ããŸãã Push éç¥ïŒAndroid ã¯ãã³ããªã³ã°ãã API ãå
¬åŒã§æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã ã«ã¡ã©ãããŒãã§ãŒã³ã¢ã¯ã»ã¹/ãŠãŒã¶ããã©ã«ãïŒå
¬åŒã® API ã¯æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã äœçœ®æ
å ±ã®ååŸïŒå
¬åŒ API ãæäŸãããŠãã ãã£ãŒããªã³ã¯ïŒã¢ããªèµ·åæã«ãã³ããªã³ã°ãè¡ã API ã¯æäŸãããŠããããŠãããŒãµã«ãªã³ã¯ã IntentFilter ã®èšå®ã¯åãã©ãããã©ãŒã ã§åå¥ã«å¿
èŠã«ãªã ãªãªãŒã¹ã¯ã©ãããã ã¢ãŒã«ã€ããã¹ãã¢é
åžã«ã€ããŠã¯ãã€ãã£ãã¢ããªã®é
åžãšåãããã»ã¹ã«ãªããŸãã åãã©ãããã©ãŒã ã§èšŒææžçã®èšå®ãè¡ããXcode ã Android Studioãããã㯠CLI ã§ã³ãã³ããå®è¡ããŠãipa / apk ãã¡ã€ã«ãäœæããå Store ã«ã¢ããããŒãããå¿
èŠããããŸãã CI 㯠Bitrise ãªã©ã䜿ããŸããBitrise ã§ãã«ãã詊ããŠã¿ãŸããããReact Native ã®ãªããžããªãšæ¥ç¶ãããšãã«ã§ããããã©ã«ãã®ã¯ãŒã¯ãããŒã䜿ãã°ãåæã« 2 ãã©ãããã©ãŒã ã®ã¢ãŒã«ã€ããäœæã§ããŠäŸ¿å©ã§ããã ããšããŸã 詊ããŠã¯ããªãã®ã§ãã CodePush ã䜿ãã°ã審æ»ã«æåºããããšãªãã«æ¢åã®ã¢ããªã倿Žããããšãã§ãããããã®ã§ãéåžžã«äŸ¿å©ã ãšæããŸããã ã©ããªå Žåã« React Native ãæ¡çšã§ãããã? React Native ã§éçºããããšã§ãWeb éçºè
ã®èŠç¹ã§èŠããšãã©ãããã©ãŒã ã®ãã€ãã£ãèšèªã§éçºããããããã ãã¶åŠç¿ã³ã¹ããäžããã®ã§ã¯ãªãããšæããŸããããŸããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ãã°ãæ©èœçã«å€§ããªåé¡ãšãªããããªããšã¯ãªãããã§ããããã ãç»é¢é·ç§»ã®ã©ã€ãã©ãªãããã ã£ãããã«ãããããããããšãã§ããªããšããå Žåã¯ã劥åããªããšãããªãéšåãåºãŠãããã ãšæããŸããã äžæ¹ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ãæ
£ãããŸã§ã¯ããªãéçºé床ãäžãããããªã®ã§ãã¡ãªããã倧ããããªãšæããŸãããReact ãš JSããŸã Redux ãªã©ãæ°ãã«çè§£ãã€ã€éçºããŠããã®ã§çµæ§ããŒãã«ãé«ããšæããŸãããéçºç°å¢ããã«ããéã£ãŠããã¡ã¯ãView åšãã®èª¿æŽãããã«ç¢ºèªã§ããŠè¯ãã£ãã®ã§ãããã©ã³ã¿ã€ã ãšã©ãŒã«ãªããªã©ã§ãã·ãã¥ã¬ãŒã¿ããªããŒãã§ããªããªã£ãå Žåã«å床ãã«ããçŽããšããããšãããèµ·ãããåžžã«å¿«é©ã«éçºã§ãããšããããã§ã¯ãããŸããã§ããã éçšé¢ã§ã¿ããšäžéãã¢ãããªéçºã«å¿
èŠãããªããŒã«ã¯æã£ãŠããã(ã¯ã©ãã·ã¥ç£èŠãCIããã¹ãé
ä¿¡ããªãªãŒã¹)ãCode Push ãªã©äŸ¿å©ãªããŒã«ãããã®ã§å©ç¹ãå€ããšæããŸããã çµè«ãšããŠã¯ãWeb ãšã³ãžãã¢ã瀟å
ã«å€ãã£ãããéçºããŒã ã« ReactãJS ãåŸæãªã¡ã³ããŒããããªããå®éã®éçºã§ã䜿ããããªãšæããŸããããã ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ããªãã¹ãã¬ã¹ãããŸããããžã§ã¯ãã«ãªãããã ãšæããŸããã ãŸãšã èªåã®çŸç¶ã§èãããšãã¢ããªã¯åŸæã ãã© JS ã React ã«ãããŸã§è©³ãããªãã®ã§ãããçŽè¿ã®ãããžã§ã¯ãã§é£æåºŠãããããé«ãããã§ããã°ãæ£çŽãããŸã䜿ããããªããªããšããæ°æã¡ããããŸãããã ãæè¡ã®å¹
ãåºãããšããçµç¹å
šäœã®ããŒã¿ããªãã£ãªã©ã®èгç¹ã§èãããšå©ç¹ãçµæ§ããã®ããªãšæããŸãããã£ã³ã¹ãããã°ãã²ããã£ã¬ã³ãžããŠã¿ããã§ãã ãããã¯ã©ã¡ãããšãããšæè¡ãéçºããŒã«ã®æ°ãããããããŠãŒã¶ãšã®æ¥ç¹ã®ãšããã§æ°ããããšãé¢çœãããšã远æ±ããããšæã£ãŠããŸãããéçºå¹çãå質ã®åäžã®ããã«æé©ãªãã®ãéžæã§ããããã«ãä»åŸãæ°ããããŒã«ã®ãã£ããã¢ããã¯ç©æ¥µçã«è¡ã£ãŠãããããšæã£ãŠããŸãã ãç¥ãã ã¡ãã¬ãŒã¯ã5/31-6/2 ã«éå¬ããã RubyKaigi 2018 ã« LT ã¹ãã³ãµãŒãšããŠåè³ããŸããããŒã¹ãæ§ããŠãããŸãã®ã§ãã€ãã³ãã«ãè¶ãã«ãªãæ¹ã¯ããã²ããŒã¹ã«ãéã³ã«ããããŠãã ããïŒ RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®é«äºã§ããã¡ãã¬ãŒéçºæ¬éšã§è¡ãããŠããå匷äŒãTechLunchãã§ React Native ã«ã€ããŠçºè¡šããŸããã ç§ã¯æ®æ®µã¯ SwiftãKotlin/Java ã䜿ã£ãŠãã€ãã£ãã¢ããªãéçºããŠãããReact Native ã«è§Šãã®ã¯åããŠã§ãããããã§ä»åã¯ãã¢ããªãšã³ãžãã¢ã®èŠç¹ãããå®è£
ããããã®åºæ¬çãªç¥èãšåŒç€Ÿã®å®éã®éçºã§äœ¿ãããããæ€èšããçµæã«ã€ããŠã玹ä»ããŸãã ãªã React Native ãè§Šã£ãŠã¿ãããšæã£ãã ãªã³ã©ã€ã³èšºçã¢ããªã CLINICS ãã®éçºã§ã¯ãiOS/Android ã¢ããªãããããã®ãã€ãã£ãèšèªã§å¥ã
ã«éçºããŠãããããå®è£
ãã¬ãã¥ãŒã®éã«ã¯ãã©ãããã©ãŒã éã®ä»æ§ã®éããçè§£ããå¿
èŠãããããªããªã倧å€ã ãšæããŠããŸããã ãããã®èª²é¡ã«å¯Ÿã㊠ãã¡ã ã®ããã°ã§ã玹ä»ãããããªæœçãè¡ã£ãŠæ¹åãè¡ã£ãŠããŸãããããœãŒã¹ãå
±éåããããšã§ããéçºå¹çãåäžã§ããªãããšæããã¯ãã¹ãã©ãããã©ãŒã éçºã«ã€ããŠã調ã¹ãŠã¿ãããšã«ããŸããã ãã®äžã§ã以äžã®çç±ãããä»å㯠React Native ã«ã€ããŠèª¿ã¹ãŠã¿ãããšã«ããŸããã JavaScriptïŒä»¥äž JSïŒã» React ã®ãããWeb ãšã³ãžãã¢ããã€ãã£ãã¢ããªéçºãè¡ãéã®ããŒãã«ãäœãããããšãã§ããã UI ã®å®è£
ã«ãã€ãã£ã UI ã䜿çšããŠããã®ã§èªç¶ãªãã¶ã€ã³ãã€ã³ã¿ã©ã¯ã·ã§ã³ãäœããããã ããçšåºŠãªãªãŒã¹ããæéãçµã£ãŠæ
å ±ãè±å¯ã«ãã ç¹ã«åŒç€Ÿã§ã¯ããã€ãã£ãã¢ããªãã Web éçºãã¡ã€ã³ã«è¡ã£ãŠãããšã³ãžãã¢ã®æ¹ãå€ãããŸã Web ããã³ãã« React ã䜿ãããŠãããããã¯ããããã€ãããã®ã§ãReact Native ãæ¡çšããããšã§ããŒã ã®éçºå¹çã®åäžã ãã§ãªããéçºæ¬éšå
šäœã§ããã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäœããªãã®ã§ã¯ãªãããšèããŸããã ããã§ã以éã§ã¯ãã€ãã£ãã¢ããªãšã³ãžãã¢ãš Web ãšã³ãžãã¢ããããã«ãšã£ãŠãéçºãããããã©ãããšãã芳ç¹ã§ React Native ã®éçºæ¹æ³ãèŠãŠãããããšæããŸãã åæèšå®ã«ã€ã㊠ã€ã³ã¹ããŒã«ãã¢ããªå®è¡ ã€ã³ã¹ããŒã«ã¯å
¬åŒã® Getting Started ã«ããããŸããã以äžã®ã³ãã³ãã§å®äºã§ãã $ brew install node $ brew install watchman $ npm install -g react-native-cli ä»åãç§ãè§Šãã«ããã£ãŠã¯ Xcode ãš Android Studio ã®ã·ãã¥ã¬ãŒã¿ïŒãšãã¥ã¬ãŒã¿ïŒã§å®è¡ããªããéçºããŸããããReact Native 㯠Xcode ã Android Studio ãã€ã³ã¹ããŒã«ãããŠããªããŠãã Expo ãšããã¯ã©ã€ã¢ã³ãã¢ããªã宿©ã«ã€ã³ã¹ããŒã«ããããšã§ç»é¢ããã¬ãã¥ãŒããªããéçºããããšãã§ããŸãã ãããªããXcode ã®ããŠã³ããŒããåŸ
ã€å¿
èŠããããŸããïŒïŒiOS ãšã³ãžãã¢ã§ãã¢ããã°ã¬ãŒãã®ãã³ã« Xcode ã®ããŠã³ããŒããåŸ
ã€ã®ã¯ã€ã©ã€ã©ããŸãïŒ æ¬¡ã«ããããžã§ã¯ãäœæãã·ãã¥ã¬ãŒã¿ã§ã®ã¢ããªå®è¡ã¯ä»¥äžã®ã³ãã³ãã§å®è¡ã§ããŸãã ãã ããã·ãã¥ã¬ãŒã¿å®è¡åã« Xcode Command Line Tools ã®ã€ã³ã¹ããŒã«ãš Android Studio ã§ããã€ãã®èšå®ïŒSDK ã®ã€ã³ã¹ããŒã«ãAVD ã®äœæãç°å¢å€æ°ã®èšå®ïŒãå¿
èŠã§ãã # ãããžã§ã¯ãäœæ $ react-native init AwesomeProject  # ã¢ããªå®è¡ïŒã·ãã¥ã¬ãŒã¿ïŒ $ cd AwesomeProject $ react-native run-ios or react-native run-android # Android ã®å Žåãemulator ãå¥éèµ·åããŠããã§ãªããšå®è¡ã§ããªã å®è£
ããŠã¿ãææ³ UI ã®å®è£
æ¹æ³ React Native ã§ã¯ React åæ§ UI ã®åããŒããã³ã³ããŒãã³ããšåŒã³ãããããé
眮ããããšã§ UI ãå®è£
ããŠãããŸããéã㯠Web ã® HTML ã®ä»£ããã« Native ã® UI ãæç»ããããã®ã³ã³ããŒãã³ããšããŠäœ¿ãç¹ã§ãã èŠãç®ãã¬ã€ã¢ãŠã㯠CSS ãšäŒŒããããªåœ¢åŒã§èšè¿°ããŸããReact Native ã§äœ¿ããã¹ã¿ã€ã«ã®ããããã£ã¯åã³ã³ããŒãã³ãã§ç°ãªããŸãããäŸãã°ãView ã³ã³ããŒãã³ãã«èšå®ã§ããããããã£ã«ã¯ä»¥äžã®ãããªãã®ããããŸãã View Style Props Layout Props Web ã§äœ¿ãããŠãããã®ãšå
šãåããšããããã§ã¯ãªãã§ãããflexãmarginãborder ãªã©ã®äœ¿ãæ
£ããŠãã CSS ã®ããããã£åã§èšå®ã§ããã®ã§ãWeb ãšã³ãžãã¢ã«ãšã£ãŠã¯å®è£
ã®ããŒãã«ãäžããã®ã§ã¯ãªãããšæããŸããããã ãæ®æ®µ CSS ãè§Šã£ãŠããªããã€ãã£ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯åŠç¿ã³ã¹ããããããšæããŸãã ãŸãäžåºŠãã«ãããã°ãJS ã«ããä¿®æ£å
容ããã«ããªãã§ã·ãã¥ã¬ãŒã¿ã«åæ ããããšãã§ããã®ã§ãView åšãã®èª¿æŽã¯å¹ççã«ã§ãããã§ããã // js/components/home.js const renderItem = ({ item , index }) => ( < View style = { styles . row } > < Text style = { styles . title } >        { parseInt ( index , 10 ) + 1 }        { ". " }        { item . title } </ Text >      < Text style = { styles . description } > { item . description } </ Text > </ View > ); const styles = StyleSheet . create ({ row: { borderBottomWidth: 1 , borderColor: "#ccc" , padding: 10 , }, title: { fontSize: 15 , fontWeight: "600" , }, description: { marginTop: 5 , fontSize: 14 , }, }); ãã ãOS ããšã«ãããµãã€ã³ãåãããæ¹éã«ããªãéãã¯ãã³ãŒããå¥ã
ã«ãªããšããããããšå€ããªãããã ãšæããŸããã äŸãã°ãTabBar(iOS)ãš DrawerLayout(Android)ãDatePicker(iOS)ãš TimePicker(Android)ãProgressView(iOS)ãš ProgressBar(Android)ãªã©ã¯ React Native ã§ã¯å¥ã³ã³ããŒãã³ããšããŠæäŸãããŠããŠãAPI ãéã£ãŠããŸããã ç»é¢é·ç§» ç»é¢é·ç§»ïŒããã·ã¥ãã¢ãŒãã«ãã¿ãé·ç§»ãªã©ïŒã®ããã« API ãšããŠå
¬åŒã§æäŸãããŠããã®ã¯ iOS ã®ã¿ã§ Android ã¯å¥éãå®è£
ãããããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿çšããå¿
èŠããããŸãã ãããã䜿ã£ãŠã¿ã react-native-navigation ã¯ã¢ãŒãã«ãããã·ã¥ãªã©ã®é·ç§»ããã€ãã£ã API ããŒã¹ã§å®è£
ãããŠããã®ã§ããã€ãã£ãèšèªã§å®è£
ããå Žåãšæ¯ã¹ãŠéåæãªãå®è£
ããããšãã§ããŸããã äžèšã®ãããªåœ¢ã§ããã·ã¥ãã¢ãŒãã«è¡šç€ºã§ã®é·ç§»ãã§ããŸããç¹å®ã®ç»é¢ã«æ»ãæ©èœã«ã€ããŠã¯éçºäžã§ãã£ãããæ©èœçãªå¶çŽã¯å°ãããããã§ãããããã现ãããšããã¯ãã€ãã£ãèšèªã§ãã£ãæ¹ãèªç±ãå¹ãã®ã§ãè¯ããªãšæããŸãã ããã§ããiOS ãš Android ã§ã¯è€æ°ç»é¢ã®ç®¡çãé·ç§»ã«ã€ããŠã®èãæ¹ãéããAndroid ãåããŠéçºããæã«åãããšãå®çŸããã®ãé£ããã£ãèŠããããã®ã§ãå
±éã®æ¹æ³ã§å®çŸã§ããã®ã¯äŸ¿å©ã§ãããç¹ã« Web ã ãšããŸãç»é¢éã®é·ç§»ã«ã€ããŠèããããšã¯ãªããšæãã®ã§ãå
±éåãããŠãããšãã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäžãããšæããŸãã this . props . navigator . push ({ // ããã·ã¥ screen: "example.PushedScreen" , title: "Pushed Screen" , }); this . props . navigator . pop ({ // åã®ç»é¢ã«æ»ã animated: true , animationType: "fade" , }); this . props . navigator . showModal ({ // ã¢ãŒãã« screen: "example.ModalScreen" , title: "Modal" , animationType: "slide-up" , }); ãããã¯ãŒã¯åšã ãããã¯ãŒã¯çµç±ã§ããŒã¿ãååŸããŠãã¢ãã«ã«å€æããã¢ããªå
ã§äœ¿ããšããããããæäœãè¡ãã«ã¯ Fetch API ãå©çšããŸãã Fetch API 㯠JS ã§æäŸãããŠãã Promise ããŒã¹ã® API ã§ããäŸãã°ã以äžã®ãããªåœ¢ã§ JSON ãè¿ã API ããããŒã¿ãååŸãã receiveHelthNews 颿°ã«ãªããžã§ã¯ãã«å€æããé
åãæž¡ãããšãã§ããŸããJS ã® API ãªã®ã§ Web ãšã³ãžãã¢ã«ãšã£ãŠã¯äœ¿ããããã®ã§ã¯ãªãããšæããŸãã ãã€ãã£ãèšèªã§ããããå®è£
ããå Žåã¯ãURLSession(iOS)ãš HttpURLConnection(Android)ããããã¯åãã©ãããã©ãŒã åãã«æäŸãããŠãããµãŒãããŒãã£ã®ã©ã€ãã©ãªãªã©ã䜿ããšæããŸãããåœç¶ãAPI ã¯ç°ãªãã®ã§ããããã®å®è£
æ¹æ³ãææ¡ããªããšãããªããªããŸããããã«æ¯ã¹ããšåŠç¿ã³ã¹ãã¯äœããªãããã§ãã // js/actions/index.js export function fetchHelthNews () { return ( dispatch ) => fetch ( constructHealthNewsUrl ()) . then (( response ) => response . json ()) . then (( json ) => dispatch ( receiveHelthNews ( json . articles ))) . catch (( error ) => { console . log ( error ); }); } ãã€ãã£ãã¢ããªç¹æã®æ©èœã«ã€ã㊠ãã®ä»ã®ã¢ããªéçºã§ãã䜿ããã€ãã£ãã¢ããªç¹æã®æ©èœãå®è£
ããæ¹æ³ã¯ä»¥äžã®ããã«ãªããŸããå€ãã®æ©èœããµãŒãããŒãã£ã®ã©ã€ãã©ãªã«äŸåããŠããã®ã§ãåèšèªã®ããŒãžã§ã³ã¢ããæã®å¯Ÿå¿ãå°ãå¿é
ã§ã¯ãããŸãããããäœ¿ãæ©èœã«ã€ããŠã¯å®çŸããããšãã§ããŸãã Push éç¥ïŒAndroid ã¯ãã³ããªã³ã°ãã API ãå
¬åŒã§æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã ã«ã¡ã©ãããŒãã§ãŒã³ã¢ã¯ã»ã¹/ãŠãŒã¶ããã©ã«ãïŒå
¬åŒã® API ã¯æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã äœçœ®æ
å ±ã®ååŸïŒå
¬åŒ API ãæäŸãããŠãã ãã£ãŒããªã³ã¯ïŒã¢ããªèµ·åæã«ãã³ããªã³ã°ãè¡ã API ã¯æäŸãããŠããããŠãããŒãµã«ãªã³ã¯ã IntentFilter ã®èšå®ã¯åãã©ãããã©ãŒã ã§åå¥ã«å¿
èŠã«ãªã ãªãªãŒã¹ã¯ã©ãããã ã¢ãŒã«ã€ããã¹ãã¢é
åžã«ã€ããŠã¯ãã€ãã£ãã¢ããªã®é
åžãšåãããã»ã¹ã«ãªããŸãã åãã©ãããã©ãŒã ã§èšŒææžçã®èšå®ãè¡ããXcode ã Android Studioãããã㯠CLI ã§ã³ãã³ããå®è¡ããŠãipa / apk ãã¡ã€ã«ãäœæããå Store ã«ã¢ããããŒãããå¿
èŠããããŸãã CI 㯠Bitrise ãªã©ã䜿ããŸããBitrise ã§ãã«ãã詊ããŠã¿ãŸããããReact Native ã®ãªããžããªãšæ¥ç¶ãããšãã«ã§ããããã©ã«ãã®ã¯ãŒã¯ãããŒã䜿ãã°ãåæã« 2 ãã©ãããã©ãŒã ã®ã¢ãŒã«ã€ããäœæã§ããŠäŸ¿å©ã§ããã ããšããŸã 詊ããŠã¯ããªãã®ã§ãã CodePush ã䜿ãã°ã審æ»ã«æåºããããšãªãã«æ¢åã®ã¢ããªã倿Žããããšãã§ãããããã®ã§ãéåžžã«äŸ¿å©ã ãšæããŸããã ã©ããªå Žåã« React Native ãæ¡çšã§ãããã? React Native ã§éçºããããšã§ãWeb éçºè
ã®èŠç¹ã§èŠããšãã©ãããã©ãŒã ã®ãã€ãã£ãèšèªã§éçºããããããã ãã¶åŠç¿ã³ã¹ããäžããã®ã§ã¯ãªãããšæããŸããããŸããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ãã°ãæ©èœçã«å€§ããªåé¡ãšãªããããªããšã¯ãªãããã§ããããã ãç»é¢é·ç§»ã®ã©ã€ãã©ãªãããã ã£ãããã«ãããããããããšãã§ããªããšããå Žåã¯ã劥åããªããšãããªãéšåãåºãŠãããã ãšæããŸããã äžæ¹ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ãæ
£ãããŸã§ã¯ããªãéçºé床ãäžãããããªã®ã§ãã¡ãªããã倧ããããªãšæããŸãããReact ãš JSããŸã Redux ãªã©ãæ°ãã«çè§£ãã€ã€éçºããŠããã®ã§çµæ§ããŒãã«ãé«ããšæããŸãããéçºç°å¢ããã«ããéã£ãŠããã¡ã¯ãView åšãã®èª¿æŽãããã«ç¢ºèªã§ããŠè¯ãã£ãã®ã§ãããã©ã³ã¿ã€ã ãšã©ãŒã«ãªããªã©ã§ãã·ãã¥ã¬ãŒã¿ããªããŒãã§ããªããªã£ãå Žåã«å床ãã«ããçŽããšããããšãããèµ·ãããåžžã«å¿«é©ã«éçºã§ãããšããããã§ã¯ãããŸããã§ããã éçšé¢ã§ã¿ããšäžéãã¢ãããªéçºã«å¿
èŠãããªããŒã«ã¯æã£ãŠããã(ã¯ã©ãã·ã¥ç£èŠãCIããã¹ãé
ä¿¡ããªãªãŒã¹)ãCode Push ãªã©äŸ¿å©ãªããŒã«ãããã®ã§å©ç¹ãå€ããšæããŸããã çµè«ãšããŠã¯ãWeb ãšã³ãžãã¢ã瀟å
ã«å€ãã£ãããéçºããŒã ã« ReactãJS ãåŸæãªã¡ã³ããŒããããªããå®éã®éçºã§ã䜿ããããªãšæããŸããããã ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ããªãã¹ãã¬ã¹ãããŸããããžã§ã¯ãã«ãªãããã ãšæããŸããã ãŸãšã èªåã®çŸç¶ã§èãããšãã¢ããªã¯åŸæã ãã© JS ã React ã«ãããŸã§è©³ãããªãã®ã§ãããçŽè¿ã®ãããžã§ã¯ãã§é£æåºŠãããããé«ãããã§ããã°ãæ£çŽãããŸã䜿ããããªããªããšããæ°æã¡ããããŸãããã ãæè¡ã®å¹
ãåºãããšããçµç¹å
šäœã®ããŒã¿ããªãã£ãªã©ã®èгç¹ã§èãããšå©ç¹ãçµæ§ããã®ããªãšæããŸãããã£ã³ã¹ãããã°ãã²ããã£ã¬ã³ãžããŠã¿ããã§ãã ãããã¯ã©ã¡ãããšãããšæè¡ãéçºããŒã«ã®æ°ãããããããŠãŒã¶ãšã®æ¥ç¹ã®ãšããã§æ°ããããšãé¢çœãããšã远æ±ããããšæã£ãŠããŸãããéçºå¹çãå質ã®åäžã®ããã«æé©ãªãã®ãéžæã§ããããã«ãä»åŸãæ°ããããŒã«ã®ãã£ããã¢ããã¯ç©æ¥µçã«è¡ã£ãŠãããããšæã£ãŠããŸãã ãç¥ãã ã¡ãã¬ãŒã¯ã5/31-6/2 ã«éå¬ããã RubyKaigi 2018 ã« LT ã¹ãã³ãµãŒãšããŠåè³ããŸããããŒã¹ãæ§ããŠãããŸãã®ã§ãã€ãã³ãã«ãè¶ãã«ãªãæ¹ã¯ããã²ããŒã¹ã«ãéã³ã«ããããŠãã ããïŒ RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®é«äºã§ããã¡ãã¬ãŒéçºæ¬éšã§è¡ãããŠããå匷äŒãTechLunchãã§ React Native ã«ã€ããŠçºè¡šããŸããã ç§ã¯æ®æ®µã¯ SwiftãKotlin/Java ã䜿ã£ãŠãã€ãã£ãã¢ããªãéçºããŠãããReact Native ã«è§Šãã®ã¯åããŠã§ãããããã§ä»åã¯ãã¢ããªãšã³ãžãã¢ã®èŠç¹ãããå®è£
ããããã®åºæ¬çãªç¥èãšåŒç€Ÿã®å®éã®éçºã§äœ¿ãããããæ€èšããçµæã«ã€ããŠã玹ä»ããŸãã ãªã React Native ãè§Šã£ãŠã¿ãããšæã£ãã ãªã³ã©ã€ã³èšºçã¢ããªã CLINICS ãã®éçºã§ã¯ãiOS/Android ã¢ããªãããããã®ãã€ãã£ãèšèªã§å¥ã
ã«éçºããŠãããããå®è£
ãã¬ãã¥ãŒã®éã«ã¯ãã©ãããã©ãŒã éã®ä»æ§ã®éããçè§£ããå¿
èŠãããããªããªã倧å€ã ãšæããŠããŸããã ãããã®èª²é¡ã«å¯Ÿã㊠ãã¡ã ã®ããã°ã§ã玹ä»ãããããªæœçãè¡ã£ãŠæ¹åãè¡ã£ãŠããŸãããããœãŒã¹ãå
±éåããããšã§ããéçºå¹çãåäžã§ããªãããšæããã¯ãã¹ãã©ãããã©ãŒã éçºã«ã€ããŠã調ã¹ãŠã¿ãããšã«ããŸããã ãã®äžã§ã以äžã®çç±ãããä»å㯠React Native ã«ã€ããŠèª¿ã¹ãŠã¿ãããšã«ããŸããã JavaScriptïŒä»¥äž JSïŒã» React ã®ãããWeb ãšã³ãžãã¢ããã€ãã£ãã¢ããªéçºãè¡ãéã®ããŒãã«ãäœãããããšãã§ããã UI ã®å®è£
ã«ãã€ãã£ã UI ã䜿çšããŠããã®ã§èªç¶ãªãã¶ã€ã³ãã€ã³ã¿ã©ã¯ã·ã§ã³ãäœããããã ããçšåºŠãªãªãŒã¹ããæéãçµã£ãŠæ
å ±ãè±å¯ã«ãã ç¹ã«åŒç€Ÿã§ã¯ããã€ãã£ãã¢ããªãã Web éçºãã¡ã€ã³ã«è¡ã£ãŠãããšã³ãžãã¢ã®æ¹ãå€ãããŸã Web ããã³ãã« React ã䜿ãããŠãããããã¯ããããã€ãããã®ã§ãReact Native ãæ¡çšããããšã§ããŒã ã®éçºå¹çã®åäžã ãã§ãªããéçºæ¬éšå
šäœã§ããã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäœããªãã®ã§ã¯ãªãããšèããŸããã ããã§ã以éã§ã¯ãã€ãã£ãã¢ããªãšã³ãžãã¢ãš Web ãšã³ãžãã¢ããããã«ãšã£ãŠãéçºãããããã©ãããšãã芳ç¹ã§ React Native ã®éçºæ¹æ³ãèŠãŠãããããšæããŸãã åæèšå®ã«ã€ã㊠ã€ã³ã¹ããŒã«ãã¢ããªå®è¡ ã€ã³ã¹ããŒã«ã¯å
¬åŒã® Getting Started ã«ããããŸããã以äžã®ã³ãã³ãã§å®äºã§ãã $ brew install node $ brew install watchman $ npm install -g react-native-cli ä»åãç§ãè§Šãã«ããã£ãŠã¯ Xcode ãš Android Studio ã®ã·ãã¥ã¬ãŒã¿ïŒãšãã¥ã¬ãŒã¿ïŒã§å®è¡ããªããéçºããŸããããReact Native 㯠Xcode ã Android Studio ãã€ã³ã¹ããŒã«ãããŠããªããŠãã Expo ãšããã¯ã©ã€ã¢ã³ãã¢ããªã宿©ã«ã€ã³ã¹ããŒã«ããããšã§ç»é¢ããã¬ãã¥ãŒããªããéçºããããšãã§ããŸãã ãããªããXcode ã®ããŠã³ããŒããåŸ
ã€å¿
èŠããããŸããïŒïŒiOS ãšã³ãžãã¢ã§ãã¢ããã°ã¬ãŒãã®ãã³ã« Xcode ã®ããŠã³ããŒããåŸ
ã€ã®ã¯ã€ã©ã€ã©ããŸãïŒ æ¬¡ã«ããããžã§ã¯ãäœæãã·ãã¥ã¬ãŒã¿ã§ã®ã¢ããªå®è¡ã¯ä»¥äžã®ã³ãã³ãã§å®è¡ã§ããŸãã ãã ããã·ãã¥ã¬ãŒã¿å®è¡åã« Xcode Command Line Tools ã®ã€ã³ã¹ããŒã«ãš Android Studio ã§ããã€ãã®èšå®ïŒSDK ã®ã€ã³ã¹ããŒã«ãAVD ã®äœæãç°å¢å€æ°ã®èšå®ïŒãå¿
èŠã§ãã # ãããžã§ã¯ãäœæ $ react-native init AwesomeProject  # ã¢ããªå®è¡ïŒã·ãã¥ã¬ãŒã¿ïŒ $ cd AwesomeProject $ react-native run-ios or react-native run-android # Android ã®å Žåãemulator ãå¥éèµ·åããŠããã§ãªããšå®è¡ã§ããªã å®è£
ããŠã¿ãææ³ UI ã®å®è£
æ¹æ³ React Native ã§ã¯ React åæ§ UI ã®åããŒããã³ã³ããŒãã³ããšåŒã³ãããããé
眮ããããšã§ UI ãå®è£
ããŠãããŸããéã㯠Web ã® HTML ã®ä»£ããã« Native ã® UI ãæç»ããããã®ã³ã³ããŒãã³ããšããŠäœ¿ãç¹ã§ãã èŠãç®ãã¬ã€ã¢ãŠã㯠CSS ãšäŒŒããããªåœ¢åŒã§èšè¿°ããŸããReact Native ã§äœ¿ããã¹ã¿ã€ã«ã®ããããã£ã¯åã³ã³ããŒãã³ãã§ç°ãªããŸãããäŸãã°ãView ã³ã³ããŒãã³ãã«èšå®ã§ããããããã£ã«ã¯ä»¥äžã®ãããªãã®ããããŸãã View Style Props Layout Props Web ã§äœ¿ãããŠãããã®ãšå
šãåããšããããã§ã¯ãªãã§ãããflexãmarginãborder ãªã©ã®äœ¿ãæ
£ããŠãã CSS ã®ããããã£åã§èšå®ã§ããã®ã§ãWeb ãšã³ãžãã¢ã«ãšã£ãŠã¯å®è£
ã®ããŒãã«ãäžããã®ã§ã¯ãªãããšæããŸããããã ãæ®æ®µ CSS ãè§Šã£ãŠããªããã€ãã£ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯åŠç¿ã³ã¹ããããããšæããŸãã ãŸãäžåºŠãã«ãããã°ãJS ã«ããä¿®æ£å
容ããã«ããªãã§ã·ãã¥ã¬ãŒã¿ã«åæ ããããšãã§ããã®ã§ãView åšãã®èª¿æŽã¯å¹ççã«ã§ãããã§ããã // js/components/home.js const renderItem = ({ item , index }) => ( < View style = { styles . row } > < Text style = { styles . title } >        { parseInt ( index , 10 ) + 1 }        { ". " }        { item . title } </ Text >      < Text style = { styles . description } > { item . description } </ Text > </ View > ); const styles = StyleSheet . create ({ row: { borderBottomWidth: 1 , borderColor: "#ccc" , padding: 10 , }, title: { fontSize: 15 , fontWeight: "600" , }, description: { marginTop: 5 , fontSize: 14 , }, }); ãã ãOS ããšã«ãããµãã€ã³ãåãããæ¹éã«ããªãéãã¯ãã³ãŒããå¥ã
ã«ãªããšããããããšå€ããªãããã ãšæããŸããã äŸãã°ãTabBar(iOS)ãš DrawerLayout(Android)ãDatePicker(iOS)ãš TimePicker(Android)ãProgressView(iOS)ãš ProgressBar(Android)ãªã©ã¯ React Native ã§ã¯å¥ã³ã³ããŒãã³ããšããŠæäŸãããŠããŠãAPI ãéã£ãŠããŸããã ç»é¢é·ç§» ç»é¢é·ç§»ïŒããã·ã¥ãã¢ãŒãã«ãã¿ãé·ç§»ãªã©ïŒã®ããã« API ãšããŠå
¬åŒã§æäŸãããŠããã®ã¯ iOS ã®ã¿ã§ Android ã¯å¥éãå®è£
ãããããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿çšããå¿
èŠããããŸãã ãããã䜿ã£ãŠã¿ã react-native-navigation ã¯ã¢ãŒãã«ãããã·ã¥ãªã©ã®é·ç§»ããã€ãã£ã API ããŒã¹ã§å®è£
ãããŠããã®ã§ããã€ãã£ãèšèªã§å®è£
ããå Žåãšæ¯ã¹ãŠéåæãªãå®è£
ããããšãã§ããŸããã äžèšã®ãããªåœ¢ã§ããã·ã¥ãã¢ãŒãã«è¡šç€ºã§ã®é·ç§»ãã§ããŸããç¹å®ã®ç»é¢ã«æ»ãæ©èœã«ã€ããŠã¯éçºäžã§ãã£ãããæ©èœçãªå¶çŽã¯å°ãããããã§ãããããã现ãããšããã¯ãã€ãã£ãèšèªã§ãã£ãæ¹ãèªç±ãå¹ãã®ã§ãè¯ããªãšæããŸãã ããã§ããiOS ãš Android ã§ã¯è€æ°ç»é¢ã®ç®¡çãé·ç§»ã«ã€ããŠã®èãæ¹ãéããAndroid ãåããŠéçºããæã«åãããšãå®çŸããã®ãé£ããã£ãèŠããããã®ã§ãå
±éã®æ¹æ³ã§å®çŸã§ããã®ã¯äŸ¿å©ã§ãããç¹ã« Web ã ãšããŸãç»é¢éã®é·ç§»ã«ã€ããŠèããããšã¯ãªããšæãã®ã§ãå
±éåãããŠãããšãã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäžãããšæããŸãã this . props . navigator . push ({ // ããã·ã¥ screen: "example.PushedScreen" , title: "Pushed Screen" , }); this . props . navigator . pop ({ // åã®ç»é¢ã«æ»ã animated: true , animationType: "fade" , }); this . props . navigator . showModal ({ // ã¢ãŒãã« screen: "example.ModalScreen" , title: "Modal" , animationType: "slide-up" , }); ãããã¯ãŒã¯åšã ãããã¯ãŒã¯çµç±ã§ããŒã¿ãååŸããŠãã¢ãã«ã«å€æããã¢ããªå
ã§äœ¿ããšããããããæäœãè¡ãã«ã¯ Fetch API ãå©çšããŸãã Fetch API 㯠JS ã§æäŸãããŠãã Promise ããŒã¹ã® API ã§ããäŸãã°ã以äžã®ãããªåœ¢ã§ JSON ãè¿ã API ããããŒã¿ãååŸãã receiveHelthNews 颿°ã«ãªããžã§ã¯ãã«å€æããé
åãæž¡ãããšãã§ããŸããJS ã® API ãªã®ã§ Web ãšã³ãžãã¢ã«ãšã£ãŠã¯äœ¿ããããã®ã§ã¯ãªãããšæããŸãã ãã€ãã£ãèšèªã§ããããå®è£
ããå Žåã¯ãURLSession(iOS)ãš HttpURLConnection(Android)ããããã¯åãã©ãããã©ãŒã åãã«æäŸãããŠãããµãŒãããŒãã£ã®ã©ã€ãã©ãªãªã©ã䜿ããšæããŸãããåœç¶ãAPI ã¯ç°ãªãã®ã§ããããã®å®è£
æ¹æ³ãææ¡ããªããšãããªããªããŸããããã«æ¯ã¹ããšåŠç¿ã³ã¹ãã¯äœããªãããã§ãã // js/actions/index.js export function fetchHelthNews () { return ( dispatch ) => fetch ( constructHealthNewsUrl ()) . then (( response ) => response . json ()) . then (( json ) => dispatch ( receiveHelthNews ( json . articles ))) . catch (( error ) => { console . log ( error ); }); } ãã€ãã£ãã¢ããªç¹æã®æ©èœã«ã€ã㊠ãã®ä»ã®ã¢ããªéçºã§ãã䜿ããã€ãã£ãã¢ããªç¹æã®æ©èœãå®è£
ããæ¹æ³ã¯ä»¥äžã®ããã«ãªããŸããå€ãã®æ©èœããµãŒãããŒãã£ã®ã©ã€ãã©ãªã«äŸåããŠããã®ã§ãåèšèªã®ããŒãžã§ã³ã¢ããæã®å¯Ÿå¿ãå°ãå¿é
ã§ã¯ãããŸãããããäœ¿ãæ©èœã«ã€ããŠã¯å®çŸããããšãã§ããŸãã Push éç¥ïŒAndroid ã¯ãã³ããªã³ã°ãã API ãå
¬åŒã§æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã ã«ã¡ã©ãããŒãã§ãŒã³ã¢ã¯ã»ã¹/ãŠãŒã¶ããã©ã«ãïŒå
¬åŒã® API ã¯æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã äœçœ®æ
å ±ã®ååŸïŒå
¬åŒ API ãæäŸãããŠãã ãã£ãŒããªã³ã¯ïŒã¢ããªèµ·åæã«ãã³ããªã³ã°ãè¡ã API ã¯æäŸãããŠããããŠãããŒãµã«ãªã³ã¯ã IntentFilter ã®èšå®ã¯åãã©ãããã©ãŒã ã§åå¥ã«å¿
èŠã«ãªã ãªãªãŒã¹ã¯ã©ãããã ã¢ãŒã«ã€ããã¹ãã¢é
åžã«ã€ããŠã¯ãã€ãã£ãã¢ããªã®é
åžãšåãããã»ã¹ã«ãªããŸãã åãã©ãããã©ãŒã ã§èšŒææžçã®èšå®ãè¡ããXcode ã Android Studioãããã㯠CLI ã§ã³ãã³ããå®è¡ããŠãipa / apk ãã¡ã€ã«ãäœæããå Store ã«ã¢ããããŒãããå¿
èŠããããŸãã CI 㯠Bitrise ãªã©ã䜿ããŸããBitrise ã§ãã«ãã詊ããŠã¿ãŸããããReact Native ã®ãªããžããªãšæ¥ç¶ãããšãã«ã§ããããã©ã«ãã®ã¯ãŒã¯ãããŒã䜿ãã°ãåæã« 2 ãã©ãããã©ãŒã ã®ã¢ãŒã«ã€ããäœæã§ããŠäŸ¿å©ã§ããã ããšããŸã 詊ããŠã¯ããªãã®ã§ãã CodePush ã䜿ãã°ã審æ»ã«æåºããããšãªãã«æ¢åã®ã¢ããªã倿Žããããšãã§ãããããã®ã§ãéåžžã«äŸ¿å©ã ãšæããŸããã ã©ããªå Žåã« React Native ãæ¡çšã§ãããã? React Native ã§éçºããããšã§ãWeb éçºè
ã®èŠç¹ã§èŠããšãã©ãããã©ãŒã ã®ãã€ãã£ãèšèªã§éçºããããããã ãã¶åŠç¿ã³ã¹ããäžããã®ã§ã¯ãªãããšæããŸããããŸããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ãã°ãæ©èœçã«å€§ããªåé¡ãšãªããããªããšã¯ãªãããã§ããããã ãç»é¢é·ç§»ã®ã©ã€ãã©ãªãããã ã£ãããã«ãããããããããšãã§ããªããšããå Žåã¯ã劥åããªããšãããªãéšåãåºãŠãããã ãšæããŸããã äžæ¹ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ãæ
£ãããŸã§ã¯ããªãéçºé床ãäžãããããªã®ã§ãã¡ãªããã倧ããããªãšæããŸãããReact ãš JSããŸã Redux ãªã©ãæ°ãã«çè§£ãã€ã€éçºããŠããã®ã§çµæ§ããŒãã«ãé«ããšæããŸãããéçºç°å¢ããã«ããéã£ãŠããã¡ã¯ãView åšãã®èª¿æŽãããã«ç¢ºèªã§ããŠè¯ãã£ãã®ã§ãããã©ã³ã¿ã€ã ãšã©ãŒã«ãªããªã©ã§ãã·ãã¥ã¬ãŒã¿ããªããŒãã§ããªããªã£ãå Žåã«å床ãã«ããçŽããšããããšãããèµ·ãããåžžã«å¿«é©ã«éçºã§ãããšããããã§ã¯ãããŸããã§ããã éçšé¢ã§ã¿ããšäžéãã¢ãããªéçºã«å¿
èŠãããªããŒã«ã¯æã£ãŠããã(ã¯ã©ãã·ã¥ç£èŠãCIããã¹ãé
ä¿¡ããªãªãŒã¹)ãCode Push ãªã©äŸ¿å©ãªããŒã«ãããã®ã§å©ç¹ãå€ããšæããŸããã çµè«ãšããŠã¯ãWeb ãšã³ãžãã¢ã瀟å
ã«å€ãã£ãããéçºããŒã ã« ReactãJS ãåŸæãªã¡ã³ããŒããããªããå®éã®éçºã§ã䜿ããããªãšæããŸããããã ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ããªãã¹ãã¬ã¹ãããŸããããžã§ã¯ãã«ãªãããã ãšæããŸããã ãŸãšã èªåã®çŸç¶ã§èãããšãã¢ããªã¯åŸæã ãã© JS ã React ã«ãããŸã§è©³ãããªãã®ã§ãããçŽè¿ã®ãããžã§ã¯ãã§é£æåºŠãããããé«ãããã§ããã°ãæ£çŽãããŸã䜿ããããªããªããšããæ°æã¡ããããŸãããã ãæè¡ã®å¹
ãåºãããšããçµç¹å
šäœã®ããŒã¿ããªãã£ãªã©ã®èгç¹ã§èãããšå©ç¹ãçµæ§ããã®ããªãšæããŸãããã£ã³ã¹ãããã°ãã²ããã£ã¬ã³ãžããŠã¿ããã§ãã ãããã¯ã©ã¡ãããšãããšæè¡ãéçºããŒã«ã®æ°ãããããããŠãŒã¶ãšã®æ¥ç¹ã®ãšããã§æ°ããããšãé¢çœãããšã远æ±ããããšæã£ãŠããŸãããéçºå¹çãå質ã®åäžã®ããã«æé©ãªãã®ãéžæã§ããããã«ãä»åŸãæ°ããããŒã«ã®ãã£ããã¢ããã¯ç©æ¥µçã«è¡ã£ãŠãããããšæã£ãŠããŸãã ãç¥ãã ã¡ãã¬ãŒã¯ã5/31-6/2 ã«éå¬ããã RubyKaigi 2018 ã« LT ã¹ãã³ãµãŒãšããŠåè³ããŸããããŒã¹ãæ§ããŠãããŸãã®ã§ãã€ãã³ãã«ãè¶ãã«ãªãæ¹ã¯ããã²ããŒã¹ã«ãéã³ã«ããããŠãã ããïŒ RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®é«äºã§ããã¡ãã¬ãŒéçºæ¬éšã§è¡ãããŠããå匷äŒãTechLunchãã§ React Native ã«ã€ããŠçºè¡šããŸããã ç§ã¯æ®æ®µã¯ SwiftãKotlin/Java ã䜿ã£ãŠãã€ãã£ãã¢ããªãéçºããŠãããReact Native ã«è§Šãã®ã¯åããŠã§ãããããã§ä»åã¯ãã¢ããªãšã³ãžãã¢ã®èŠç¹ãããå®è£
ããããã®åºæ¬çãªç¥èãšåŒç€Ÿã®å®éã®éçºã§äœ¿ãããããæ€èšããçµæã«ã€ããŠã玹ä»ããŸãã ãªã React Native ãè§Šã£ãŠã¿ãããšæã£ãã ãªã³ã©ã€ã³èšºçã¢ããªã CLINICS ãã®éçºã§ã¯ãiOS/Android ã¢ããªãããããã®ãã€ãã£ãèšèªã§å¥ã
ã«éçºããŠãããããå®è£
ãã¬ãã¥ãŒã®éã«ã¯ãã©ãããã©ãŒã éã®ä»æ§ã®éããçè§£ããå¿
èŠãããããªããªã倧å€ã ãšæããŠããŸããã ãããã®èª²é¡ã«å¯Ÿã㊠ãã¡ã ã®ããã°ã§ã玹ä»ãããããªæœçãè¡ã£ãŠæ¹åãè¡ã£ãŠããŸãããããœãŒã¹ãå
±éåããããšã§ããéçºå¹çãåäžã§ããªãããšæããã¯ãã¹ãã©ãããã©ãŒã éçºã«ã€ããŠã調ã¹ãŠã¿ãããšã«ããŸããã ãã®äžã§ã以äžã®çç±ãããä»å㯠React Native ã«ã€ããŠèª¿ã¹ãŠã¿ãããšã«ããŸããã JavaScriptïŒä»¥äž JSïŒã» React ã®ãããWeb ãšã³ãžãã¢ããã€ãã£ãã¢ããªéçºãè¡ãéã®ããŒãã«ãäœãããããšãã§ããã UI ã®å®è£
ã«ãã€ãã£ã UI ã䜿çšããŠããã®ã§èªç¶ãªãã¶ã€ã³ãã€ã³ã¿ã©ã¯ã·ã§ã³ãäœããããã ããçšåºŠãªãªãŒã¹ããæéãçµã£ãŠæ
å ±ãè±å¯ã«ãã ç¹ã«åŒç€Ÿã§ã¯ããã€ãã£ãã¢ããªãã Web éçºãã¡ã€ã³ã«è¡ã£ãŠãããšã³ãžãã¢ã®æ¹ãå€ãããŸã Web ããã³ãã« React ã䜿ãããŠãããããã¯ããããã€ãããã®ã§ãReact Native ãæ¡çšããããšã§ããŒã ã®éçºå¹çã®åäžã ãã§ãªããéçºæ¬éšå
šäœã§ããã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäœããªãã®ã§ã¯ãªãããšèããŸããã ããã§ã以éã§ã¯ãã€ãã£ãã¢ããªãšã³ãžãã¢ãš Web ãšã³ãžãã¢ããããã«ãšã£ãŠãéçºãããããã©ãããšãã芳ç¹ã§ React Native ã®éçºæ¹æ³ãèŠãŠãããããšæããŸãã åæèšå®ã«ã€ã㊠ã€ã³ã¹ããŒã«ãã¢ããªå®è¡ ã€ã³ã¹ããŒã«ã¯å
¬åŒã® Getting Started ã«ããããŸããã以äžã®ã³ãã³ãã§å®äºã§ãã $ brew install node $ brew install watchman $ npm install -g react-native-cli ä»åãç§ãè§Šãã«ããã£ãŠã¯ Xcode ãš Android Studio ã®ã·ãã¥ã¬ãŒã¿ïŒãšãã¥ã¬ãŒã¿ïŒã§å®è¡ããªããéçºããŸããããReact Native 㯠Xcode ã Android Studio ãã€ã³ã¹ããŒã«ãããŠããªããŠãã Expo ãšããã¯ã©ã€ã¢ã³ãã¢ããªã宿©ã«ã€ã³ã¹ããŒã«ããããšã§ç»é¢ããã¬ãã¥ãŒããªããéçºããããšãã§ããŸãã ãããªããXcode ã®ããŠã³ããŒããåŸ
ã€å¿
èŠããããŸããïŒïŒiOS ãšã³ãžãã¢ã§ãã¢ããã°ã¬ãŒãã®ãã³ã« Xcode ã®ããŠã³ããŒããåŸ
ã€ã®ã¯ã€ã©ã€ã©ããŸãïŒ æ¬¡ã«ããããžã§ã¯ãäœæãã·ãã¥ã¬ãŒã¿ã§ã®ã¢ããªå®è¡ã¯ä»¥äžã®ã³ãã³ãã§å®è¡ã§ããŸãã ãã ããã·ãã¥ã¬ãŒã¿å®è¡åã« Xcode Command Line Tools ã®ã€ã³ã¹ããŒã«ãš Android Studio ã§ããã€ãã®èšå®ïŒSDK ã®ã€ã³ã¹ããŒã«ãAVD ã®äœæãç°å¢å€æ°ã®èšå®ïŒãå¿
èŠã§ãã # ãããžã§ã¯ãäœæ $ react-native init AwesomeProject  # ã¢ããªå®è¡ïŒã·ãã¥ã¬ãŒã¿ïŒ $ cd AwesomeProject $ react-native run-ios or react-native run-android # Android ã®å Žåãemulator ãå¥éèµ·åããŠããã§ãªããšå®è¡ã§ããªã å®è£
ããŠã¿ãææ³ UI ã®å®è£
æ¹æ³ React Native ã§ã¯ React åæ§ UI ã®åããŒããã³ã³ããŒãã³ããšåŒã³ãããããé
眮ããããšã§ UI ãå®è£
ããŠãããŸããéã㯠Web ã® HTML ã®ä»£ããã« Native ã® UI ãæç»ããããã®ã³ã³ããŒãã³ããšããŠäœ¿ãç¹ã§ãã èŠãç®ãã¬ã€ã¢ãŠã㯠CSS ãšäŒŒããããªåœ¢åŒã§èšè¿°ããŸããReact Native ã§äœ¿ããã¹ã¿ã€ã«ã®ããããã£ã¯åã³ã³ããŒãã³ãã§ç°ãªããŸãããäŸãã°ãView ã³ã³ããŒãã³ãã«èšå®ã§ããããããã£ã«ã¯ä»¥äžã®ãããªãã®ããããŸãã View Style Props Layout Props Web ã§äœ¿ãããŠãããã®ãšå
šãåããšããããã§ã¯ãªãã§ãããflexãmarginãborder ãªã©ã®äœ¿ãæ
£ããŠãã CSS ã®ããããã£åã§èšå®ã§ããã®ã§ãWeb ãšã³ãžãã¢ã«ãšã£ãŠã¯å®è£
ã®ããŒãã«ãäžããã®ã§ã¯ãªãããšæããŸããããã ãæ®æ®µ CSS ãè§Šã£ãŠããªããã€ãã£ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯åŠç¿ã³ã¹ããããããšæããŸãã ãŸãäžåºŠãã«ãããã°ãJS ã«ããä¿®æ£å
容ããã«ããªãã§ã·ãã¥ã¬ãŒã¿ã«åæ ããããšãã§ããã®ã§ãView åšãã®èª¿æŽã¯å¹ççã«ã§ãããã§ããã // js/components/home.js const renderItem = ({ item , index }) => ( < View style = { styles . row } > < Text style = { styles . title } >        { parseInt ( index , 10 ) + 1 }        { ". " }        { item . title } </ Text >      < Text style = { styles . description } > { item . description } </ Text > </ View > ); const styles = StyleSheet . create ({ row: { borderBottomWidth: 1 , borderColor: "#ccc" , padding: 10 , }, title: { fontSize: 15 , fontWeight: "600" , }, description: { marginTop: 5 , fontSize: 14 , }, }); ãã ãOS ããšã«ãããµãã€ã³ãåãããæ¹éã«ããªãéãã¯ãã³ãŒããå¥ã
ã«ãªããšããããããšå€ããªãããã ãšæããŸããã äŸãã°ãTabBar(iOS)ãš DrawerLayout(Android)ãDatePicker(iOS)ãš TimePicker(Android)ãProgressView(iOS)ãš ProgressBar(Android)ãªã©ã¯ React Native ã§ã¯å¥ã³ã³ããŒãã³ããšããŠæäŸãããŠããŠãAPI ãéã£ãŠããŸããã ç»é¢é·ç§» ç»é¢é·ç§»ïŒããã·ã¥ãã¢ãŒãã«ãã¿ãé·ç§»ãªã©ïŒã®ããã« API ãšããŠå
¬åŒã§æäŸãããŠããã®ã¯ iOS ã®ã¿ã§ Android ã¯å¥éãå®è£
ãããããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿çšããå¿
èŠããããŸãã ãããã䜿ã£ãŠã¿ã react-native-navigation ã¯ã¢ãŒãã«ãããã·ã¥ãªã©ã®é·ç§»ããã€ãã£ã API ããŒã¹ã§å®è£
ãããŠããã®ã§ããã€ãã£ãèšèªã§å®è£
ããå Žåãšæ¯ã¹ãŠéåæãªãå®è£
ããããšãã§ããŸããã äžèšã®ãããªåœ¢ã§ããã·ã¥ãã¢ãŒãã«è¡šç€ºã§ã®é·ç§»ãã§ããŸããç¹å®ã®ç»é¢ã«æ»ãæ©èœã«ã€ããŠã¯éçºäžã§ãã£ãããæ©èœçãªå¶çŽã¯å°ãããããã§ãããããã现ãããšããã¯ãã€ãã£ãèšèªã§ãã£ãæ¹ãèªç±ãå¹ãã®ã§ãè¯ããªãšæããŸãã ããã§ããiOS ãš Android ã§ã¯è€æ°ç»é¢ã®ç®¡çãé·ç§»ã«ã€ããŠã®èãæ¹ãéããAndroid ãåããŠéçºããæã«åãããšãå®çŸããã®ãé£ããã£ãèŠããããã®ã§ãå
±éã®æ¹æ³ã§å®çŸã§ããã®ã¯äŸ¿å©ã§ãããç¹ã« Web ã ãšããŸãç»é¢éã®é·ç§»ã«ã€ããŠèããããšã¯ãªããšæãã®ã§ãå
±éåãããŠãããšãã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäžãããšæããŸãã this . props . navigator . push ({ // ããã·ã¥ screen: "example.PushedScreen" , title: "Pushed Screen" , }); this . props . navigator . pop ({ // åã®ç»é¢ã«æ»ã animated: true , animationType: "fade" , }); this . props . navigator . showModal ({ // ã¢ãŒãã« screen: "example.ModalScreen" , title: "Modal" , animationType: "slide-up" , }); ãããã¯ãŒã¯åšã ãããã¯ãŒã¯çµç±ã§ããŒã¿ãååŸããŠãã¢ãã«ã«å€æããã¢ããªå
ã§äœ¿ããšããããããæäœãè¡ãã«ã¯ Fetch API ãå©çšããŸãã Fetch API 㯠JS ã§æäŸãããŠãã Promise ããŒã¹ã® API ã§ããäŸãã°ã以äžã®ãããªåœ¢ã§ JSON ãè¿ã API ããããŒã¿ãååŸãã receiveHelthNews 颿°ã«ãªããžã§ã¯ãã«å€æããé
åãæž¡ãããšãã§ããŸããJS ã® API ãªã®ã§ Web ãšã³ãžãã¢ã«ãšã£ãŠã¯äœ¿ããããã®ã§ã¯ãªãããšæããŸãã ãã€ãã£ãèšèªã§ããããå®è£
ããå Žåã¯ãURLSession(iOS)ãš HttpURLConnection(Android)ããããã¯åãã©ãããã©ãŒã åãã«æäŸãããŠãããµãŒãããŒãã£ã®ã©ã€ãã©ãªãªã©ã䜿ããšæããŸãããåœç¶ãAPI ã¯ç°ãªãã®ã§ããããã®å®è£
æ¹æ³ãææ¡ããªããšãããªããªããŸããããã«æ¯ã¹ããšåŠç¿ã³ã¹ãã¯äœããªãããã§ãã // js/actions/index.js export function fetchHelthNews () { return ( dispatch ) => fetch ( constructHealthNewsUrl ()) . then (( response ) => response . json ()) . then (( json ) => dispatch ( receiveHelthNews ( json . articles ))) . catch (( error ) => { console . log ( error ); }); } ãã€ãã£ãã¢ããªç¹æã®æ©èœã«ã€ã㊠ãã®ä»ã®ã¢ããªéçºã§ãã䜿ããã€ãã£ãã¢ããªç¹æã®æ©èœãå®è£
ããæ¹æ³ã¯ä»¥äžã®ããã«ãªããŸããå€ãã®æ©èœããµãŒãããŒãã£ã®ã©ã€ãã©ãªã«äŸåããŠããã®ã§ãåèšèªã®ããŒãžã§ã³ã¢ããæã®å¯Ÿå¿ãå°ãå¿é
ã§ã¯ãããŸãããããäœ¿ãæ©èœã«ã€ããŠã¯å®çŸããããšãã§ããŸãã Push éç¥ïŒAndroid ã¯ãã³ããªã³ã°ãã API ãå
¬åŒã§æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã ã«ã¡ã©ãããŒãã§ãŒã³ã¢ã¯ã»ã¹/ãŠãŒã¶ããã©ã«ãïŒå
¬åŒã® API ã¯æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã äœçœ®æ
å ±ã®ååŸïŒå
¬åŒ API ãæäŸãããŠãã ãã£ãŒããªã³ã¯ïŒã¢ããªèµ·åæã«ãã³ããªã³ã°ãè¡ã API ã¯æäŸãããŠããããŠãããŒãµã«ãªã³ã¯ã IntentFilter ã®èšå®ã¯åãã©ãããã©ãŒã ã§åå¥ã«å¿
èŠã«ãªã ãªãªãŒã¹ã¯ã©ãããã ã¢ãŒã«ã€ããã¹ãã¢é
åžã«ã€ããŠã¯ãã€ãã£ãã¢ããªã®é
åžãšåãããã»ã¹ã«ãªããŸãã åãã©ãããã©ãŒã ã§èšŒææžçã®èšå®ãè¡ããXcode ã Android Studioãããã㯠CLI ã§ã³ãã³ããå®è¡ããŠãipa / apk ãã¡ã€ã«ãäœæããå Store ã«ã¢ããããŒãããå¿
èŠããããŸãã CI 㯠Bitrise ãªã©ã䜿ããŸããBitrise ã§ãã«ãã詊ããŠã¿ãŸããããReact Native ã®ãªããžããªãšæ¥ç¶ãããšãã«ã§ããããã©ã«ãã®ã¯ãŒã¯ãããŒã䜿ãã°ãåæã« 2 ãã©ãããã©ãŒã ã®ã¢ãŒã«ã€ããäœæã§ããŠäŸ¿å©ã§ããã ããšããŸã 詊ããŠã¯ããªãã®ã§ãã CodePush ã䜿ãã°ã審æ»ã«æåºããããšãªãã«æ¢åã®ã¢ããªã倿Žããããšãã§ãããããã®ã§ãéåžžã«äŸ¿å©ã ãšæããŸããã ã©ããªå Žåã« React Native ãæ¡çšã§ãããã? React Native ã§éçºããããšã§ãWeb éçºè
ã®èŠç¹ã§èŠããšãã©ãããã©ãŒã ã®ãã€ãã£ãèšèªã§éçºããããããã ãã¶åŠç¿ã³ã¹ããäžããã®ã§ã¯ãªãããšæããŸããããŸããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ãã°ãæ©èœçã«å€§ããªåé¡ãšãªããããªããšã¯ãªãããã§ããããã ãç»é¢é·ç§»ã®ã©ã€ãã©ãªãããã ã£ãããã«ãããããããããšãã§ããªããšããå Žåã¯ã劥åããªããšãããªãéšåãåºãŠãããã ãšæããŸããã äžæ¹ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ãæ
£ãããŸã§ã¯ããªãéçºé床ãäžãããããªã®ã§ãã¡ãªããã倧ããããªãšæããŸãããReact ãš JSããŸã Redux ãªã©ãæ°ãã«çè§£ãã€ã€éçºããŠããã®ã§çµæ§ããŒãã«ãé«ããšæããŸãããéçºç°å¢ããã«ããéã£ãŠããã¡ã¯ãView åšãã®èª¿æŽãããã«ç¢ºèªã§ããŠè¯ãã£ãã®ã§ãããã©ã³ã¿ã€ã ãšã©ãŒã«ãªããªã©ã§ãã·ãã¥ã¬ãŒã¿ããªããŒãã§ããªããªã£ãå Žåã«å床ãã«ããçŽããšããããšãããèµ·ãããåžžã«å¿«é©ã«éçºã§ãããšããããã§ã¯ãããŸããã§ããã éçšé¢ã§ã¿ããšäžéãã¢ãããªéçºã«å¿
èŠãããªããŒã«ã¯æã£ãŠããã(ã¯ã©ãã·ã¥ç£èŠãCIããã¹ãé
ä¿¡ããªãªãŒã¹)ãCode Push ãªã©äŸ¿å©ãªããŒã«ãããã®ã§å©ç¹ãå€ããšæããŸããã çµè«ãšããŠã¯ãWeb ãšã³ãžãã¢ã瀟å
ã«å€ãã£ãããéçºããŒã ã« ReactãJS ãåŸæãªã¡ã³ããŒããããªããå®éã®éçºã§ã䜿ããããªãšæããŸããããã ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ããªãã¹ãã¬ã¹ãããŸããããžã§ã¯ãã«ãªãããã ãšæããŸããã ãŸãšã èªåã®çŸç¶ã§èãããšãã¢ããªã¯åŸæã ãã© JS ã React ã«ãããŸã§è©³ãããªãã®ã§ãããçŽè¿ã®ãããžã§ã¯ãã§é£æåºŠãããããé«ãããã§ããã°ãæ£çŽãããŸã䜿ããããªããªããšããæ°æã¡ããããŸãããã ãæè¡ã®å¹
ãåºãããšããçµç¹å
šäœã®ããŒã¿ããªãã£ãªã©ã®èгç¹ã§èãããšå©ç¹ãçµæ§ããã®ããªãšæããŸãããã£ã³ã¹ãããã°ãã²ããã£ã¬ã³ãžããŠã¿ããã§ãã ãããã¯ã©ã¡ãããšãããšæè¡ãéçºããŒã«ã®æ°ãããããããŠãŒã¶ãšã®æ¥ç¹ã®ãšããã§æ°ããããšãé¢çœãããšã远æ±ããããšæã£ãŠããŸãããéçºå¹çãå質ã®åäžã®ããã«æé©ãªãã®ãéžæã§ããããã«ãä»åŸãæ°ããããŒã«ã®ãã£ããã¢ããã¯ç©æ¥µçã«è¡ã£ãŠãããããšæã£ãŠããŸãã ãç¥ãã ã¡ãã¬ãŒã¯ã5/31-6/2 ã«éå¬ããã RubyKaigi 2018 ã« LT ã¹ãã³ãµãŒãšããŠåè³ããŸããããŒã¹ãæ§ããŠãããŸãã®ã§ãã€ãã³ãã«ãè¶ãã«ãªãæ¹ã¯ããã²ããŒã¹ã«ãéã³ã«ããããŠãã ããïŒ RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®é«äºã§ããã¡ãã¬ãŒéçºæ¬éšã§è¡ãããŠããå匷äŒãTechLunchãã§ React Native ã«ã€ããŠçºè¡šããŸããã ç§ã¯æ®æ®µã¯ SwiftãKotlin/Java ã䜿ã£ãŠãã€ãã£ãã¢ããªãéçºããŠãããReact Native ã«è§Šãã®ã¯åããŠã§ãããããã§ä»åã¯ãã¢ããªãšã³ãžãã¢ã®èŠç¹ãããå®è£
ããããã®åºæ¬çãªç¥èãšåŒç€Ÿã®å®éã®éçºã§äœ¿ãããããæ€èšããçµæã«ã€ããŠã玹ä»ããŸãã ãªã React Native ãè§Šã£ãŠã¿ãããšæã£ãã ãªã³ã©ã€ã³èšºçã¢ããªã CLINICS ãã®éçºã§ã¯ãiOS/Android ã¢ããªãããããã®ãã€ãã£ãèšèªã§å¥ã
ã«éçºããŠãããããå®è£
ãã¬ãã¥ãŒã®éã«ã¯ãã©ãããã©ãŒã éã®ä»æ§ã®éããçè§£ããå¿
èŠãããããªããªã倧å€ã ãšæããŠããŸããã ãããã®èª²é¡ã«å¯Ÿã㊠ãã¡ã ã®ããã°ã§ã玹ä»ãããããªæœçãè¡ã£ãŠæ¹åãè¡ã£ãŠããŸãããããœãŒã¹ãå
±éåããããšã§ããéçºå¹çãåäžã§ããªãããšæããã¯ãã¹ãã©ãããã©ãŒã éçºã«ã€ããŠã調ã¹ãŠã¿ãããšã«ããŸããã ãã®äžã§ã以äžã®çç±ãããä»å㯠React Native ã«ã€ããŠèª¿ã¹ãŠã¿ãããšã«ããŸããã JavaScriptïŒä»¥äž JSïŒã» React ã®ãããWeb ãšã³ãžãã¢ããã€ãã£ãã¢ããªéçºãè¡ãéã®ããŒãã«ãäœãããããšãã§ããã UI ã®å®è£
ã«ãã€ãã£ã UI ã䜿çšããŠããã®ã§èªç¶ãªãã¶ã€ã³ãã€ã³ã¿ã©ã¯ã·ã§ã³ãäœããããã ããçšåºŠãªãªãŒã¹ããæéãçµã£ãŠæ
å ±ãè±å¯ã«ãã ç¹ã«åŒç€Ÿã§ã¯ããã€ãã£ãã¢ããªãã Web éçºãã¡ã€ã³ã«è¡ã£ãŠãããšã³ãžãã¢ã®æ¹ãå€ãããŸã Web ããã³ãã« React ã䜿ãããŠãããããã¯ããããã€ãããã®ã§ãReact Native ãæ¡çšããããšã§ããŒã ã®éçºå¹çã®åäžã ãã§ãªããéçºæ¬éšå
šäœã§ããã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäœããªãã®ã§ã¯ãªãããšèããŸããã ããã§ã以éã§ã¯ãã€ãã£ãã¢ããªãšã³ãžãã¢ãš Web ãšã³ãžãã¢ããããã«ãšã£ãŠãéçºãããããã©ãããšãã芳ç¹ã§ React Native ã®éçºæ¹æ³ãèŠãŠãããããšæããŸãã åæèšå®ã«ã€ã㊠ã€ã³ã¹ããŒã«ãã¢ããªå®è¡ ã€ã³ã¹ããŒã«ã¯å
¬åŒã® Getting Started ã«ããããŸããã以äžã®ã³ãã³ãã§å®äºã§ãã $ brew install node $ brew install watchman $ npm install -g react-native-cli ä»åãç§ãè§Šãã«ããã£ãŠã¯ Xcode ãš Android Studio ã®ã·ãã¥ã¬ãŒã¿ïŒãšãã¥ã¬ãŒã¿ïŒã§å®è¡ããªããéçºããŸããããReact Native 㯠Xcode ã Android Studio ãã€ã³ã¹ããŒã«ãããŠããªããŠãã Expo ãšããã¯ã©ã€ã¢ã³ãã¢ããªã宿©ã«ã€ã³ã¹ããŒã«ããããšã§ç»é¢ããã¬ãã¥ãŒããªããéçºããããšãã§ããŸãã ãããªããXcode ã®ããŠã³ããŒããåŸ
ã€å¿
èŠããããŸããïŒïŒiOS ãšã³ãžãã¢ã§ãã¢ããã°ã¬ãŒãã®ãã³ã« Xcode ã®ããŠã³ããŒããåŸ
ã€ã®ã¯ã€ã©ã€ã©ããŸãïŒ æ¬¡ã«ããããžã§ã¯ãäœæãã·ãã¥ã¬ãŒã¿ã§ã®ã¢ããªå®è¡ã¯ä»¥äžã®ã³ãã³ãã§å®è¡ã§ããŸãã ãã ããã·ãã¥ã¬ãŒã¿å®è¡åã« Xcode Command Line Tools ã®ã€ã³ã¹ããŒã«ãš Android Studio ã§ããã€ãã®èšå®ïŒSDK ã®ã€ã³ã¹ããŒã«ãAVD ã®äœæãç°å¢å€æ°ã®èšå®ïŒãå¿
èŠã§ãã # ãããžã§ã¯ãäœæ $ react-native init AwesomeProject  # ã¢ããªå®è¡ïŒã·ãã¥ã¬ãŒã¿ïŒ $ cd AwesomeProject $ react-native run-ios or react-native run-android # Android ã®å Žåãemulator ãå¥éèµ·åããŠããã§ãªããšå®è¡ã§ããªã å®è£
ããŠã¿ãææ³ UI ã®å®è£
æ¹æ³ React Native ã§ã¯ React åæ§ UI ã®åããŒããã³ã³ããŒãã³ããšåŒã³ãããããé
眮ããããšã§ UI ãå®è£
ããŠãããŸããéã㯠Web ã® HTML ã®ä»£ããã« Native ã® UI ãæç»ããããã®ã³ã³ããŒãã³ããšããŠäœ¿ãç¹ã§ãã èŠãç®ãã¬ã€ã¢ãŠã㯠CSS ãšäŒŒããããªåœ¢åŒã§èšè¿°ããŸããReact Native ã§äœ¿ããã¹ã¿ã€ã«ã®ããããã£ã¯åã³ã³ããŒãã³ãã§ç°ãªããŸãããäŸãã°ãView ã³ã³ããŒãã³ãã«èšå®ã§ããããããã£ã«ã¯ä»¥äžã®ãããªãã®ããããŸãã View Style Props Layout Props Web ã§äœ¿ãããŠãããã®ãšå
šãåããšããããã§ã¯ãªãã§ãããflexãmarginãborder ãªã©ã®äœ¿ãæ
£ããŠãã CSS ã®ããããã£åã§èšå®ã§ããã®ã§ãWeb ãšã³ãžãã¢ã«ãšã£ãŠã¯å®è£
ã®ããŒãã«ãäžããã®ã§ã¯ãªãããšæããŸããããã ãæ®æ®µ CSS ãè§Šã£ãŠããªããã€ãã£ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯åŠç¿ã³ã¹ããããããšæããŸãã ãŸãäžåºŠãã«ãããã°ãJS ã«ããä¿®æ£å
容ããã«ããªãã§ã·ãã¥ã¬ãŒã¿ã«åæ ããããšãã§ããã®ã§ãView åšãã®èª¿æŽã¯å¹ççã«ã§ãããã§ããã // js/components/home.js const renderItem = ({ item , index }) => ( < View style = { styles . row } > < Text style = { styles . title } >        { parseInt ( index , 10 ) + 1 }        { ". " }        { item . title } </ Text >      < Text style = { styles . description } > { item . description } </ Text > </ View > ); const styles = StyleSheet . create ({ row: { borderBottomWidth: 1 , borderColor: "#ccc" , padding: 10 , }, title: { fontSize: 15 , fontWeight: "600" , }, description: { marginTop: 5 , fontSize: 14 , }, }); ãã ãOS ããšã«ãããµãã€ã³ãåãããæ¹éã«ããªãéãã¯ãã³ãŒããå¥ã
ã«ãªããšããããããšå€ããªãããã ãšæããŸããã äŸãã°ãTabBar(iOS)ãš DrawerLayout(Android)ãDatePicker(iOS)ãš TimePicker(Android)ãProgressView(iOS)ãš ProgressBar(Android)ãªã©ã¯ React Native ã§ã¯å¥ã³ã³ããŒãã³ããšããŠæäŸãããŠããŠãAPI ãéã£ãŠããŸããã ç»é¢é·ç§» ç»é¢é·ç§»ïŒããã·ã¥ãã¢ãŒãã«ãã¿ãé·ç§»ãªã©ïŒã®ããã« API ãšããŠå
¬åŒã§æäŸãããŠããã®ã¯ iOS ã®ã¿ã§ Android ã¯å¥éãå®è£
ãããããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿çšããå¿
èŠããããŸãã ãããã䜿ã£ãŠã¿ã react-native-navigation ã¯ã¢ãŒãã«ãããã·ã¥ãªã©ã®é·ç§»ããã€ãã£ã API ããŒã¹ã§å®è£
ãããŠããã®ã§ããã€ãã£ãèšèªã§å®è£
ããå Žåãšæ¯ã¹ãŠéåæãªãå®è£
ããããšãã§ããŸããã äžèšã®ãããªåœ¢ã§ããã·ã¥ãã¢ãŒãã«è¡šç€ºã§ã®é·ç§»ãã§ããŸããç¹å®ã®ç»é¢ã«æ»ãæ©èœã«ã€ããŠã¯éçºäžã§ãã£ãããæ©èœçãªå¶çŽã¯å°ãããããã§ãããããã现ãããšããã¯ãã€ãã£ãèšèªã§ãã£ãæ¹ãèªç±ãå¹ãã®ã§ãè¯ããªãšæããŸãã ããã§ããiOS ãš Android ã§ã¯è€æ°ç»é¢ã®ç®¡çãé·ç§»ã«ã€ããŠã®èãæ¹ãéããAndroid ãåããŠéçºããæã«åãããšãå®çŸããã®ãé£ããã£ãèŠããããã®ã§ãå
±éã®æ¹æ³ã§å®çŸã§ããã®ã¯äŸ¿å©ã§ãããç¹ã« Web ã ãšããŸãç»é¢éã®é·ç§»ã«ã€ããŠèããããšã¯ãªããšæãã®ã§ãå
±éåãããŠãããšãã€ãã£ãã¢ããªéçºã®åŠç¿ã³ã¹ããäžãããšæããŸãã this . props . navigator . push ({ // ããã·ã¥ screen: "example.PushedScreen" , title: "Pushed Screen" , }); this . props . navigator . pop ({ // åã®ç»é¢ã«æ»ã animated: true , animationType: "fade" , }); this . props . navigator . showModal ({ // ã¢ãŒãã« screen: "example.ModalScreen" , title: "Modal" , animationType: "slide-up" , }); ãããã¯ãŒã¯åšã ãããã¯ãŒã¯çµç±ã§ããŒã¿ãååŸããŠãã¢ãã«ã«å€æããã¢ããªå
ã§äœ¿ããšããããããæäœãè¡ãã«ã¯ Fetch API ãå©çšããŸãã Fetch API 㯠JS ã§æäŸãããŠãã Promise ããŒã¹ã® API ã§ããäŸãã°ã以äžã®ãããªåœ¢ã§ JSON ãè¿ã API ããããŒã¿ãååŸãã receiveHelthNews 颿°ã«ãªããžã§ã¯ãã«å€æããé
åãæž¡ãããšãã§ããŸããJS ã® API ãªã®ã§ Web ãšã³ãžãã¢ã«ãšã£ãŠã¯äœ¿ããããã®ã§ã¯ãªãããšæããŸãã ãã€ãã£ãèšèªã§ããããå®è£
ããå Žåã¯ãURLSession(iOS)ãš HttpURLConnection(Android)ããããã¯åãã©ãããã©ãŒã åãã«æäŸãããŠãããµãŒãããŒãã£ã®ã©ã€ãã©ãªãªã©ã䜿ããšæããŸãããåœç¶ãAPI ã¯ç°ãªãã®ã§ããããã®å®è£
æ¹æ³ãææ¡ããªããšãããªããªããŸããããã«æ¯ã¹ããšåŠç¿ã³ã¹ãã¯äœããªãããã§ãã // js/actions/index.js export function fetchHelthNews () { return ( dispatch ) => fetch ( constructHealthNewsUrl ()) . then (( response ) => response . json ()) . then (( json ) => dispatch ( receiveHelthNews ( json . articles ))) . catch (( error ) => { console . log ( error ); }); } ãã€ãã£ãã¢ããªç¹æã®æ©èœã«ã€ã㊠ãã®ä»ã®ã¢ããªéçºã§ãã䜿ããã€ãã£ãã¢ããªç¹æã®æ©èœãå®è£
ããæ¹æ³ã¯ä»¥äžã®ããã«ãªããŸããå€ãã®æ©èœããµãŒãããŒãã£ã®ã©ã€ãã©ãªã«äŸåããŠããã®ã§ãåèšèªã®ããŒãžã§ã³ã¢ããæã®å¯Ÿå¿ãå°ãå¿é
ã§ã¯ãããŸãããããäœ¿ãæ©èœã«ã€ããŠã¯å®çŸããããšãã§ããŸãã Push éç¥ïŒAndroid ã¯ãã³ããªã³ã°ãã API ãå
¬åŒã§æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã ã«ã¡ã©ãããŒãã§ãŒã³ã¢ã¯ã»ã¹/ãŠãŒã¶ããã©ã«ãïŒå
¬åŒã® API ã¯æäŸãããŠããªãã®ã§ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ã äœçœ®æ
å ±ã®ååŸïŒå
¬åŒ API ãæäŸãããŠãã ãã£ãŒããªã³ã¯ïŒã¢ããªèµ·åæã«ãã³ããªã³ã°ãè¡ã API ã¯æäŸãããŠããããŠãããŒãµã«ãªã³ã¯ã IntentFilter ã®èšå®ã¯åãã©ãããã©ãŒã ã§åå¥ã«å¿
èŠã«ãªã ãªãªãŒã¹ã¯ã©ãããã ã¢ãŒã«ã€ããã¹ãã¢é
åžã«ã€ããŠã¯ãã€ãã£ãã¢ããªã®é
åžãšåãããã»ã¹ã«ãªããŸãã åãã©ãããã©ãŒã ã§èšŒææžçã®èšå®ãè¡ããXcode ã Android Studioãããã㯠CLI ã§ã³ãã³ããå®è¡ããŠãipa / apk ãã¡ã€ã«ãäœæããå Store ã«ã¢ããããŒãããå¿
èŠããããŸãã CI 㯠Bitrise ãªã©ã䜿ããŸããBitrise ã§ãã«ãã詊ããŠã¿ãŸããããReact Native ã®ãªããžããªãšæ¥ç¶ãããšãã«ã§ããããã©ã«ãã®ã¯ãŒã¯ãããŒã䜿ãã°ãåæã« 2 ãã©ãããã©ãŒã ã®ã¢ãŒã«ã€ããäœæã§ããŠäŸ¿å©ã§ããã ããšããŸã 詊ããŠã¯ããªãã®ã§ãã CodePush ã䜿ãã°ã審æ»ã«æåºããããšãªãã«æ¢åã®ã¢ããªã倿Žããããšãã§ãããããã®ã§ãéåžžã«äŸ¿å©ã ãšæããŸããã ã©ããªå Žåã« React Native ãæ¡çšã§ãããã? React Native ã§éçºããããšã§ãWeb éçºè
ã®èŠç¹ã§èŠããšãã©ãããã©ãŒã ã®ãã€ãã£ãèšèªã§éçºããããããã ãã¶åŠç¿ã³ã¹ããäžããã®ã§ã¯ãªãããšæããŸããããŸããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿ãã°ãæ©èœçã«å€§ããªåé¡ãšãªããããªããšã¯ãªãããã§ããããã ãç»é¢é·ç§»ã®ã©ã€ãã©ãªãããã ã£ãããã«ãããããããããšãã§ããªããšããå Žåã¯ã劥åããªããšãããªãéšåãåºãŠãããã ãšæããŸããã äžæ¹ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ãæ
£ãããŸã§ã¯ããªãéçºé床ãäžãããããªã®ã§ãã¡ãªããã倧ããããªãšæããŸãããReact ãš JSããŸã Redux ãªã©ãæ°ãã«çè§£ãã€ã€éçºããŠããã®ã§çµæ§ããŒãã«ãé«ããšæããŸãããéçºç°å¢ããã«ããéã£ãŠããã¡ã¯ãView åšãã®èª¿æŽãããã«ç¢ºèªã§ããŠè¯ãã£ãã®ã§ãããã©ã³ã¿ã€ã ãšã©ãŒã«ãªããªã©ã§ãã·ãã¥ã¬ãŒã¿ããªããŒãã§ããªããªã£ãå Žåã«å床ãã«ããçŽããšããããšãããèµ·ãããåžžã«å¿«é©ã«éçºã§ãããšããããã§ã¯ãããŸããã§ããã éçšé¢ã§ã¿ããšäžéãã¢ãããªéçºã«å¿
èŠãããªããŒã«ã¯æã£ãŠããã(ã¯ã©ãã·ã¥ç£èŠãCIããã¹ãé
ä¿¡ããªãªãŒã¹)ãCode Push ãªã©äŸ¿å©ãªããŒã«ãããã®ã§å©ç¹ãå€ããšæããŸããã çµè«ãšããŠã¯ãWeb ãšã³ãžãã¢ã瀟å
ã«å€ãã£ãããéçºããŒã ã« ReactãJS ãåŸæãªã¡ã³ããŒããããªããå®éã®éçºã§ã䜿ããããªãšæããŸããããã ãã¢ããªãšã³ãžãã¢ã«ãšã£ãŠã¯ããªãã¹ãã¬ã¹ãããŸããããžã§ã¯ãã«ãªãããã ãšæããŸããã ãŸãšã èªåã®çŸç¶ã§èãããšãã¢ããªã¯åŸæã ãã© JS ã React ã«ãããŸã§è©³ãããªãã®ã§ãããçŽè¿ã®ãããžã§ã¯ãã§é£æåºŠãããããé«ãããã§ããã°ãæ£çŽãããŸã䜿ããããªããªããšããæ°æã¡ããããŸãããã ãæè¡ã®å¹
ãåºãããšããçµç¹å
šäœã®ããŒã¿ããªãã£ãªã©ã®èгç¹ã§èãããšå©ç¹ãçµæ§ããã®ããªãšæããŸãããã£ã³ã¹ãããã°ãã²ããã£ã¬ã³ãžããŠã¿ããã§ãã ãããã¯ã©ã¡ãããšãããšæè¡ãéçºããŒã«ã®æ°ãããããããŠãŒã¶ãšã®æ¥ç¹ã®ãšããã§æ°ããããšãé¢çœãããšã远æ±ããããšæã£ãŠããŸãããéçºå¹çãå質ã®åäžã®ããã«æé©ãªãã®ãéžæã§ããããã«ãä»åŸãæ°ããããŒã«ã®ãã£ããã¢ããã¯ç©æ¥µçã«è¡ã£ãŠãããããšæã£ãŠããŸãã ãç¥ãã ã¡ãã¬ãŒã¯ã5/31-6/2 ã«éå¬ããã RubyKaigi 2018 ã« LT ã¹ãã³ãµãŒãšããŠåè³ããŸããããŒã¹ãæ§ããŠãããŸãã®ã§ãã€ãã³ãã«ãè¶ãã«ãªãæ¹ã¯ããã²ããŒã¹ã«ãéã³ã«ããããŠãã ããïŒ RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®åŸè€ã§ããå»çä»è·ã®æ±äººãµã€ãããžã§ãã¡ãã¬ãŒãã®éçºãæ
åœããŠããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯åçš®ãã£ãã·ã¥ã sidekiq ã® queue çã« ElastiCache for Redis ãå©çšããŠããŸãã å
æ¥ãã¡ãã¬ãŒã§å®æéå¬ããŠãã瀟å
ååŒ·äŒ TechLunch ã«ãŠããžã§ãã¡ãã¬ãŒã§ã® ElastiCache for Redis ã®éçšåšãã®ãã¿ãç¥èŠã«ã€ããŠçºè¡šããŸãããæ¬èšäºã§ã¯ããã®äžããæç²ããŠã¡ã¢ãªåšãã®è©±ã«ã€ããŠç޹ä»ããŸãã ããŒåé€åšãã®ä»æ§ã«ã€ã㊠ãã£ãã·ã¥ãšã㊠ElastiCache for Redis ãå©çšããŠããäžã§ãŸãææ¡ããŠããããã®ããããŒã®åé€åšãã®ä»æ§ã§ãã Redis æ¬å®¶ã® Expiration/Eviction Expiration ã«ã€ããŠã¯ Redis ã§ã¯ããŒã« TTL ãèšå®ããããšã§æå¹æéãèšå®ããããšãã§ãã ãã¡ã ã«èšèŒã®ããžãã¯ã§åé€åŠçã宿œããŠãããŸãã Eviction ã«ã€ããŠã¯ Redis æ¬å®¶ã®å®è£
ã§ã¯ä»¥äžã®ãããªä»æ§ã«ãªã£ãŠããŸããRedis æ¬å®¶ããã¥ã¡ã³ã㯠ãã¡ã ã used_memory ïŒã¢ããªãå©çšããŠããã¡ã¢ãªéïŒã maxmemory å€ãè¶
ãå§ããã Eviction ãçºç«ãå§ãã maxmemory 㯠redis.conf æå®ã CONFIG SET ã³ãã³ãã§èšå®ã§ãã maxmemory ã«å°éãããã©ã®ããã«æ¯ãèãã¹ããã maxmemory-policy ã§æå® noeviction : 容éãå¿
èŠãªãªãã¬ãŒã·ã§ã³ã§ã¯ evit ããããšã©ãŒãšãªã allkeys-lru : åžžã« LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® volatile-lru : TTL ãèšå®ãããããŒå
ã§ LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® allkeys-random : åžžã«ã©ã³ãã ã«åé€å¯Ÿè±¡éžå®ããŠåé€ volatile-random : TTL ãèšå®ãããããŒå
ã§ã©ã³ãã ã«åé€å¯Ÿè±¡éžå® volatile-ttl : TTL ãèšå®ãããããŒå
ã§ TTL ãŸããElastiCache for Redis ã§ã¯ãŸã 3 ç³»åãŸã§ãã䜿ããŸãããã4 ç³»åã§ã¯æ°ãã« LFU ãéžæè¢ã«å
¥ã£ãŠããããã§ãã Redis æ¬å®¶ã® Eviction ã®åäœä»æ§ãšããŠã¯ä»¥äžã®ã€ã¡ãŒãžã§ãã github.com github.com ElastiCache for Redis ã§ã¯ maxmemory ã¯ç·šéã§ããããã®ä»£ããã«åŸè¿°ãã reserved-memory ïŒ reserved-memory-percent ïŒãèšå®ãããš Eviction ãçºç«ããã¡ã¢ãªéã®éŸå€ãå€ããããšããäžèšåšãã®å®è£
㯠AWS åŽã§æãå
¥ããŠãããã§ãã ElastiCache for Redis ã§ã® Eviction ElastiCache for Redis ã§ã¯ä»¥äžã®ããã« Redis æ¬å®¶ã«ã¯ãªã reserved-memory ãšããæŠå¿µãããã®ã§æ³šæãå¿
èŠã§ãã maxmemory ã¯ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã«ãã£ãŠåºå®å€ã«èšå®ãããŠãã maxmemory ã¯ å€æŽã§ããªã 代ããã« reserved-memory or reserved-memory-percent ãèšå®ã㊠Eviction çºç«ã¡ã¢ãªéãèšå®ã§ãã maxmemory - reserved-memory < used_memory ã§ Eviction ãçºç«ãã å€ãã®ã€ã³ã¹ã¿ã³ã¹ïŒ2017 幎 3 æ 16 æ¥ä»¥åäœæïŒã§ã¯ reserved-memory ããã©ã¡ãŒã¿ãšããŠå©çšã§ãããã reserved-memory ã®ããã©ã«ãå€ã¯ 0byte reserved-memory-percent ã®ããã©ã«ãå€ã¯ 25% ãã®åšèŸºã® AWS å
¬åŒããã¥ã¡ã³ã㯠ãã¡ã ãžã§ãã¡ãã¬ãŒã§ã¯åäžã® ElastiCache for Redis ã€ã³ã¹ã¿ã³ã¹ã§éçšå¯Ÿè±¡ãæžããæŠç¥ãåã£ãŠããŸãïŒRedis æ¬å®¶ã§ã¯çšéå¥ã«åããŠé©åã«ãã¥ãŒãã³ã°ããããšãæšå¥šããŠãããããå°æ¥çã«ã¯ãã®æ§æã¯å€ãããããããŸããïŒããã®ããããã£ãã·ã¥å©çšã®ããŒã«ã¯å¿
ã TTL ãèšå®ããEviction policy 㯠volatile-lru ãšããŠããŸãã ãããŠãå°ãäœè£ãããã㊠reserved-memory ãèšå®ãEvictions ã¡ããªã¯ã¹ã®ç£èŠãããŠããŸãã ã¡ã¢ãªå©çšéã SQL ã§åæãã çŸåšçšŒåããŠããæ¬çªç°å¢äžã§ã©ã®ãã¿ãŒã³ã®ããŒãã©ã®çšåºŠã®ã¡ã¢ãªã䜿ã£ãŠããããææ¡ããããªãå Žé¢ã«åºããããæ¹ãããã£ãããã®ã§ã¯ãªãã§ããããã ElastiCache for Redis ã§ã¯ç°¡åã« RDB ã¹ãããã·ã§ãããååŸããããšãã§ããŸãããã®ããŒã¿ãããŸã䜿ãã°çŽæ¥æ¬çªçšŒåã®ã€ã³ã¹ã¿ã³ã¹ãè§Šãã«ããããšãªããæå
ã§å®å¿ããŠåæäœæ¥ã宿œã§ããŸãã ãã®åæäœæ¥ã«äŸ¿å©ãªã®ã redis-rdb-tools ã§ãããã®ããŒã«ã¯ RDB ãã¡ã€ã«ã®å
容ãããšã«ããŒããšã® byte å€ã以äžã®ãã㪠CSV ã«åºåããããšãã§ããŸãïŒ size_in_bytes ã¯çè«å€ïŒã $ rdb -c memory dump.rdb > memory.csv ; $ cat memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,list,lizards,241,quicklist,5,19 2,hash,baloon,138,ziplist,3,11 ãã® csv ã以äžã®ããã« SQLite çã®ããŒã¿ããŒã¹ã«çªã£èŸŒãããšã§æå
ã§ SQL ã䜿ã£ãŠã¡ã¢ãªçµ±èšã®åæãã§ããããã«ãªããŸãã $ rdb -c memory dump.rdb > memory.csv ; $ sqlite3 memory.db sqlite > create table memory ( database int,type varchar ( 128 ) ,key varchar ( 128 ) ,size_in_bytes int,encoding varchar ( 128 ) ,num_elements int,len_largest_element varchar ( 128 )); sqlite > .mode csv memory sqlite > .import memory.csv memory ãã£ãããšããåæã®æµã㯠æ¬çªç°å¢ã® daily backup RDB ååŸ redis-rdb-tools ã§ csv åºå csv ã sqlite ã« csv format ã§ import SQL ã§åæ ã®ããã«ãªããŸããããŒã¿ããŒã¹ã«ã€ã³ããŒãããåºæ¥ãŠããŸãã°ä»¥äžã®ããã«æ§ã
ãªåæãå¯èœã«ãªããŸãã sqlite > select sum ( size_in_bytes ) from memory where key like '%cells%' ; XXXXX sqlite > select count (*) from memory where key like '%cells%' ; XXXXX 泚æç¹ãšããŠã¯å®éã«æ¬çªçšŒåããŠããã¡ã¢ãªéãååŸããŠããããã§ã¯ãªãã®ã§å®æž¬å€ãšå€ããããŠããããšã§ãïŒæèŠçã«ã¯çè«å€ã¯å®æž¬å€ã® 1/2 ãããã§ããïŒããã¡ãã®è©³çŽ°ã®æšå®ããžãã¯ãæ°ã«ãªãæ¹ã¯ å®è£
ã確èªããã ããã°ãšæããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯ãã®ææ³ã䜿ã£ãŠåæããããšã§ã¢ããªããžãã¯ãä¿®æ£ããŠäžèŠãªã¡ã¢ãªå©çšã®æ¹åçã«åœ¹ç«ãŠãŠããŸãã ãŸãšã ElastiCache for Redis ã®ã¡ã¢ãªåšããäžå¿ãšããéçšãã¿ã«ã€ããŠç޹ä»ããŸããã ElastiCache for Redis ã¯ãšãŠã䟿å©ã§ã·ã¥ããšèšå®ããŠãããªãã®èŠæš¡ã§ããªããšãªãéçšã§ããŠããŸãæè»œãããããŸãããæ²¹æããŠãããšæãã¬èœãšã穎ã«ã¯ãŸãããšããããŸãã æ¬èšäºãã¿ãªããŸã® ElastiCache for Redis éçšã©ã€ãã®äžå©ã«ãªãã°å¹žãã§ãã ãŸãããžã§ãã¡ãã¬ãŒãã¯ãããã¡ãã¬ãŒã®éçºã«ãèå³ããæ¹ã¯ããã²ãé£çµ¡ãã ããã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp ã¡ãã¬ãŒã LT ã¹ãã³ãµãŒãåãã RubyKaigi2018 ã«ããéªéããäºå®ïŒããŸã«ããŒã¹ã«ç«ã£ãŠããŸãïŒã®ã§ããã¡ãã§ããäŒãããŸãããã RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®åŸè€ã§ããå»çä»è·ã®æ±äººãµã€ãããžã§ãã¡ãã¬ãŒãã®éçºãæ
åœããŠããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯åçš®ãã£ãã·ã¥ã sidekiq ã® queue çã« ElastiCache for Redis ãå©çšããŠããŸãã å
æ¥ãã¡ãã¬ãŒã§å®æéå¬ããŠãã瀟å
ååŒ·äŒ TechLunch ã«ãŠããžã§ãã¡ãã¬ãŒã§ã® ElastiCache for Redis ã®éçšåšãã®ãã¿ãç¥èŠã«ã€ããŠçºè¡šããŸãããæ¬èšäºã§ã¯ããã®äžããæç²ããŠã¡ã¢ãªåšãã®è©±ã«ã€ããŠç޹ä»ããŸãã ããŒåé€åšãã®ä»æ§ã«ã€ã㊠ãã£ãã·ã¥ãšã㊠ElastiCache for Redis ãå©çšããŠããäžã§ãŸãææ¡ããŠããããã®ããããŒã®åé€åšãã®ä»æ§ã§ãã Redis æ¬å®¶ã® Expiration/Eviction Expiration ã«ã€ããŠã¯ Redis ã§ã¯ããŒã« TTL ãèšå®ããããšã§æå¹æéãèšå®ããããšãã§ãã ãã¡ã ã«èšèŒã®ããžãã¯ã§åé€åŠçã宿œããŠãããŸãã Eviction ã«ã€ããŠã¯ Redis æ¬å®¶ã®å®è£
ã§ã¯ä»¥äžã®ãããªä»æ§ã«ãªã£ãŠããŸããRedis æ¬å®¶ããã¥ã¡ã³ã㯠ãã¡ã ã used_memory ïŒã¢ããªãå©çšããŠããã¡ã¢ãªéïŒã maxmemory å€ãè¶
ãå§ããã Eviction ãçºç«ãå§ãã maxmemory 㯠redis.conf æå®ã CONFIG SET ã³ãã³ãã§èšå®ã§ãã maxmemory ã«å°éãããã©ã®ããã«æ¯ãèãã¹ããã maxmemory-policy ã§æå® noeviction : 容éãå¿
èŠãªãªãã¬ãŒã·ã§ã³ã§ã¯ evit ããããšã©ãŒãšãªã allkeys-lru : åžžã« LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® volatile-lru : TTL ãèšå®ãããããŒå
ã§ LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® allkeys-random : åžžã«ã©ã³ãã ã«åé€å¯Ÿè±¡éžå®ããŠåé€ volatile-random : TTL ãèšå®ãããããŒå
ã§ã©ã³ãã ã«åé€å¯Ÿè±¡éžå® volatile-ttl : TTL ãèšå®ãããããŒå
ã§ TTL ãŸããElastiCache for Redis ã§ã¯ãŸã 3 ç³»åãŸã§ãã䜿ããŸãããã4 ç³»åã§ã¯æ°ãã« LFU ãéžæè¢ã«å
¥ã£ãŠããããã§ãã Redis æ¬å®¶ã® Eviction ã®åäœä»æ§ãšããŠã¯ä»¥äžã®ã€ã¡ãŒãžã§ãã https://github.com/antirez/redis/blob/3.2.10/src/server.c#L3343-L3357 ElastiCache for Redis ã§ã¯ maxmemory ã¯ç·šéã§ããããã®ä»£ããã«åŸè¿°ãã reserved-memory ïŒ reserved-memory-percent ïŒãèšå®ãããš Eviction ãçºç«ããã¡ã¢ãªéã®éŸå€ãå€ããããšããäžèšåšãã®å®è£
㯠AWS åŽã§æãå
¥ããŠãããã§ãã ElastiCache for Redis ã§ã® Eviction ElastiCache for Redis ã§ã¯ä»¥äžã®ããã« Redis æ¬å®¶ã«ã¯ãªã reserved-memory ãšããæŠå¿µãããã®ã§æ³šæãå¿
èŠã§ãã maxmemory ã¯ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã«ãã£ãŠåºå®å€ã«èšå®ãããŠãã maxmemory ã¯ å€æŽã§ããªã 代ããã« reserved-memory or reserved-memory-percent ãèšå®ã㊠Eviction çºç«ã¡ã¢ãªéãèšå®ã§ãã maxmemory - reserved-memory < used_memory ã§ Eviction ãçºç«ãã å€ãã®ã€ã³ã¹ã¿ã³ã¹ïŒ2017 幎 3 æ 16 æ¥ä»¥åäœæïŒã§ã¯ reserved-memory ããã©ã¡ãŒã¿ãšããŠå©çšã§ãããã reserved-memory ã®ããã©ã«ãå€ã¯ 0byte reserved-memory-percent ã®ããã©ã«ãå€ã¯ 25% ãã®åšèŸºã® AWS å
¬åŒããã¥ã¡ã³ã㯠ãã¡ã ãžã§ãã¡ãã¬ãŒã§ã¯åäžã® ElastiCache for Redis ã€ã³ã¹ã¿ã³ã¹ã§éçšå¯Ÿè±¡ãæžããæŠç¥ãåã£ãŠããŸãïŒRedis æ¬å®¶ã§ã¯çšéå¥ã«åããŠé©åã«ãã¥ãŒãã³ã°ããããšãæšå¥šããŠãããããå°æ¥çã«ã¯ãã®æ§æã¯å€ãããããããŸããïŒããã®ããããã£ãã·ã¥å©çšã®ããŒã«ã¯å¿
ã TTL ãèšå®ããEviction policy 㯠volatile-lru ãšããŠããŸãã ãããŠãå°ãäœè£ãããã㊠reserved-memory ãèšå®ãEvictions ã¡ããªã¯ã¹ã®ç£èŠãããŠããŸãã ã¡ã¢ãªå©çšéã SQL ã§åæãã çŸåšçšŒåããŠããæ¬çªç°å¢äžã§ã©ã®ãã¿ãŒã³ã®ããŒãã©ã®çšåºŠã®ã¡ã¢ãªã䜿ã£ãŠããããææ¡ããããªãå Žé¢ã«åºããããæ¹ãããã£ãããã®ã§ã¯ãªãã§ããããã ElastiCache for Redis ã§ã¯ç°¡åã« RDB ã¹ãããã·ã§ãããååŸããããšãã§ããŸãããã®ããŒã¿ãããŸã䜿ãã°çŽæ¥æ¬çªçšŒåã®ã€ã³ã¹ã¿ã³ã¹ãè§Šãã«ããããšãªããæå
ã§å®å¿ããŠåæäœæ¥ã宿œã§ããŸãã ãã®åæäœæ¥ã«äŸ¿å©ãªã®ã redis-rdb-tools ã§ãããã®ããŒã«ã¯ RDB ãã¡ã€ã«ã®å
容ãããšã«ããŒããšã® byte å€ã以äžã®ãã㪠CSV ã«åºåããããšãã§ããŸãïŒ size_in_bytes ã¯çè«å€ïŒã $ rdb -c memory dump.rdb > memory.csv ; $ cat memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,list,lizards,241,quicklist,5,19 2,hash,baloon,138,ziplist,3,11 ãã® csv ã以äžã®ããã« SQLite çã®ããŒã¿ããŒã¹ã«çªã£èŸŒãããšã§æå
ã§ SQL ã䜿ã£ãŠã¡ã¢ãªçµ±èšã®åæãã§ããããã«ãªããŸãã $ rdb -c memory dump.rdb > memory.csv ; $ sqlite3 memory.db sqlite > create table memory ( database int,type varchar ( 128 ) ,key varchar ( 128 ) ,size_in_bytes int,encoding varchar ( 128 ) ,num_elements int,len_largest_element varchar ( 128 )); sqlite > .mode csv memory sqlite > .import memory.csv memory ãã£ãããšããåæã®æµã㯠æ¬çªç°å¢ã® daily backup RDB ååŸ redis-rdb-tools ã§ csv åºå csv ã sqlite ã« csv format ã§ import SQL ã§åæ ã®ããã«ãªããŸããããŒã¿ããŒã¹ã«ã€ã³ããŒãããåºæ¥ãŠããŸãã°ä»¥äžã®ããã«æ§ã
ãªåæãå¯èœã«ãªããŸãã sqlite > select sum ( size_in_bytes ) from memory where key like '%cells%' ; XXXXX sqlite > select count (*) from memory where key like '%cells%' ; XXXXX 泚æç¹ãšããŠã¯å®éã«æ¬çªçšŒåããŠããã¡ã¢ãªéãååŸããŠããããã§ã¯ãªãã®ã§å®æž¬å€ãšå€ããããŠããããšã§ãïŒæèŠçã«ã¯çè«å€ã¯å®æž¬å€ã® 1/2 ãããã§ããïŒããã¡ãã®è©³çŽ°ã®æšå®ããžãã¯ãæ°ã«ãªãæ¹ã¯ å®è£
ã確èªããã ããã°ãšæããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯ãã®ææ³ã䜿ã£ãŠåæããããšã§ã¢ããªããžãã¯ãä¿®æ£ããŠäžèŠãªã¡ã¢ãªå©çšã®æ¹åçã«åœ¹ç«ãŠãŠããŸãã ãŸãšã ElastiCache for Redis ã®ã¡ã¢ãªåšããäžå¿ãšããéçšãã¿ã«ã€ããŠç޹ä»ããŸããã ElastiCache for Redis ã¯ãšãŠã䟿å©ã§ã·ã¥ããšèšå®ããŠãããªãã®èŠæš¡ã§ããªããšãªãéçšã§ããŠããŸãæè»œãããããŸãããæ²¹æããŠãããšæãã¬èœãšã穎ã«ã¯ãŸãããšããããŸãã æ¬èšäºãã¿ãªããŸã® ElastiCache for Redis éçšã©ã€ãã®äžå©ã«ãªãã°å¹žãã§ãã ãŸãããžã§ãã¡ãã¬ãŒãã¯ãããã¡ãã¬ãŒã®éçºã«ãèå³ããæ¹ã¯ããã²ãé£çµ¡ãã ããã https://www.medley.jp/recruit/creative.html ã¡ãã¬ãŒã LT ã¹ãã³ãµãŒãåãã RubyKaigi2018 ã«ããéªéããäºå®ïŒããŸã«ããŒã¹ã«ç«ã£ãŠããŸãïŒã®ã§ããã¡ãã§ããäŒãããŸãããã https://rubykaigi.org/2018
ããã«ã¡ã¯ãéçºæ¬éšã®åŸè€ã§ããå»çä»è·ã®æ±äººãµã€ãããžã§ãã¡ãã¬ãŒãã®éçºãæ
åœããŠããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯åçš®ãã£ãã·ã¥ã sidekiq ã® queue çã« ElastiCache for Redis ãå©çšããŠããŸãã å
æ¥ãã¡ãã¬ãŒã§å®æéå¬ããŠãã瀟å
ååŒ·äŒ TechLunch ã«ãŠããžã§ãã¡ãã¬ãŒã§ã® ElastiCache for Redis ã®éçšåšãã®ãã¿ãç¥èŠã«ã€ããŠçºè¡šããŸãããæ¬èšäºã§ã¯ããã®äžããæç²ããŠã¡ã¢ãªåšãã®è©±ã«ã€ããŠç޹ä»ããŸãã ããŒåé€åšãã®ä»æ§ã«ã€ã㊠ãã£ãã·ã¥ãšã㊠ElastiCache for Redis ãå©çšããŠããäžã§ãŸãææ¡ããŠããããã®ããããŒã®åé€åšãã®ä»æ§ã§ãã Redis æ¬å®¶ã® Expiration/Eviction Expiration ã«ã€ããŠã¯ Redis ã§ã¯ããŒã« TTL ãèšå®ããããšã§æå¹æéãèšå®ããããšãã§ãã ãã¡ã ã«èšèŒã®ããžãã¯ã§åé€åŠçã宿œããŠãããŸãã Eviction ã«ã€ããŠã¯ Redis æ¬å®¶ã®å®è£
ã§ã¯ä»¥äžã®ãããªä»æ§ã«ãªã£ãŠããŸããRedis æ¬å®¶ããã¥ã¡ã³ã㯠ãã¡ã ã used_memory ïŒã¢ããªãå©çšããŠããã¡ã¢ãªéïŒã maxmemory å€ãè¶
ãå§ããã Eviction ãçºç«ãå§ãã maxmemory 㯠redis.conf æå®ã CONFIG SET ã³ãã³ãã§èšå®ã§ãã maxmemory ã«å°éãããã©ã®ããã«æ¯ãèãã¹ããã maxmemory-policy ã§æå® noeviction : 容éãå¿
èŠãªãªãã¬ãŒã·ã§ã³ã§ã¯ evit ããããšã©ãŒãšãªã allkeys-lru : åžžã« LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® volatile-lru : TTL ãèšå®ãããããŒå
ã§ LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® allkeys-random : åžžã«ã©ã³ãã ã«åé€å¯Ÿè±¡éžå®ããŠåé€ volatile-random : TTL ãèšå®ãããããŒå
ã§ã©ã³ãã ã«åé€å¯Ÿè±¡éžå® volatile-ttl : TTL ãèšå®ãããããŒå
ã§ TTL ãŸããElastiCache for Redis ã§ã¯ãŸã 3 ç³»åãŸã§ãã䜿ããŸãããã4 ç³»åã§ã¯æ°ãã« LFU ãéžæè¢ã«å
¥ã£ãŠããããã§ãã Redis æ¬å®¶ã® Eviction ã®åäœä»æ§ãšããŠã¯ä»¥äžã®ã€ã¡ãŒãžã§ãã github.com github.com ElastiCache for Redis ã§ã¯ maxmemory ã¯ç·šéã§ããããã®ä»£ããã«åŸè¿°ãã reserved-memory ïŒ reserved-memory-percent ïŒãèšå®ãããš Eviction ãçºç«ããã¡ã¢ãªéã®éŸå€ãå€ããããšããäžèšåšãã®å®è£
㯠AWS åŽã§æãå
¥ããŠãããã§ãã ElastiCache for Redis ã§ã® Eviction ElastiCache for Redis ã§ã¯ä»¥äžã®ããã« Redis æ¬å®¶ã«ã¯ãªã reserved-memory ãšããæŠå¿µãããã®ã§æ³šæãå¿
èŠã§ãã maxmemory ã¯ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã«ãã£ãŠåºå®å€ã«èšå®ãããŠãã maxmemory ã¯ å€æŽã§ããªã 代ããã« reserved-memory or reserved-memory-percent ãèšå®ã㊠Eviction çºç«ã¡ã¢ãªéãèšå®ã§ãã maxmemory - reserved-memory < used_memory ã§ Eviction ãçºç«ãã å€ãã®ã€ã³ã¹ã¿ã³ã¹ïŒ2017 幎 3 æ 16 æ¥ä»¥åäœæïŒã§ã¯ reserved-memory ããã©ã¡ãŒã¿ãšããŠå©çšã§ãããã reserved-memory ã®ããã©ã«ãå€ã¯ 0byte reserved-memory-percent ã®ããã©ã«ãå€ã¯ 25% ãã®åšèŸºã® AWS å
¬åŒããã¥ã¡ã³ã㯠ãã¡ã ãžã§ãã¡ãã¬ãŒã§ã¯åäžã® ElastiCache for Redis ã€ã³ã¹ã¿ã³ã¹ã§éçšå¯Ÿè±¡ãæžããæŠç¥ãåã£ãŠããŸãïŒRedis æ¬å®¶ã§ã¯çšéå¥ã«åããŠé©åã«ãã¥ãŒãã³ã°ããããšãæšå¥šããŠãããããå°æ¥çã«ã¯ãã®æ§æã¯å€ãããããããŸããïŒããã®ããããã£ãã·ã¥å©çšã®ããŒã«ã¯å¿
ã TTL ãèšå®ããEviction policy 㯠volatile-lru ãšããŠããŸãã ãããŠãå°ãäœè£ãããã㊠reserved-memory ãèšå®ãEvictions ã¡ããªã¯ã¹ã®ç£èŠãããŠããŸãã ã¡ã¢ãªå©çšéã SQL ã§åæãã çŸåšçšŒåããŠããæ¬çªç°å¢äžã§ã©ã®ãã¿ãŒã³ã®ããŒãã©ã®çšåºŠã®ã¡ã¢ãªã䜿ã£ãŠããããææ¡ããããªãå Žé¢ã«åºããããæ¹ãããã£ãããã®ã§ã¯ãªãã§ããããã ElastiCache for Redis ã§ã¯ç°¡åã« RDB ã¹ãããã·ã§ãããååŸããããšãã§ããŸãããã®ããŒã¿ãããŸã䜿ãã°çŽæ¥æ¬çªçšŒåã®ã€ã³ã¹ã¿ã³ã¹ãè§Šãã«ããããšãªããæå
ã§å®å¿ããŠåæäœæ¥ã宿œã§ããŸãã ãã®åæäœæ¥ã«äŸ¿å©ãªã®ã redis-rdb-tools ã§ãããã®ããŒã«ã¯ RDB ãã¡ã€ã«ã®å
容ãããšã«ããŒããšã® byte å€ã以äžã®ãã㪠CSV ã«åºåããããšãã§ããŸãïŒ size_in_bytes ã¯çè«å€ïŒã $ rdb -c memory dump.rdb > memory.csv ; $ cat memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,list,lizards,241,quicklist,5,19 2,hash,baloon,138,ziplist,3,11 ãã® csv ã以äžã®ããã« SQLite çã®ããŒã¿ããŒã¹ã«çªã£èŸŒãããšã§æå
ã§ SQL ã䜿ã£ãŠã¡ã¢ãªçµ±èšã®åæãã§ããããã«ãªããŸãã $ rdb -c memory dump.rdb > memory.csv ; $ sqlite3 memory.db sqlite > create table memory ( database int,type varchar ( 128 ) ,key varchar ( 128 ) ,size_in_bytes int,encoding varchar ( 128 ) ,num_elements int,len_largest_element varchar ( 128 )); sqlite > .mode csv memory sqlite > .import memory.csv memory ãã£ãããšããåæã®æµã㯠æ¬çªç°å¢ã® daily backup RDB ååŸ redis-rdb-tools ã§ csv åºå csv ã sqlite ã« csv format ã§ import SQL ã§åæ ã®ããã«ãªããŸããããŒã¿ããŒã¹ã«ã€ã³ããŒãããåºæ¥ãŠããŸãã°ä»¥äžã®ããã«æ§ã
ãªåæãå¯èœã«ãªããŸãã sqlite > select sum ( size_in_bytes ) from memory where key like '%cells%' ; XXXXX sqlite > select count (*) from memory where key like '%cells%' ; XXXXX 泚æç¹ãšããŠã¯å®éã«æ¬çªçšŒåããŠããã¡ã¢ãªéãååŸããŠããããã§ã¯ãªãã®ã§å®æž¬å€ãšå€ããããŠããããšã§ãïŒæèŠçã«ã¯çè«å€ã¯å®æž¬å€ã® 1/2 ãããã§ããïŒããã¡ãã®è©³çŽ°ã®æšå®ããžãã¯ãæ°ã«ãªãæ¹ã¯ å®è£
ã確èªããã ããã°ãšæããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯ãã®ææ³ã䜿ã£ãŠåæããããšã§ã¢ããªããžãã¯ãä¿®æ£ããŠäžèŠãªã¡ã¢ãªå©çšã®æ¹åçã«åœ¹ç«ãŠãŠããŸãã ãŸãšã ElastiCache for Redis ã®ã¡ã¢ãªåšããäžå¿ãšããéçšãã¿ã«ã€ããŠç޹ä»ããŸããã ElastiCache for Redis ã¯ãšãŠã䟿å©ã§ã·ã¥ããšèšå®ããŠãããªãã®èŠæš¡ã§ããªããšãªãéçšã§ããŠããŸãæè»œãããããŸãããæ²¹æããŠãããšæãã¬èœãšã穎ã«ã¯ãŸãããšããããŸãã æ¬èšäºãã¿ãªããŸã® ElastiCache for Redis éçšã©ã€ãã®äžå©ã«ãªãã°å¹žãã§ãã ãŸãããžã§ãã¡ãã¬ãŒãã¯ãããã¡ãã¬ãŒã®éçºã«ãèå³ããæ¹ã¯ããã²ãé£çµ¡ãã ããã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp ã¡ãã¬ãŒã LT ã¹ãã³ãµãŒãåãã RubyKaigi2018 ã«ããéªéããäºå®ïŒããŸã«ããŒã¹ã«ç«ã£ãŠããŸãïŒã®ã§ããã¡ãã§ããäŒãããŸãããã RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®åŸè€ã§ããå»çä»è·ã®æ±äººãµã€ãããžã§ãã¡ãã¬ãŒãã®éçºãæ
åœããŠããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯åçš®ãã£ãã·ã¥ã sidekiq ã® queue çã« ElastiCache for Redis ãå©çšããŠããŸãã å
æ¥ãã¡ãã¬ãŒã§å®æéå¬ããŠãã瀟å
ååŒ·äŒ TechLunch ã«ãŠããžã§ãã¡ãã¬ãŒã§ã® ElastiCache for Redis ã®éçšåšãã®ãã¿ãç¥èŠã«ã€ããŠçºè¡šããŸãããæ¬èšäºã§ã¯ããã®äžããæç²ããŠã¡ã¢ãªåšãã®è©±ã«ã€ããŠç޹ä»ããŸãã ããŒåé€åšãã®ä»æ§ã«ã€ã㊠ãã£ãã·ã¥ãšã㊠ElastiCache for Redis ãå©çšããŠããäžã§ãŸãææ¡ããŠããããã®ããããŒã®åé€åšãã®ä»æ§ã§ãã Redis æ¬å®¶ã® Expiration/Eviction Expiration ã«ã€ããŠã¯ Redis ã§ã¯ããŒã« TTL ãèšå®ããããšã§æå¹æéãèšå®ããããšãã§ãã ãã¡ã ã«èšèŒã®ããžãã¯ã§åé€åŠçã宿œããŠãããŸãã Eviction ã«ã€ããŠã¯ Redis æ¬å®¶ã®å®è£
ã§ã¯ä»¥äžã®ãããªä»æ§ã«ãªã£ãŠããŸããRedis æ¬å®¶ããã¥ã¡ã³ã㯠ãã¡ã ã used_memory ïŒã¢ããªãå©çšããŠããã¡ã¢ãªéïŒã maxmemory å€ãè¶
ãå§ããã Eviction ãçºç«ãå§ãã maxmemory 㯠redis.conf æå®ã CONFIG SET ã³ãã³ãã§èšå®ã§ãã maxmemory ã«å°éãããã©ã®ããã«æ¯ãèãã¹ããã maxmemory-policy ã§æå® noeviction : 容éãå¿
èŠãªãªãã¬ãŒã·ã§ã³ã§ã¯ evit ããããšã©ãŒãšãªã allkeys-lru : åžžã« LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® volatile-lru : TTL ãèšå®ãããããŒå
ã§ LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® allkeys-random : åžžã«ã©ã³ãã ã«åé€å¯Ÿè±¡éžå®ããŠåé€ volatile-random : TTL ãèšå®ãããããŒå
ã§ã©ã³ãã ã«åé€å¯Ÿè±¡éžå® volatile-ttl : TTL ãèšå®ãããããŒå
ã§ TTL ãŸããElastiCache for Redis ã§ã¯ãŸã 3 ç³»åãŸã§ãã䜿ããŸãããã4 ç³»åã§ã¯æ°ãã« LFU ãéžæè¢ã«å
¥ã£ãŠããããã§ãã Redis æ¬å®¶ã® Eviction ã®åäœä»æ§ãšããŠã¯ä»¥äžã®ã€ã¡ãŒãžã§ãã github.com github.com ElastiCache for Redis ã§ã¯ maxmemory ã¯ç·šéã§ããããã®ä»£ããã«åŸè¿°ãã reserved-memory ïŒ reserved-memory-percent ïŒãèšå®ãããš Eviction ãçºç«ããã¡ã¢ãªéã®éŸå€ãå€ããããšããäžèšåšãã®å®è£
㯠AWS åŽã§æãå
¥ããŠãããã§ãã ElastiCache for Redis ã§ã® Eviction ElastiCache for Redis ã§ã¯ä»¥äžã®ããã« Redis æ¬å®¶ã«ã¯ãªã reserved-memory ãšããæŠå¿µãããã®ã§æ³šæãå¿
èŠã§ãã maxmemory ã¯ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã«ãã£ãŠåºå®å€ã«èšå®ãããŠãã maxmemory ã¯ å€æŽã§ããªã 代ããã« reserved-memory or reserved-memory-percent ãèšå®ã㊠Eviction çºç«ã¡ã¢ãªéãèšå®ã§ãã maxmemory - reserved-memory < used_memory ã§ Eviction ãçºç«ãã å€ãã®ã€ã³ã¹ã¿ã³ã¹ïŒ2017 幎 3 æ 16 æ¥ä»¥åäœæïŒã§ã¯ reserved-memory ããã©ã¡ãŒã¿ãšããŠå©çšã§ãããã reserved-memory ã®ããã©ã«ãå€ã¯ 0byte reserved-memory-percent ã®ããã©ã«ãå€ã¯ 25% ãã®åšèŸºã® AWS å
¬åŒããã¥ã¡ã³ã㯠ãã¡ã ãžã§ãã¡ãã¬ãŒã§ã¯åäžã® ElastiCache for Redis ã€ã³ã¹ã¿ã³ã¹ã§éçšå¯Ÿè±¡ãæžããæŠç¥ãåã£ãŠããŸãïŒRedis æ¬å®¶ã§ã¯çšéå¥ã«åããŠé©åã«ãã¥ãŒãã³ã°ããããšãæšå¥šããŠãããããå°æ¥çã«ã¯ãã®æ§æã¯å€ãããããããŸããïŒããã®ããããã£ãã·ã¥å©çšã®ããŒã«ã¯å¿
ã TTL ãèšå®ããEviction policy 㯠volatile-lru ãšããŠããŸãã ãããŠãå°ãäœè£ãããã㊠reserved-memory ãèšå®ãEvictions ã¡ããªã¯ã¹ã®ç£èŠãããŠããŸãã ã¡ã¢ãªå©çšéã SQL ã§åæãã çŸåšçšŒåããŠããæ¬çªç°å¢äžã§ã©ã®ãã¿ãŒã³ã®ããŒãã©ã®çšåºŠã®ã¡ã¢ãªã䜿ã£ãŠããããææ¡ããããªãå Žé¢ã«åºããããæ¹ãããã£ãããã®ã§ã¯ãªãã§ããããã ElastiCache for Redis ã§ã¯ç°¡åã« RDB ã¹ãããã·ã§ãããååŸããããšãã§ããŸãããã®ããŒã¿ãããŸã䜿ãã°çŽæ¥æ¬çªçšŒåã®ã€ã³ã¹ã¿ã³ã¹ãè§Šãã«ããããšãªããæå
ã§å®å¿ããŠåæäœæ¥ã宿œã§ããŸãã ãã®åæäœæ¥ã«äŸ¿å©ãªã®ã redis-rdb-tools ã§ãããã®ããŒã«ã¯ RDB ãã¡ã€ã«ã®å
容ãããšã«ããŒããšã® byte å€ã以äžã®ãã㪠CSV ã«åºåããããšãã§ããŸãïŒ size_in_bytes ã¯çè«å€ïŒã $ rdb -c memory dump.rdb > memory.csv ; $ cat memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,list,lizards,241,quicklist,5,19 2,hash,baloon,138,ziplist,3,11 ãã® csv ã以äžã®ããã« SQLite çã®ããŒã¿ããŒã¹ã«çªã£èŸŒãããšã§æå
ã§ SQL ã䜿ã£ãŠã¡ã¢ãªçµ±èšã®åæãã§ããããã«ãªããŸãã $ rdb -c memory dump.rdb > memory.csv ; $ sqlite3 memory.db sqlite > create table memory ( database int,type varchar ( 128 ) ,key varchar ( 128 ) ,size_in_bytes int,encoding varchar ( 128 ) ,num_elements int,len_largest_element varchar ( 128 )); sqlite > .mode csv memory sqlite > .import memory.csv memory ãã£ãããšããåæã®æµã㯠æ¬çªç°å¢ã® daily backup RDB ååŸ redis-rdb-tools ã§ csv åºå csv ã sqlite ã« csv format ã§ import SQL ã§åæ ã®ããã«ãªããŸããããŒã¿ããŒã¹ã«ã€ã³ããŒãããåºæ¥ãŠããŸãã°ä»¥äžã®ããã«æ§ã
ãªåæãå¯èœã«ãªããŸãã sqlite > select sum ( size_in_bytes ) from memory where key like '%cells%' ; XXXXX sqlite > select count (*) from memory where key like '%cells%' ; XXXXX 泚æç¹ãšããŠã¯å®éã«æ¬çªçšŒåããŠããã¡ã¢ãªéãååŸããŠããããã§ã¯ãªãã®ã§å®æž¬å€ãšå€ããããŠããããšã§ãïŒæèŠçã«ã¯çè«å€ã¯å®æž¬å€ã® 1/2 ãããã§ããïŒããã¡ãã®è©³çŽ°ã®æšå®ããžãã¯ãæ°ã«ãªãæ¹ã¯ å®è£
ã確èªããã ããã°ãšæããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯ãã®ææ³ã䜿ã£ãŠåæããããšã§ã¢ããªããžãã¯ãä¿®æ£ããŠäžèŠãªã¡ã¢ãªå©çšã®æ¹åçã«åœ¹ç«ãŠãŠããŸãã ãŸãšã ElastiCache for Redis ã®ã¡ã¢ãªåšããäžå¿ãšããéçšãã¿ã«ã€ããŠç޹ä»ããŸããã ElastiCache for Redis ã¯ãšãŠã䟿å©ã§ã·ã¥ããšèšå®ããŠãããªãã®èŠæš¡ã§ããªããšãªãéçšã§ããŠããŸãæè»œãããããŸãããæ²¹æããŠãããšæãã¬èœãšã穎ã«ã¯ãŸãããšããããŸãã æ¬èšäºãã¿ãªããŸã® ElastiCache for Redis éçšã©ã€ãã®äžå©ã«ãªãã°å¹žãã§ãã ãŸãããžã§ãã¡ãã¬ãŒãã¯ãããã¡ãã¬ãŒã®éçºã«ãèå³ããæ¹ã¯ããã²ãé£çµ¡ãã ããã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp ã¡ãã¬ãŒã LT ã¹ãã³ãµãŒãåãã RubyKaigi2018 ã«ããéªéããäºå®ïŒããŸã«ããŒã¹ã«ç«ã£ãŠããŸãïŒã®ã§ããã¡ãã§ããäŒãããŸãããã RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®åŸè€ã§ããå»çä»è·ã®æ±äººãµã€ãããžã§ãã¡ãã¬ãŒãã®éçºãæ
åœããŠããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯åçš®ãã£ãã·ã¥ã sidekiq ã® queue çã« ElastiCache for Redis ãå©çšããŠããŸãã å
æ¥ãã¡ãã¬ãŒã§å®æéå¬ããŠãã瀟å
ååŒ·äŒ TechLunch ã«ãŠããžã§ãã¡ãã¬ãŒã§ã® ElastiCache for Redis ã®éçšåšãã®ãã¿ãç¥èŠã«ã€ããŠçºè¡šããŸãããæ¬èšäºã§ã¯ããã®äžããæç²ããŠã¡ã¢ãªåšãã®è©±ã«ã€ããŠç޹ä»ããŸãã ããŒåé€åšãã®ä»æ§ã«ã€ã㊠ãã£ãã·ã¥ãšã㊠ElastiCache for Redis ãå©çšããŠããäžã§ãŸãææ¡ããŠããããã®ããããŒã®åé€åšãã®ä»æ§ã§ãã Redis æ¬å®¶ã® Expiration/Eviction Expiration ã«ã€ããŠã¯ Redis ã§ã¯ããŒã« TTL ãèšå®ããããšã§æå¹æéãèšå®ããããšãã§ãã ãã¡ã ã«èšèŒã®ããžãã¯ã§åé€åŠçã宿œããŠãããŸãã Eviction ã«ã€ããŠã¯ Redis æ¬å®¶ã®å®è£
ã§ã¯ä»¥äžã®ãããªä»æ§ã«ãªã£ãŠããŸããRedis æ¬å®¶ããã¥ã¡ã³ã㯠ãã¡ã ã used_memory ïŒã¢ããªãå©çšããŠããã¡ã¢ãªéïŒã maxmemory å€ãè¶
ãå§ããã Eviction ãçºç«ãå§ãã maxmemory 㯠redis.conf æå®ã CONFIG SET ã³ãã³ãã§èšå®ã§ãã maxmemory ã«å°éãããã©ã®ããã«æ¯ãèãã¹ããã maxmemory-policy ã§æå® noeviction : 容éãå¿
èŠãªãªãã¬ãŒã·ã§ã³ã§ã¯ evit ããããšã©ãŒãšãªã allkeys-lru : åžžã« LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® volatile-lru : TTL ãèšå®ãããããŒå
ã§ LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® allkeys-random : åžžã«ã©ã³ãã ã«åé€å¯Ÿè±¡éžå®ããŠåé€ volatile-random : TTL ãèšå®ãããããŒå
ã§ã©ã³ãã ã«åé€å¯Ÿè±¡éžå® volatile-ttl : TTL ãèšå®ãããããŒå
ã§ TTL ãŸããElastiCache for Redis ã§ã¯ãŸã 3 ç³»åãŸã§ãã䜿ããŸãããã4 ç³»åã§ã¯æ°ãã« LFU ãéžæè¢ã«å
¥ã£ãŠããããã§ãã Redis æ¬å®¶ã® Eviction ã®åäœä»æ§ãšããŠã¯ä»¥äžã®ã€ã¡ãŒãžã§ãã github.com github.com ElastiCache for Redis ã§ã¯ maxmemory ã¯ç·šéã§ããããã®ä»£ããã«åŸè¿°ãã reserved-memory ïŒ reserved-memory-percent ïŒãèšå®ãããš Eviction ãçºç«ããã¡ã¢ãªéã®éŸå€ãå€ããããšããäžèšåšãã®å®è£
㯠AWS åŽã§æãå
¥ããŠãããã§ãã ElastiCache for Redis ã§ã® Eviction ElastiCache for Redis ã§ã¯ä»¥äžã®ããã« Redis æ¬å®¶ã«ã¯ãªã reserved-memory ãšããæŠå¿µãããã®ã§æ³šæãå¿
èŠã§ãã maxmemory ã¯ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã«ãã£ãŠåºå®å€ã«èšå®ãããŠãã maxmemory ã¯ å€æŽã§ããªã 代ããã« reserved-memory or reserved-memory-percent ãèšå®ã㊠Eviction çºç«ã¡ã¢ãªéãèšå®ã§ãã maxmemory - reserved-memory < used_memory ã§ Eviction ãçºç«ãã å€ãã®ã€ã³ã¹ã¿ã³ã¹ïŒ2017 幎 3 æ 16 æ¥ä»¥åäœæïŒã§ã¯ reserved-memory ããã©ã¡ãŒã¿ãšããŠå©çšã§ãããã reserved-memory ã®ããã©ã«ãå€ã¯ 0byte reserved-memory-percent ã®ããã©ã«ãå€ã¯ 25% ãã®åšèŸºã® AWS å
¬åŒããã¥ã¡ã³ã㯠ãã¡ã ãžã§ãã¡ãã¬ãŒã§ã¯åäžã® ElastiCache for Redis ã€ã³ã¹ã¿ã³ã¹ã§éçšå¯Ÿè±¡ãæžããæŠç¥ãåã£ãŠããŸãïŒRedis æ¬å®¶ã§ã¯çšéå¥ã«åããŠé©åã«ãã¥ãŒãã³ã°ããããšãæšå¥šããŠãããããå°æ¥çã«ã¯ãã®æ§æã¯å€ãããããããŸããïŒããã®ããããã£ãã·ã¥å©çšã®ããŒã«ã¯å¿
ã TTL ãèšå®ããEviction policy 㯠volatile-lru ãšããŠããŸãã ãããŠãå°ãäœè£ãããã㊠reserved-memory ãèšå®ãEvictions ã¡ããªã¯ã¹ã®ç£èŠãããŠããŸãã ã¡ã¢ãªå©çšéã SQL ã§åæãã çŸåšçšŒåããŠããæ¬çªç°å¢äžã§ã©ã®ãã¿ãŒã³ã®ããŒãã©ã®çšåºŠã®ã¡ã¢ãªã䜿ã£ãŠããããææ¡ããããªãå Žé¢ã«åºããããæ¹ãããã£ãããã®ã§ã¯ãªãã§ããããã ElastiCache for Redis ã§ã¯ç°¡åã« RDB ã¹ãããã·ã§ãããååŸããããšãã§ããŸãããã®ããŒã¿ãããŸã䜿ãã°çŽæ¥æ¬çªçšŒåã®ã€ã³ã¹ã¿ã³ã¹ãè§Šãã«ããããšãªããæå
ã§å®å¿ããŠåæäœæ¥ã宿œã§ããŸãã ãã®åæäœæ¥ã«äŸ¿å©ãªã®ã redis-rdb-tools ã§ãããã®ããŒã«ã¯ RDB ãã¡ã€ã«ã®å
容ãããšã«ããŒããšã® byte å€ã以äžã®ãã㪠CSV ã«åºåããããšãã§ããŸãïŒ size_in_bytes ã¯çè«å€ïŒã $ rdb -c memory dump.rdb > memory.csv ; $ cat memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,list,lizards,241,quicklist,5,19 2,hash,baloon,138,ziplist,3,11 ãã® csv ã以äžã®ããã« SQLite çã®ããŒã¿ããŒã¹ã«çªã£èŸŒãããšã§æå
ã§ SQL ã䜿ã£ãŠã¡ã¢ãªçµ±èšã®åæãã§ããããã«ãªããŸãã $ rdb -c memory dump.rdb > memory.csv ; $ sqlite3 memory.db sqlite > create table memory ( database int,type varchar ( 128 ) ,key varchar ( 128 ) ,size_in_bytes int,encoding varchar ( 128 ) ,num_elements int,len_largest_element varchar ( 128 )); sqlite > .mode csv memory sqlite > .import memory.csv memory ãã£ãããšããåæã®æµã㯠æ¬çªç°å¢ã® daily backup RDB ååŸ redis-rdb-tools ã§ csv åºå csv ã sqlite ã« csv format ã§ import SQL ã§åæ ã®ããã«ãªããŸããããŒã¿ããŒã¹ã«ã€ã³ããŒãããåºæ¥ãŠããŸãã°ä»¥äžã®ããã«æ§ã
ãªåæãå¯èœã«ãªããŸãã sqlite > select sum ( size_in_bytes ) from memory where key like '%cells%' ; XXXXX sqlite > select count (*) from memory where key like '%cells%' ; XXXXX 泚æç¹ãšããŠã¯å®éã«æ¬çªçšŒåããŠããã¡ã¢ãªéãååŸããŠããããã§ã¯ãªãã®ã§å®æž¬å€ãšå€ããããŠããããšã§ãïŒæèŠçã«ã¯çè«å€ã¯å®æž¬å€ã® 1/2 ãããã§ããïŒããã¡ãã®è©³çŽ°ã®æšå®ããžãã¯ãæ°ã«ãªãæ¹ã¯ å®è£
ã確èªããã ããã°ãšæããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯ãã®ææ³ã䜿ã£ãŠåæããããšã§ã¢ããªããžãã¯ãä¿®æ£ããŠäžèŠãªã¡ã¢ãªå©çšã®æ¹åçã«åœ¹ç«ãŠãŠããŸãã ãŸãšã ElastiCache for Redis ã®ã¡ã¢ãªåšããäžå¿ãšããéçšãã¿ã«ã€ããŠç޹ä»ããŸããã ElastiCache for Redis ã¯ãšãŠã䟿å©ã§ã·ã¥ããšèšå®ããŠãããªãã®èŠæš¡ã§ããªããšãªãéçšã§ããŠããŸãæè»œãããããŸãããæ²¹æããŠãããšæãã¬èœãšã穎ã«ã¯ãŸãããšããããŸãã æ¬èšäºãã¿ãªããŸã® ElastiCache for Redis éçšã©ã€ãã®äžå©ã«ãªãã°å¹žãã§ãã ãŸãããžã§ãã¡ãã¬ãŒãã¯ãããã¡ãã¬ãŒã®éçºã«ãèå³ããæ¹ã¯ããã²ãé£çµ¡ãã ããã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp ã¡ãã¬ãŒã LT ã¹ãã³ãµãŒãåãã RubyKaigi2018 ã«ããéªéããäºå®ïŒããŸã«ããŒã¹ã«ç«ã£ãŠããŸãïŒã®ã§ããã¡ãã§ããäŒãããŸãããã RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®åŸè€ã§ããå»çä»è·ã®æ±äººãµã€ãããžã§ãã¡ãã¬ãŒãã®éçºãæ
åœããŠããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯åçš®ãã£ãã·ã¥ã sidekiq ã® queue çã« ElastiCache for Redis ãå©çšããŠããŸãã å
æ¥ãã¡ãã¬ãŒã§å®æéå¬ããŠãã瀟å
ååŒ·äŒ TechLunch ã«ãŠããžã§ãã¡ãã¬ãŒã§ã® ElastiCache for Redis ã®éçšåšãã®ãã¿ãç¥èŠã«ã€ããŠçºè¡šããŸãããæ¬èšäºã§ã¯ããã®äžããæç²ããŠã¡ã¢ãªåšãã®è©±ã«ã€ããŠç޹ä»ããŸãã ããŒåé€åšãã®ä»æ§ã«ã€ã㊠ãã£ãã·ã¥ãšã㊠ElastiCache for Redis ãå©çšããŠããäžã§ãŸãææ¡ããŠããããã®ããããŒã®åé€åšãã®ä»æ§ã§ãã Redis æ¬å®¶ã® Expiration/Eviction Expiration ã«ã€ããŠã¯ Redis ã§ã¯ããŒã« TTL ãèšå®ããããšã§æå¹æéãèšå®ããããšãã§ãã ãã¡ã ã«èšèŒã®ããžãã¯ã§åé€åŠçã宿œããŠãããŸãã Eviction ã«ã€ããŠã¯ Redis æ¬å®¶ã®å®è£
ã§ã¯ä»¥äžã®ãããªä»æ§ã«ãªã£ãŠããŸããRedis æ¬å®¶ããã¥ã¡ã³ã㯠ãã¡ã ã used_memory ïŒã¢ããªãå©çšããŠããã¡ã¢ãªéïŒã maxmemory å€ãè¶
ãå§ããã Eviction ãçºç«ãå§ãã maxmemory 㯠redis.conf æå®ã CONFIG SET ã³ãã³ãã§èšå®ã§ãã maxmemory ã«å°éãããã©ã®ããã«æ¯ãèãã¹ããã maxmemory-policy ã§æå® noeviction : 容éãå¿
èŠãªãªãã¬ãŒã·ã§ã³ã§ã¯ evit ããããšã©ãŒãšãªã allkeys-lru : åžžã« LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® volatile-lru : TTL ãèšå®ãããããŒå
ã§ LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® allkeys-random : åžžã«ã©ã³ãã ã«åé€å¯Ÿè±¡éžå®ããŠåé€ volatile-random : TTL ãèšå®ãããããŒå
ã§ã©ã³ãã ã«åé€å¯Ÿè±¡éžå® volatile-ttl : TTL ãèšå®ãããããŒå
ã§ TTL ãŸããElastiCache for Redis ã§ã¯ãŸã 3 ç³»åãŸã§ãã䜿ããŸãããã4 ç³»åã§ã¯æ°ãã« LFU ãéžæè¢ã«å
¥ã£ãŠããããã§ãã Redis æ¬å®¶ã® Eviction ã®åäœä»æ§ãšããŠã¯ä»¥äžã®ã€ã¡ãŒãžã§ãã github.com github.com ElastiCache for Redis ã§ã¯ maxmemory ã¯ç·šéã§ããããã®ä»£ããã«åŸè¿°ãã reserved-memory ïŒ reserved-memory-percent ïŒãèšå®ãããš Eviction ãçºç«ããã¡ã¢ãªéã®éŸå€ãå€ããããšããäžèšåšãã®å®è£
㯠AWS åŽã§æãå
¥ããŠãããã§ãã ElastiCache for Redis ã§ã® Eviction ElastiCache for Redis ã§ã¯ä»¥äžã®ããã« Redis æ¬å®¶ã«ã¯ãªã reserved-memory ãšããæŠå¿µãããã®ã§æ³šæãå¿
èŠã§ãã maxmemory ã¯ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã«ãã£ãŠåºå®å€ã«èšå®ãããŠãã maxmemory ã¯ å€æŽã§ããªã 代ããã« reserved-memory or reserved-memory-percent ãèšå®ã㊠Eviction çºç«ã¡ã¢ãªéãèšå®ã§ãã maxmemory - reserved-memory < used_memory ã§ Eviction ãçºç«ãã å€ãã®ã€ã³ã¹ã¿ã³ã¹ïŒ2017 幎 3 æ 16 æ¥ä»¥åäœæïŒã§ã¯ reserved-memory ããã©ã¡ãŒã¿ãšããŠå©çšã§ãããã reserved-memory ã®ããã©ã«ãå€ã¯ 0byte reserved-memory-percent ã®ããã©ã«ãå€ã¯ 25% ãã®åšèŸºã® AWS å
¬åŒããã¥ã¡ã³ã㯠ãã¡ã ãžã§ãã¡ãã¬ãŒã§ã¯åäžã® ElastiCache for Redis ã€ã³ã¹ã¿ã³ã¹ã§éçšå¯Ÿè±¡ãæžããæŠç¥ãåã£ãŠããŸãïŒRedis æ¬å®¶ã§ã¯çšéå¥ã«åããŠé©åã«ãã¥ãŒãã³ã°ããããšãæšå¥šããŠãããããå°æ¥çã«ã¯ãã®æ§æã¯å€ãããããããŸããïŒããã®ããããã£ãã·ã¥å©çšã®ããŒã«ã¯å¿
ã TTL ãèšå®ããEviction policy 㯠volatile-lru ãšããŠããŸãã ãããŠãå°ãäœè£ãããã㊠reserved-memory ãèšå®ãEvictions ã¡ããªã¯ã¹ã®ç£èŠãããŠããŸãã ã¡ã¢ãªå©çšéã SQL ã§åæãã çŸåšçšŒåããŠããæ¬çªç°å¢äžã§ã©ã®ãã¿ãŒã³ã®ããŒãã©ã®çšåºŠã®ã¡ã¢ãªã䜿ã£ãŠããããææ¡ããããªãå Žé¢ã«åºããããæ¹ãããã£ãããã®ã§ã¯ãªãã§ããããã ElastiCache for Redis ã§ã¯ç°¡åã« RDB ã¹ãããã·ã§ãããååŸããããšãã§ããŸãããã®ããŒã¿ãããŸã䜿ãã°çŽæ¥æ¬çªçšŒåã®ã€ã³ã¹ã¿ã³ã¹ãè§Šãã«ããããšãªããæå
ã§å®å¿ããŠåæäœæ¥ã宿œã§ããŸãã ãã®åæäœæ¥ã«äŸ¿å©ãªã®ã redis-rdb-tools ã§ãããã®ããŒã«ã¯ RDB ãã¡ã€ã«ã®å
容ãããšã«ããŒããšã® byte å€ã以äžã®ãã㪠CSV ã«åºåããããšãã§ããŸãïŒ size_in_bytes ã¯çè«å€ïŒã $ rdb -c memory dump.rdb > memory.csv ; $ cat memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,list,lizards,241,quicklist,5,19 2,hash,baloon,138,ziplist,3,11 ãã® csv ã以äžã®ããã« SQLite çã®ããŒã¿ããŒã¹ã«çªã£èŸŒãããšã§æå
ã§ SQL ã䜿ã£ãŠã¡ã¢ãªçµ±èšã®åæãã§ããããã«ãªããŸãã $ rdb -c memory dump.rdb > memory.csv ; $ sqlite3 memory.db sqlite > create table memory ( database int,type varchar ( 128 ) ,key varchar ( 128 ) ,size_in_bytes int,encoding varchar ( 128 ) ,num_elements int,len_largest_element varchar ( 128 )); sqlite > .mode csv memory sqlite > .import memory.csv memory ãã£ãããšããåæã®æµã㯠æ¬çªç°å¢ã® daily backup RDB ååŸ redis-rdb-tools ã§ csv åºå csv ã sqlite ã« csv format ã§ import SQL ã§åæ ã®ããã«ãªããŸããããŒã¿ããŒã¹ã«ã€ã³ããŒãããåºæ¥ãŠããŸãã°ä»¥äžã®ããã«æ§ã
ãªåæãå¯èœã«ãªããŸãã sqlite > select sum ( size_in_bytes ) from memory where key like '%cells%' ; XXXXX sqlite > select count (*) from memory where key like '%cells%' ; XXXXX 泚æç¹ãšããŠã¯å®éã«æ¬çªçšŒåããŠããã¡ã¢ãªéãååŸããŠããããã§ã¯ãªãã®ã§å®æž¬å€ãšå€ããããŠããããšã§ãïŒæèŠçã«ã¯çè«å€ã¯å®æž¬å€ã® 1/2 ãããã§ããïŒããã¡ãã®è©³çŽ°ã®æšå®ããžãã¯ãæ°ã«ãªãæ¹ã¯ å®è£
ã確èªããã ããã°ãšæããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯ãã®ææ³ã䜿ã£ãŠåæããããšã§ã¢ããªããžãã¯ãä¿®æ£ããŠäžèŠãªã¡ã¢ãªå©çšã®æ¹åçã«åœ¹ç«ãŠãŠããŸãã ãŸãšã ElastiCache for Redis ã®ã¡ã¢ãªåšããäžå¿ãšããéçšãã¿ã«ã€ããŠç޹ä»ããŸããã ElastiCache for Redis ã¯ãšãŠã䟿å©ã§ã·ã¥ããšèšå®ããŠãããªãã®èŠæš¡ã§ããªããšãªãéçšã§ããŠããŸãæè»œãããããŸãããæ²¹æããŠãããšæãã¬èœãšã穎ã«ã¯ãŸãããšããããŸãã æ¬èšäºãã¿ãªããŸã® ElastiCache for Redis éçšã©ã€ãã®äžå©ã«ãªãã°å¹žãã§ãã ãŸãããžã§ãã¡ãã¬ãŒãã¯ãããã¡ãã¬ãŒã®éçºã«ãèå³ããæ¹ã¯ããã²ãé£çµ¡ãã ããã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp ã¡ãã¬ãŒã LT ã¹ãã³ãµãŒãåãã RubyKaigi2018 ã«ããéªéããäºå®ïŒããŸã«ããŒã¹ã«ç«ã£ãŠããŸãïŒã®ã§ããã¡ãã§ããäŒãããŸãããã RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®åŸè€ã§ããå»çä»è·ã®æ±äººãµã€ãããžã§ãã¡ãã¬ãŒãã®éçºãæ
åœããŠããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯åçš®ãã£ãã·ã¥ã sidekiq ã® queue çã« ElastiCache for Redis ãå©çšããŠããŸãã å
æ¥ãã¡ãã¬ãŒã§å®æéå¬ããŠãã瀟å
ååŒ·äŒ TechLunch ã«ãŠããžã§ãã¡ãã¬ãŒã§ã® ElastiCache for Redis ã®éçšåšãã®ãã¿ãç¥èŠã«ã€ããŠçºè¡šããŸãããæ¬èšäºã§ã¯ããã®äžããæç²ããŠã¡ã¢ãªåšãã®è©±ã«ã€ããŠç޹ä»ããŸãã ããŒåé€åšãã®ä»æ§ã«ã€ã㊠ãã£ãã·ã¥ãšã㊠ElastiCache for Redis ãå©çšããŠããäžã§ãŸãææ¡ããŠããããã®ããããŒã®åé€åšãã®ä»æ§ã§ãã Redis æ¬å®¶ã® Expiration/Eviction Expiration ã«ã€ããŠã¯ Redis ã§ã¯ããŒã« TTL ãèšå®ããããšã§æå¹æéãèšå®ããããšãã§ãã ãã¡ã ã«èšèŒã®ããžãã¯ã§åé€åŠçã宿œããŠãããŸãã Eviction ã«ã€ããŠã¯ Redis æ¬å®¶ã®å®è£
ã§ã¯ä»¥äžã®ãããªä»æ§ã«ãªã£ãŠããŸããRedis æ¬å®¶ããã¥ã¡ã³ã㯠ãã¡ã ã used_memory ïŒã¢ããªãå©çšããŠããã¡ã¢ãªéïŒã maxmemory å€ãè¶
ãå§ããã Eviction ãçºç«ãå§ãã maxmemory 㯠redis.conf æå®ã CONFIG SET ã³ãã³ãã§èšå®ã§ãã maxmemory ã«å°éãããã©ã®ããã«æ¯ãèãã¹ããã maxmemory-policy ã§æå® noeviction : 容éãå¿
èŠãªãªãã¬ãŒã·ã§ã³ã§ã¯ evit ããããšã©ãŒãšãªã allkeys-lru : åžžã« LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® volatile-lru : TTL ãèšå®ãããããŒå
ã§ LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® allkeys-random : åžžã«ã©ã³ãã ã«åé€å¯Ÿè±¡éžå®ããŠåé€ volatile-random : TTL ãèšå®ãããããŒå
ã§ã©ã³ãã ã«åé€å¯Ÿè±¡éžå® volatile-ttl : TTL ãèšå®ãããããŒå
ã§ TTL ãŸããElastiCache for Redis ã§ã¯ãŸã 3 ç³»åãŸã§ãã䜿ããŸãããã4 ç³»åã§ã¯æ°ãã« LFU ãéžæè¢ã«å
¥ã£ãŠããããã§ãã Redis æ¬å®¶ã® Eviction ã®åäœä»æ§ãšããŠã¯ä»¥äžã®ã€ã¡ãŒãžã§ãã github.com github.com ElastiCache for Redis ã§ã¯ maxmemory ã¯ç·šéã§ããããã®ä»£ããã«åŸè¿°ãã reserved-memory ïŒ reserved-memory-percent ïŒãèšå®ãããš Eviction ãçºç«ããã¡ã¢ãªéã®éŸå€ãå€ããããšããäžèšåšãã®å®è£
㯠AWS åŽã§æãå
¥ããŠãããã§ãã ElastiCache for Redis ã§ã® Eviction ElastiCache for Redis ã§ã¯ä»¥äžã®ããã« Redis æ¬å®¶ã«ã¯ãªã reserved-memory ãšããæŠå¿µãããã®ã§æ³šæãå¿
èŠã§ãã maxmemory ã¯ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã«ãã£ãŠåºå®å€ã«èšå®ãããŠãã maxmemory ã¯ å€æŽã§ããªã 代ããã« reserved-memory or reserved-memory-percent ãèšå®ã㊠Eviction çºç«ã¡ã¢ãªéãèšå®ã§ãã maxmemory - reserved-memory < used_memory ã§ Eviction ãçºç«ãã å€ãã®ã€ã³ã¹ã¿ã³ã¹ïŒ2017 幎 3 æ 16 æ¥ä»¥åäœæïŒã§ã¯ reserved-memory ããã©ã¡ãŒã¿ãšããŠå©çšã§ãããã reserved-memory ã®ããã©ã«ãå€ã¯ 0byte reserved-memory-percent ã®ããã©ã«ãå€ã¯ 25% ãã®åšèŸºã® AWS å
¬åŒããã¥ã¡ã³ã㯠ãã¡ã ãžã§ãã¡ãã¬ãŒã§ã¯åäžã® ElastiCache for Redis ã€ã³ã¹ã¿ã³ã¹ã§éçšå¯Ÿè±¡ãæžããæŠç¥ãåã£ãŠããŸãïŒRedis æ¬å®¶ã§ã¯çšéå¥ã«åããŠé©åã«ãã¥ãŒãã³ã°ããããšãæšå¥šããŠãããããå°æ¥çã«ã¯ãã®æ§æã¯å€ãããããããŸããïŒããã®ããããã£ãã·ã¥å©çšã®ããŒã«ã¯å¿
ã TTL ãèšå®ããEviction policy 㯠volatile-lru ãšããŠããŸãã ãããŠãå°ãäœè£ãããã㊠reserved-memory ãèšå®ãEvictions ã¡ããªã¯ã¹ã®ç£èŠãããŠããŸãã ã¡ã¢ãªå©çšéã SQL ã§åæãã çŸåšçšŒåããŠããæ¬çªç°å¢äžã§ã©ã®ãã¿ãŒã³ã®ããŒãã©ã®çšåºŠã®ã¡ã¢ãªã䜿ã£ãŠããããææ¡ããããªãå Žé¢ã«åºããããæ¹ãããã£ãããã®ã§ã¯ãªãã§ããããã ElastiCache for Redis ã§ã¯ç°¡åã« RDB ã¹ãããã·ã§ãããååŸããããšãã§ããŸãããã®ããŒã¿ãããŸã䜿ãã°çŽæ¥æ¬çªçšŒåã®ã€ã³ã¹ã¿ã³ã¹ãè§Šãã«ããããšãªããæå
ã§å®å¿ããŠåæäœæ¥ã宿œã§ããŸãã ãã®åæäœæ¥ã«äŸ¿å©ãªã®ã redis-rdb-tools ã§ãããã®ããŒã«ã¯ RDB ãã¡ã€ã«ã®å
容ãããšã«ããŒããšã® byte å€ã以äžã®ãã㪠CSV ã«åºåããããšãã§ããŸãïŒ size_in_bytes ã¯çè«å€ïŒã $ rdb -c memory dump.rdb > memory.csv ; $ cat memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,list,lizards,241,quicklist,5,19 2,hash,baloon,138,ziplist,3,11 ãã® csv ã以äžã®ããã« SQLite çã®ããŒã¿ããŒã¹ã«çªã£èŸŒãããšã§æå
ã§ SQL ã䜿ã£ãŠã¡ã¢ãªçµ±èšã®åæãã§ããããã«ãªããŸãã $ rdb -c memory dump.rdb > memory.csv ; $ sqlite3 memory.db sqlite > create table memory ( database int,type varchar ( 128 ) ,key varchar ( 128 ) ,size_in_bytes int,encoding varchar ( 128 ) ,num_elements int,len_largest_element varchar ( 128 )); sqlite > .mode csv memory sqlite > .import memory.csv memory ãã£ãããšããåæã®æµã㯠æ¬çªç°å¢ã® daily backup RDB ååŸ redis-rdb-tools ã§ csv åºå csv ã sqlite ã« csv format ã§ import SQL ã§åæ ã®ããã«ãªããŸããããŒã¿ããŒã¹ã«ã€ã³ããŒãããåºæ¥ãŠããŸãã°ä»¥äžã®ããã«æ§ã
ãªåæãå¯èœã«ãªããŸãã sqlite > select sum ( size_in_bytes ) from memory where key like '%cells%' ; XXXXX sqlite > select count (*) from memory where key like '%cells%' ; XXXXX 泚æç¹ãšããŠã¯å®éã«æ¬çªçšŒåããŠããã¡ã¢ãªéãååŸããŠããããã§ã¯ãªãã®ã§å®æž¬å€ãšå€ããããŠããããšã§ãïŒæèŠçã«ã¯çè«å€ã¯å®æž¬å€ã® 1/2 ãããã§ããïŒããã¡ãã®è©³çŽ°ã®æšå®ããžãã¯ãæ°ã«ãªãæ¹ã¯ å®è£
ã確èªããã ããã°ãšæããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯ãã®ææ³ã䜿ã£ãŠåæããããšã§ã¢ããªããžãã¯ãä¿®æ£ããŠäžèŠãªã¡ã¢ãªå©çšã®æ¹åçã«åœ¹ç«ãŠãŠããŸãã ãŸãšã ElastiCache for Redis ã®ã¡ã¢ãªåšããäžå¿ãšããéçšãã¿ã«ã€ããŠç޹ä»ããŸããã ElastiCache for Redis ã¯ãšãŠã䟿å©ã§ã·ã¥ããšèšå®ããŠãããªãã®èŠæš¡ã§ããªããšãªãéçšã§ããŠããŸãæè»œãããããŸãããæ²¹æããŠãããšæãã¬èœãšã穎ã«ã¯ãŸãããšããããŸãã æ¬èšäºãã¿ãªããŸã® ElastiCache for Redis éçšã©ã€ãã®äžå©ã«ãªãã°å¹žãã§ãã ãŸãããžã§ãã¡ãã¬ãŒãã¯ãããã¡ãã¬ãŒã®éçºã«ãèå³ããæ¹ã¯ããã²ãé£çµ¡ãã ããã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp ã¡ãã¬ãŒã LT ã¹ãã³ãµãŒãåãã RubyKaigi2018 ã«ããéªéããäºå®ïŒããŸã«ããŒã¹ã«ç«ã£ãŠããŸãïŒã®ã§ããã¡ãã§ããäŒãããŸãããã RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
ããã«ã¡ã¯ãéçºæ¬éšã®åŸè€ã§ããå»çä»è·ã®æ±äººãµã€ãããžã§ãã¡ãã¬ãŒãã®éçºãæ
åœããŠããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯åçš®ãã£ãã·ã¥ã sidekiq ã® queue çã« ElastiCache for Redis ãå©çšããŠããŸãã å
æ¥ãã¡ãã¬ãŒã§å®æéå¬ããŠãã瀟å
ååŒ·äŒ TechLunch ã«ãŠããžã§ãã¡ãã¬ãŒã§ã® ElastiCache for Redis ã®éçšåšãã®ãã¿ãç¥èŠã«ã€ããŠçºè¡šããŸãããæ¬èšäºã§ã¯ããã®äžããæç²ããŠã¡ã¢ãªåšãã®è©±ã«ã€ããŠç޹ä»ããŸãã ããŒåé€åšãã®ä»æ§ã«ã€ã㊠ãã£ãã·ã¥ãšã㊠ElastiCache for Redis ãå©çšããŠããäžã§ãŸãææ¡ããŠããããã®ããããŒã®åé€åšãã®ä»æ§ã§ãã Redis æ¬å®¶ã® Expiration/Eviction Expiration ã«ã€ããŠã¯ Redis ã§ã¯ããŒã« TTL ãèšå®ããããšã§æå¹æéãèšå®ããããšãã§ãã ãã¡ã ã«èšèŒã®ããžãã¯ã§åé€åŠçã宿œããŠãããŸãã Eviction ã«ã€ããŠã¯ Redis æ¬å®¶ã®å®è£
ã§ã¯ä»¥äžã®ãããªä»æ§ã«ãªã£ãŠããŸããRedis æ¬å®¶ããã¥ã¡ã³ã㯠ãã¡ã ã used_memory ïŒã¢ããªãå©çšããŠããã¡ã¢ãªéïŒã maxmemory å€ãè¶
ãå§ããã Eviction ãçºç«ãå§ãã maxmemory 㯠redis.conf æå®ã CONFIG SET ã³ãã³ãã§èšå®ã§ãã maxmemory ã«å°éãããã©ã®ããã«æ¯ãèãã¹ããã maxmemory-policy ã§æå® noeviction : 容éãå¿
èŠãªãªãã¬ãŒã·ã§ã³ã§ã¯ evit ããããšã©ãŒãšãªã allkeys-lru : åžžã« LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® volatile-lru : TTL ãèšå®ãããããŒå
ã§ LRU ã¢ã«ãŽãªãºã ã§åé€å¯Ÿè±¡éžå® allkeys-random : åžžã«ã©ã³ãã ã«åé€å¯Ÿè±¡éžå®ããŠåé€ volatile-random : TTL ãèšå®ãããããŒå
ã§ã©ã³ãã ã«åé€å¯Ÿè±¡éžå® volatile-ttl : TTL ãèšå®ãããããŒå
ã§ TTL ãŸããElastiCache for Redis ã§ã¯ãŸã 3 ç³»åãŸã§ãã䜿ããŸãããã4 ç³»åã§ã¯æ°ãã« LFU ãéžæè¢ã«å
¥ã£ãŠããããã§ãã Redis æ¬å®¶ã® Eviction ã®åäœä»æ§ãšããŠã¯ä»¥äžã®ã€ã¡ãŒãžã§ãã https://github.com/antirez/redis/blob/3.2.10/src/server.c#L3343-L3357 ElastiCache for Redis ã§ã¯ maxmemory ã¯ç·šéã§ããããã®ä»£ããã«åŸè¿°ãã reserved-memory ïŒ reserved-memory-percent ïŒãèšå®ãããš Eviction ãçºç«ããã¡ã¢ãªéã®éŸå€ãå€ããããšããäžèšåšãã®å®è£
㯠AWS åŽã§æãå
¥ããŠãããã§ãã ElastiCache for Redis ã§ã® Eviction ElastiCache for Redis ã§ã¯ä»¥äžã®ããã« Redis æ¬å®¶ã«ã¯ãªã reserved-memory ãšããæŠå¿µãããã®ã§æ³šæãå¿
èŠã§ãã maxmemory ã¯ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã«ãã£ãŠåºå®å€ã«èšå®ãããŠãã maxmemory ã¯ å€æŽã§ããªã 代ããã« reserved-memory or reserved-memory-percent ãèšå®ã㊠Eviction çºç«ã¡ã¢ãªéãèšå®ã§ãã maxmemory - reserved-memory < used_memory ã§ Eviction ãçºç«ãã å€ãã®ã€ã³ã¹ã¿ã³ã¹ïŒ2017 幎 3 æ 16 æ¥ä»¥åäœæïŒã§ã¯ reserved-memory ããã©ã¡ãŒã¿ãšããŠå©çšã§ãããã reserved-memory ã®ããã©ã«ãå€ã¯ 0byte reserved-memory-percent ã®ããã©ã«ãå€ã¯ 25% ãã®åšèŸºã® AWS å
¬åŒããã¥ã¡ã³ã㯠ãã¡ã ãžã§ãã¡ãã¬ãŒã§ã¯åäžã® ElastiCache for Redis ã€ã³ã¹ã¿ã³ã¹ã§éçšå¯Ÿè±¡ãæžããæŠç¥ãåã£ãŠããŸãïŒRedis æ¬å®¶ã§ã¯çšéå¥ã«åããŠé©åã«ãã¥ãŒãã³ã°ããããšãæšå¥šããŠãããããå°æ¥çã«ã¯ãã®æ§æã¯å€ãããããããŸããïŒããã®ããããã£ãã·ã¥å©çšã®ããŒã«ã¯å¿
ã TTL ãèšå®ããEviction policy 㯠volatile-lru ãšããŠããŸãã ãããŠãå°ãäœè£ãããã㊠reserved-memory ãèšå®ãEvictions ã¡ããªã¯ã¹ã®ç£èŠãããŠããŸãã ã¡ã¢ãªå©çšéã SQL ã§åæãã çŸåšçšŒåããŠããæ¬çªç°å¢äžã§ã©ã®ãã¿ãŒã³ã®ããŒãã©ã®çšåºŠã®ã¡ã¢ãªã䜿ã£ãŠããããææ¡ããããªãå Žé¢ã«åºããããæ¹ãããã£ãããã®ã§ã¯ãªãã§ããããã ElastiCache for Redis ã§ã¯ç°¡åã« RDB ã¹ãããã·ã§ãããååŸããããšãã§ããŸãããã®ããŒã¿ãããŸã䜿ãã°çŽæ¥æ¬çªçšŒåã®ã€ã³ã¹ã¿ã³ã¹ãè§Šãã«ããããšãªããæå
ã§å®å¿ããŠåæäœæ¥ã宿œã§ããŸãã ãã®åæäœæ¥ã«äŸ¿å©ãªã®ã redis-rdb-tools ã§ãããã®ããŒã«ã¯ RDB ãã¡ã€ã«ã®å
容ãããšã«ããŒããšã® byte å€ã以äžã®ãã㪠CSV ã«åºåããããšãã§ããŸãïŒ size_in_bytes ã¯çè«å€ïŒã $ rdb -c memory dump.rdb > memory.csv ; $ cat memory.csv database,type,key,size_in_bytes,encoding,num_elements,len_largest_element 0,list,lizards,241,quicklist,5,19 2,hash,baloon,138,ziplist,3,11 ãã® csv ã以äžã®ããã« SQLite çã®ããŒã¿ããŒã¹ã«çªã£èŸŒãããšã§æå
ã§ SQL ã䜿ã£ãŠã¡ã¢ãªçµ±èšã®åæãã§ããããã«ãªããŸãã $ rdb -c memory dump.rdb > memory.csv ; $ sqlite3 memory.db sqlite > create table memory ( database int,type varchar ( 128 ) ,key varchar ( 128 ) ,size_in_bytes int,encoding varchar ( 128 ) ,num_elements int,len_largest_element varchar ( 128 )); sqlite > .mode csv memory sqlite > .import memory.csv memory ãã£ãããšããåæã®æµã㯠æ¬çªç°å¢ã® daily backup RDB ååŸ redis-rdb-tools ã§ csv åºå csv ã sqlite ã« csv format ã§ import SQL ã§åæ ã®ããã«ãªããŸããããŒã¿ããŒã¹ã«ã€ã³ããŒãããåºæ¥ãŠããŸãã°ä»¥äžã®ããã«æ§ã
ãªåæãå¯èœã«ãªããŸãã sqlite > select sum ( size_in_bytes ) from memory where key like '%cells%' ; XXXXX sqlite > select count (*) from memory where key like '%cells%' ; XXXXX 泚æç¹ãšããŠã¯å®éã«æ¬çªçšŒåããŠããã¡ã¢ãªéãååŸããŠããããã§ã¯ãªãã®ã§å®æž¬å€ãšå€ããããŠããããšã§ãïŒæèŠçã«ã¯çè«å€ã¯å®æž¬å€ã® 1/2 ãããã§ããïŒããã¡ãã®è©³çŽ°ã®æšå®ããžãã¯ãæ°ã«ãªãæ¹ã¯ å®è£
ã確èªããã ããã°ãšæããŸãã ãžã§ãã¡ãã¬ãŒã§ã¯ãã®ææ³ã䜿ã£ãŠåæããããšã§ã¢ããªããžãã¯ãä¿®æ£ããŠäžèŠãªã¡ã¢ãªå©çšã®æ¹åçã«åœ¹ç«ãŠãŠããŸãã ãŸãšã ElastiCache for Redis ã®ã¡ã¢ãªåšããäžå¿ãšããéçšãã¿ã«ã€ããŠç޹ä»ããŸããã ElastiCache for Redis ã¯ãšãŠã䟿å©ã§ã·ã¥ããšèšå®ããŠãããªãã®èŠæš¡ã§ããªããšãªãéçšã§ããŠããŸãæè»œãããããŸãããæ²¹æããŠãããšæãã¬èœãšã穎ã«ã¯ãŸãããšããããŸãã æ¬èšäºãã¿ãªããŸã® ElastiCache for Redis éçšã©ã€ãã®äžå©ã«ãªãã°å¹žãã§ãã ãŸãããžã§ãã¡ãã¬ãŒãã¯ãããã¡ãã¬ãŒã®éçºã«ãèå³ããæ¹ã¯ããã²ãé£çµ¡ãã ããã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp ã¡ãã¬ãŒã LT ã¹ãã³ãµãŒãåãã RubyKaigi2018 ã«ããéªéããäºå®ïŒããŸã«ããŒã¹ã«ç«ã£ãŠããŸãïŒã®ã§ããã¡ãã§ããäŒãããŸãããã RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan #rubykaigi RubyKaigi 2018, 5/31...6/2, Sendai, Miyagi, Japan rubykaigi.org
4 ææ«ã«æ°ãã«ãªãªãŒã¹ããã¯ã©ãŠãåé»åã«ã«ãã CLINICS ã«ã«ã ãã®éçºãæ
åœããŠããç°äžã§ãã é»åã«ã«ããšããå»çè¡çºãæ¯ãããããã¯ãéçºãªãã§ã¯ã®ééå³ãé£ãããæããæ¥ã
ãéãããŠããŸããåå㯠CLINICS ã«ã«ãã®ãã¶ã€ã³ã«ã€ããŠããšãã玹ä»ããŸãã ããä»åã¯ãšã³ãžãã¢ããèŠãèŠæ©ãšèè€ã«ã€ããŠã話ããŸãã èŠåŽããç¹ãšããŠã¯ãå»çäºåã®æ¥åãã®ãã®ã®è€éããããã«äŒŽãã¢ããªã±ãŒã·ã§ã³éçºã®è€éãã¯ãã¡ããã®ããšã é»åã«ã«ãéçºã®ç¹åŸŽãšããŠé¢é£çåºã®ã¬ã€ãã©ã€ã³ã®æºæ ãã¬ã»ãããœããïŒå»çäŒèšå°çšã®ã·ã¹ãã ïŒã®ã·ã¹ãã 管çãªã©ãå€å²ã«ããã察å¿ãå¿
èŠãªããš ãæããããŸãã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ã«é¢ããã話ã¯çްãããªã£ãŠããŸãã®ã§ã倧ãŸããªå
容ãšããŠãä»åã¯äž»ã«ã¬ã»ããã·ã¹ãã ãšããŠé£æºããŠãã ORCA ã®ã·ã¹ãã ç®¡çæ¹æ³ã«ã€ããŠãäŒããããŠããã ããã°ãšæããŸãïŒORCA ã«é¢ãã説æã¯åŸè¿°ããŸãïŒã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ é»åã«ã«ãã®ããã«å»çæ
å ±ãæ±ãéã«éµå®ããå¿
èŠãããã¬ã€ãã©ã€ã³ãšã㊠3 ç 4 ã¬ã€ãã©ã€ã³ïŒåçåŽåçãçµæžç£æ¥çãç·åçã® 3 çãåºããŠãã 4 ã€ã®ã¬ã€ãã©ã€ã³ïŒããããŸãã CLINICS ã«ã«ãã®éçºãé²ããã«ãããããã®ã¬ã€ãã©ã€ã³ãã·ã¹ãã èšèšãéçšã«å€§ããªåœ±é¿ãåãŒãããããŸãã¯ã¬ã€ãã©ã€ã³ãèªã¿èŸŒã¿æŽçãããšããããå§ããŸããã ã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãšãã«å¯Ÿå¿ãã¹ãããšã¯å€ãã£ãã®ã§ãããã·ã¹ãã æ§æã«ç¹ã«åœ±é¿ã倧ããã£ãã®ã¯ä»¥äžã® 2 ç¹ãšãªããŸãã ãµãŒãã¹æäŸã«çšããã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãæ¥æ¬åœå
æ³ã®é©çšãåã¶å Žæã«èšçœ®ããããš ã¯ã©ã€ã¢ã³ãèšŒææžãå©çšãã TLS ã¯ã©ã€ã¢ã³ãèªèšŒã宿œããããš CLINICS ã«ã«ãã¯åŒç€Ÿã§æ¢ã«éçšããŠãããªã³ã©ã€ã³èšºçã¢ããªãCLINICSããšé£æºãããåæã§ãã£ããããã¬ã€ãã©ã€ã³ã«å³ããã·ã¹ãã æ§æãšããŠããããã«ããŸã CLINICS ã®ã·ã¹ãã ã Heroku ãã AWS ã«ç§»è¡ããããšããå§ãŸããŸããã ãŸããã¯ã©ã€ã¢ã³ãèªèšŒãè¡ãããã« AWS ã®æ§æãè²ã
ãšæ€èšããNginx ãšãæ¥ã
æ ŒéãããããŸããããã ãããã®å¯Ÿå¿å
容ã«é¢é£ããããã°ãéå»ã«æžããŠããŸãã®ã§ãèå³ãããæ¹ã¯ãã²ãåèã«ããŠãã ããã https://developer.medley.jp/entry/2017/08/24/120000_01 https://developer.medley.jp/entry/2017/08/24/120000_02 https://developer.medley.jp/entry/2017/09/22/124000 ORCA ãµãŒãã®ç®¡çæ¹æ³ CLINICS ã«ã«ãã¯ãæ¥æ¬å»åž«äŒ ORCA ç®¡çæ©æ§æ ªåŒäŒç€ŸãæäŸããå»çäŒèšãœããã§ãããORCAããçµã¿èŸŒãã ãORCA å
å
åãã®ã¯ã©ãŠãåé»åã«ã«ãã§ãã åè: ORCA ãšã¯ å»ççŸå Ž IT åãæšé²ããæ¥æ¬å»åž«äŒãäŒå¡çã®ããã«æäŸããŠããã¬ã»ãããœããïŒèšºçå ±é
¬ã®è«æ±æ¥åãè¡ãããã®å»çäŒèšãœããïŒã2002 幎ã«ãªãŒãã³ãœãŒã¹ãšããŠå
¬éãããçŸåšã蚺çæãäžå¿ã« 17,000 ãè¶
ããå
šåœã®å»çæ©é¢ã«å°å
¥ãããŠããŸãã å»çæ
å ±ãããã¯ãŒã¯æšé²å§å¡äŒã«ãŠãå»åž«äŒç·åæ
å ±ãããã¯ãŒã¯æ§æ³ãïŒ1997 幎 æ
å ±åæ€èšå§å¡äŒïŒãæ§æããããŒã«ã®äžã€ãšããŠèªããããæ¥æ¬å»åž«äŒã®ç ç©¶äºæ¥ãããžã§ã¯ããORCA ãããžã§ã¯ãããéçºãæäŸãéå§ãããã®ã§ãã ORCA ProjectïŒ ORCAãããžã§ã¯ãã®æŠèŠ æ¥æ¬å»åž«äŒéçºã»æ¥å»æšæºã¬ã»ãããœãããŠã§ã¢ã®ãµã€ãã§ã www.orca.med.or.jp CLINICS ã«ã«ãã¯ãããŸãã«ä»¥äžã®ãããªæ§æãšãªã£ãŠãããRuby on Rails ã§çšŒåããŠããã«ã«ãã¢ããªã±ãŒã·ã§ã³ãšå»çæ©é¢ããšã® ORCA ãµãŒããããããã®éã ORCA ãæäŸããŠãã API ã§æ¥ç¶ããŠããŸãã ïŒäžå³ã¯äžäŸãšããŠäžããŠãããã®ã§å°æ°ãè©³çŽ°ãªæ§æã¯å®éã®ã·ã¹ãã ãšã¯ç°ãªããŸãïŒ ãã® ORCA ãµãŒãã§ãããå»çæ©é¢ããšã« 1 ã€ã® EC2 ã€ã³ã¹ã¿ã³ã¹æ§æãšãªã£ãŠãããå©çšããå»çæ©é¢ãå¢ãã床㫠EC2 ã€ã³ã¹ã¿ã³ã¹ãå¢ãããããå°å
¥å»çæ©é¢ãå¢ããã»ã©æ§ç¯ãéçšãã€ãããªã£ãŠãããŸãããã®ããããåºæ¥ãã ãèªååããã話ãä»åã®ã¡ã€ã³ããŒãã§ãã ïŒããããããã£ãšæ¥œãã§ããæ§æã«ããããšè²ã
æ€èšãããã®ã§ãããã·ã¹ãã ã®ç¹æ®æ§ãªã©ã®è«žäºæ
ããããçµæ EC2 ã€ã³ã¹ã¿ã³ã¹åäœã§ç®¡çããæ§æã«ãªã£ãŠããŸãïŒ ORCA ãµãŒããŒé¢é£ã§äž»ã«äœ¿çšãã AWS ãµãŒãã¹ AMI äœæãã€ã³ã¹ã¿ã³ã¹äœæãªã©ã®ãã«ã系㯠CodeBuild ããããé©çšãã³ãã³ãå®è¡ãªã©ã®ã€ã³ã¹ã¿ã³ã¹ç®¡ç㯠Systems Manager ãè匱æ§ãã§ãã¯ãªã©ã®ã»ãã¥ãªãã£é¢é£ã«ã¯ Guard Duty ãšãã£ããµãŒãã¹ãäž»ã«å©çšããŠããŸãã æ¬¡ã«ãã€ã³ã¹ã¿ã³ã¹æ§ç¯ã«é¢ããŠããå°ãå
·äœçã«èª¬æããŸãã ORCA ãµãŒãã®ã€ã³ã¹ã¿ã³ã¹æ§ç¯ ORCA ãµãŒãçš AMIïŒãŽãŒã«ãã³ã€ã¡ãŒãžïŒäœæ ãã«ãã®å®è¡ã¯ CodeBuild ã§è¡ã£ãŠããŸããAMI ã®ãã«ãã«ã¯ Packer ã䜿çšããŠããããã«ãå®äºæã«äœæããã AMI ã® ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é²ããŠããŸãããã® AMI ID ãã€ã³ã¹ã¿ã³ã¹äœææã«åç
§ããŸãã åèãŸã§ã«ãCodeBuild ã§äœ¿çšããŠãã buildspec.yaml ã¯ä»¥äžã®ããã«ãªããŸãïŒèª¬æç®æãªã©ãäžéšå®éãšã¯ç°ãªããŸãïŒã phases : pre_build : ## 説æ * packer ãš jq ããã«ãçšã³ã³ããã«ã€ã³ã¹ããŒã« commands : - curl -qL -o packer.zip https://releases.hashicorp.com/packer/1.1.3/packer_1.1.3_linux_amd64.zip && unzip packer.zip - curl -qL -o jq https://stedolan.github.io/jq/download/linux64/jq && chmod +x ./jq build : ## 説æ * åŠçã«å¿
èŠãª AWS credential æ
å ±ãååŸïŒèšå®ïŒåŸã® aws cli 䜿ãçšïŒ * packer ãã«ãå®è¡ãAMI äœæ * packer ãã«ãçµæããäœæããã AMI ID ãååŸ * AMI ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é² commands : - curl -qL -o aws_credentials.json https://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > aws_credentials.json - aws configure set region $AWS_REGION - aws configure set aws_access_key_id `./jq -r '.AccessKeyId' aws_credentials.json` - aws configure set aws_secret_access_key `./jq -r '.SecretAccessKey' aws_credentials.json` - aws configure set aws_session_token `./jq -r '.Token' aws_credentials.json` - ../packer build -machine-readable bin/packer.json | tee packer.log - cat packer.log | grep "artifact,0,id" | cut -d "," -f6 | cut -d ":" -f2 > ami.txt - ORCA_AMI_ID=`cat ami.txt` - aws ssm put-parameter --name ORCA_AMI_ID --value $ORCA_AMI_ID --type String --overwrite ORCA ãµãŒãçš EC2 ã€ã³ã¹ã¿ã³ã¹äœæ å»çæ©é¢çšã®ã¢ã«ãŠã³ããæ°èŠè¿œå ããå Žåã瀟å
çšã®ç®¡çããŒã«ã§ãŸãå»çæ©é¢ã®åºæ¬æ
å ±ãç»é²ããŸãããã®åŸãORCA ã€ã³ã¹ã¿ã³ã¹èšå®ã«å¿
èŠãªãã©ã¡ãŒã¿ïŒå»çæ©é¢ãèå¥ãã ID ãªã©ïŒãèšå®ããã€ã³ã¹ã¿ã³ã¹äœæã®ãã«ãåŠçãå®è¡ããŸãã CodeBuild ããŽãŒã«ãã³ã€ã¡ãŒãžçšã® AMI ãããŒã¹ã« ORCA ã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ããŸããORCA ã€ã³ã¹ã¿ã³ã¹ã¯èµ·åæã«åçš®èšå®åŠçãè¡ããŸãïŒcloud-initïŒ ãªããã€ã³ã¹ã¿ã³ã¹èµ·åæã«è¡ã£ãŠããåŠçãšããŠäž»ã«ä»¥äžã®ãããªããšãè¡ã£ãŠããŸãã 該åœã€ã³ã¹ã¿ã³ã¹ã®å
éš IP ã Private DNS ã«ç»é² ORCA ã®ã»ããã¢ãã/ããã°ã©ã /ãã¹ã¿æŽæ° Postgres ã®ããã¯ã¢ããèšå® Mackerel ã Systems Manager çã®åçš® Agent ã€ã³ã¹ããŒã«ãèšå® ORCA ãµãŒãéçš æ§ç¯ãå®äºã皌åããåŸããORCA èªäœã®ã¢ããããŒãããããã®é©çšãªã©æ§ã
ãªéçšãçºçããŸããããããã©ã®ããã«è¡ã£ãŠãããããŸã æ¹åäžã§ã¯ãããŸããäžéšã玹ä»ããŸãã ã€ã³ã¹ã¿ã³ã¹ã«å¯Ÿããåçš®æäœã®å®è¡ ORCA ã®ã¢ããããŒããªã©ã宿çã«è¡ãæäœã«å¿
èŠãªã³ãã³ãã document ãšããŠç»é²ããRunCommand ã§ç¹å®ã€ã³ã¹ã¿ã³ã¹ãŸãã¯è€æ°ã€ã³ã¹ã¿ã³ã¹ã«äžæ¬å®è¡ã§ããããã«ããŠããŸãã ORCA ã¢ããªã±ãŒã·ã§ã³ã®æ»æŽ»ç£èŠ ORCA ã¢ããªã±ãŒã·ã§ã³èªäœæ§æãè€éã§ãããã€ãã®ããã«ãŠã§ã¢ãšé£æºããŠåããŠããŸãããããã®åçš®ããã»ã¹/ãã°ç£èŠã¯è¡ã£ãäžã§ãAPI ãšããŠæ£ãã皌åããŠãããã確èªããããã®æ»æŽ»ç£èŠã Mackerel ã®ã«ã¹ã¿ã ã¡ããªã¯ã¹ãšããŠç»é²ããäžå®æ°ä»¥äžå€±æããå Žåã¯åçš®ããã»ã¹ãåèµ·åããããã§ãæ£åžžã«åããªãå Žå㯠Mackerel ãã Slack ã«éç¥ãããŠããŸãã ã»ãã¥ãªãã£ãã§ã㯠CloudTrail ã VPC ãããŒãã°ãªã©ãããšã«ãGuardDuty ã§å®æçã«ãã§ãã¯ãè匱æ§ãèŠã€ãã£ãå Žå㯠Slack ã«éç¥ãããããã«ããŠããŸãããã®ä»ãã»ãã¥ãªãã£ãããé©çšãªã©ãããããããŒãžã£ãŒãå©çšãèªååãããŠããŸãã ãŸãšã é»åã«ã«ãã®ã·ã¹ãã ã¯æ€æ»ãç»åããŒã¿ãªã©ãåãæ±ãå€éšã·ã¹ãã ãšé£æºããããšããéèŠããããŸãããã®ãããªé£æºãèŠéã«å
¥ãããšããŒã¿æšæºåã®åé¡ãªã©ãããé£ããåéã§ã¯ãããŸãããCLINICS ã«ã«ããšããŠæ¥ã
é²åããŠããããã«ãããã«ãããŒãžããµãŒãã¹ãªã©æŽ»çšã§ãããšããã¯ç©æ¥µçã«æŽ»çšããéäžãã¹ãåé¡ã解決ããŠãããããšæããŸãã ãŸããé»åã«ã«ãã®ã·ã¹ãã ãšããŠã®æ§è³ªäžã絶察ã«èœãšããªãã·ã¹ãã éçšãå¿
èŠã§ããããã«å
ç¢ãªã·ã¹ãã ã«ããããã«ããã©ãã«ãæªç¶ã«é²ããããªéæ©èœé¢ã®åŒ·åãæ¥ã
ã®ã¢ãã¿ãªã³ã°ãªã©å°éãªããšãå«ãããã£ãšãã£ãšåãçµãã§ããå¿
èŠããããŸãã ãŸã ãŸã ãããã¯ããšããŠæªæçãªæ®µéã§ã¯ãããŸããããå»çã®èª²é¡ã解決ããããããCLINICS ã«ã«ãã§ã¯å»çæ¥åãå¹çåããå»çãã©ãããã©ãŒã ãšãªãã¹ãé²åããŠãããããšããæ§æ³ãæã£ãŠããŸããïŒCLINICS ã«ã«ããç®æãå»çã®ãã©ãããã©ãŒã ãšã¯ïŒãšãã話ã¯ããã¡ãã§è©³ããæžãããŠããŸãïŒ ãCLINICSã«ã«ãããç®æã âå»çã®ãã©ãããã©ãŒã â ãšã¯ïŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ãä¹
ãã¶ãã§ããã¡ãã¬ãŒã§æ¡çšãšåºå ±ãæ
åœããŠããå è€ã§ããæšå¹Žããã¯ãããããã®ããŒãã圹å¡ã¿ããªã§è©±ããŸããããã®ã³ãŒããŒã§ãããæšå¹Žãšç¶æ³ãå€ãããããããªã¡ã³ããŒã«JOINããŠããããã... www.wantedly.com CLINICS ã«ã«ãã¯ããŸãã¯å€ãã®å»çæ©é¢ã«äœ¿ã£ãŠããããã®ã§ã¯ãããŸãããå°æ¥çã«ã¯ãæ£è
ãããšå»çæ©é¢ãã€ãªãã蚺çãæ€æ»ããŒã¿ãªã©ããããšããããã©ãããã©ãŒã ãšãªãäºå®ã§ããããããæ°ããå»çã®ãããã¯ãã«èå³ã®ãããã¶ã€ããŒã»ãšã³ãžãã¢ã»ãã£ã¬ã¯ã¿ãŒã®æ¹ã¯ãã²ãã¡ããŸã§ãå¿åããŸã¡ããŠãããŸãã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp
4 ææ«ã«æ°ãã«ãªãªãŒã¹ããã¯ã©ãŠãåé»åã«ã«ãã CLINICS ã«ã«ã ãã®éçºãæ
åœããŠããç°äžã§ãã é»åã«ã«ããšããå»çè¡çºãæ¯ãããããã¯ãéçºãªãã§ã¯ã®ééå³ãé£ãããæããæ¥ã
ãéãããŠããŸããåå㯠CLINICS ã«ã«ãã®ãã¶ã€ã³ã«ã€ããŠããšãã玹ä»ããŸãã ããä»åã¯ãšã³ãžãã¢ããèŠãèŠæ©ãšèè€ã«ã€ããŠã話ããŸãã èŠåŽããç¹ãšããŠã¯ãå»çäºåã®æ¥åãã®ãã®ã®è€éããããã«äŒŽãã¢ããªã±ãŒã·ã§ã³éçºã®è€éãã¯ãã¡ããã®ããšã é»åã«ã«ãéçºã®ç¹åŸŽãšããŠé¢é£çåºã®ã¬ã€ãã©ã€ã³ã®æºæ ãã¬ã»ãããœããïŒå»çäŒèšå°çšã®ã·ã¹ãã ïŒã®ã·ã¹ãã 管çãªã©ãå€å²ã«ããã察å¿ãå¿
èŠãªããš ãæããããŸãã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ã«é¢ããã話ã¯çްãããªã£ãŠããŸãã®ã§ã倧ãŸããªå
容ãšããŠãä»åã¯äž»ã«ã¬ã»ããã·ã¹ãã ãšããŠé£æºããŠãã ORCA ã®ã·ã¹ãã ç®¡çæ¹æ³ã«ã€ããŠãäŒããããŠããã ããã°ãšæããŸãïŒORCA ã«é¢ãã説æã¯åŸè¿°ããŸãïŒã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ é»åã«ã«ãã®ããã«å»çæ
å ±ãæ±ãéã«éµå®ããå¿
èŠãããã¬ã€ãã©ã€ã³ãšã㊠3 ç 4 ã¬ã€ãã©ã€ã³ïŒåçåŽåçãçµæžç£æ¥çãç·åçã® 3 çãåºããŠãã 4 ã€ã®ã¬ã€ãã©ã€ã³ïŒããããŸãã CLINICS ã«ã«ãã®éçºãé²ããã«ãããããã®ã¬ã€ãã©ã€ã³ãã·ã¹ãã èšèšãéçšã«å€§ããªåœ±é¿ãåãŒãããããŸãã¯ã¬ã€ãã©ã€ã³ãèªã¿èŸŒã¿æŽçãããšããããå§ããŸããã ã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãšãã«å¯Ÿå¿ãã¹ãããšã¯å€ãã£ãã®ã§ãããã·ã¹ãã æ§æã«ç¹ã«åœ±é¿ã倧ããã£ãã®ã¯ä»¥äžã® 2 ç¹ãšãªããŸãã ãµãŒãã¹æäŸã«çšããã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãæ¥æ¬åœå
æ³ã®é©çšãåã¶å Žæã«èšçœ®ããããš ã¯ã©ã€ã¢ã³ãèšŒææžãå©çšãã TLS ã¯ã©ã€ã¢ã³ãèªèšŒã宿œããããš CLINICS ã«ã«ãã¯åŒç€Ÿã§æ¢ã«éçšããŠãããªã³ã©ã€ã³èšºçã¢ããªãCLINICSããšé£æºãããåæã§ãã£ããããã¬ã€ãã©ã€ã³ã«å³ããã·ã¹ãã æ§æãšããŠããããã«ããŸã CLINICS ã®ã·ã¹ãã ã Heroku ãã AWS ã«ç§»è¡ããããšããå§ãŸããŸããã ãŸããã¯ã©ã€ã¢ã³ãèªèšŒãè¡ãããã« AWS ã®æ§æãè²ã
ãšæ€èšããNginx ãšãæ¥ã
æ ŒéãããããŸããããã ãããã®å¯Ÿå¿å
容ã«é¢é£ããããã°ãéå»ã«æžããŠããŸãã®ã§ãèå³ãããæ¹ã¯ãã²ãåèã«ããŠãã ããã https://developer.medley.jp/entry/2017/08/24/120000_01 https://developer.medley.jp/entry/2017/08/24/120000_02 https://developer.medley.jp/entry/2017/09/22/124000 ORCA ãµãŒãã®ç®¡çæ¹æ³ CLINICS ã«ã«ãã¯ãæ¥æ¬å»åž«äŒ ORCA ç®¡çæ©æ§æ ªåŒäŒç€ŸãæäŸããå»çäŒèšãœããã§ãããORCAããçµã¿èŸŒãã ãORCA å
å
åãã®ã¯ã©ãŠãåé»åã«ã«ãã§ãã åè: ORCA ãšã¯ å»ççŸå Ž IT åãæšé²ããæ¥æ¬å»åž«äŒãäŒå¡çã®ããã«æäŸããŠããã¬ã»ãããœããïŒèšºçå ±é
¬ã®è«æ±æ¥åãè¡ãããã®å»çäŒèšãœããïŒã2002 幎ã«ãªãŒãã³ãœãŒã¹ãšããŠå
¬éãããçŸåšã蚺çæãäžå¿ã« 17,000 ãè¶
ããå
šåœã®å»çæ©é¢ã«å°å
¥ãããŠããŸãã å»çæ
å ±ãããã¯ãŒã¯æšé²å§å¡äŒã«ãŠãå»åž«äŒç·åæ
å ±ãããã¯ãŒã¯æ§æ³ãïŒ1997 幎 æ
å ±åæ€èšå§å¡äŒïŒãæ§æããããŒã«ã®äžã€ãšããŠèªããããæ¥æ¬å»åž«äŒã®ç ç©¶äºæ¥ãããžã§ã¯ããORCA ãããžã§ã¯ãããéçºãæäŸãéå§ãããã®ã§ãã https://www.orca.med.or.jp/orca/summary/outline.html CLINICS ã«ã«ãã¯ãããŸãã«ä»¥äžã®ãããªæ§æãšãªã£ãŠãããRuby on Rails ã§çšŒåããŠããã«ã«ãã¢ããªã±ãŒã·ã§ã³ãšå»çæ©é¢ããšã® ORCA ãµãŒããããããã®éã ORCA ãæäŸããŠãã API ã§æ¥ç¶ããŠããŸãã ïŒäžå³ã¯äžäŸãšããŠäžããŠãããã®ã§å°æ°ãè©³çŽ°ãªæ§æã¯å®éã®ã·ã¹ãã ãšã¯ç°ãªããŸãïŒ ãã® ORCA ãµãŒãã§ãããå»çæ©é¢ããšã« 1 ã€ã® EC2 ã€ã³ã¹ã¿ã³ã¹æ§æãšãªã£ãŠãããå©çšããå»çæ©é¢ãå¢ãã床㫠EC2 ã€ã³ã¹ã¿ã³ã¹ãå¢ãããããå°å
¥å»çæ©é¢ãå¢ããã»ã©æ§ç¯ãéçšãã€ãããªã£ãŠãããŸãããã®ããããåºæ¥ãã ãèªååããã話ãä»åã®ã¡ã€ã³ããŒãã§ãã ïŒããããããã£ãšæ¥œãã§ããæ§æã«ããããšè²ã
æ€èšãããã®ã§ãããã·ã¹ãã ã®ç¹æ®æ§ãªã©ã®è«žäºæ
ããããçµæ EC2 ã€ã³ã¹ã¿ã³ã¹åäœã§ç®¡çããæ§æã«ãªã£ãŠããŸãïŒ ORCA ãµãŒããŒé¢é£ã§äž»ã«äœ¿çšãã AWS ãµãŒãã¹ AMI äœæãã€ã³ã¹ã¿ã³ã¹äœæãªã©ã®ãã«ã系㯠CodeBuild ããããé©çšãã³ãã³ãå®è¡ãªã©ã®ã€ã³ã¹ã¿ã³ã¹ç®¡ç㯠Systems Manager ãè匱æ§ãã§ãã¯ãªã©ã®ã»ãã¥ãªãã£é¢é£ã«ã¯ Guard Duty ãšãã£ããµãŒãã¹ãäž»ã«å©çšããŠããŸãã æ¬¡ã«ãã€ã³ã¹ã¿ã³ã¹æ§ç¯ã«é¢ããŠããå°ãå
·äœçã«èª¬æããŸãã ORCA ãµãŒãã®ã€ã³ã¹ã¿ã³ã¹æ§ç¯ ORCA ãµãŒãçš AMIïŒãŽãŒã«ãã³ã€ã¡ãŒãžïŒäœæ ãã«ãã®å®è¡ã¯ CodeBuild ã§è¡ã£ãŠããŸããAMI ã®ãã«ãã«ã¯ Packer ã䜿çšããŠããããã«ãå®äºæã«äœæããã AMI ã® ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é²ããŠããŸãããã® AMI ID ãã€ã³ã¹ã¿ã³ã¹äœææã«åç
§ããŸãã åèãŸã§ã«ãCodeBuild ã§äœ¿çšããŠãã buildspec.yaml ã¯ä»¥äžã®ããã«ãªããŸãïŒèª¬æç®æãªã©ãäžéšå®éãšã¯ç°ãªããŸãïŒã phases : pre_build : ## 説æ * packer ãš jq ããã«ãçšã³ã³ããã«ã€ã³ã¹ããŒã« commands : - curl -qL -o packer.zip https://releases.hashicorp.com/packer/1.1.3/packer_1.1.3_linux_amd64.zip && unzip packer.zip - curl -qL -o jq https://stedolan.github.io/jq/download/linux64/jq && chmod +x ./jq build : ## 説æ * åŠçã«å¿
èŠãª AWS credential æ
å ±ãååŸïŒèšå®ïŒåŸã® aws cli 䜿ãçšïŒ * packer ãã«ãå®è¡ãAMI äœæ * packer ãã«ãçµæããäœæããã AMI ID ãååŸ * AMI ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é² commands : - curl -qL -o aws_credentials.json https://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > aws_credentials.json - aws configure set region $AWS_REGION - aws configure set aws_access_key_id `./jq -r '.AccessKeyId' aws_credentials.json` - aws configure set aws_secret_access_key `./jq -r '.SecretAccessKey' aws_credentials.json` - aws configure set aws_session_token `./jq -r '.Token' aws_credentials.json` - ../packer build -machine-readable bin/packer.json | tee packer.log - cat packer.log | grep "artifact,0,id" | cut -d "," -f6 | cut -d ":" -f2 > ami.txt - ORCA_AMI_ID=`cat ami.txt` - aws ssm put-parameter --name ORCA_AMI_ID --value $ORCA_AMI_ID --type String --overwrite ORCA ãµãŒãçš EC2 ã€ã³ã¹ã¿ã³ã¹äœæ å»çæ©é¢çšã®ã¢ã«ãŠã³ããæ°èŠè¿œå ããå Žåã瀟å
çšã®ç®¡çããŒã«ã§ãŸãå»çæ©é¢ã®åºæ¬æ
å ±ãç»é²ããŸãããã®åŸãORCA ã€ã³ã¹ã¿ã³ã¹èšå®ã«å¿
èŠãªãã©ã¡ãŒã¿ïŒå»çæ©é¢ãèå¥ãã ID ãªã©ïŒãèšå®ããã€ã³ã¹ã¿ã³ã¹äœæã®ãã«ãåŠçãå®è¡ããŸãã CodeBuild ããŽãŒã«ãã³ã€ã¡ãŒãžçšã® AMI ãããŒã¹ã« ORCA ã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ããŸããORCA ã€ã³ã¹ã¿ã³ã¹ã¯èµ·åæã«åçš®èšå®åŠçãè¡ããŸãïŒcloud-initïŒ ãªããã€ã³ã¹ã¿ã³ã¹èµ·åæã«è¡ã£ãŠããåŠçãšããŠäž»ã«ä»¥äžã®ãããªããšãè¡ã£ãŠããŸãã 該åœã€ã³ã¹ã¿ã³ã¹ã®å
éš IP ã Private DNS ã«ç»é² ORCA ã®ã»ããã¢ãã/ããã°ã©ã /ãã¹ã¿æŽæ° Postgres ã®ããã¯ã¢ããèšå® Mackerel ã Systems Manager çã®åçš® Agent ã€ã³ã¹ããŒã«ãèšå® ORCA ãµãŒãéçš æ§ç¯ãå®äºã皌åããåŸããORCA èªäœã®ã¢ããããŒãããããã®é©çšãªã©æ§ã
ãªéçšãçºçããŸããããããã©ã®ããã«è¡ã£ãŠãããããŸã æ¹åäžã§ã¯ãããŸããäžéšã玹ä»ããŸãã ã€ã³ã¹ã¿ã³ã¹ã«å¯Ÿããåçš®æäœã®å®è¡ ORCA ã®ã¢ããããŒããªã©ã宿çã«è¡ãæäœã«å¿
èŠãªã³ãã³ãã document ãšããŠç»é²ããRunCommand ã§ç¹å®ã€ã³ã¹ã¿ã³ã¹ãŸãã¯è€æ°ã€ã³ã¹ã¿ã³ã¹ã«äžæ¬å®è¡ã§ããããã«ããŠããŸãã ORCA ã¢ããªã±ãŒã·ã§ã³ã®æ»æŽ»ç£èŠ ORCA ã¢ããªã±ãŒã·ã§ã³èªäœæ§æãè€éã§ãããã€ãã®ããã«ãŠã§ã¢ãšé£æºããŠåããŠããŸãããããã®åçš®ããã»ã¹/ãã°ç£èŠã¯è¡ã£ãäžã§ãAPI ãšããŠæ£ãã皌åããŠãããã確èªããããã®æ»æŽ»ç£èŠã Mackerel ã®ã«ã¹ã¿ã ã¡ããªã¯ã¹ãšããŠç»é²ããäžå®æ°ä»¥äžå€±æããå Žåã¯åçš®ããã»ã¹ãåèµ·åããããã§ãæ£åžžã«åããªãå Žå㯠Mackerel ãã Slack ã«éç¥ãããŠããŸãã ã»ãã¥ãªãã£ãã§ã㯠CloudTrail ã VPC ãããŒãã°ãªã©ãããšã«ãGuardDuty ã§å®æçã«ãã§ãã¯ãè匱æ§ãèŠã€ãã£ãå Žå㯠Slack ã«éç¥ãããããã«ããŠããŸãããã®ä»ãã»ãã¥ãªãã£ãããé©çšãªã©ãããããããŒãžã£ãŒãå©çšãèªååãããŠããŸãã ãŸãšã é»åã«ã«ãã®ã·ã¹ãã ã¯æ€æ»ãç»åããŒã¿ãªã©ãåãæ±ãå€éšã·ã¹ãã ãšé£æºããããšããéèŠããããŸãããã®ãããªé£æºãèŠéã«å
¥ãããšããŒã¿æšæºåã®åé¡ãªã©ãããé£ããåéã§ã¯ãããŸãããCLINICS ã«ã«ããšããŠæ¥ã
é²åããŠããããã«ãããã«ãããŒãžããµãŒãã¹ãªã©æŽ»çšã§ãããšããã¯ç©æ¥µçã«æŽ»çšããéäžãã¹ãåé¡ã解決ããŠãããããšæããŸãã ãŸããé»åã«ã«ãã®ã·ã¹ãã ãšããŠã®æ§è³ªäžã絶察ã«èœãšããªãã·ã¹ãã éçšãå¿
èŠã§ããããã«å
ç¢ãªã·ã¹ãã ã«ããããã«ããã©ãã«ãæªç¶ã«é²ããããªéæ©èœé¢ã®åŒ·åãæ¥ã
ã®ã¢ãã¿ãªã³ã°ãªã©å°éãªããšãå«ãããã£ãšãã£ãšåãçµãã§ããå¿
èŠããããŸãã ãŸã ãŸã ãããã¯ããšããŠæªæçãªæ®µéã§ã¯ãããŸããããå»çã®èª²é¡ã解決ããããããCLINICS ã«ã«ãã§ã¯å»çæ¥åãå¹çåããå»çãã©ãããã©ãŒã ãšãªãã¹ãé²åããŠãããããšããæ§æ³ãæã£ãŠããŸããïŒCLINICS ã«ã«ããç®æãå»çã®ãã©ãããã©ãŒã ãšã¯ïŒãšãã話ã¯ããã¡ãã§è©³ããæžãããŠããŸãïŒ https://www.wantedly.com/companies/medley/post_articles/118281 CLINICS ã«ã«ãã¯ããŸãã¯å€ãã®å»çæ©é¢ã«äœ¿ã£ãŠããããã®ã§ã¯ãããŸãããå°æ¥çã«ã¯ãæ£è
ãããšå»çæ©é¢ãã€ãªãã蚺çãæ€æ»ããŒã¿ãªã©ããããšããããã©ãããã©ãŒã ãšãªãäºå®ã§ããããããæ°ããå»çã®ãããã¯ãã«èå³ã®ãããã¶ã€ããŒã»ãšã³ãžãã¢ã»ãã£ã¬ã¯ã¿ãŒã®æ¹ã¯ãã²ãã¡ããŸã§ãå¿åããŸã¡ããŠãããŸãã https://www.medley.jp/recruit/creative.html
4 ææ«ã«æ°ãã«ãªãªãŒã¹ããã¯ã©ãŠãåé»åã«ã«ãã CLINICS ã«ã«ã ãã®éçºãæ
åœããŠããç°äžã§ãã é»åã«ã«ããšããå»çè¡çºãæ¯ãããããã¯ãéçºãªãã§ã¯ã®ééå³ãé£ãããæããæ¥ã
ãéãããŠããŸããåå㯠CLINICS ã«ã«ãã®ãã¶ã€ã³ã«ã€ããŠããšãã玹ä»ããŸãã ããä»åã¯ãšã³ãžãã¢ããèŠãèŠæ©ãšèè€ã«ã€ããŠã話ããŸãã èŠåŽããç¹ãšããŠã¯ãå»çäºåã®æ¥åãã®ãã®ã®è€éããããã«äŒŽãã¢ããªã±ãŒã·ã§ã³éçºã®è€éãã¯ãã¡ããã®ããšã é»åã«ã«ãéçºã®ç¹åŸŽãšããŠé¢é£çåºã®ã¬ã€ãã©ã€ã³ã®æºæ ãã¬ã»ãããœããïŒå»çäŒèšå°çšã®ã·ã¹ãã ïŒã®ã·ã¹ãã 管çãªã©ãå€å²ã«ããã察å¿ãå¿
èŠãªããš ãæããããŸãã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ã«é¢ããã話ã¯çްãããªã£ãŠããŸãã®ã§ã倧ãŸããªå
容ãšããŠãä»åã¯äž»ã«ã¬ã»ããã·ã¹ãã ãšããŠé£æºããŠãã ORCA ã®ã·ã¹ãã ç®¡çæ¹æ³ã«ã€ããŠãäŒããããŠããã ããã°ãšæããŸãïŒORCA ã«é¢ãã説æã¯åŸè¿°ããŸãïŒã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ é»åã«ã«ãã®ããã«å»çæ
å ±ãæ±ãéã«éµå®ããå¿
èŠãããã¬ã€ãã©ã€ã³ãšã㊠3 ç 4 ã¬ã€ãã©ã€ã³ïŒåçåŽåçãçµæžç£æ¥çãç·åçã® 3 çãåºããŠãã 4 ã€ã®ã¬ã€ãã©ã€ã³ïŒããããŸãã CLINICS ã«ã«ãã®éçºãé²ããã«ãããããã®ã¬ã€ãã©ã€ã³ãã·ã¹ãã èšèšãéçšã«å€§ããªåœ±é¿ãåãŒãããããŸãã¯ã¬ã€ãã©ã€ã³ãèªã¿èŸŒã¿æŽçãããšããããå§ããŸããã ã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãšãã«å¯Ÿå¿ãã¹ãããšã¯å€ãã£ãã®ã§ãããã·ã¹ãã æ§æã«ç¹ã«åœ±é¿ã倧ããã£ãã®ã¯ä»¥äžã® 2 ç¹ãšãªããŸãã ãµãŒãã¹æäŸã«çšããã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãæ¥æ¬åœå
æ³ã®é©çšãåã¶å Žæã«èšçœ®ããããš ã¯ã©ã€ã¢ã³ãèšŒææžãå©çšãã TLS ã¯ã©ã€ã¢ã³ãèªèšŒã宿œããããš CLINICS ã«ã«ãã¯åŒç€Ÿã§æ¢ã«éçšããŠãããªã³ã©ã€ã³èšºçã¢ããªãCLINICSããšé£æºãããåæã§ãã£ããããã¬ã€ãã©ã€ã³ã«å³ããã·ã¹ãã æ§æãšããŠããããã«ããŸã CLINICS ã®ã·ã¹ãã ã Heroku ãã AWS ã«ç§»è¡ããããšããå§ãŸããŸããã ãŸããã¯ã©ã€ã¢ã³ãèªèšŒãè¡ãããã« AWS ã®æ§æãè²ã
ãšæ€èšããNginx ãšãæ¥ã
æ ŒéãããããŸããããã ãããã®å¯Ÿå¿å
容ã«é¢é£ããããã°ãéå»ã«æžããŠããŸãã®ã§ãèå³ãããæ¹ã¯ãã²ãåèã«ããŠãã ããã https://developer.medley.jp/entry/2017/08/24/120000_01 https://developer.medley.jp/entry/2017/08/24/120000_02 https://developer.medley.jp/entry/2017/09/22/124000 ORCA ãµãŒãã®ç®¡çæ¹æ³ CLINICS ã«ã«ãã¯ãæ¥æ¬å»åž«äŒ ORCA ç®¡çæ©æ§æ ªåŒäŒç€ŸãæäŸããå»çäŒèšãœããã§ãããORCAããçµã¿èŸŒãã ãORCA å
å
åãã®ã¯ã©ãŠãåé»åã«ã«ãã§ãã åè: ORCA ãšã¯ å»ççŸå Ž IT åãæšé²ããæ¥æ¬å»åž«äŒãäŒå¡çã®ããã«æäŸããŠããã¬ã»ãããœããïŒèšºçå ±é
¬ã®è«æ±æ¥åãè¡ãããã®å»çäŒèšãœããïŒã2002 幎ã«ãªãŒãã³ãœãŒã¹ãšããŠå
¬éãããçŸåšã蚺çæãäžå¿ã« 17,000 ãè¶
ããå
šåœã®å»çæ©é¢ã«å°å
¥ãããŠããŸãã å»çæ
å ±ãããã¯ãŒã¯æšé²å§å¡äŒã«ãŠãå»åž«äŒç·åæ
å ±ãããã¯ãŒã¯æ§æ³ãïŒ1997 幎 æ
å ±åæ€èšå§å¡äŒïŒãæ§æããããŒã«ã®äžã€ãšããŠèªããããæ¥æ¬å»åž«äŒã®ç ç©¶äºæ¥ãããžã§ã¯ããORCA ãããžã§ã¯ãããéçºãæäŸãéå§ãããã®ã§ãã ORCA ProjectïŒ ORCAãããžã§ã¯ãã®æŠèŠ æ¥æ¬å»åž«äŒéçºã»æ¥å»æšæºã¬ã»ãããœãããŠã§ã¢ã®ãµã€ãã§ã www.orca.med.or.jp CLINICS ã«ã«ãã¯ãããŸãã«ä»¥äžã®ãããªæ§æãšãªã£ãŠãããRuby on Rails ã§çšŒåããŠããã«ã«ãã¢ããªã±ãŒã·ã§ã³ãšå»çæ©é¢ããšã® ORCA ãµãŒããããããã®éã ORCA ãæäŸããŠãã API ã§æ¥ç¶ããŠããŸãã ïŒäžå³ã¯äžäŸãšããŠäžããŠãããã®ã§å°æ°ãè©³çŽ°ãªæ§æã¯å®éã®ã·ã¹ãã ãšã¯ç°ãªããŸãïŒ ãã® ORCA ãµãŒãã§ãããå»çæ©é¢ããšã« 1 ã€ã® EC2 ã€ã³ã¹ã¿ã³ã¹æ§æãšãªã£ãŠãããå©çšããå»çæ©é¢ãå¢ãã床㫠EC2 ã€ã³ã¹ã¿ã³ã¹ãå¢ãããããå°å
¥å»çæ©é¢ãå¢ããã»ã©æ§ç¯ãéçšãã€ãããªã£ãŠãããŸãããã®ããããåºæ¥ãã ãèªååããã話ãä»åã®ã¡ã€ã³ããŒãã§ãã ïŒããããããã£ãšæ¥œãã§ããæ§æã«ããããšè²ã
æ€èšãããã®ã§ãããã·ã¹ãã ã®ç¹æ®æ§ãªã©ã®è«žäºæ
ããããçµæ EC2 ã€ã³ã¹ã¿ã³ã¹åäœã§ç®¡çããæ§æã«ãªã£ãŠããŸãïŒ ORCA ãµãŒããŒé¢é£ã§äž»ã«äœ¿çšãã AWS ãµãŒãã¹ AMI äœæãã€ã³ã¹ã¿ã³ã¹äœæãªã©ã®ãã«ã系㯠CodeBuild ããããé©çšãã³ãã³ãå®è¡ãªã©ã®ã€ã³ã¹ã¿ã³ã¹ç®¡ç㯠Systems Manager ãè匱æ§ãã§ãã¯ãªã©ã®ã»ãã¥ãªãã£é¢é£ã«ã¯ Guard Duty ãšãã£ããµãŒãã¹ãäž»ã«å©çšããŠããŸãã æ¬¡ã«ãã€ã³ã¹ã¿ã³ã¹æ§ç¯ã«é¢ããŠããå°ãå
·äœçã«èª¬æããŸãã ORCA ãµãŒãã®ã€ã³ã¹ã¿ã³ã¹æ§ç¯ ORCA ãµãŒãçš AMIïŒãŽãŒã«ãã³ã€ã¡ãŒãžïŒäœæ ãã«ãã®å®è¡ã¯ CodeBuild ã§è¡ã£ãŠããŸããAMI ã®ãã«ãã«ã¯ Packer ã䜿çšããŠããããã«ãå®äºæã«äœæããã AMI ã® ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é²ããŠããŸãããã® AMI ID ãã€ã³ã¹ã¿ã³ã¹äœææã«åç
§ããŸãã åèãŸã§ã«ãCodeBuild ã§äœ¿çšããŠãã buildspec.yaml ã¯ä»¥äžã®ããã«ãªããŸãïŒèª¬æç®æãªã©ãäžéšå®éãšã¯ç°ãªããŸãïŒã phases : pre_build : ## 説æ * packer ãš jq ããã«ãçšã³ã³ããã«ã€ã³ã¹ããŒã« commands : - curl -qL -o packer.zip https://releases.hashicorp.com/packer/1.1.3/packer_1.1.3_linux_amd64.zip && unzip packer.zip - curl -qL -o jq https://stedolan.github.io/jq/download/linux64/jq && chmod +x ./jq build : ## 説æ * åŠçã«å¿
èŠãª AWS credential æ
å ±ãååŸïŒèšå®ïŒåŸã® aws cli 䜿ãçšïŒ * packer ãã«ãå®è¡ãAMI äœæ * packer ãã«ãçµæããäœæããã AMI ID ãååŸ * AMI ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é² commands : - curl -qL -o aws_credentials.json https://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > aws_credentials.json - aws configure set region $AWS_REGION - aws configure set aws_access_key_id `./jq -r '.AccessKeyId' aws_credentials.json` - aws configure set aws_secret_access_key `./jq -r '.SecretAccessKey' aws_credentials.json` - aws configure set aws_session_token `./jq -r '.Token' aws_credentials.json` - ../packer build -machine-readable bin/packer.json | tee packer.log - cat packer.log | grep "artifact,0,id" | cut -d "," -f6 | cut -d ":" -f2 > ami.txt - ORCA_AMI_ID=`cat ami.txt` - aws ssm put-parameter --name ORCA_AMI_ID --value $ORCA_AMI_ID --type String --overwrite ORCA ãµãŒãçš EC2 ã€ã³ã¹ã¿ã³ã¹äœæ å»çæ©é¢çšã®ã¢ã«ãŠã³ããæ°èŠè¿œå ããå Žåã瀟å
çšã®ç®¡çããŒã«ã§ãŸãå»çæ©é¢ã®åºæ¬æ
å ±ãç»é²ããŸãããã®åŸãORCA ã€ã³ã¹ã¿ã³ã¹èšå®ã«å¿
èŠãªãã©ã¡ãŒã¿ïŒå»çæ©é¢ãèå¥ãã ID ãªã©ïŒãèšå®ããã€ã³ã¹ã¿ã³ã¹äœæã®ãã«ãåŠçãå®è¡ããŸãã CodeBuild ããŽãŒã«ãã³ã€ã¡ãŒãžçšã® AMI ãããŒã¹ã« ORCA ã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ããŸããORCA ã€ã³ã¹ã¿ã³ã¹ã¯èµ·åæã«åçš®èšå®åŠçãè¡ããŸãïŒcloud-initïŒ ãªããã€ã³ã¹ã¿ã³ã¹èµ·åæã«è¡ã£ãŠããåŠçãšããŠäž»ã«ä»¥äžã®ãããªããšãè¡ã£ãŠããŸãã 該åœã€ã³ã¹ã¿ã³ã¹ã®å
éš IP ã Private DNS ã«ç»é² ORCA ã®ã»ããã¢ãã/ããã°ã©ã /ãã¹ã¿æŽæ° Postgres ã®ããã¯ã¢ããèšå® Mackerel ã Systems Manager çã®åçš® Agent ã€ã³ã¹ããŒã«ãèšå® ORCA ãµãŒãéçš æ§ç¯ãå®äºã皌åããåŸããORCA èªäœã®ã¢ããããŒãããããã®é©çšãªã©æ§ã
ãªéçšãçºçããŸããããããã©ã®ããã«è¡ã£ãŠãããããŸã æ¹åäžã§ã¯ãããŸããäžéšã玹ä»ããŸãã ã€ã³ã¹ã¿ã³ã¹ã«å¯Ÿããåçš®æäœã®å®è¡ ORCA ã®ã¢ããããŒããªã©ã宿çã«è¡ãæäœã«å¿
èŠãªã³ãã³ãã document ãšããŠç»é²ããRunCommand ã§ç¹å®ã€ã³ã¹ã¿ã³ã¹ãŸãã¯è€æ°ã€ã³ã¹ã¿ã³ã¹ã«äžæ¬å®è¡ã§ããããã«ããŠããŸãã ORCA ã¢ããªã±ãŒã·ã§ã³ã®æ»æŽ»ç£èŠ ORCA ã¢ããªã±ãŒã·ã§ã³èªäœæ§æãè€éã§ãããã€ãã®ããã«ãŠã§ã¢ãšé£æºããŠåããŠããŸãããããã®åçš®ããã»ã¹/ãã°ç£èŠã¯è¡ã£ãäžã§ãAPI ãšããŠæ£ãã皌åããŠãããã確èªããããã®æ»æŽ»ç£èŠã Mackerel ã®ã«ã¹ã¿ã ã¡ããªã¯ã¹ãšããŠç»é²ããäžå®æ°ä»¥äžå€±æããå Žåã¯åçš®ããã»ã¹ãåèµ·åããããã§ãæ£åžžã«åããªãå Žå㯠Mackerel ãã Slack ã«éç¥ãããŠããŸãã ã»ãã¥ãªãã£ãã§ã㯠CloudTrail ã VPC ãããŒãã°ãªã©ãããšã«ãGuardDuty ã§å®æçã«ãã§ãã¯ãè匱æ§ãèŠã€ãã£ãå Žå㯠Slack ã«éç¥ãããããã«ããŠããŸãããã®ä»ãã»ãã¥ãªãã£ãããé©çšãªã©ãããããããŒãžã£ãŒãå©çšãèªååãããŠããŸãã ãŸãšã é»åã«ã«ãã®ã·ã¹ãã ã¯æ€æ»ãç»åããŒã¿ãªã©ãåãæ±ãå€éšã·ã¹ãã ãšé£æºããããšããéèŠããããŸãããã®ãããªé£æºãèŠéã«å
¥ãããšããŒã¿æšæºåã®åé¡ãªã©ãããé£ããåéã§ã¯ãããŸãããCLINICS ã«ã«ããšããŠæ¥ã
é²åããŠããããã«ãããã«ãããŒãžããµãŒãã¹ãªã©æŽ»çšã§ãããšããã¯ç©æ¥µçã«æŽ»çšããéäžãã¹ãåé¡ã解決ããŠãããããšæããŸãã ãŸããé»åã«ã«ãã®ã·ã¹ãã ãšããŠã®æ§è³ªäžã絶察ã«èœãšããªãã·ã¹ãã éçšãå¿
èŠã§ããããã«å
ç¢ãªã·ã¹ãã ã«ããããã«ããã©ãã«ãæªç¶ã«é²ããããªéæ©èœé¢ã®åŒ·åãæ¥ã
ã®ã¢ãã¿ãªã³ã°ãªã©å°éãªããšãå«ãããã£ãšãã£ãšåãçµãã§ããå¿
èŠããããŸãã ãŸã ãŸã ãããã¯ããšããŠæªæçãªæ®µéã§ã¯ãããŸããããå»çã®èª²é¡ã解決ããããããCLINICS ã«ã«ãã§ã¯å»çæ¥åãå¹çåããå»çãã©ãããã©ãŒã ãšãªãã¹ãé²åããŠãããããšããæ§æ³ãæã£ãŠããŸããïŒCLINICS ã«ã«ããç®æãå»çã®ãã©ãããã©ãŒã ãšã¯ïŒãšãã話ã¯ããã¡ãã§è©³ããæžãããŠããŸãïŒ ãCLINICSã«ã«ãããç®æã âå»çã®ãã©ãããã©ãŒã â ãšã¯ïŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ãä¹
ãã¶ãã§ããã¡ãã¬ãŒã§æ¡çšãšåºå ±ãæ
åœããŠããå è€ã§ããæšå¹Žããã¯ãããããã®ããŒãã圹å¡ã¿ããªã§è©±ããŸããããã®ã³ãŒããŒã§ãããæšå¹Žãšç¶æ³ãå€ãããããããªã¡ã³ããŒã«JOINããŠããããã... www.wantedly.com CLINICS ã«ã«ãã¯ããŸãã¯å€ãã®å»çæ©é¢ã«äœ¿ã£ãŠããããã®ã§ã¯ãããŸãããå°æ¥çã«ã¯ãæ£è
ãããšå»çæ©é¢ãã€ãªãã蚺çãæ€æ»ããŒã¿ãªã©ããããšããããã©ãããã©ãŒã ãšãªãäºå®ã§ããããããæ°ããå»çã®ãããã¯ãã«èå³ã®ãããã¶ã€ããŒã»ãšã³ãžãã¢ã»ãã£ã¬ã¯ã¿ãŒã®æ¹ã¯ãã²ãã¡ããŸã§ãå¿åããŸã¡ããŠãããŸãã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp
4 ææ«ã«æ°ãã«ãªãªãŒã¹ããã¯ã©ãŠãåé»åã«ã«ãã CLINICS ã«ã«ã ãã®éçºãæ
åœããŠããç°äžã§ãã é»åã«ã«ããšããå»çè¡çºãæ¯ãããããã¯ãéçºãªãã§ã¯ã®ééå³ãé£ãããæããæ¥ã
ãéãããŠããŸããåå㯠CLINICS ã«ã«ãã®ãã¶ã€ã³ã«ã€ããŠããšãã玹ä»ããŸãã ããä»åã¯ãšã³ãžãã¢ããèŠãèŠæ©ãšèè€ã«ã€ããŠã話ããŸãã èŠåŽããç¹ãšããŠã¯ãå»çäºåã®æ¥åãã®ãã®ã®è€éããããã«äŒŽãã¢ããªã±ãŒã·ã§ã³éçºã®è€éãã¯ãã¡ããã®ããšã é»åã«ã«ãéçºã®ç¹åŸŽãšããŠé¢é£çåºã®ã¬ã€ãã©ã€ã³ã®æºæ ãã¬ã»ãããœããïŒå»çäŒèšå°çšã®ã·ã¹ãã ïŒã®ã·ã¹ãã 管çãªã©ãå€å²ã«ããã察å¿ãå¿
èŠãªããš ãæããããŸãã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ã«é¢ããã話ã¯çްãããªã£ãŠããŸãã®ã§ã倧ãŸããªå
容ãšããŠãä»åã¯äž»ã«ã¬ã»ããã·ã¹ãã ãšããŠé£æºããŠãã ORCA ã®ã·ã¹ãã ç®¡çæ¹æ³ã«ã€ããŠãäŒããããŠããã ããã°ãšæããŸãïŒORCA ã«é¢ãã説æã¯åŸè¿°ããŸãïŒã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ é»åã«ã«ãã®ããã«å»çæ
å ±ãæ±ãéã«éµå®ããå¿
èŠãããã¬ã€ãã©ã€ã³ãšã㊠3 ç 4 ã¬ã€ãã©ã€ã³ïŒåçåŽåçãçµæžç£æ¥çãç·åçã® 3 çãåºããŠãã 4 ã€ã®ã¬ã€ãã©ã€ã³ïŒããããŸãã CLINICS ã«ã«ãã®éçºãé²ããã«ãããããã®ã¬ã€ãã©ã€ã³ãã·ã¹ãã èšèšãéçšã«å€§ããªåœ±é¿ãåãŒãããããŸãã¯ã¬ã€ãã©ã€ã³ãèªã¿èŸŒã¿æŽçãããšããããå§ããŸããã ã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãšãã«å¯Ÿå¿ãã¹ãããšã¯å€ãã£ãã®ã§ãããã·ã¹ãã æ§æã«ç¹ã«åœ±é¿ã倧ããã£ãã®ã¯ä»¥äžã® 2 ç¹ãšãªããŸãã ãµãŒãã¹æäŸã«çšããã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãæ¥æ¬åœå
æ³ã®é©çšãåã¶å Žæã«èšçœ®ããããš ã¯ã©ã€ã¢ã³ãèšŒææžãå©çšãã TLS ã¯ã©ã€ã¢ã³ãèªèšŒã宿œããããš CLINICS ã«ã«ãã¯åŒç€Ÿã§æ¢ã«éçšããŠãããªã³ã©ã€ã³èšºçã¢ããªãCLINICSããšé£æºãããåæã§ãã£ããããã¬ã€ãã©ã€ã³ã«å³ããã·ã¹ãã æ§æãšããŠããããã«ããŸã CLINICS ã®ã·ã¹ãã ã Heroku ãã AWS ã«ç§»è¡ããããšããå§ãŸããŸããã ãŸããã¯ã©ã€ã¢ã³ãèªèšŒãè¡ãããã« AWS ã®æ§æãè²ã
ãšæ€èšããNginx ãšãæ¥ã
æ ŒéãããããŸããããã ãããã®å¯Ÿå¿å
容ã«é¢é£ããããã°ãéå»ã«æžããŠããŸãã®ã§ãèå³ãããæ¹ã¯ãã²ãåèã«ããŠãã ããã https://developer.medley.jp/entry/2017/08/24/120000_01 https://developer.medley.jp/entry/2017/08/24/120000_02 https://developer.medley.jp/entry/2017/09/22/124000 ORCA ãµãŒãã®ç®¡çæ¹æ³ CLINICS ã«ã«ãã¯ãæ¥æ¬å»åž«äŒ ORCA ç®¡çæ©æ§æ ªåŒäŒç€ŸãæäŸããå»çäŒèšãœããã§ãããORCAããçµã¿èŸŒãã ãORCA å
å
åãã®ã¯ã©ãŠãåé»åã«ã«ãã§ãã åè: ORCA ãšã¯ å»ççŸå Ž IT åãæšé²ããæ¥æ¬å»åž«äŒãäŒå¡çã®ããã«æäŸããŠããã¬ã»ãããœããïŒèšºçå ±é
¬ã®è«æ±æ¥åãè¡ãããã®å»çäŒèšãœããïŒã2002 幎ã«ãªãŒãã³ãœãŒã¹ãšããŠå
¬éãããçŸåšã蚺çæãäžå¿ã« 17,000 ãè¶
ããå
šåœã®å»çæ©é¢ã«å°å
¥ãããŠããŸãã å»çæ
å ±ãããã¯ãŒã¯æšé²å§å¡äŒã«ãŠãå»åž«äŒç·åæ
å ±ãããã¯ãŒã¯æ§æ³ãïŒ1997 幎 æ
å ±åæ€èšå§å¡äŒïŒãæ§æããããŒã«ã®äžã€ãšããŠèªããããæ¥æ¬å»åž«äŒã®ç ç©¶äºæ¥ãããžã§ã¯ããORCA ãããžã§ã¯ãããéçºãæäŸãéå§ãããã®ã§ãã ORCA ProjectïŒ ORCAãããžã§ã¯ãã®æŠèŠ æ¥æ¬å»åž«äŒéçºã»æ¥å»æšæºã¬ã»ãããœãããŠã§ã¢ã®ãµã€ãã§ã www.orca.med.or.jp CLINICS ã«ã«ãã¯ãããŸãã«ä»¥äžã®ãããªæ§æãšãªã£ãŠãããRuby on Rails ã§çšŒåããŠããã«ã«ãã¢ããªã±ãŒã·ã§ã³ãšå»çæ©é¢ããšã® ORCA ãµãŒããããããã®éã ORCA ãæäŸããŠãã API ã§æ¥ç¶ããŠããŸãã ïŒäžå³ã¯äžäŸãšããŠäžããŠãããã®ã§å°æ°ãè©³çŽ°ãªæ§æã¯å®éã®ã·ã¹ãã ãšã¯ç°ãªããŸãïŒ ãã® ORCA ãµãŒãã§ãããå»çæ©é¢ããšã« 1 ã€ã® EC2 ã€ã³ã¹ã¿ã³ã¹æ§æãšãªã£ãŠãããå©çšããå»çæ©é¢ãå¢ãã床㫠EC2 ã€ã³ã¹ã¿ã³ã¹ãå¢ãããããå°å
¥å»çæ©é¢ãå¢ããã»ã©æ§ç¯ãéçšãã€ãããªã£ãŠãããŸãããã®ããããåºæ¥ãã ãèªååããã話ãä»åã®ã¡ã€ã³ããŒãã§ãã ïŒããããããã£ãšæ¥œãã§ããæ§æã«ããããšè²ã
æ€èšãããã®ã§ãããã·ã¹ãã ã®ç¹æ®æ§ãªã©ã®è«žäºæ
ããããçµæ EC2 ã€ã³ã¹ã¿ã³ã¹åäœã§ç®¡çããæ§æã«ãªã£ãŠããŸãïŒ ORCA ãµãŒããŒé¢é£ã§äž»ã«äœ¿çšãã AWS ãµãŒãã¹ AMI äœæãã€ã³ã¹ã¿ã³ã¹äœæãªã©ã®ãã«ã系㯠CodeBuild ããããé©çšãã³ãã³ãå®è¡ãªã©ã®ã€ã³ã¹ã¿ã³ã¹ç®¡ç㯠Systems Manager ãè匱æ§ãã§ãã¯ãªã©ã®ã»ãã¥ãªãã£é¢é£ã«ã¯ Guard Duty ãšãã£ããµãŒãã¹ãäž»ã«å©çšããŠããŸãã æ¬¡ã«ãã€ã³ã¹ã¿ã³ã¹æ§ç¯ã«é¢ããŠããå°ãå
·äœçã«èª¬æããŸãã ORCA ãµãŒãã®ã€ã³ã¹ã¿ã³ã¹æ§ç¯ ORCA ãµãŒãçš AMIïŒãŽãŒã«ãã³ã€ã¡ãŒãžïŒäœæ ãã«ãã®å®è¡ã¯ CodeBuild ã§è¡ã£ãŠããŸããAMI ã®ãã«ãã«ã¯ Packer ã䜿çšããŠããããã«ãå®äºæã«äœæããã AMI ã® ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é²ããŠããŸãããã® AMI ID ãã€ã³ã¹ã¿ã³ã¹äœææã«åç
§ããŸãã åèãŸã§ã«ãCodeBuild ã§äœ¿çšããŠãã buildspec.yaml ã¯ä»¥äžã®ããã«ãªããŸãïŒèª¬æç®æãªã©ãäžéšå®éãšã¯ç°ãªããŸãïŒã phases : pre_build : ## 説æ * packer ãš jq ããã«ãçšã³ã³ããã«ã€ã³ã¹ããŒã« commands : - curl -qL -o packer.zip https://releases.hashicorp.com/packer/1.1.3/packer_1.1.3_linux_amd64.zip && unzip packer.zip - curl -qL -o jq https://stedolan.github.io/jq/download/linux64/jq && chmod +x ./jq build : ## 説æ * åŠçã«å¿
èŠãª AWS credential æ
å ±ãååŸïŒèšå®ïŒåŸã® aws cli 䜿ãçšïŒ * packer ãã«ãå®è¡ãAMI äœæ * packer ãã«ãçµæããäœæããã AMI ID ãååŸ * AMI ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é² commands : - curl -qL -o aws_credentials.json https://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > aws_credentials.json - aws configure set region $AWS_REGION - aws configure set aws_access_key_id `./jq -r '.AccessKeyId' aws_credentials.json` - aws configure set aws_secret_access_key `./jq -r '.SecretAccessKey' aws_credentials.json` - aws configure set aws_session_token `./jq -r '.Token' aws_credentials.json` - ../packer build -machine-readable bin/packer.json | tee packer.log - cat packer.log | grep "artifact,0,id" | cut -d "," -f6 | cut -d ":" -f2 > ami.txt - ORCA_AMI_ID=`cat ami.txt` - aws ssm put-parameter --name ORCA_AMI_ID --value $ORCA_AMI_ID --type String --overwrite ORCA ãµãŒãçš EC2 ã€ã³ã¹ã¿ã³ã¹äœæ å»çæ©é¢çšã®ã¢ã«ãŠã³ããæ°èŠè¿œå ããå Žåã瀟å
çšã®ç®¡çããŒã«ã§ãŸãå»çæ©é¢ã®åºæ¬æ
å ±ãç»é²ããŸãããã®åŸãORCA ã€ã³ã¹ã¿ã³ã¹èšå®ã«å¿
èŠãªãã©ã¡ãŒã¿ïŒå»çæ©é¢ãèå¥ãã ID ãªã©ïŒãèšå®ããã€ã³ã¹ã¿ã³ã¹äœæã®ãã«ãåŠçãå®è¡ããŸãã CodeBuild ããŽãŒã«ãã³ã€ã¡ãŒãžçšã® AMI ãããŒã¹ã« ORCA ã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ããŸããORCA ã€ã³ã¹ã¿ã³ã¹ã¯èµ·åæã«åçš®èšå®åŠçãè¡ããŸãïŒcloud-initïŒ ãªããã€ã³ã¹ã¿ã³ã¹èµ·åæã«è¡ã£ãŠããåŠçãšããŠäž»ã«ä»¥äžã®ãããªããšãè¡ã£ãŠããŸãã 該åœã€ã³ã¹ã¿ã³ã¹ã®å
éš IP ã Private DNS ã«ç»é² ORCA ã®ã»ããã¢ãã/ããã°ã©ã /ãã¹ã¿æŽæ° Postgres ã®ããã¯ã¢ããèšå® Mackerel ã Systems Manager çã®åçš® Agent ã€ã³ã¹ããŒã«ãèšå® ORCA ãµãŒãéçš æ§ç¯ãå®äºã皌åããåŸããORCA èªäœã®ã¢ããããŒãããããã®é©çšãªã©æ§ã
ãªéçšãçºçããŸããããããã©ã®ããã«è¡ã£ãŠãããããŸã æ¹åäžã§ã¯ãããŸããäžéšã玹ä»ããŸãã ã€ã³ã¹ã¿ã³ã¹ã«å¯Ÿããåçš®æäœã®å®è¡ ORCA ã®ã¢ããããŒããªã©ã宿çã«è¡ãæäœã«å¿
èŠãªã³ãã³ãã document ãšããŠç»é²ããRunCommand ã§ç¹å®ã€ã³ã¹ã¿ã³ã¹ãŸãã¯è€æ°ã€ã³ã¹ã¿ã³ã¹ã«äžæ¬å®è¡ã§ããããã«ããŠããŸãã ORCA ã¢ããªã±ãŒã·ã§ã³ã®æ»æŽ»ç£èŠ ORCA ã¢ããªã±ãŒã·ã§ã³èªäœæ§æãè€éã§ãããã€ãã®ããã«ãŠã§ã¢ãšé£æºããŠåããŠããŸãããããã®åçš®ããã»ã¹/ãã°ç£èŠã¯è¡ã£ãäžã§ãAPI ãšããŠæ£ãã皌åããŠãããã確èªããããã®æ»æŽ»ç£èŠã Mackerel ã®ã«ã¹ã¿ã ã¡ããªã¯ã¹ãšããŠç»é²ããäžå®æ°ä»¥äžå€±æããå Žåã¯åçš®ããã»ã¹ãåèµ·åããããã§ãæ£åžžã«åããªãå Žå㯠Mackerel ãã Slack ã«éç¥ãããŠããŸãã ã»ãã¥ãªãã£ãã§ã㯠CloudTrail ã VPC ãããŒãã°ãªã©ãããšã«ãGuardDuty ã§å®æçã«ãã§ãã¯ãè匱æ§ãèŠã€ãã£ãå Žå㯠Slack ã«éç¥ãããããã«ããŠããŸãããã®ä»ãã»ãã¥ãªãã£ãããé©çšãªã©ãããããããŒãžã£ãŒãå©çšãèªååãããŠããŸãã ãŸãšã é»åã«ã«ãã®ã·ã¹ãã ã¯æ€æ»ãç»åããŒã¿ãªã©ãåãæ±ãå€éšã·ã¹ãã ãšé£æºããããšããéèŠããããŸãããã®ãããªé£æºãèŠéã«å
¥ãããšããŒã¿æšæºåã®åé¡ãªã©ãããé£ããåéã§ã¯ãããŸãããCLINICS ã«ã«ããšããŠæ¥ã
é²åããŠããããã«ãããã«ãããŒãžããµãŒãã¹ãªã©æŽ»çšã§ãããšããã¯ç©æ¥µçã«æŽ»çšããéäžãã¹ãåé¡ã解決ããŠãããããšæããŸãã ãŸããé»åã«ã«ãã®ã·ã¹ãã ãšããŠã®æ§è³ªäžã絶察ã«èœãšããªãã·ã¹ãã éçšãå¿
èŠã§ããããã«å
ç¢ãªã·ã¹ãã ã«ããããã«ããã©ãã«ãæªç¶ã«é²ããããªéæ©èœé¢ã®åŒ·åãæ¥ã
ã®ã¢ãã¿ãªã³ã°ãªã©å°éãªããšãå«ãããã£ãšãã£ãšåãçµãã§ããå¿
èŠããããŸãã ãŸã ãŸã ãããã¯ããšããŠæªæçãªæ®µéã§ã¯ãããŸããããå»çã®èª²é¡ã解決ããããããCLINICS ã«ã«ãã§ã¯å»çæ¥åãå¹çåããå»çãã©ãããã©ãŒã ãšãªãã¹ãé²åããŠãããããšããæ§æ³ãæã£ãŠããŸããïŒCLINICS ã«ã«ããç®æãå»çã®ãã©ãããã©ãŒã ãšã¯ïŒãšãã話ã¯ããã¡ãã§è©³ããæžãããŠããŸãïŒ ãCLINICSã«ã«ãããç®æã âå»çã®ãã©ãããã©ãŒã â ãšã¯ïŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ãä¹
ãã¶ãã§ããã¡ãã¬ãŒã§æ¡çšãšåºå ±ãæ
åœããŠããå è€ã§ããæšå¹Žããã¯ãããããã®ããŒãã圹å¡ã¿ããªã§è©±ããŸããããã®ã³ãŒããŒã§ãããæšå¹Žãšç¶æ³ãå€ãããããããªã¡ã³ããŒã«JOINããŠããããã... www.wantedly.com CLINICS ã«ã«ãã¯ããŸãã¯å€ãã®å»çæ©é¢ã«äœ¿ã£ãŠããããã®ã§ã¯ãããŸãããå°æ¥çã«ã¯ãæ£è
ãããšå»çæ©é¢ãã€ãªãã蚺çãæ€æ»ããŒã¿ãªã©ããããšããããã©ãããã©ãŒã ãšãªãäºå®ã§ããããããæ°ããå»çã®ãããã¯ãã«èå³ã®ãããã¶ã€ããŒã»ãšã³ãžãã¢ã»ãã£ã¬ã¯ã¿ãŒã®æ¹ã¯ãã²ãã¡ããŸã§ãå¿åããŸã¡ããŠãããŸãã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp
4 ææ«ã«æ°ãã«ãªãªãŒã¹ããã¯ã©ãŠãåé»åã«ã«ãã CLINICS ã«ã«ã ãã®éçºãæ
åœããŠããç°äžã§ãã é»åã«ã«ããšããå»çè¡çºãæ¯ãããããã¯ãéçºãªãã§ã¯ã®ééå³ãé£ãããæããæ¥ã
ãéãããŠããŸããåå㯠CLINICS ã«ã«ãã®ãã¶ã€ã³ã«ã€ããŠããšãã玹ä»ããŸãã ããä»åã¯ãšã³ãžãã¢ããèŠãèŠæ©ãšèè€ã«ã€ããŠã話ããŸãã èŠåŽããç¹ãšããŠã¯ãå»çäºåã®æ¥åãã®ãã®ã®è€éããããã«äŒŽãã¢ããªã±ãŒã·ã§ã³éçºã®è€éãã¯ãã¡ããã®ããšã é»åã«ã«ãéçºã®ç¹åŸŽãšããŠé¢é£çåºã®ã¬ã€ãã©ã€ã³ã®æºæ ãã¬ã»ãããœããïŒå»çäŒèšå°çšã®ã·ã¹ãã ïŒã®ã·ã¹ãã 管çãªã©ãå€å²ã«ããã察å¿ãå¿
èŠãªããš ãæããããŸãã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ã«é¢ããã話ã¯çްãããªã£ãŠããŸãã®ã§ã倧ãŸããªå
容ãšããŠãä»åã¯äž»ã«ã¬ã»ããã·ã¹ãã ãšããŠé£æºããŠãã ORCA ã®ã·ã¹ãã ç®¡çæ¹æ³ã«ã€ããŠãäŒããããŠããã ããã°ãšæããŸãïŒORCA ã«é¢ãã説æã¯åŸè¿°ããŸãïŒã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ é»åã«ã«ãã®ããã«å»çæ
å ±ãæ±ãéã«éµå®ããå¿
èŠãããã¬ã€ãã©ã€ã³ãšã㊠3 ç 4 ã¬ã€ãã©ã€ã³ïŒåçåŽåçãçµæžç£æ¥çãç·åçã® 3 çãåºããŠãã 4 ã€ã®ã¬ã€ãã©ã€ã³ïŒããããŸãã CLINICS ã«ã«ãã®éçºãé²ããã«ãããããã®ã¬ã€ãã©ã€ã³ãã·ã¹ãã èšèšãéçšã«å€§ããªåœ±é¿ãåãŒãããããŸãã¯ã¬ã€ãã©ã€ã³ãèªã¿èŸŒã¿æŽçãããšããããå§ããŸããã ã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãšãã«å¯Ÿå¿ãã¹ãããšã¯å€ãã£ãã®ã§ãããã·ã¹ãã æ§æã«ç¹ã«åœ±é¿ã倧ããã£ãã®ã¯ä»¥äžã® 2 ç¹ãšãªããŸãã ãµãŒãã¹æäŸã«çšããã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãæ¥æ¬åœå
æ³ã®é©çšãåã¶å Žæã«èšçœ®ããããš ã¯ã©ã€ã¢ã³ãèšŒææžãå©çšãã TLS ã¯ã©ã€ã¢ã³ãèªèšŒã宿œããããš CLINICS ã«ã«ãã¯åŒç€Ÿã§æ¢ã«éçšããŠãããªã³ã©ã€ã³èšºçã¢ããªãCLINICSããšé£æºãããåæã§ãã£ããããã¬ã€ãã©ã€ã³ã«å³ããã·ã¹ãã æ§æãšããŠããããã«ããŸã CLINICS ã®ã·ã¹ãã ã Heroku ãã AWS ã«ç§»è¡ããããšããå§ãŸããŸããã ãŸããã¯ã©ã€ã¢ã³ãèªèšŒãè¡ãããã« AWS ã®æ§æãè²ã
ãšæ€èšããNginx ãšãæ¥ã
æ ŒéãããããŸããããã ãããã®å¯Ÿå¿å
容ã«é¢é£ããããã°ãéå»ã«æžããŠããŸãã®ã§ãèå³ãããæ¹ã¯ãã²ãåèã«ããŠãã ããã https://developer.medley.jp/entry/2017/08/24/120000_01 https://developer.medley.jp/entry/2017/08/24/120000_02 https://developer.medley.jp/entry/2017/09/22/124000 ORCA ãµãŒãã®ç®¡çæ¹æ³ CLINICS ã«ã«ãã¯ãæ¥æ¬å»åž«äŒ ORCA ç®¡çæ©æ§æ ªåŒäŒç€ŸãæäŸããå»çäŒèšãœããã§ãããORCAããçµã¿èŸŒãã ãORCA å
å
åãã®ã¯ã©ãŠãåé»åã«ã«ãã§ãã åè: ORCA ãšã¯ å»ççŸå Ž IT åãæšé²ããæ¥æ¬å»åž«äŒãäŒå¡çã®ããã«æäŸããŠããã¬ã»ãããœããïŒèšºçå ±é
¬ã®è«æ±æ¥åãè¡ãããã®å»çäŒèšãœããïŒã2002 幎ã«ãªãŒãã³ãœãŒã¹ãšããŠå
¬éãããçŸåšã蚺çæãäžå¿ã« 17,000 ãè¶
ããå
šåœã®å»çæ©é¢ã«å°å
¥ãããŠããŸãã å»çæ
å ±ãããã¯ãŒã¯æšé²å§å¡äŒã«ãŠãå»åž«äŒç·åæ
å ±ãããã¯ãŒã¯æ§æ³ãïŒ1997 幎 æ
å ±åæ€èšå§å¡äŒïŒãæ§æããããŒã«ã®äžã€ãšããŠèªããããæ¥æ¬å»åž«äŒã®ç ç©¶äºæ¥ãããžã§ã¯ããORCA ãããžã§ã¯ãããéçºãæäŸãéå§ãããã®ã§ãã ORCA ProjectïŒ ORCAãããžã§ã¯ãã®æŠèŠ æ¥æ¬å»åž«äŒéçºã»æ¥å»æšæºã¬ã»ãããœãããŠã§ã¢ã®ãµã€ãã§ã www.orca.med.or.jp CLINICS ã«ã«ãã¯ãããŸãã«ä»¥äžã®ãããªæ§æãšãªã£ãŠãããRuby on Rails ã§çšŒåããŠããã«ã«ãã¢ããªã±ãŒã·ã§ã³ãšå»çæ©é¢ããšã® ORCA ãµãŒããããããã®éã ORCA ãæäŸããŠãã API ã§æ¥ç¶ããŠããŸãã ïŒäžå³ã¯äžäŸãšããŠäžããŠãããã®ã§å°æ°ãè©³çŽ°ãªæ§æã¯å®éã®ã·ã¹ãã ãšã¯ç°ãªããŸãïŒ ãã® ORCA ãµãŒãã§ãããå»çæ©é¢ããšã« 1 ã€ã® EC2 ã€ã³ã¹ã¿ã³ã¹æ§æãšãªã£ãŠãããå©çšããå»çæ©é¢ãå¢ãã床㫠EC2 ã€ã³ã¹ã¿ã³ã¹ãå¢ãããããå°å
¥å»çæ©é¢ãå¢ããã»ã©æ§ç¯ãéçšãã€ãããªã£ãŠãããŸãããã®ããããåºæ¥ãã ãèªååããã話ãä»åã®ã¡ã€ã³ããŒãã§ãã ïŒããããããã£ãšæ¥œãã§ããæ§æã«ããããšè²ã
æ€èšãããã®ã§ãããã·ã¹ãã ã®ç¹æ®æ§ãªã©ã®è«žäºæ
ããããçµæ EC2 ã€ã³ã¹ã¿ã³ã¹åäœã§ç®¡çããæ§æã«ãªã£ãŠããŸãïŒ ORCA ãµãŒããŒé¢é£ã§äž»ã«äœ¿çšãã AWS ãµãŒãã¹ AMI äœæãã€ã³ã¹ã¿ã³ã¹äœæãªã©ã®ãã«ã系㯠CodeBuild ããããé©çšãã³ãã³ãå®è¡ãªã©ã®ã€ã³ã¹ã¿ã³ã¹ç®¡ç㯠Systems Manager ãè匱æ§ãã§ãã¯ãªã©ã®ã»ãã¥ãªãã£é¢é£ã«ã¯ Guard Duty ãšãã£ããµãŒãã¹ãäž»ã«å©çšããŠããŸãã æ¬¡ã«ãã€ã³ã¹ã¿ã³ã¹æ§ç¯ã«é¢ããŠããå°ãå
·äœçã«èª¬æããŸãã ORCA ãµãŒãã®ã€ã³ã¹ã¿ã³ã¹æ§ç¯ ORCA ãµãŒãçš AMIïŒãŽãŒã«ãã³ã€ã¡ãŒãžïŒäœæ ãã«ãã®å®è¡ã¯ CodeBuild ã§è¡ã£ãŠããŸããAMI ã®ãã«ãã«ã¯ Packer ã䜿çšããŠããããã«ãå®äºæã«äœæããã AMI ã® ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é²ããŠããŸãããã® AMI ID ãã€ã³ã¹ã¿ã³ã¹äœææã«åç
§ããŸãã åèãŸã§ã«ãCodeBuild ã§äœ¿çšããŠãã buildspec.yaml ã¯ä»¥äžã®ããã«ãªããŸãïŒèª¬æç®æãªã©ãäžéšå®éãšã¯ç°ãªããŸãïŒã phases : pre_build : ## 説æ * packer ãš jq ããã«ãçšã³ã³ããã«ã€ã³ã¹ããŒã« commands : - curl -qL -o packer.zip https://releases.hashicorp.com/packer/1.1.3/packer_1.1.3_linux_amd64.zip && unzip packer.zip - curl -qL -o jq https://stedolan.github.io/jq/download/linux64/jq && chmod +x ./jq build : ## 説æ * åŠçã«å¿
èŠãª AWS credential æ
å ±ãååŸïŒèšå®ïŒåŸã® aws cli 䜿ãçšïŒ * packer ãã«ãå®è¡ãAMI äœæ * packer ãã«ãçµæããäœæããã AMI ID ãååŸ * AMI ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é² commands : - curl -qL -o aws_credentials.json https://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > aws_credentials.json - aws configure set region $AWS_REGION - aws configure set aws_access_key_id `./jq -r '.AccessKeyId' aws_credentials.json` - aws configure set aws_secret_access_key `./jq -r '.SecretAccessKey' aws_credentials.json` - aws configure set aws_session_token `./jq -r '.Token' aws_credentials.json` - ../packer build -machine-readable bin/packer.json | tee packer.log - cat packer.log | grep "artifact,0,id" | cut -d "," -f6 | cut -d ":" -f2 > ami.txt - ORCA_AMI_ID=`cat ami.txt` - aws ssm put-parameter --name ORCA_AMI_ID --value $ORCA_AMI_ID --type String --overwrite ORCA ãµãŒãçš EC2 ã€ã³ã¹ã¿ã³ã¹äœæ å»çæ©é¢çšã®ã¢ã«ãŠã³ããæ°èŠè¿œå ããå Žåã瀟å
çšã®ç®¡çããŒã«ã§ãŸãå»çæ©é¢ã®åºæ¬æ
å ±ãç»é²ããŸãããã®åŸãORCA ã€ã³ã¹ã¿ã³ã¹èšå®ã«å¿
èŠãªãã©ã¡ãŒã¿ïŒå»çæ©é¢ãèå¥ãã ID ãªã©ïŒãèšå®ããã€ã³ã¹ã¿ã³ã¹äœæã®ãã«ãåŠçãå®è¡ããŸãã CodeBuild ããŽãŒã«ãã³ã€ã¡ãŒãžçšã® AMI ãããŒã¹ã« ORCA ã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ããŸããORCA ã€ã³ã¹ã¿ã³ã¹ã¯èµ·åæã«åçš®èšå®åŠçãè¡ããŸãïŒcloud-initïŒ ãªããã€ã³ã¹ã¿ã³ã¹èµ·åæã«è¡ã£ãŠããåŠçãšããŠäž»ã«ä»¥äžã®ãããªããšãè¡ã£ãŠããŸãã 該åœã€ã³ã¹ã¿ã³ã¹ã®å
éš IP ã Private DNS ã«ç»é² ORCA ã®ã»ããã¢ãã/ããã°ã©ã /ãã¹ã¿æŽæ° Postgres ã®ããã¯ã¢ããèšå® Mackerel ã Systems Manager çã®åçš® Agent ã€ã³ã¹ããŒã«ãèšå® ORCA ãµãŒãéçš æ§ç¯ãå®äºã皌åããåŸããORCA èªäœã®ã¢ããããŒãããããã®é©çšãªã©æ§ã
ãªéçšãçºçããŸããããããã©ã®ããã«è¡ã£ãŠãããããŸã æ¹åäžã§ã¯ãããŸããäžéšã玹ä»ããŸãã ã€ã³ã¹ã¿ã³ã¹ã«å¯Ÿããåçš®æäœã®å®è¡ ORCA ã®ã¢ããããŒããªã©ã宿çã«è¡ãæäœã«å¿
èŠãªã³ãã³ãã document ãšããŠç»é²ããRunCommand ã§ç¹å®ã€ã³ã¹ã¿ã³ã¹ãŸãã¯è€æ°ã€ã³ã¹ã¿ã³ã¹ã«äžæ¬å®è¡ã§ããããã«ããŠããŸãã ORCA ã¢ããªã±ãŒã·ã§ã³ã®æ»æŽ»ç£èŠ ORCA ã¢ããªã±ãŒã·ã§ã³èªäœæ§æãè€éã§ãããã€ãã®ããã«ãŠã§ã¢ãšé£æºããŠåããŠããŸãããããã®åçš®ããã»ã¹/ãã°ç£èŠã¯è¡ã£ãäžã§ãAPI ãšããŠæ£ãã皌åããŠãããã確èªããããã®æ»æŽ»ç£èŠã Mackerel ã®ã«ã¹ã¿ã ã¡ããªã¯ã¹ãšããŠç»é²ããäžå®æ°ä»¥äžå€±æããå Žåã¯åçš®ããã»ã¹ãåèµ·åããããã§ãæ£åžžã«åããªãå Žå㯠Mackerel ãã Slack ã«éç¥ãããŠããŸãã ã»ãã¥ãªãã£ãã§ã㯠CloudTrail ã VPC ãããŒãã°ãªã©ãããšã«ãGuardDuty ã§å®æçã«ãã§ãã¯ãè匱æ§ãèŠã€ãã£ãå Žå㯠Slack ã«éç¥ãããããã«ããŠããŸãããã®ä»ãã»ãã¥ãªãã£ãããé©çšãªã©ãããããããŒãžã£ãŒãå©çšãèªååãããŠããŸãã ãŸãšã é»åã«ã«ãã®ã·ã¹ãã ã¯æ€æ»ãç»åããŒã¿ãªã©ãåãæ±ãå€éšã·ã¹ãã ãšé£æºããããšããéèŠããããŸãããã®ãããªé£æºãèŠéã«å
¥ãããšããŒã¿æšæºåã®åé¡ãªã©ãããé£ããåéã§ã¯ãããŸãããCLINICS ã«ã«ããšããŠæ¥ã
é²åããŠããããã«ãããã«ãããŒãžããµãŒãã¹ãªã©æŽ»çšã§ãããšããã¯ç©æ¥µçã«æŽ»çšããéäžãã¹ãåé¡ã解決ããŠãããããšæããŸãã ãŸããé»åã«ã«ãã®ã·ã¹ãã ãšããŠã®æ§è³ªäžã絶察ã«èœãšããªãã·ã¹ãã éçšãå¿
èŠã§ããããã«å
ç¢ãªã·ã¹ãã ã«ããããã«ããã©ãã«ãæªç¶ã«é²ããããªéæ©èœé¢ã®åŒ·åãæ¥ã
ã®ã¢ãã¿ãªã³ã°ãªã©å°éãªããšãå«ãããã£ãšãã£ãšåãçµãã§ããå¿
èŠããããŸãã ãŸã ãŸã ãããã¯ããšããŠæªæçãªæ®µéã§ã¯ãããŸããããå»çã®èª²é¡ã解決ããããããCLINICS ã«ã«ãã§ã¯å»çæ¥åãå¹çåããå»çãã©ãããã©ãŒã ãšãªãã¹ãé²åããŠãããããšããæ§æ³ãæã£ãŠããŸããïŒCLINICS ã«ã«ããç®æãå»çã®ãã©ãããã©ãŒã ãšã¯ïŒãšãã話ã¯ããã¡ãã§è©³ããæžãããŠããŸãïŒ ãCLINICSã«ã«ãããç®æã âå»çã®ãã©ãããã©ãŒã â ãšã¯ïŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ãä¹
ãã¶ãã§ããã¡ãã¬ãŒã§æ¡çšãšåºå ±ãæ
åœããŠããå è€ã§ããæšå¹Žããã¯ãããããã®ããŒãã圹å¡ã¿ããªã§è©±ããŸããããã®ã³ãŒããŒã§ãããæšå¹Žãšç¶æ³ãå€ãããããããªã¡ã³ããŒã«JOINããŠããããã... www.wantedly.com CLINICS ã«ã«ãã¯ããŸãã¯å€ãã®å»çæ©é¢ã«äœ¿ã£ãŠããããã®ã§ã¯ãããŸãããå°æ¥çã«ã¯ãæ£è
ãããšå»çæ©é¢ãã€ãªãã蚺çãæ€æ»ããŒã¿ãªã©ããããšããããã©ãããã©ãŒã ãšãªãäºå®ã§ããããããæ°ããå»çã®ãããã¯ãã«èå³ã®ãããã¶ã€ããŒã»ãšã³ãžãã¢ã»ãã£ã¬ã¯ã¿ãŒã®æ¹ã¯ãã²ãã¡ããŸã§ãå¿åããŸã¡ããŠãããŸãã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp
4 ææ«ã«æ°ãã«ãªãªãŒã¹ããã¯ã©ãŠãåé»åã«ã«ãã CLINICS ã«ã«ã ãã®éçºãæ
åœããŠããç°äžã§ãã é»åã«ã«ããšããå»çè¡çºãæ¯ãããããã¯ãéçºãªãã§ã¯ã®ééå³ãé£ãããæããæ¥ã
ãéãããŠããŸããåå㯠CLINICS ã«ã«ãã®ãã¶ã€ã³ã«ã€ããŠããšãã玹ä»ããŸãã ããä»åã¯ãšã³ãžãã¢ããèŠãèŠæ©ãšèè€ã«ã€ããŠã話ããŸãã èŠåŽããç¹ãšããŠã¯ãå»çäºåã®æ¥åãã®ãã®ã®è€éããããã«äŒŽãã¢ããªã±ãŒã·ã§ã³éçºã®è€éãã¯ãã¡ããã®ããšã é»åã«ã«ãéçºã®ç¹åŸŽãšããŠé¢é£çåºã®ã¬ã€ãã©ã€ã³ã®æºæ ãã¬ã»ãããœããïŒå»çäŒèšå°çšã®ã·ã¹ãã ïŒã®ã·ã¹ãã 管çãªã©ãå€å²ã«ããã察å¿ãå¿
èŠãªããš ãæããããŸãã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ã«é¢ããã話ã¯çްãããªã£ãŠããŸãã®ã§ã倧ãŸããªå
容ãšããŠãä»åã¯äž»ã«ã¬ã»ããã·ã¹ãã ãšããŠé£æºããŠãã ORCA ã®ã·ã¹ãã ç®¡çæ¹æ³ã«ã€ããŠãäŒããããŠããã ããã°ãšæããŸãïŒORCA ã«é¢ãã説æã¯åŸè¿°ããŸãïŒã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ é»åã«ã«ãã®ããã«å»çæ
å ±ãæ±ãéã«éµå®ããå¿
èŠãããã¬ã€ãã©ã€ã³ãšã㊠3 ç 4 ã¬ã€ãã©ã€ã³ïŒåçåŽåçãçµæžç£æ¥çãç·åçã® 3 çãåºããŠãã 4 ã€ã®ã¬ã€ãã©ã€ã³ïŒããããŸãã CLINICS ã«ã«ãã®éçºãé²ããã«ãããããã®ã¬ã€ãã©ã€ã³ãã·ã¹ãã èšèšãéçšã«å€§ããªåœ±é¿ãåãŒãããããŸãã¯ã¬ã€ãã©ã€ã³ãèªã¿èŸŒã¿æŽçãããšããããå§ããŸããã ã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãšãã«å¯Ÿå¿ãã¹ãããšã¯å€ãã£ãã®ã§ãããã·ã¹ãã æ§æã«ç¹ã«åœ±é¿ã倧ããã£ãã®ã¯ä»¥äžã® 2 ç¹ãšãªããŸãã ãµãŒãã¹æäŸã«çšããã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãæ¥æ¬åœå
æ³ã®é©çšãåã¶å Žæã«èšçœ®ããããš ã¯ã©ã€ã¢ã³ãèšŒææžãå©çšãã TLS ã¯ã©ã€ã¢ã³ãèªèšŒã宿œããããš CLINICS ã«ã«ãã¯åŒç€Ÿã§æ¢ã«éçšããŠãããªã³ã©ã€ã³èšºçã¢ããªãCLINICSããšé£æºãããåæã§ãã£ããããã¬ã€ãã©ã€ã³ã«å³ããã·ã¹ãã æ§æãšããŠããããã«ããŸã CLINICS ã®ã·ã¹ãã ã Heroku ãã AWS ã«ç§»è¡ããããšããå§ãŸããŸããã ãŸããã¯ã©ã€ã¢ã³ãèªèšŒãè¡ãããã« AWS ã®æ§æãè²ã
ãšæ€èšããNginx ãšãæ¥ã
æ ŒéãããããŸããããã ãããã®å¯Ÿå¿å
容ã«é¢é£ããããã°ãéå»ã«æžããŠããŸãã®ã§ãèå³ãããæ¹ã¯ãã²ãåèã«ããŠãã ããã https://developer.medley.jp/entry/2017/08/24/120000_01 https://developer.medley.jp/entry/2017/08/24/120000_02 https://developer.medley.jp/entry/2017/09/22/124000 ORCA ãµãŒãã®ç®¡çæ¹æ³ CLINICS ã«ã«ãã¯ãæ¥æ¬å»åž«äŒ ORCA ç®¡çæ©æ§æ ªåŒäŒç€ŸãæäŸããå»çäŒèšãœããã§ãããORCAããçµã¿èŸŒãã ãORCA å
å
åãã®ã¯ã©ãŠãåé»åã«ã«ãã§ãã åè: ORCA ãšã¯ å»ççŸå Ž IT åãæšé²ããæ¥æ¬å»åž«äŒãäŒå¡çã®ããã«æäŸããŠããã¬ã»ãããœããïŒèšºçå ±é
¬ã®è«æ±æ¥åãè¡ãããã®å»çäŒèšãœããïŒã2002 幎ã«ãªãŒãã³ãœãŒã¹ãšããŠå
¬éãããçŸåšã蚺çæãäžå¿ã« 17,000 ãè¶
ããå
šåœã®å»çæ©é¢ã«å°å
¥ãããŠããŸãã å»çæ
å ±ãããã¯ãŒã¯æšé²å§å¡äŒã«ãŠãå»åž«äŒç·åæ
å ±ãããã¯ãŒã¯æ§æ³ãïŒ1997 幎 æ
å ±åæ€èšå§å¡äŒïŒãæ§æããããŒã«ã®äžã€ãšããŠèªããããæ¥æ¬å»åž«äŒã®ç ç©¶äºæ¥ãããžã§ã¯ããORCA ãããžã§ã¯ãããéçºãæäŸãéå§ãããã®ã§ãã ORCA ProjectïŒ ORCAãããžã§ã¯ãã®æŠèŠ æ¥æ¬å»åž«äŒéçºã»æ¥å»æšæºã¬ã»ãããœãããŠã§ã¢ã®ãµã€ãã§ã www.orca.med.or.jp CLINICS ã«ã«ãã¯ãããŸãã«ä»¥äžã®ãããªæ§æãšãªã£ãŠãããRuby on Rails ã§çšŒåããŠããã«ã«ãã¢ããªã±ãŒã·ã§ã³ãšå»çæ©é¢ããšã® ORCA ãµãŒããããããã®éã ORCA ãæäŸããŠãã API ã§æ¥ç¶ããŠããŸãã ïŒäžå³ã¯äžäŸãšããŠäžããŠãããã®ã§å°æ°ãè©³çŽ°ãªæ§æã¯å®éã®ã·ã¹ãã ãšã¯ç°ãªããŸãïŒ ãã® ORCA ãµãŒãã§ãããå»çæ©é¢ããšã« 1 ã€ã® EC2 ã€ã³ã¹ã¿ã³ã¹æ§æãšãªã£ãŠãããå©çšããå»çæ©é¢ãå¢ãã床㫠EC2 ã€ã³ã¹ã¿ã³ã¹ãå¢ãããããå°å
¥å»çæ©é¢ãå¢ããã»ã©æ§ç¯ãéçšãã€ãããªã£ãŠãããŸãããã®ããããåºæ¥ãã ãèªååããã話ãä»åã®ã¡ã€ã³ããŒãã§ãã ïŒããããããã£ãšæ¥œãã§ããæ§æã«ããããšè²ã
æ€èšãããã®ã§ãããã·ã¹ãã ã®ç¹æ®æ§ãªã©ã®è«žäºæ
ããããçµæ EC2 ã€ã³ã¹ã¿ã³ã¹åäœã§ç®¡çããæ§æã«ãªã£ãŠããŸãïŒ ORCA ãµãŒããŒé¢é£ã§äž»ã«äœ¿çšãã AWS ãµãŒãã¹ AMI äœæãã€ã³ã¹ã¿ã³ã¹äœæãªã©ã®ãã«ã系㯠CodeBuild ããããé©çšãã³ãã³ãå®è¡ãªã©ã®ã€ã³ã¹ã¿ã³ã¹ç®¡ç㯠Systems Manager ãè匱æ§ãã§ãã¯ãªã©ã®ã»ãã¥ãªãã£é¢é£ã«ã¯ Guard Duty ãšãã£ããµãŒãã¹ãäž»ã«å©çšããŠããŸãã æ¬¡ã«ãã€ã³ã¹ã¿ã³ã¹æ§ç¯ã«é¢ããŠããå°ãå
·äœçã«èª¬æããŸãã ORCA ãµãŒãã®ã€ã³ã¹ã¿ã³ã¹æ§ç¯ ORCA ãµãŒãçš AMIïŒãŽãŒã«ãã³ã€ã¡ãŒãžïŒäœæ ãã«ãã®å®è¡ã¯ CodeBuild ã§è¡ã£ãŠããŸããAMI ã®ãã«ãã«ã¯ Packer ã䜿çšããŠããããã«ãå®äºæã«äœæããã AMI ã® ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é²ããŠããŸãããã® AMI ID ãã€ã³ã¹ã¿ã³ã¹äœææã«åç
§ããŸãã åèãŸã§ã«ãCodeBuild ã§äœ¿çšããŠãã buildspec.yaml ã¯ä»¥äžã®ããã«ãªããŸãïŒèª¬æç®æãªã©ãäžéšå®éãšã¯ç°ãªããŸãïŒã phases : pre_build : ## 説æ * packer ãš jq ããã«ãçšã³ã³ããã«ã€ã³ã¹ããŒã« commands : - curl -qL -o packer.zip https://releases.hashicorp.com/packer/1.1.3/packer_1.1.3_linux_amd64.zip && unzip packer.zip - curl -qL -o jq https://stedolan.github.io/jq/download/linux64/jq && chmod +x ./jq build : ## 説æ * åŠçã«å¿
èŠãª AWS credential æ
å ±ãååŸïŒèšå®ïŒåŸã® aws cli 䜿ãçšïŒ * packer ãã«ãå®è¡ãAMI äœæ * packer ãã«ãçµæããäœæããã AMI ID ãååŸ * AMI ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é² commands : - curl -qL -o aws_credentials.json https://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > aws_credentials.json - aws configure set region $AWS_REGION - aws configure set aws_access_key_id `./jq -r '.AccessKeyId' aws_credentials.json` - aws configure set aws_secret_access_key `./jq -r '.SecretAccessKey' aws_credentials.json` - aws configure set aws_session_token `./jq -r '.Token' aws_credentials.json` - ../packer build -machine-readable bin/packer.json | tee packer.log - cat packer.log | grep "artifact,0,id" | cut -d "," -f6 | cut -d ":" -f2 > ami.txt - ORCA_AMI_ID=`cat ami.txt` - aws ssm put-parameter --name ORCA_AMI_ID --value $ORCA_AMI_ID --type String --overwrite ORCA ãµãŒãçš EC2 ã€ã³ã¹ã¿ã³ã¹äœæ å»çæ©é¢çšã®ã¢ã«ãŠã³ããæ°èŠè¿œå ããå Žåã瀟å
çšã®ç®¡çããŒã«ã§ãŸãå»çæ©é¢ã®åºæ¬æ
å ±ãç»é²ããŸãããã®åŸãORCA ã€ã³ã¹ã¿ã³ã¹èšå®ã«å¿
èŠãªãã©ã¡ãŒã¿ïŒå»çæ©é¢ãèå¥ãã ID ãªã©ïŒãèšå®ããã€ã³ã¹ã¿ã³ã¹äœæã®ãã«ãåŠçãå®è¡ããŸãã CodeBuild ããŽãŒã«ãã³ã€ã¡ãŒãžçšã® AMI ãããŒã¹ã« ORCA ã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ããŸããORCA ã€ã³ã¹ã¿ã³ã¹ã¯èµ·åæã«åçš®èšå®åŠçãè¡ããŸãïŒcloud-initïŒ ãªããã€ã³ã¹ã¿ã³ã¹èµ·åæã«è¡ã£ãŠããåŠçãšããŠäž»ã«ä»¥äžã®ãããªããšãè¡ã£ãŠããŸãã 該åœã€ã³ã¹ã¿ã³ã¹ã®å
éš IP ã Private DNS ã«ç»é² ORCA ã®ã»ããã¢ãã/ããã°ã©ã /ãã¹ã¿æŽæ° Postgres ã®ããã¯ã¢ããèšå® Mackerel ã Systems Manager çã®åçš® Agent ã€ã³ã¹ããŒã«ãèšå® ORCA ãµãŒãéçš æ§ç¯ãå®äºã皌åããåŸããORCA èªäœã®ã¢ããããŒãããããã®é©çšãªã©æ§ã
ãªéçšãçºçããŸããããããã©ã®ããã«è¡ã£ãŠãããããŸã æ¹åäžã§ã¯ãããŸããäžéšã玹ä»ããŸãã ã€ã³ã¹ã¿ã³ã¹ã«å¯Ÿããåçš®æäœã®å®è¡ ORCA ã®ã¢ããããŒããªã©ã宿çã«è¡ãæäœã«å¿
èŠãªã³ãã³ãã document ãšããŠç»é²ããRunCommand ã§ç¹å®ã€ã³ã¹ã¿ã³ã¹ãŸãã¯è€æ°ã€ã³ã¹ã¿ã³ã¹ã«äžæ¬å®è¡ã§ããããã«ããŠããŸãã ORCA ã¢ããªã±ãŒã·ã§ã³ã®æ»æŽ»ç£èŠ ORCA ã¢ããªã±ãŒã·ã§ã³èªäœæ§æãè€éã§ãããã€ãã®ããã«ãŠã§ã¢ãšé£æºããŠåããŠããŸãããããã®åçš®ããã»ã¹/ãã°ç£èŠã¯è¡ã£ãäžã§ãAPI ãšããŠæ£ãã皌åããŠãããã確èªããããã®æ»æŽ»ç£èŠã Mackerel ã®ã«ã¹ã¿ã ã¡ããªã¯ã¹ãšããŠç»é²ããäžå®æ°ä»¥äžå€±æããå Žåã¯åçš®ããã»ã¹ãåèµ·åããããã§ãæ£åžžã«åããªãå Žå㯠Mackerel ãã Slack ã«éç¥ãããŠããŸãã ã»ãã¥ãªãã£ãã§ã㯠CloudTrail ã VPC ãããŒãã°ãªã©ãããšã«ãGuardDuty ã§å®æçã«ãã§ãã¯ãè匱æ§ãèŠã€ãã£ãå Žå㯠Slack ã«éç¥ãããããã«ããŠããŸãããã®ä»ãã»ãã¥ãªãã£ãããé©çšãªã©ãããããããŒãžã£ãŒãå©çšãèªååãããŠããŸãã ãŸãšã é»åã«ã«ãã®ã·ã¹ãã ã¯æ€æ»ãç»åããŒã¿ãªã©ãåãæ±ãå€éšã·ã¹ãã ãšé£æºããããšããéèŠããããŸãããã®ãããªé£æºãèŠéã«å
¥ãããšããŒã¿æšæºåã®åé¡ãªã©ãããé£ããåéã§ã¯ãããŸãããCLINICS ã«ã«ããšããŠæ¥ã
é²åããŠããããã«ãããã«ãããŒãžããµãŒãã¹ãªã©æŽ»çšã§ãããšããã¯ç©æ¥µçã«æŽ»çšããéäžãã¹ãåé¡ã解決ããŠãããããšæããŸãã ãŸããé»åã«ã«ãã®ã·ã¹ãã ãšããŠã®æ§è³ªäžã絶察ã«èœãšããªãã·ã¹ãã éçšãå¿
èŠã§ããããã«å
ç¢ãªã·ã¹ãã ã«ããããã«ããã©ãã«ãæªç¶ã«é²ããããªéæ©èœé¢ã®åŒ·åãæ¥ã
ã®ã¢ãã¿ãªã³ã°ãªã©å°éãªããšãå«ãããã£ãšãã£ãšåãçµãã§ããå¿
èŠããããŸãã ãŸã ãŸã ãããã¯ããšããŠæªæçãªæ®µéã§ã¯ãããŸããããå»çã®èª²é¡ã解決ããããããCLINICS ã«ã«ãã§ã¯å»çæ¥åãå¹çåããå»çãã©ãããã©ãŒã ãšãªãã¹ãé²åããŠãããããšããæ§æ³ãæã£ãŠããŸããïŒCLINICS ã«ã«ããç®æãå»çã®ãã©ãããã©ãŒã ãšã¯ïŒãšãã話ã¯ããã¡ãã§è©³ããæžãããŠããŸãïŒ ãCLINICSã«ã«ãããç®æã âå»çã®ãã©ãããã©ãŒã â ãšã¯ïŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ãä¹
ãã¶ãã§ããã¡ãã¬ãŒã§æ¡çšãšåºå ±ãæ
åœããŠããå è€ã§ããæšå¹Žããã¯ãããããã®ããŒãã圹å¡ã¿ããªã§è©±ããŸããããã®ã³ãŒããŒã§ãããæšå¹Žãšç¶æ³ãå€ãããããããªã¡ã³ããŒã«JOINããŠããããã... www.wantedly.com CLINICS ã«ã«ãã¯ããŸãã¯å€ãã®å»çæ©é¢ã«äœ¿ã£ãŠããããã®ã§ã¯ãããŸãããå°æ¥çã«ã¯ãæ£è
ãããšå»çæ©é¢ãã€ãªãã蚺çãæ€æ»ããŒã¿ãªã©ããããšããããã©ãããã©ãŒã ãšãªãäºå®ã§ããããããæ°ããå»çã®ãããã¯ãã«èå³ã®ãããã¶ã€ããŒã»ãšã³ãžãã¢ã»ãã£ã¬ã¯ã¿ãŒã®æ¹ã¯ãã²ãã¡ããŸã§ãå¿åããŸã¡ããŠãããŸãã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp
4 ææ«ã«æ°ãã«ãªãªãŒã¹ããã¯ã©ãŠãåé»åã«ã«ãã CLINICS ã«ã«ã ãã®éçºãæ
åœããŠããç°äžã§ãã é»åã«ã«ããšããå»çè¡çºãæ¯ãããããã¯ãéçºãªãã§ã¯ã®ééå³ãé£ãããæããæ¥ã
ãéãããŠããŸããåå㯠CLINICS ã«ã«ãã®ãã¶ã€ã³ã«ã€ããŠããšãã玹ä»ããŸãã ããä»åã¯ãšã³ãžãã¢ããèŠãèŠæ©ãšèè€ã«ã€ããŠã話ããŸãã èŠåŽããç¹ãšããŠã¯ãå»çäºåã®æ¥åãã®ãã®ã®è€éããããã«äŒŽãã¢ããªã±ãŒã·ã§ã³éçºã®è€éãã¯ãã¡ããã®ããšã é»åã«ã«ãéçºã®ç¹åŸŽãšããŠé¢é£çåºã®ã¬ã€ãã©ã€ã³ã®æºæ ãã¬ã»ãããœããïŒå»çäŒèšå°çšã®ã·ã¹ãã ïŒã®ã·ã¹ãã 管çãªã©ãå€å²ã«ããã察å¿ãå¿
èŠãªããš ãæããããŸãã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ã«é¢ããã話ã¯çްãããªã£ãŠããŸãã®ã§ã倧ãŸããªå
容ãšããŠãä»åã¯äž»ã«ã¬ã»ããã·ã¹ãã ãšããŠé£æºããŠãã ORCA ã®ã·ã¹ãã ç®¡çæ¹æ³ã«ã€ããŠãäŒããããŠããã ããã°ãšæããŸãïŒORCA ã«é¢ãã説æã¯åŸè¿°ããŸãïŒã ã¬ã€ãã©ã€ã³ãžã®å¯Ÿå¿ é»åã«ã«ãã®ããã«å»çæ
å ±ãæ±ãéã«éµå®ããå¿
èŠãããã¬ã€ãã©ã€ã³ãšã㊠3 ç 4 ã¬ã€ãã©ã€ã³ïŒåçåŽåçãçµæžç£æ¥çãç·åçã® 3 çãåºããŠãã 4 ã€ã®ã¬ã€ãã©ã€ã³ïŒããããŸãã CLINICS ã«ã«ãã®éçºãé²ããã«ãããããã®ã¬ã€ãã©ã€ã³ãã·ã¹ãã èšèšãéçšã«å€§ããªåœ±é¿ãåãŒãããããŸãã¯ã¬ã€ãã©ã€ã³ãèªã¿èŸŒã¿æŽçãããšããããå§ããŸããã ã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãšãã«å¯Ÿå¿ãã¹ãããšã¯å€ãã£ãã®ã§ãããã·ã¹ãã æ§æã«ç¹ã«åœ±é¿ã倧ããã£ãã®ã¯ä»¥äžã® 2 ç¹ãšãªããŸãã ãµãŒãã¹æäŸã«çšããã·ã¹ãã ãã¢ããªã±ãŒã·ã§ã³ãæ¥æ¬åœå
æ³ã®é©çšãåã¶å Žæã«èšçœ®ããããš ã¯ã©ã€ã¢ã³ãèšŒææžãå©çšãã TLS ã¯ã©ã€ã¢ã³ãèªèšŒã宿œããããš CLINICS ã«ã«ãã¯åŒç€Ÿã§æ¢ã«éçšããŠãããªã³ã©ã€ã³èšºçã¢ããªãCLINICSããšé£æºãããåæã§ãã£ããããã¬ã€ãã©ã€ã³ã«å³ããã·ã¹ãã æ§æãšããŠããããã«ããŸã CLINICS ã®ã·ã¹ãã ã Heroku ãã AWS ã«ç§»è¡ããããšããå§ãŸããŸããã ãŸããã¯ã©ã€ã¢ã³ãèªèšŒãè¡ãããã« AWS ã®æ§æãè²ã
ãšæ€èšããNginx ãšãæ¥ã
æ ŒéãããããŸããããã ãããã®å¯Ÿå¿å
容ã«é¢é£ããããã°ãéå»ã«æžããŠããŸãã®ã§ãèå³ãããæ¹ã¯ãã²ãåèã«ããŠãã ããã https://developer.medley.jp/entry/2017/08/24/120000_01 https://developer.medley.jp/entry/2017/08/24/120000_02 https://developer.medley.jp/entry/2017/09/22/124000 ORCA ãµãŒãã®ç®¡çæ¹æ³ CLINICS ã«ã«ãã¯ãæ¥æ¬å»åž«äŒ ORCA ç®¡çæ©æ§æ ªåŒäŒç€ŸãæäŸããå»çäŒèšãœããã§ãããORCAããçµã¿èŸŒãã ãORCA å
å
åãã®ã¯ã©ãŠãåé»åã«ã«ãã§ãã åè: ORCA ãšã¯ å»ççŸå Ž IT åãæšé²ããæ¥æ¬å»åž«äŒãäŒå¡çã®ããã«æäŸããŠããã¬ã»ãããœããïŒèšºçå ±é
¬ã®è«æ±æ¥åãè¡ãããã®å»çäŒèšãœããïŒã2002 幎ã«ãªãŒãã³ãœãŒã¹ãšããŠå
¬éãããçŸåšã蚺çæãäžå¿ã« 17,000 ãè¶
ããå
šåœã®å»çæ©é¢ã«å°å
¥ãããŠããŸãã å»çæ
å ±ãããã¯ãŒã¯æšé²å§å¡äŒã«ãŠãå»åž«äŒç·åæ
å ±ãããã¯ãŒã¯æ§æ³ãïŒ1997 幎 æ
å ±åæ€èšå§å¡äŒïŒãæ§æããããŒã«ã®äžã€ãšããŠèªããããæ¥æ¬å»åž«äŒã®ç ç©¶äºæ¥ãããžã§ã¯ããORCA ãããžã§ã¯ãããéçºãæäŸãéå§ãããã®ã§ãã ORCA ProjectïŒ ORCAãããžã§ã¯ãã®æŠèŠ æ¥æ¬å»åž«äŒéçºã»æ¥å»æšæºã¬ã»ãããœãããŠã§ã¢ã®ãµã€ãã§ã www.orca.med.or.jp CLINICS ã«ã«ãã¯ãããŸãã«ä»¥äžã®ãããªæ§æãšãªã£ãŠãããRuby on Rails ã§çšŒåããŠããã«ã«ãã¢ããªã±ãŒã·ã§ã³ãšå»çæ©é¢ããšã® ORCA ãµãŒããããããã®éã ORCA ãæäŸããŠãã API ã§æ¥ç¶ããŠããŸãã ïŒäžå³ã¯äžäŸãšããŠäžããŠãããã®ã§å°æ°ãè©³çŽ°ãªæ§æã¯å®éã®ã·ã¹ãã ãšã¯ç°ãªããŸãïŒ ãã® ORCA ãµãŒãã§ãããå»çæ©é¢ããšã« 1 ã€ã® EC2 ã€ã³ã¹ã¿ã³ã¹æ§æãšãªã£ãŠãããå©çšããå»çæ©é¢ãå¢ãã床㫠EC2 ã€ã³ã¹ã¿ã³ã¹ãå¢ãããããå°å
¥å»çæ©é¢ãå¢ããã»ã©æ§ç¯ãéçšãã€ãããªã£ãŠãããŸãããã®ããããåºæ¥ãã ãèªååããã話ãä»åã®ã¡ã€ã³ããŒãã§ãã ïŒããããããã£ãšæ¥œãã§ããæ§æã«ããããšè²ã
æ€èšãããã®ã§ãããã·ã¹ãã ã®ç¹æ®æ§ãªã©ã®è«žäºæ
ããããçµæ EC2 ã€ã³ã¹ã¿ã³ã¹åäœã§ç®¡çããæ§æã«ãªã£ãŠããŸãïŒ ORCA ãµãŒããŒé¢é£ã§äž»ã«äœ¿çšãã AWS ãµãŒãã¹ AMI äœæãã€ã³ã¹ã¿ã³ã¹äœæãªã©ã®ãã«ã系㯠CodeBuild ããããé©çšãã³ãã³ãå®è¡ãªã©ã®ã€ã³ã¹ã¿ã³ã¹ç®¡ç㯠Systems Manager ãè匱æ§ãã§ãã¯ãªã©ã®ã»ãã¥ãªãã£é¢é£ã«ã¯ Guard Duty ãšãã£ããµãŒãã¹ãäž»ã«å©çšããŠããŸãã æ¬¡ã«ãã€ã³ã¹ã¿ã³ã¹æ§ç¯ã«é¢ããŠããå°ãå
·äœçã«èª¬æããŸãã ORCA ãµãŒãã®ã€ã³ã¹ã¿ã³ã¹æ§ç¯ ORCA ãµãŒãçš AMIïŒãŽãŒã«ãã³ã€ã¡ãŒãžïŒäœæ ãã«ãã®å®è¡ã¯ CodeBuild ã§è¡ã£ãŠããŸããAMI ã®ãã«ãã«ã¯ Packer ã䜿çšããŠããããã«ãå®äºæã«äœæããã AMI ã® ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é²ããŠããŸãããã® AMI ID ãã€ã³ã¹ã¿ã³ã¹äœææã«åç
§ããŸãã åèãŸã§ã«ãCodeBuild ã§äœ¿çšããŠãã buildspec.yaml ã¯ä»¥äžã®ããã«ãªããŸãïŒèª¬æç®æãªã©ãäžéšå®éãšã¯ç°ãªããŸãïŒã phases : pre_build : ## 説æ * packer ãš jq ããã«ãçšã³ã³ããã«ã€ã³ã¹ããŒã« commands : - curl -qL -o packer.zip https://releases.hashicorp.com/packer/1.1.3/packer_1.1.3_linux_amd64.zip && unzip packer.zip - curl -qL -o jq https://stedolan.github.io/jq/download/linux64/jq && chmod +x ./jq build : ## 説æ * åŠçã«å¿
èŠãª AWS credential æ
å ±ãååŸïŒèšå®ïŒåŸã® aws cli 䜿ãçšïŒ * packer ãã«ãå®è¡ãAMI äœæ * packer ãã«ãçµæããäœæããã AMI ID ãååŸ * AMI ID ããã©ã¡ãŒã¿ã¹ãã¢ã«ç»é² commands : - curl -qL -o aws_credentials.json https://169.254.170.2/$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > aws_credentials.json - aws configure set region $AWS_REGION - aws configure set aws_access_key_id `./jq -r '.AccessKeyId' aws_credentials.json` - aws configure set aws_secret_access_key `./jq -r '.SecretAccessKey' aws_credentials.json` - aws configure set aws_session_token `./jq -r '.Token' aws_credentials.json` - ../packer build -machine-readable bin/packer.json | tee packer.log - cat packer.log | grep "artifact,0,id" | cut -d "," -f6 | cut -d ":" -f2 > ami.txt - ORCA_AMI_ID=`cat ami.txt` - aws ssm put-parameter --name ORCA_AMI_ID --value $ORCA_AMI_ID --type String --overwrite ORCA ãµãŒãçš EC2 ã€ã³ã¹ã¿ã³ã¹äœæ å»çæ©é¢çšã®ã¢ã«ãŠã³ããæ°èŠè¿œå ããå Žåã瀟å
çšã®ç®¡çããŒã«ã§ãŸãå»çæ©é¢ã®åºæ¬æ
å ±ãç»é²ããŸãããã®åŸãORCA ã€ã³ã¹ã¿ã³ã¹èšå®ã«å¿
èŠãªãã©ã¡ãŒã¿ïŒå»çæ©é¢ãèå¥ãã ID ãªã©ïŒãèšå®ããã€ã³ã¹ã¿ã³ã¹äœæã®ãã«ãåŠçãå®è¡ããŸãã CodeBuild ããŽãŒã«ãã³ã€ã¡ãŒãžçšã® AMI ãããŒã¹ã« ORCA ã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ããŸããORCA ã€ã³ã¹ã¿ã³ã¹ã¯èµ·åæã«åçš®èšå®åŠçãè¡ããŸãïŒcloud-initïŒ ãªããã€ã³ã¹ã¿ã³ã¹èµ·åæã«è¡ã£ãŠããåŠçãšããŠäž»ã«ä»¥äžã®ãããªããšãè¡ã£ãŠããŸãã 該åœã€ã³ã¹ã¿ã³ã¹ã®å
éš IP ã Private DNS ã«ç»é² ORCA ã®ã»ããã¢ãã/ããã°ã©ã /ãã¹ã¿æŽæ° Postgres ã®ããã¯ã¢ããèšå® Mackerel ã Systems Manager çã®åçš® Agent ã€ã³ã¹ããŒã«ãèšå® ORCA ãµãŒãéçš æ§ç¯ãå®äºã皌åããåŸããORCA èªäœã®ã¢ããããŒãããããã®é©çšãªã©æ§ã
ãªéçšãçºçããŸããããããã©ã®ããã«è¡ã£ãŠãããããŸã æ¹åäžã§ã¯ãããŸããäžéšã玹ä»ããŸãã ã€ã³ã¹ã¿ã³ã¹ã«å¯Ÿããåçš®æäœã®å®è¡ ORCA ã®ã¢ããããŒããªã©ã宿çã«è¡ãæäœã«å¿
èŠãªã³ãã³ãã document ãšããŠç»é²ããRunCommand ã§ç¹å®ã€ã³ã¹ã¿ã³ã¹ãŸãã¯è€æ°ã€ã³ã¹ã¿ã³ã¹ã«äžæ¬å®è¡ã§ããããã«ããŠããŸãã ORCA ã¢ããªã±ãŒã·ã§ã³ã®æ»æŽ»ç£èŠ ORCA ã¢ããªã±ãŒã·ã§ã³èªäœæ§æãè€éã§ãããã€ãã®ããã«ãŠã§ã¢ãšé£æºããŠåããŠããŸãããããã®åçš®ããã»ã¹/ãã°ç£èŠã¯è¡ã£ãäžã§ãAPI ãšããŠæ£ãã皌åããŠãããã確èªããããã®æ»æŽ»ç£èŠã Mackerel ã®ã«ã¹ã¿ã ã¡ããªã¯ã¹ãšããŠç»é²ããäžå®æ°ä»¥äžå€±æããå Žåã¯åçš®ããã»ã¹ãåèµ·åããããã§ãæ£åžžã«åããªãå Žå㯠Mackerel ãã Slack ã«éç¥ãããŠããŸãã ã»ãã¥ãªãã£ãã§ã㯠CloudTrail ã VPC ãããŒãã°ãªã©ãããšã«ãGuardDuty ã§å®æçã«ãã§ãã¯ãè匱æ§ãèŠã€ãã£ãå Žå㯠Slack ã«éç¥ãããããã«ããŠããŸãããã®ä»ãã»ãã¥ãªãã£ãããé©çšãªã©ãããããããŒãžã£ãŒãå©çšãèªååãããŠããŸãã ãŸãšã é»åã«ã«ãã®ã·ã¹ãã ã¯æ€æ»ãç»åããŒã¿ãªã©ãåãæ±ãå€éšã·ã¹ãã ãšé£æºããããšããéèŠããããŸãããã®ãããªé£æºãèŠéã«å
¥ãããšããŒã¿æšæºåã®åé¡ãªã©ãããé£ããåéã§ã¯ãããŸãããCLINICS ã«ã«ããšããŠæ¥ã
é²åããŠããããã«ãããã«ãããŒãžããµãŒãã¹ãªã©æŽ»çšã§ãããšããã¯ç©æ¥µçã«æŽ»çšããéäžãã¹ãåé¡ã解決ããŠãããããšæããŸãã ãŸããé»åã«ã«ãã®ã·ã¹ãã ãšããŠã®æ§è³ªäžã絶察ã«èœãšããªãã·ã¹ãã éçšãå¿
èŠã§ããããã«å
ç¢ãªã·ã¹ãã ã«ããããã«ããã©ãã«ãæªç¶ã«é²ããããªéæ©èœé¢ã®åŒ·åãæ¥ã
ã®ã¢ãã¿ãªã³ã°ãªã©å°éãªããšãå«ãããã£ãšãã£ãšåãçµãã§ããå¿
èŠããããŸãã ãŸã ãŸã ãããã¯ããšããŠæªæçãªæ®µéã§ã¯ãããŸããããå»çã®èª²é¡ã解決ããããããCLINICS ã«ã«ãã§ã¯å»çæ¥åãå¹çåããå»çãã©ãããã©ãŒã ãšãªãã¹ãé²åããŠãããããšããæ§æ³ãæã£ãŠããŸããïŒCLINICS ã«ã«ããç®æãå»çã®ãã©ãããã©ãŒã ãšã¯ïŒãšãã話ã¯ããã¡ãã§è©³ããæžãããŠããŸãïŒ ãCLINICSã«ã«ãããç®æã âå»çã®ãã©ãããã©ãŒã â ãšã¯ïŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ãä¹
ãã¶ãã§ããã¡ãã¬ãŒã§æ¡çšãšåºå ±ãæ
åœããŠããå è€ã§ããæšå¹Žããã¯ãããããã®ããŒãã圹å¡ã¿ããªã§è©±ããŸããããã®ã³ãŒããŒã§ãããæšå¹Žãšç¶æ³ãå€ãããããããªã¡ã³ããŒã«JOINããŠããããã... www.wantedly.com CLINICS ã«ã«ãã¯ããŸãã¯å€ãã®å»çæ©é¢ã«äœ¿ã£ãŠããããã®ã§ã¯ãããŸãããå°æ¥çã«ã¯ãæ£è
ãããšå»çæ©é¢ãã€ãªãã蚺çãæ€æ»ããŒã¿ãªã©ããããšããããã©ãããã©ãŒã ãšãªãäºå®ã§ããããããæ°ããå»çã®ãããã¯ãã«èå³ã®ãããã¶ã€ããŒã»ãšã³ãžãã¢ã»ãã£ã¬ã¯ã¿ãŒã®æ¹ã¯ãã²ãã¡ããŸã§ãå¿åããŸã¡ããŠãããŸãã ã¡ã³ããŒã®ã¹ããŒãªãŒ | æ ªåŒäŒç€Ÿã¡ãã¬ãŒ ã¡ã³ããŒã®ã¹ããŒãªãŒ å®¶æãå人ãç
æ°ã«ãªã£ãæã«æãã®æãå·®ãã®ã¹ãå»çã®åã... www.medley.jp