Slide 1

Slide 1 text

࣮ྫͰֶͿGoϓϩάϥϜ։ൃ Tatsuhiko Kubo@cubicdaiya Gunosy.go#11@2015/03/11

Slide 2

Slide 2 text

ࣗݾ঺հ • ٱอୡ඙(Tatsuhiko Kubo) • bokko@cubicdaiya • Software Engineer in Infrastructure Engineering • Mercari, Inc. • Go / C / mruby / nginx / ngx_(lua|mruby) / h2o /etc…

Slide 3

Slide 3 text

࣮ྫͰֶͿGoϓϩάϥϜ։ൃ

Slide 4

Slide 4 text

ࠓճͷςʔϚ • ͜Ε·Ͱʹ։ൃͨ͠GoͷϓϩάϥϜΛྫʹ • ԿނGoͰ։ൃͨ͠ͷ͔ʁ • ࣮ࡍͷGoͷίʔυ • ֤GoϓϩάϥϜΛӡ༻ͯ͠Έͨײ૝ • ͳͲʹ͍ͭͯ࿩͠·͢

Slide 5

Slide 5 text

ࠓճ঺հ͢ΔGoϓϩάϥϜ • nginx-build • cachectl • slackboard • શ෦ϝϧΧϦͰ΋ར༻͍ͯ͠·͢ˢ • in-house program on ϝϧΧϦ

Slide 6

Slide 6 text

nginx-build

Slide 7

Slide 7 text

nginx-build • nginxͷϏϧυπʔϧ • nginxͷϏϧυʹ·ͭΘΔ໘౗ࣄΛࣗಈԽ • ιʔείʔυ΍ґଘϥΠϒϥϦͷμ΢ϯϩʔυ • 3rd PartyϞδϡʔϧͷμ΢ϯϩʔυɺ૊ΈࠐΈ • https://github.com/cubicdaiya/nginx-build

Slide 8

Slide 8 text

Why is nginx-build written in Go? • ࠷ॳ͸shͰॻ͍ͯͨ • ੲ͍ͨձࣾʹ͸શࣗಈԽsh͕͋ͬͨ • స৬ͯ͠࢖͑ͳ͘ͳͬͨ • ·ͨshॻ͘ͷͭΒ͍͠ɺϝϯς΋ͨ͘͠ͳ͍ • ͦ͏ͩɺGoͰॻ͜͏ʂ

Slide 9

Slide 9 text

Why is nginx-build written in Go? • ϙʔλϒϧ • ϝϯςָ͕ • ഑෍΋ָ • ΫϩείϯύΠϧ͕؆୯ • ฒྻॲཧ͕؆୯

Slide 10

Slide 10 text

nginx-buildͷ࣮ߦ෩ܠ $ nginx-build -d work -pcre -zlib -openssl nginx-build: 0.3.1 Compiler: gc go1.4.1 2015/03/10 02:04:23 Download pcre-8.36..... 2015/03/10 02:04:23 Download zlib-1.2.8..... 2015/03/10 02:04:23 Download openssl-1.0.2..... 2015/03/10 02:04:23 Download nginx-1.7.10..... 2015/03/10 02:04:28 Extract zlib-1.2.8.tar.gz..... 2015/03/10 02:04:28 Extract nginx-1.7.10.tar.gz..... 2015/03/10 02:04:35 Extract openssl-1.0.2.tar.gz..... 2015/03/10 02:04:39 Extract pcre-8.36.tar.gz..... 2015/03/10 02:04:39 Generate configure script for nginx-1.7.10..... 2015/03/10 02:04:39 Configure nginx-1.7.10..... 2015/03/10 02:04:45 Build nginx-1.7.10..... 2015/03/10 02:07:34 Complete building nginx! ɾ ɾ ɾ $ ฒྻͰ࣮ߦ͞Ε·͢

Slide 11

Slide 11 text

͜Μͳײ͡ parallels := 0 done := make(chan bool) (தུ) if *pcreStatic { parallels++ go downloadAndExtractParallel(&pcreBuilder, done) } if *openSSLStatic { parallels++ go downloadAndExtractParallel(&openSSLBuilder, done) } if *zlibStatic { parallels++ go downloadAndExtractParallel(&zlibBuilder, done) } parallels++ go downloadAndExtractParallel(&nginxBuilder, done) (தུ) for i := 0; i < parallels; i++ { <-done }

Slide 12

Slide 12 text

shΑΓͣͬͱָͰ͢

Slide 13

Slide 13 text

cachectl

Slide 14

Slide 14 text

cachectl • OSͷϖʔδΩϟογϡ֬ೝɾ࡟আπʔϧ • ແବͳϖʔδΩϟογϡΛղ์͢Δͷʹར༻ • cachectld͍ͬͯ͏σʔϞϯ΋෇͍ͯΔ • https://github.com/cubicdaiya/cachectl

Slide 15

Slide 15 text

Why is cachectl written in Go? • طଘͷπʔϧ͕࢖͍ʹ͔ͬͨ͘ • e.g. σΟϨΫτϦࢦఆ͕Ͱ͖ͳ͍ • σʔϞϯԽͯ͠ఆظతʹ࣮ߦ͔͚ͨͬͨ͠ͲɺͦΜͳػ ೳ࣋ͬͯΔπʔϧ͕ͳ͔ͬͨ • γεςϜίʔϧ͕cgo΍syscallͰ؆୯ʹݺͼग़ͤΔ • ϖʔδΩϟογϡͷ৘ใऔಘ΍ղ์ʹ͸mmap΍ mincoreɺposix_fadvise౳ͷγεςϜίʔϧ͕ඞཁ

Slide 16

Slide 16 text

cachectlͰϖʔδΩϟογϡͷ ར༻۩߹ΛνΣοΫ $ cachectl -f /var/log/nginx/access.log 2015/03/10 03:08:37 /var/log/nginx/ access.log 's pages in cache: 1323464/1323464 (100.0%) [filesize=5293852.1K, pagesize=4K] $ 5GBͷϩάϑΝΠϧͷத਎͕ શ෦ϖʔδΩϟογϡʹࡌͬͯΔ

Slide 17

Slide 17 text

ফͯ͠ΈΔ $ # ϖʔδΩϟογϡΛ࡟আ $ cachectl -f /var/log/nginx/access.log -op purge 2015/03/10 03:13:03 purging /var/log/nginx/ access.log 's page cache $ $ # ࠶౓ϖʔδΩϟογϡͷར༻۩߹ΛνΣοΫ $ cachectl -f /var/log/nginx/access.log 2015/03/10 03:13:07 /var/log/nginx/access.log 's pages in cache: 94/1325181 (0.0%) [filesize=5300722.2K, pagesize=4K] $ 5GBͷϝϞϦ͕ղ์͞Ε·ͨ͠

Slide 18

Slide 18 text

ࢦఆͨ͠ϑΝΠϧͷϖʔδΩϟογϡΛղ์͢ΔCͷؔ਺ /* #include #include #include #include int fadvise(const char *path, float r) { int fd; struct stat st; off_t l; fd = open(path, O_RDONLY); if(fd == -1) { return -1; } if(fstat(fd, &st) == -1) { goto error; } l = (off_t)(st.st_size * r); if(posix_fadvise(fd, 0, l, POSIX_FADV_DONTNEED) != 0) { goto error; } close(fd); return 1; error: close(fd); return -1; } */ import "C"

Slide 19

Slide 19 text

Go͔Βͷݺͼग़͠ func purgePages(fpath string, fsize int64, rate float64) error { if rate < 0.0 || rate > 1.0 { return errors.New(fmt.Sprintf("%f: rate should be less than 1.0\n", rate)) } cs := C.CString(fpath) defer C.free(unsafe.Pointer(cs)) result := C.fadvise(cs, C.float(rate)) if result == -1 { return errors.New(fmt.Sprintf("failed to purge page cache for %s", fpath)) } return nil } C.(ؔ਺໊)Ͱݺͼग़ͤΔ

Slide 20

Slide 20 text

cgoΛར༻͢Δࡍͷ஫ҙ఺ • CͳͷͰϝϞϦ؅ཧ͸ࣗલ • e.g. C.CStringͷ஋͸ޙͰC.free͢Δ • cgoͷίʔυ࣮ߦத͸goroutineͷίϯςΩετε Πον͕ޮ͔ͳ͍ • ίϯύΠϧ͕஗͘ͳΔ • ϙʔλϏϦςΟ͕Լ͕Δ

Slide 21

Slide 21 text

slackboard

Slide 22

Slide 22 text

slackboard • SlackϓϩΩγ • clientίϚϯυ(slackboard-cli)෇ଐ • https://github.com/cubicdaiya/slackboard

Slide 23

Slide 23 text

Why is slackboard written in Go? • net/httpͰ؆୯ʹHTTPαʔό/ΫϥΠΞϯτ͕ॻ ͚Δ • slackboard-cli͸શαʔόʹ഑ஔ͍ͨ͠ • GoͳΒ഑෍ָ͕ • LLΈ͍ͨʹ֤αʔόʹ࣮ߦ؀ڥ༻ҙ͠ͳ͍͍ͯ͘

Slide 24

Slide 24 text

࣮ߦΠϝʔδ

Slide 25

Slide 25 text

in-house programs on ϝϧΧϦ

Slide 26

Slide 26 text

Ωϟογϡੜ੒σʔϞϯ • ಛఆAPIͷϨεϙϯεͷΩϟογϡΛͻͨ͢Β࡞Γଓ ͚ΔσʔϞϯ • ΞΫηε਺͕ଟ͍ͷͰϢʔβ͕ΞΫηε͢Δલʹ ΩϟογϡΛ࡞੒͓͍ͯͯ͠ߴ଎Խ • 1ඵ͝ͱʹฒྻʹ݁ߏͳྔͷHTTPϦΫΤετΛૹΓଓ͚Δ • ݩʑRubyͰॻ͔Ε͍ͯͨ(࣮ߦαʔό͕ॏ͔ͬͨ)

Slide 27

Slide 27 text

ݩͷRubyίʔυ Parallel.map(params_list, :in_processes => in_processes) do |params| (தུ) res = http_request('GET', url, params) (தུ) end.compact params_listͷαΠζ͕େ͖͍ ↓ େྔʹfork͢ΔͷͰॏ͍

Slide 28

Slide 28 text

GoͰॻ͖௚ͨ͠ done := make(chan error) size := len(paramCombs.Params) var errors []error for i := 0; i < size; i++ { go makeCache(URL, paramCombs.Params[i], done) } for i := 0; i < size; i++ { err := <-done if err != nil { errors = append(errors, err) } } gorutine͸͍ܰʂ

Slide 29

Slide 29 text

࣮ߦαʔόͷάϥϑ(CPU) ϦϥΠτͨ͠λΠϛϯά

Slide 30

Slide 30 text

࣮ߦαʔόͷάϥϑ(LA) ϦϥΠτͨ͠λΠϛϯά ேԜΜͰΔ෦෼͸ϝϯςφϯε

Slide 31

Slide 31 text

ͦͷଞ • σʔϞϯԽ͢Δͱ͖͸supervisordΛར༻ • go-server-starter͔circusࢼ͍ͨ͠ • ύοέʔδ؅ཧ͸gom࢖ͬͯ·͢ • ϏϧυλεΫ͸Makefileʹॻ͍ͯ·͢

Slide 32

Slide 32 text

࣌ؒ଍Γͳͯ͘࡟ͬͨ΍ͭ • ϓογϡ௨஌αʔό in Go • https://speakerdeck.com/cubicdaiya/1000mo- daunrodoapuri-merukari-wozhi-eruji-shu? slide=57 • GoαʔόͷϞχλϦϯά • http://qiita.com/cubicdaiya/items/ b90c1ae147a72f4970b2

Slide 33

Slide 33 text

Ҏ্ͷϓϩάϥϜΛ GoͰॻ͍ͯӡ༻ͯ͠Έͨײ૝ • ૣ͍ɾ଎͍ɾ͍ܰ • ੜ࢈ੑߴ͍(શ෦1ʙ2࣌ؒͰ࠷ॳͷόʔδϣϯΛॻ͚ͨ) • े෼ʹύϑΥʔϚϯε͕Α͍ • ϑοτϓϦϯτ΋Α͍ • ඇৗʹ҆ఆ͍ͯ͠Δ • ։ൃऀʹ΋ӡ༻ऀʹ΋΍͍͞͠