読者です 読者をやめる 読者になる 読者になる

形態素解析器 kagome を Google App Engine で動かす

概要

kagome を GAE で動かしたいってのをチラホラ耳にしてたのですが,先日ついに issue が投げられたので対応してみました. 正確には UniDic をあきらめて IPADic だけ対応してる kagome.ipadic で動かせることを確認しました.

何が問題なのか?

golang のプログラムを GAE で動かすには以下の2点の制限があります.

  • GAE では unsafe, syscall, cgo を使ってると動かせない
  • GAE では1ファイル32MBのサイズ制限がある

kagome を最初に作ったときは辞書を有限状態トランスデューサー(fst)で構築してて,どうしてもこいつが unsafe 使う実装になってたので対応あきらめてたんですが,なんかの時に辞書を double array trie になおして,辞書からは殆ど unsafe をなくしていたので,今回は1カ所直しただけでいけました. unsafe 使わなくてもパフォーマンスもそれほど変わるわけではないみたい・・・なのは意外でした(もちろん使った方が速いけど

これで対応できたかなと思ったんですけど,GAE には1ファイル32MBのサイズ制限があってそもそもGAEにデプロイ出来ないと教えてもらい (kaneshinさんありがとうございます),kagome から UniDic を削除した kagome.ipadic の方で対応する方針に切り替えました.

kagome.ipadic は blevesearch で「辞書重すぎで go get できんぞな」という声があって用意してたやつなんですけど,こちらに kagome の差分をバックポートして unsafe を取り除く対応しました.

github.com

ではGAE で動かしてみよう

アカウント作成

そもそも GAE の環境がなかったので,アカウント作るところからはじめました. 登録にクレカが必要ですが,試用期間があるのと試用期間後に勝手に課金しないというのを信じて登録.

cloud.google.com

SDK のダウンロード/設定

GAE/Go 用の SDK をダウンロードして設定します.

Download the App Engine SDK for Go  |  App Engine standard environment for Go  |  Google Cloud Platform

★ 注: macOS serria だと SDK がうまく動きません.VM 用意するか,Docker でやるかする必要があります.

qiita.com

プログラム作成

色々やり方あると思いますが,手っ取り早く $GOPATH/src 以下に myapp というフォルダ作って,そこに app.yaml と hello/hello.go を設定します. これはサンプルで用意されてるプログラムで kagome を呼ぶようにしただけの動作確認用のものです.

application: kagome-test
version: 1
runtime: go
api_version: go1
handlers:
- url: /.*
  script: _go_app
package hello

import (
        "fmt"
        "net/http"
        "strings"

        "github.com/ikawaha/kagome.ipadic/tokenizer"
)

var dic tokenizer.Dic

func init() {
        http.HandleFunc("/", handler)
        dic = tokenizer.SysDic()
}

func handler(w http.ResponseWriter, r *http.Request) {
        t := tokenizer.NewWithDic(dic)
        tokens := t.Tokenize("寿司が食べたい。")
        for _, token := range tokens {
                if token.Class == tokenizer.DUMMY {
                        fmt.Fprintf(w, "%s\n", token.Surface)
                        continue
                }
                features := strings.Join(token.Features(), ",")
                fmt.Fprintf(w, "%s\t%v\n", token.Surface, features)
        }
        fmt.Fprint(w, "Hello, world!")
}

まずはローカルで動かす

$ goapp serve myapp

localhost:8080 にアクセスすると動作を確認できるはずです.

デプロイ

GAE でデプロイするために先にプロジェクトを作成して,プロジェクトIDをひかえおいて,デプロイコマンドに渡してやります.

$ goapp deploy -application <プロジェクトID> myapp

ところがどっこい動かない

デプロイしたサービスにアクセスすると....

原因はインスタンスが非力すぎること.

qiita.com

application: kagome-test
version: 1
runtime: go
api_version: go1
instance_class: B8
basic_scaling:
  max_instances: 1
  idle_timeout: 1m
handlers:
- url: /.*
  script: _go_app

とりあえず B8 なら動く,動くぞ.(B4 あれば動きました

GAE で動かすモチベーションって何なの?

今回 GCPUG の slack で kagome を GAE で動かすためのアドバイスいただいたんですが,何人かの人が過去に kagome を GAE で動かしてみようとしてくれたことを教えてくれました.そのモチベーションは何か?GAE で形態素解析するといい感じなのか?と色々想像したんですが,一番のモチベーションは「動かせるか試してみたかった」のようでした.そうですよねー.わかりますorz

ということで,長いこと引っかかってた kagome を GAE で動かすアチーブメントを開放できました :p