[参加レポート] 『Fukuoka.go#12』 に参加してきました #fukuokago

2018年10月4日(木)に開催された、『Fukuoka.go#12』 の参加レポートです。Goroutineの内部実装やネットワーク・GraphDB・ブロックチェーンと多岐にわたる発表を聞いてきました。
2018.10.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

10/4(木)に福岡でGolangの勉強会『Fukuoka.go#12』が開催されました。 私の参加しているプロジェクトではGolangを使っているので、知見を得るためイベントに参加してきました。 本ブログはセッションのまとめになります。

イベント情報

  • Fukuoka.go#12 - connpass
  • 日時: 2018年10月4日(木) 18:45〜22:10
  • 場所: ペパステ - GMOペパボ株式会社(福岡支社)

タイムテーブル

時間 タイトル スピーカー
19:15 Talk1: Road to your goroutine @monochromegane
19:30 LT1: AWS Lambda Goのgoroutine周り @seike460
19:35 Talk2: これがGoアプリデプロイだ @linyows
19:50 LT2: Go 2のドラフトを読む ~エラー編~ @take-cheeze
19:55 Talk3: GolangでSSHプロキシサーバを実装した @tsurubee
20:10 休憩 -
20:15 Talk4: GolangでTCPパケットを読む @k1low
20:30 LT3: STNS v2の話し @pyama86
20:35 Talk5: Go×Ethereumで電子署名アプリケーションを作った 大谷 祐司
20:50 LT4: jwt?なにそれ美味しいの? @sasenomura
20:55 LT5: GraphDBのお話 @curry_on_a_rice

Road to your goroutine

GMOペパボ株式会社 三宅悠介さん

Road to your goroutines - Speaker Deck

アジェンダ

  • Motivation
  • Overview of goroutines and scheduler
  • Road to your goroutines

Motivation

  • The platinum searcher v3 を開発している
  • アルゴリズムの変更・Goroutineの使用で高速化を図る
  • Goroutineを大量に作って性能を担保していた
  • 不安定になることがある
  • Goroutineの詳細について調査した

Overview of goroutines and scheduler

  • 構成要素
    • G: Goroutine
      • Run Queueに積まれる
    • M: OS thread
    • P: Processor (scheduling context)
      • GとMを紐付ける
      • 多対多を実現する (複数のGoroutine : 複数のスレッド)
  • 誤解を恐れずに言うとGoroutineはアプリケーションレベルのスレッド

Road to your goroutines

  • Goroutineをどうやって起動するかgdbでデバッグしながら確認する
  • エントリポイントから読み進めていく
  • エントリポイント → _rt0_amd64runtime.rt0_go
    • runtime.osinit
      • CPUの(論理)コア数を取得
    • runtime.schedinit
      • 最大の同時起動数を設定する ( GOMAXPROCS とか )
    • runtime.mainPC
      • g と呼ばれるスタック・Goroutineの状態を持つ構造を作る
      • キューに g を追加する
    • runtime.mstart
      • キューから g を取得する
      • g を実行する
      • runtime.gogog を渡して起動する
        • runtime.gogo はアセンブリ実装
        • BXレジスタ = runtime.main にJMPする
    • runtime.main
      • ランタイム初期化
      • GC有効化
      • main.init で各モジュールの init を呼び出す
        • ファイナライザの Goroutine を作る
      • main.main を呼び出す
  • メイン関数 ( main.main )
    • Goroutineの生成で runtime.newproc を呼び出してる
    • g を作ってキューに追加する
    • キューから g を取り出して実行する
  • Goroutineの切り替え
    • スケジューラが切り替える
    • 切り替えの対象
      • 長時間実行している
      • システムコール
      • ネットワーク通信
      • etc...
    • 長時間実行をどうやって検出するか
      • システムモニタのスレッドが検出する
      • スタックの拡張(?)時のチェック機構を利用する
    • システムコールをどうやって検出するか
      • runtime.entersyscall でマークする
      • マークした gp および m から切り離す
      • システムコール用の m で実行させる
  • Goroutineの終了
  • まとめ
    • ランタイムのコードを読むことでGoroutineの動きを学べた
      • I/OでブロッキングするタスクをCPUバウンダリにしてくれる
      • The platinum searcherの用途にあってる
      • システムコールを発行するGoroutineを大量に作るとボトルネックになる

AWS Lambda Goのgoroutine周り

株式会社Fusic 清家史郎さん

アジェンダ

  • 今回やりたいこと
  • AWS LambdaとGoroutine
  • profiling
  • まとめ

今回やりたいこと

  • カレンダーのデータ(ical)を定期的に解析してSlackに通知してる
  • Goroutine化
    • icalデータの取得
    • Slack通知
  • プロファイリング

Goroutine化

  • 同期取得の場合は普通に関数コールしてicalデータを受け取る
  • Goroutine化の場合はチャネル経由でicalデータを受け渡す
  • WaitGroupでGoroutineの完了を待機する
    • 待機しないとSlackへの通知前にLambdaが終了してしまう

プロファイリング

  • AWS X-Rayを利用する
    • 本番環境や分散アプリケーションの分析とデバッグ
    • Serverless Frameworkでさくっと導入できる
  • 結果
    • 実行時間
      • 同期実行版: 63ms
      • Goroutine版: 32ms
    • メモリ使用量
      • 同期実行版: 27MB
      • Goroutine版: 27MB
    • メモリ使用量が変わらない理由が謎
  • まとめ
    • AWSはHTTPSのAPIアクセスが基本だからGoroutineと相性が良い
    • WaitGroupを使ってGoroutine完了前にLambdaが終了するのを防ぐ
    • X-Rayを使って速度向上したか確認できる

これがGoアプリデプロイだ

GMOペパボ株式会社 小田さん

The deployment for Go - Speaker Deck

Are you deploying?

なぜBlue/Greenじゃないか?

  • 前提
    • アプリ・その他を個別にデプロイする
    • Immutable Infrastructureではない
  • コンテナのBlue/Greenだと、OS/Middle・アプリの両方を入れ替える
    • アプリだけを入れ替えたい
  • クラウドまたはコンテナ環境を用意できないことがある
  • 予算が少なくBlue/Greenできないことがある
  • リモートからのデプロイは鍵の管理が必要だからやりたくない

元のデプロイ方法

  • シェルで泥臭くデプロイしてた
  • SCPでファイル転送
  • SSHでファイルを配置
  • サービスを再起動

Dewy

  • Mutable環境でアプリが能動的にデプロイする
  • ワークフロー
    1. 管理者: サーバーを起動する
    2. 開発者: 開発してリポジトリにプッシュする
    3. CI: ビルド&テストする
    4. オーナー: マスターブランチにマージする
    5. CI: リリースする
    6. Dewy: リリースを検知・取得する (Pull)
    7. Dewy: サーバーを再起動する
  • デプロイのデモ

  • 今後の課題
    • Hook系の追加タスク (通知など)
    • プラグイン機構
    • ロールバック
    • カナリ―デプロイ (一部のサーバーにだけ適用)
    • 分散KVSの対応

まとめ

  • システム規模が小さいとコンテナ環境でないこと、Blue/Greenできないことがある
  • そういった環境向けに、GoらしくワンバイナリをGitHub releasesにPOSTすると勝手にデプロイされる
  • ちょっとしたアプリのデプロイにちょうどいい

Go 2のドラフトを読む ~エラー編~

@take-cheezeさん

Go_2のドラフトを読む__エラー編_.pdf - Speaker Deck

Golangの2大よく言われるやつ

  • Golang2改善予定
    • エラー処理
    • interface{} のチェックがガバガバ
  • 今回はエラー処理の話がメイン
  • 公式ドキュメントやRFC読むの楽しい、オススメ

エラー処理

  • タッチバーの正しい使い方
    • タッチバーでエラー判定のボイラープレートを追加!
  • 問題提起
    • エラー処理の問題点
      • 提携処理だけど記述量が多い
        • gofmt で少なくとも3行になる
      • エラーを返す関数の場合、必ず if err != nil のチェックが必要
    • チェック漏れが起こり得る
      • 戻り値をチェックしなくてもコンパイラに怒られない
    • 他言語の例
      • Rust
      • Swift
  • 改善案
    • handle文
      • 例外処理のハンドラ、 try catchのcatchブロック内のイメージ
      • エラーにスタック情報を追加できる
        • 現行のGolangの場合デフォルトだとつかない
      • 宣言がない場合既定のエラーハンドラになる
    • check文
      • 後続の式の戻り値を判定する
      • エラーを検知したら自動で呼び出し元にエラーを返す

まとめ

  • 短くかけるのは嬉しい
  • handle文のチェインではまりそう
  • Rustのmatch式でreturnできるのずるい
  • 暗黙のチェックが弱そう

GolangでSSHプロキシサーバを実装した

GMOペパボ株式会社 鶴田 博文さん

GolangでSSHプロキシサーバを実装した - Speaker Deck

今日はなすこと

  • SSHプロトコルの概要
  • 開発の背景
  • 実装について

SSHプロトコルの概要

  • Secure Shell の略称
  • クライアント・サーバ間における通信の安全性を確保するためのプロトコル
  • 透過的な通信経路を提供してくれる
    • 透過的は仮想的の反対の意味
    • 実際には存在するものを存在しないように見せかける
    • 利用者は特に意識せずに通信内容が安全に暗号化・復号されている
  • 利用するだけならプロトコルの詳細を理解する必要ない
  • 詳細を知っていると、意図的に割り込んでコントロールすることができる
  • プロトコルの処理に割って入る
    • パケットレベルでログを記録したい
    • フックを仕込んで振る舞いを動的に制御したい
  • sshr というSSHプロキシサーバを作っている

開発の背景

  • なぜsshrを作ったのか
  • LOLIPOP! は月額100円から利用できる
  • 1台の物理サーバのリソースを複数のユーザに提供する (共用サーバ)
  • ユーザと接続先のサーバが紐付いている
  • ユーザは接続先のサーバ(ホストアドレス?)を知らないといけない
  • 直接サーバに接続するとサービス提供者の都合でユーザの物理配置を変更できない
  • ユーザのコンテンツ移設の障壁を極限まで下げる
  • ユーザとサーバの配置を最適化して、より快適な環境を提供したい
  • sshr
    • ユーザが接続先を意識しないプロキシサーバ
    • ユーザ名ベースで動的に接続先を決定できる
    • フックでロジックを仕込める
    • ユーザ名から接続先のサーバを引く
    • DBを更新すると自動で接続先が変わる

実装について

  • プロトコルを知るためにRFCを読む
    • RFC4252: ユーザ認証
    • RFC4253: トランスポート層
    • RFC4254: チャネル制御・ポートフォワーディング
  • SSHは複数の独立したプロトコルで構成される
  • SSHセッション接続までの流れ
    • TCP接続の確立
    • パラメタネゴシエーション
    • セッション鍵交換
    • ホスト認証
    • ユーザ認証
    • SSHセッション確立
  • ユーザ認証の実装に苦しんだ
    • プロキシを介したユーザ認証
    • sshrは認証メッセージのパケットをそのままサーバ・クライアントに受け渡しする
      • パスワード: OK
      • 公開鍵: NG
    • セッションID問題
      • セッションごとに一意なIDがある
      • 2段階の認証が必要
      • ユーザとsshr間、sshrとサーバ間はそれぞれ別のキーペアを使う

まとめ

  • 透過的な通信のプロトコルに意図的に割ってはいって自由にコントロールできる
  • ユーザが接続先を意識せずユーザ名ベースで動的に接続先を特定できるようになる
  • プロキシを介した公開鍵認証はセッションIDの関係で2段階の認証が必要

GolangでTCPパケットを読む

GMOペパボ株式会社 小山さん

※ スライドは公開され次第添付します。

tcpdumpは一般的?

  • 使ったことなかった
  • リクエストなげれば変えてくるしクエリ投げれば結果が返ってくるもの
  • TCPパケットとかバイナリを読むなんて・・・
  • バイナリを読めるとかっこいい
  • 簡単なtcpdumpを作ってみる
    • プロジェクトディレクトリを作る
    • main.goを書く
    • 32行!で書けた!
    • 全行説明します!

実装

  • google/gopacket を使う
    • Google製のパケット処理ライブラリ
    • pcapファイルの読み込みもできる
    • libpcapを使ってる
  • 対象のデバイスとフィルタ条件を用意する
  • ハンドラを作る
  • ハンドラにフィルタを設定する (BPF)
  • range でパケットを受け取る
  • 受け取っったパケットをダンプする
    • hex.Dumpでバイナリダンプ
  • fmt.Printf("%s", packet)
    • packetは文字列じゃないけどなぜ %s で表示できる?
    • Stringerが設定されている func(*p) String()
  • google/gopacketでTCPパケットを読む
    • TCPパケットの構造
      • TCPヘッダは固定長のデータと可変長のデータがある
      • 可変長のデータがやっかい
    • gopacketだとL1・L2・L3・L4とレイヤで別れている
      • オプションとかの可変構造の意識いらない
      • HTTP/MySQLなども LayerPayload() を読めばいい
  • これでTCPパケット解析をはじめられる!

Plugin STNS v2朝!!!

GMOペパボ株式会社 山下 和彦さん

Plugin STNS v2 朝!!1 - Speaker Deck

STNSが解決すること

  • LADP/DB管理したくない
  • SSHログインユーザの公開鍵認証はしたい
  • GitなどのVSと組み合わせてユーザ管理したい
    • TOMLを使う
  • シンプルで自由度の高い設計
  • サーバ実装はRESTful風
  • Dockerですぐに試せる

v2になって変わったこと

  • nscdが不要になった
    • 独自のキャッシュ機構を実装して解決
  • インタフェースがREST風に
  • libnss-stnsがGolangからC言語へ
  • etcdに対応した
    • etcdはGolangの分散KVS
    • サーバ間の設定を同期
    • 任意の情報を保存できるようになった
  • パスワード認証
  • SAML認証
  • etcdの実装
    • GolangのPluginを採用
    • .soファイルから動的に読み込む
  • stns modules
    • .soファイルを自作することでサーバを拡張できるようになった
    • Backendのインタフェースを満たせばそのまま動く

まとめ

  • 頼む、使ってみてくれ!!!!
  • STNSを導入するだけでユーザ管理を始められる
  • JST, 日本語対応は即でやります
  • v2で安定化、変化に強くなった
  • modulesで必要な機能を入れていく
  • コントリビュータ募集中

GraphDBのお話

株式会社ベガコーポレーション 田中 健太さん

LT20181004.pdf - Speaker Deck

データ分析業務

  • データ分析とGo言語
  • 実運用のDBから分析 (Python/R/Julia)
  • 大規模データを集計・Web公開する際にGolangを使いたい
  • やりたいこと
    • 商品間の関係性
    • どういう傾向があるか
    • 購買履歴から商品間の関係性を可視化
    • さらにそのデータを分析したい
  • Graph Database
    • グラフ理論のエッジとノードで記述するデータ構造
    • 関係性をデータとして保持する
    • Not only SQL
  • Neo4j
    • Javaで実装
    • 有名 (2010年〜)
    • 情報が多い
  • Dgraph
    • Goで実装
    • 若い (2017年〜)
    • 処理が早いらしい
    • 情報は少ない
  • Dgraphの可視化
    • JS書かないでもブラウザでクエリ結果を出力/可視化できる

Go×Ethereumで電子署名アプリケーションを作った

株式会社サーキュレーション 大谷 祐司さん

※ 資料は公開され次第添付します。

Go x Ethereumで署名アプリを実装

  • chaintopeさんと共同でスマートコントラクト
  • 仕事受発注における課題解決の実証実験
  • スマートコントラクト
  • 企業とフリーランスの労働契約における更新プロセスが曖昧
  • スマートコントラクトで解決できないか
  • ブロックチェーンは Ethereum
    • 時価総額が世界2位
    • 分散アプリのためのプラットフォーム
    • Solidityという独自言語でスマートコントラクトを実装
  • 選定理由
    • チュートリアルが充実
    • 基本を理解できる
    • ICOしたコードも多く参考になる
  • エコシステムが充実してる
    • Meta Mask
    • TRUFFLE
    • Geth (go-ethereum)
    • エディタやテストネットなど開発に必要なエコシステムが充実

開発したもの

  • 労働契約書を発注者と労働者が確認
  • 労働契約書に対して双方が電子署名する
  • 労働契約書の保存先、電子署名、契約書のハッシュ値をブロックチェーン上に保存
  • 契約書の証明・更新プロセスなどの専用アプリを作る
  • Go + Vue + MySQLで実装
    • 2ヶ月ぐらいで社内でテスト運用できた
  • スマートコントラクトをGoで操作
    • Ethereum <=> Goのabiを作る
    • abi経由でスマートコントラクトのデプロイ・操作できる
  • Ethereumの操作にはGoが便利
    • Ethereumの公式クライアント
    • abiベースでGoのコードを生成できる

まとめ

  • 良かったこと
    • ブロックチェーンの理解
    • ブロックチェーンの基本的な仕組みを理解できた
    • Solidityでスマートコントラクトをすらすらかけるようになった
    • ブロックチェーンの可能性を感じられた
    • やっぱり新しい技術は楽しい
  • 最近話題のブロックチェーンとスマートコントラクト
  • 仕組みの理解とアプリ実装は新鮮
  • 引き続き動向をウォッチ
  • 課題はまたこんど

JWT?なにそれ美味しいの?

福岡工業大学 福田さん - @sasenomura 福田さん 福岡工業大学

※ 資料は公開され次第添付します。

JWT

  • Json Web Token
  • JSONをBASE64エンコードして認証
  • 署名付き、トークンの改ざんチェックできる
  • . でわかれる
    • ヘッダ
    • アルゴリズム、種別
    • ペイロード
    • 実データ
    • シグネチャ
    • 署名
      • ヘッダとペイロードをアルゴリズムでハッシュ化したときの値
  • Golang-echo
    • JWTのミドルウェアがある
    • jwt-go で使えるようになる
  • API-OAuth-Serviceで構成される場合
    • APIからOAuthに認証情報を渡す
    • OAuthからAPIに認証結果をJWTで返す
    • APIからServiceにJWT使ってアクセス
  • サービスをまたぐときに有効
  • GolangもJWTに対応してる

おわりに

Golangというプログラミング言語をテーマにした勉強会でしたが、幅広い発表内容を聞けて刺激的でした。特にGoroutineの内部実装はあまり意識せずに使ってしまうことが多かったので、パフォーマンスを発揮しやすい作りを意識してコードを書いていきたいなと思いました。

次回の開催も楽しみにしています!