Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Go in production - case of Gannoy -
Search
monochromegane
October 17, 2017
Technology
540
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Go in production - case of Gannoy -
fukuokago#9
https://connpass.com/event/68358/
monochromegane
October 17, 2017
More Decks by monochromegane
See All by monochromegane
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
160
適応的スパムフィルタのための軽量な類似メッセージカウンタ / jsai2026-adaptive-spam-filter
monochromegane
0
4.6k
ベクトル検索のフィルタを用いた機械学習モデルとの統合 / python-meetup-fukuoka-06-vector-attr
monochromegane
3
850
Claude Codeセッション現状確認 2026福岡 / fukuoka-aicoding-00-beacon
monochromegane
4
610
Go言語での実装を通して学ぶLLMファインチューニングの仕組み / fukuokago22-llm-peft
monochromegane
0
270
不確実性下における目的と手段の統合的探索に向けた連続腕バンディットの応用 / iot70_gp_rff_mab
monochromegane
2
430
なめらかなシステムと運用維持の終わらぬ未来 / dicomo2025_coherently_fittable_system
monochromegane
0
31k
ベクトル検索システムの気持ち
monochromegane
38
13k
Go言語での実装を通して学ぶ、高速なベクトル検索を支えるクラスタリング技術/fukuokago-kmeans
monochromegane
1
320
Other Decks in Technology
See All in Technology
【Loop Engineeringの次に来る?】人間中心デザインをもとにしたInquiry Engineeringを提唱したい
kotahisafuru
0
100
『三匹の子ぶた』から学ぶネットワークセキュリティの昔と今 / Network Security: Then and Now Through the Lens of The Three Little Pigs
nttcom
1
1.3k
toio・myCobotでフィジカルAIっぽいことを行うための検討(とりあえず調査) / フィジカルAI LT(IoTLTによる開催)
you
PRO
0
250
CloudWatchから始めるAWS監視
butadora
0
310
論語・武士道・産業革命から見る かわるもの、かわらないもの
ichimichi
8
2.1k
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
53k
SmartHR Engineering Team Deck
smarthr
0
120
実践が先生だった— 新卒サーバーエンジニア1年目のリアル
mixi_engineers
PRO
0
230
AIエージェントの知識表現と推論に なぜグラフが使われるのか - 記号的AIの復権とニューラルAIとの統合
yohei1126
1
260
Swift&Xcodeのバージョンアップにまつわる怖かった思い出 / Scary Memories of Swift and Xcode Updates
bitkey
PRO
0
110
AIがコードを書く時代、人間は何を保証するのか———馬場さんと考える、開発者に求められる新しい責任と価値 - TECH PLAY
netmarkjp
0
1.2k
侵入は突然に 〜 IoTマルウェアと悪用される家庭の機器 ~ / When Intrusion Strikes: IoT Malware and the Abuse of Home Devices
nttcom
0
1.2k
Featured
See All Featured
The SEO identity crisis: Don't let AI make you average
varn
0
520
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
410
Technical Leadership for Architectural Decision Making
baasie
3
460
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
200
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Being A Developer After 40
akosma
91
590k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
470
Git: the NoSQL Database
bkeepers
PRO
432
67k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
750
Code Review Best Practice
trishagee
74
20k
Are puppies a ranking factor?
jonoalderson
1
3.7k
Transcript
- case of Gannoy - ࡾ༔հ / Pepabo R&D Institute,
GMO Pepabo, Inc. 2017.10.17 Fukuoka.go#9 Go in production
ϓϦϯγύϧΤϯδχΞ ࡾ ༔հ / @monochromegane 2 http://blog.monochromegane.com Yusuke Miyake ϖύϘݚڀॴ
ݚڀһ
1. Goຊ൪ӡ༻ͷཁ݅ 2. Goຊ൪ӡ༻ͷ࣮ݱ 3. ·ͱΊ 3 ࣍
1. GannoyʹΈΔ Goຊ൪ӡ༻ͷཁ݅
Gannoy Approximate nearest neighbor search server and dynamic index written
in Golang. https://github.com/monochromegane/gannoy
Similar images search system using Gannoy 6 Features Similar items
Gannoy [2048]float64 query by http find similar features mapping similar features to items response Deep CNN index Features [2048]float64 Deep CNN register by http
• HTTP based Approximate nearest neighbor search server • Using
labstack/echo • Go 1.8+ 7 Gannoy
Goຊ൪ӡ༻ͷཁ݅
• Graceful restart • Daemonize • Monitoring • Log rotation
9 Goຊ൪ӡ༻ͷཁ݅ • Configuration • Build • Deploy
2. GannoyʹΈΔ Goຊ൪ӡ༻ͷ࣮ݱ
Graceful restart 11 go-server-starter + http.Server#Shutdown() import "github.com/lestrrat/go-server-starter/listener" e :=
echo.New() listeners, err := listener.ListenAll() if err != nil && err != listener.ErrNoListeningTarget { fmt.Fprintln(os.Stderr, err) os.Exit(1) } e.Listener = netutil.LimitListener(listeners[0], opts.MaxConnections) Listen from start_server socket.
Graceful restart 12 go-server-starter + http.Server#Shutdown() go func() { if
err := e.Start(""); err != nil { e.Logger.Info("Shutting down the server") } }() sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, sig) <-sigCh ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opts.ShutDownTimeout)*time.Second) defer cancel() if err := e.Shutdown(ctx); err != nil { e.Logger.Fatal(err) } Start server as goroutines. Wait SIGTERM. Graceful shutdown using http.Server.
Daemonize 13 Systemd [Unit] Description=Gannoy DB ConditionPathExists=/usr/bin/start_server ConditionPathExists=/usr/bin/gannoy-db After=network.target [Service]
User=gannoy Group=gannoy Type=simple PIDFile=/var/run/gannoy/server_starter.pid ExecStart=/usr/bin/start_server --port 8080 --pid-file /var/run/gannoy/server_starter.pid -- / usr/bin/gannoy-db -c /etc/gannoy/gannoy-db.toml ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/kill -TERM $MAINPID [Install] WantedBy=multi-user.target gannoy-db.service
Monitoring 14 health-check endpoint + Consul e.GET("/health", func(c echo.Context) error
{ return c.NoContent(http.StatusOK) }) { "service": { (snip) "port": 80, "checks": [ { "script": "/usr/bin/check-http -u http://localhost/health", "interval": "30s" } ] } } health-check endpoint consul.d/gannoy.json
Log ratation 15 logrotate /var/log/gannoy/gannoy-db.log { daily rotate 7 missingok
notifempty compress postrotate kill -HUP `cat /var/run/gannoy/server_starter.pid` endscript } gannoy-db.logrotate reopen logfile.
Configuration 16 monochromegane/conflag // Parse option from args and configuration
file. conflag.LongHyphen = true conflag.BoolValue = false parser := flags.NewParser(&opts, flags.Default) _, err := parser.ParseArgs(os.Args[1:]) if err != nil { os.Exit(1) } if opts.Config != "" { if args, err := conflag.ArgsFrom(opts.Config); err == nil { if _, err := parser.ParseArgs(args); err != nil { os.Exit(1) } } } _, err = parser.ParseArgs(os.Args[1:]) if err != nil { os.Exit(1) } Read option from config. Overwrite option from args. data-dir = "/var/lib/gannoy" log-dir = "/var/log/gannoy" lock-dir = "/var/run/gannoy" server-starter = true auto-save = true gannoy-db —data-dir=“data”
Configuration 17 monochromegane/conflag http://blog.monochromegane.com/blog/2015/05/30/conflag/
Build 18 rpmbuild + docker-compose . !"" Dockerfile.rpmbuild !"" docker-compose.yml
!"" rpmbuild # !"" RPMS # # $"" x86_64 # # $"" gannoy-0.0.1-8.x86_64.rpm # !"" SOURCES # # !"" gannoy-db.logrotate # # !"" gannoy-db.service # # $"" gannoy-db.toml # $"" SPECS # $"" gannoy.spec $"" version.go version: '2' services: gannoy-rpmbuild: build: context: . dockerfile: Dockerfile.rpmbuild command: cp /root/rpmbuild/RPMS/x86_64/ gannoy-0.0.1-8.x86_64.rpm /tmp/rpmbuild/RPMS/ x86_64/. volumes: - .:/tmp:rw RUN rpmbuild -bb /root/rpmbuild/SPECS/gannoy.spec $ docker-compose build gannoy-rpmbuild $ docker-compose run gannoy-rpmbuild docker-compose.yml Dockerfile.rpmbuild
Deploy (and test) 19 Puppet + Serverspec class gannoy::install {
include ::go_start_server $rpm = 'gannoy-0.0.1-8.x86_64.rpm' file { "/usr/local/src/${rpm}": ensure => present, source => "puppet:///modules/gannoy/${rpm}", mode => '0755', owner => 'root', notify => Package['gannoy'], } -> package { 'gannoy': ensure => '0.0.1-8', source => "/usr/local/src/${rpm}", provider => rpm, } (snip) } (snip) describe service('gannoy-db') do it { should be_enabled } end describe package('gannoy') do it { should be_installed.with_version('0.0.1-8') } end (snip)
·ͱΊ
• σʔϞϯԽ͕ඞཁͳGoΞϓϦͷຊ൪ӡ༻όΠφϦҎ֎ʹඞཁͳ ϑΝΠϧ͕͋ΔͷͰύοέʔδϯάͨ͠΄͏͕औΓճָ͕͠ • ΦϓγϣϯͱઃఆϑΝΠϧͷڞ௨Խʹconflag͕ศར • ϕετϓϥΫςΟεࡧதɻσΟεΧογϣϯ͠·͠ΐ͏ɻ 21 ·ͱΊ
ݚڀһɺੵۃతʹืूதʂ http://rand.pepabo.com/