マルチテナントWebアプリの作成について

SaaS事業を提供する会社で働いているとマルチテナント構成について色々悩む事があるんだけど、データの分離、アプリサーバ・DBの利用効率を考えると、こんな構成が取りたい。

  • appサーバは全アカウント共通で使いたい
  • DBは小さいアカウントについてはできるだけ1台に詰め込みたい
  • 大きいアカウントについては少数のアカウントだけを入れたり、1アカウントだけで専有させたい

要するに、この中のF. シャード マルチテナント データベースを利用したマルチテナント アプリっぽい構成が良いなと思う。

docs.microsoft.com

こういう構成取る時に悩ましいのが、高度に抽象化されたORM、Web Application Frameworkとの相性が悪い事。だいたい複数DB構成には対応していないので、通常隠蔽されているコネクションを操作するコードを書くか、そのための拡張ライブラリを使う必要がある。Railsだとapartmentとかがそれに当たる。

github.com

でも最近はここ数年の個人的なRails疲れもあってバックエンドは別にファットなWeb Application Frameworkを使わなくても良いかなという気がしてきていて、例えばGoでAPIサーバを書くんだったら、コネクションを隠蔽したORMを使わないでこんなんでも良いのかなと。

github.com

ほとんどGo書いた事ないので色々突っ込みどころはあると思うんだけど、だいたいこんな感じ。

  • MySQLだったらアカウント毎にデータベースを作成して分離
  • 各アカウント向けの接続情報を共通DBに格納
  • ドメインとかpath情報にアカウント識別子を含めて、Routerのmiddlewareで共通DBから接続情報を取得、コネクションを設定
  • middlewareで設定されたコネクションを使ってリクエストの処理を実行

ただのウェッブ系エンジニアが言語処理100本ノックをPythonで解いてみた

先月、先々月あたりに、空き時間に少しずつ言語処理100本ノックを解いてみた。

github.com

基本的には全部Python3.6.0(Anaconda 4.3.0)で動作を確認している。

Pythonについての感想

普段Rubyに慣れてるせいで、以下のようなところは面倒に感じる。

  • map, sort, filterなどをメソッドチェーンで繋いでいけないのが面倒
  • ラムダ式に単一の式しか書けないのは面倒(ネストしていけば何でもできそうではあるけど…)
  • selfの意義について熱く語られるかもしれないがにわかにとっては面倒
  • if が文なのが面倒

まあ慣れれば普通に使える。リスト内包表記はやたら使いたくなる。

問題を解いていっての感想

1章~3章あたり

単純な文字列処理に関しては、PythonよりRubyのほうが慣れてるのでRubyで書きたくなる感じだった。 ウェッブエンジニアなので正規表現は苦手ではないけれど、MediaWikiの処理は少々面倒で、全部合ってる保証はない。ちゃんとやるならparser書くべきなんだろうか。

4章~6章

ようやく言語処理らしくなってきた。分からない時は他の人がどうやってるかカンニングしたりしながら。 6章はstemmingモジュールを使うと良いと書いてあったけどnltkのLancasterStemmerを使用した。 CoreNLPの出力形式や問題の用語について色々調べながら解いていく必要がありまあまあ大変だった。

7章

普段の仕事とそんなに変わらないのでまあ適当に。webアプリはgui書くの面倒なのでjsonで。

8章~10章

機械学習、ベクトル空間法について。 とにかく欲しいものはだいたいPythonで使える実装が存在するため、そりゃあみんなPython使うよなーというのを感じた。 10章は8章の単語ベクトルでやるのが時間かかりすぎて面倒になりword2vecの方だけで済ませてしまった。

全体の感想

順番にステップアップしていくことができていい問題集だったなと思いました。まあ研究やデータ分析の業務が務まるような知識も能力もないし、今の自分の仕事では言語処理も機械学習も特に使うことは無いんだけど、そのうち多少関係のある商品の担当に変わる可能性があるのでその時役に立てばと思います。

Flask使ってみる

はじめに

機械学習とかで遊ぶためにPython触っとくかと思うけど、とりあえずWebエンジニアなのでWebから触ってみる。普段の仕事はRailsとExpressだけどRailsみたいなフルスタックで重厚なWebアプリケーションフレームワークよりもExpressのような軽量なやつの方が好みに合うので、まずはFlaskを触ってみる。

Flaskインストールまで

ドキュメント見ながらインストールまで流す。fish使ってるのでactivate.fishを読み込んでるけど自分の環境に合ったやつを読み込む。

$ mkdir flask-prj
$ cd flask-prj
$ virtualenv venv
$ . venv/bin/activate.fish
$ pip install Flask

hello world

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

ルーティングはデコレータで指定する。

実行

$ env FLASK_APP=hello.py flask run
 * Serving Flask app "hello"
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

確認

$ curl http://localhost:5000/
Hello, World!

テンプレート

Jinja2というテンプレートエンジンが使える。文法はTwigとよく似たもの、っていうかTwigがJinjaを参考にして作ってるみたいなのでなんとなく使えそう。

@app.route('/template')
def template():
    return render_template('template.html', key1='val1', key2='val2')
<html>
    <body>
        <p>{{key1}}</p>
        <p>{{key2}}</p>
    </body>
</html>

確認

$ curl http://localhost:5000/template
<html>
    <body>
        <p>val1</p>
        <p>val2</p>
    </body>
</html>

JSON

最近の自分の仕事だと実際のところhtml返すよりjson返すほうが多いのでjsonの扱い方を見ておく。jsonはjsonifyを使って出力できる。

@app.route('/json')
def json():
    return jsonify(key1='val1', key2='val2')

確認

curl http://localhost:5000/json
{
  "key1": "val1",
  "key2": "val2"
}

マルチバイト文字

何も設定せずにjsonifyで出力すると、マルチバイト文字が文字コードで表示されてしまう。

@app.route('/json-multibytes')
def jsonmb():
    return jsonify(key1='日本語')

確認1

$ curl http://localhost:5000/json-multibytes
{
  "key1": "\u65e5\u672c\u8a9e"
}

対策

以下の設定を追加する。

app.config['JSON_AS_ASCII'] = False

確認2

$ curl http://localhost:5000/json-multibytes
{
  "key1": "日本語"
}

家二郎 in 熊谷 Final

はじめに

第3回の工程を書き忘れていたんだけど、第4回の家二郎を開催した。残念ながら今回を最後に熊谷の家を引き払ってしまうため、今回が熊谷で行われた最後の家二郎である。

家二郎と言いつつ、第3回で豚骨ベースのスープは一旦完成ということにしておいて、今回は鶏白湯スープの新たな方向を開拓することにした。

参加人数

4名

開催日

2015/09/21

食材

スープ

  • 鶏ガラ: 1100gほど(肉のハナマサどっきり市場池袋西口店で買えた最小の量)
  • もみじ: 1000gほど(肉のハナマサどっきり市場池袋西口店で買えた最小の量)
  • ネギの青い部分: 1本分
  • たまねぎ: 大1個
  • にんじん: 大1本
  • にんにく: 3片ぐらい

かえし

  • 醤油: 300ml
  • みりん: 100ml

チャーシュー

  • 鶏もも肉: 2枚

いつもと同じ配合

野菜

  • 白ネギ: 1本(白髪ネギのラー油和えに使用)
  • 水菜: 適量(多め)

調理工程

スープ

  1. 鶏ガラ、もみじを下茹でする。旨味が逃げてしまわないように、熱湯でさっと茹でる程度。下茹でのお湯は捨てる。
  2. 下茹でした鶏ガラ、もみじを流水で洗う。この時、鶏ガラのアバラの内側に付いている黒い肉などは臭みの原因になりそうな気がしたので丁寧に外した。
  3. 鍋に鶏ガラ、もみじ、乱切りにした野菜、凧糸で巻いた鶏肉を入れ、鍋いっぱいまで水を入れて煮る。底が焦げ付かないように時々混ぜる。今回は容量約6.8lの寸胴鍋を使用。最初は暫くの間アクが出てくるので丁寧に取る。
  4. 鶏肉は煮過ぎるとパサパサになるので火が通ったところで鍋から上げる。竹串や爪楊枝で突いて、透明な汁が出てくればOK。
  5. 煮込んでいる間に水が減ってくるので適宜追加する。
  6. 煮込み時間3時間ぐらいで十分スープが出たようなので、ざるを使ってスープを濾す。今回これだけの材料で4人分のスープというかなり贅沢な取り方をしたけど、もっと量は取れると思う。

チャーシュー

  1. 醤油、みりんを鍋で沸騰させ、火を止める。
  2. タッパーに移し、鶏肉を漬け込む。適当な時間で上下を入れ替える。
  3. 辛くなり過ぎないように1時間ほど漬け込んだら取り出す。

前回までと同様。

白髪ネギのラー油和え

  1. ネギを千切りにして白髪ネギを作る。
  2. 白髪ネギとラー油、塩少々、砂糖少々を和える。豆板醤があれば少し加えると旨いと思う。ちなみにチャーシューの量に余裕があれば、これとネギの芯の部分の小口切りとチャーシューとタレを和えて食うとうまいんじゃないかと思う。

仕上げ

  1. スープをコンロで保温しておく。
  2. チャーシューを切っておく。
  3. 麺を茹でる。今回は少し麺が硬かったようで、茹で時間を長めにした。
  4. 茹で上がる前に、丼にかえし、スープを入れる。
  5. 茹で上がった麺を湯切りし、丼に入れる。箸でスープとなじませる。
  6. 麺の上にチャーシュー、水菜山盛り、白髪ネギを盛り付ける。
  7. 食す。

総評

今回の仕上がりがこちら。

f:id:tarhashi:20150921204156j:plain

今回、鶏白湯スープに初めて挑戦したが、かなり旨いスープが取れた。多分最初の鶏ガラの下処理をちゃんとやるのと、アク取りをきちんとやるのが重要なのかな?と思う。

麺はいつもの二郎風の麺を使ったけど、今回のスープとの相性を考えれば普通〜中太麺ぐらいがちょうどいいんじゃないかと思う。また、麺は材料の配分は同じなのに毎回生地の仕上がりがかなり異なり、難易度の高さを感じる。

チャーシューは肉を鶏肉に変えていつもの漬け込みチャーシューにしたけど、オーブンで焼くチャーシューの方が醤油が焦げた香りとスープの相性が良いような気がする。

それから、スープの味付けはいつもの醤油だれを使って味はこれでも十分良かったけど、見た目的な意味合いも含めて塩ダレを作ったほうが良いかな?という感じもある。

色々改善点を書いたけど、スープの味が抜群に良かったので今回のラーメンがこれまでで一番旨かった。次回以降開催できるのかどうかがまだわからないが、もし開催できるなら更なる高みを目指したい。

家二郎2回目の報告

はじめに

前回に引き続き、2回目の家二郎を開催することとなった。2回目の工程を書き残す。

参加人数

6名

開催日

2015/05/09

食材

スープ

  • ゲンコツ: 2本 ※前日に肉のハナマサにて入手。
  • 豚脂: 約500g ※同上
  • 鶏ガラ: 1羽分
  • 豚肩ロース塊: 約400g
  • 豚バラ肉塊: 約300g
  • ネギの青い部分: 1本分
  • 生姜: 1パック 乱切りにしておく
  • にんにく: 3片 皮をむいて半分ぐらいに切っておく

かえし

  • 醤油: 300ml
  • みりん: 100ml

  • 強力粉: 7200g
  • 重曹: 7g程度
  • 塩: 7g程度
  • 水: 300ml程度

野菜

  • キャベツ: 一玉 ※少し残った
  • もやし: 2袋
  • にんにく: 3片

調理工程

スープ

  1. ゲンコツ2本を下茹で。今回は15分とした。14分ぐらいで鶏ガラも湯に投入してさっと下茹で。下茹でを行ったら湯を捨てて流水で血の塊を洗い流す。
  2. ゲンコツ1本分、豚肉、豚脂を圧力鍋に入れてひたひたになる程度まで水を加え、30分加圧。30分経過後火を止めて30分放置。
  3. 圧力調理の終わった鍋から豚脂、豚肉を取り出す。今回は容量約6.8lの寸胴鍋があったため、圧力鍋の中身を寸胴に移し、ゲンコツ残り1本、鶏ガラ、ネギ、生姜、にんにくを加え、水を容量限界まで入れてアクを取りつつひたすら煮込む。スープが減ってくるので水分を適宜追加。

チャーシュー

前回と同様。

  1. 醤油、みりんを鍋で沸騰させ、火を止める。
  2. タッパーに移し、圧力調理の終わった豚肉を漬け込む。豚肉全体が漬からないため、30分程度毎に上下を入れ替える。
  3. 辛くなり過ぎないように2時間ほど漬け込んだら取り出す。

1人分増えた以外は前回と同様。

  1. 重曹、塩を水に溶かす。
  2. 強力粉に混ぜながら少しずつ加え、全体に行き渡らせる。
  3. 一つにまとまるように捏ねる。
  4. ジップロックに入れてそれを更にビニール袋に入れ、足で踏んで捏ねる。
  5. 捏ねる工程が終わったら、一つにまとめてラップをして1時間程度生地を休ませる。
  6. 生地を6分割して、麺棒で薄くのばし、包丁で細く切っていく。

仕上げ

  1. 鍋に取っておいた豚脂を一度火にかけて溶かしておく。
  2. スープをカセットコンロで保温しておく。
  3. チャーシューを切っておく。
  4. にんにくをみじん切りにしておく。
  5. 麺を茹でる。今回は各自が好きな太さに仕上げ、茹で時間も各自の好みに任せた。
  6. 麺と同時に、別の鍋でキャベツ、もやしを茹でる。キャベツ2分、もやし10秒程度。
  7. 茹で上がる前に、丼にかえし、スープ、豚脂を入れる。
  8. 茹で上がった麺を湯切りし、丼に入れる。箸でスープとなじませる。
  9. 麺の上に野菜、にんにく、チャーシューを盛り付ける。好みにより豚脂、かえしを上からかける。
  10. 食す。

総評

前回の仕上がりがそれなりに良かったため、基本的な工程は前回のものを踏襲した。前回からのアップデートとしては、スープに鶏ガラを加えた事が大きな違いである。鶏ガラを加える事により旨味が格段に向上し、これは完全に成功であった。また、寸胴鍋の導入によりスープの煮込みがやりやすくなったのも良かった。

麺については失敗ではないものの難易度の高さを感じた。前回と材料の比率はほぼ変わらないのに茹でた時の膨らみ具合等が全く異なり、戸惑いを覚えた。気温や湿度によって種のコンディションが変わっていたのだろうか。

全体的には第2回の仕上がりはなかなかのものだったと思うが、第3回をやるとしたら次はどういう路線に進むべきだろうか。第2回の工程を元に細部を突き詰めるか、それとも少し独自色を出すために工程を更に変えるか。まあいずれにしても自宅じゃなくて他の人の家でやりたい。

以上。

初家二郎の記録

はじめに

先日、転勤により友人が関西から関東へ引っ越してきた。その彼だが1人で1LDKの部屋に住むといううらやまけしからん住環境を確保しており、この広さを活かして家二郎を開催する運びとなった。今回の工程を次回以降のために書き残す。

参加人数

5名

開催日

2015/03/07 11:00〜22:00頃

食材

スープ

  • ゲンコツ: 2本 ※前日に肉のハナマサにて入手。
  • 豚脂: 約500g ※同上
  • 豚肩?塊: 約300g
  • 豚バラ肉塊: 約300g
  • ネギの青い部分: 1本分
  • 生姜: 1パック

かえし

  • 醤油: 300ml
  • みりん: 100ml

  • 強力粉: 600g
  • 重曹: 6g
  • 塩: 6g
  • 水: 250〜270ml程度

野菜

  • キャベツ: 一玉 ※少し残った
  • もやし: 3袋 ※少し残った
  • にんにく: 3片

調理工程

スープ

  1. ゲンコツ2本を下茹で。今回は15分とした。下茹でを行ったら湯を捨てて流水で血の塊を洗い流す。
  2. ゲンコツ1本分、豚肉、豚脂を圧力鍋に入れてひたひたになる程度まで水を加え、30分加圧。30分経過後火を止めて30分放置。圧力をかけることに関しては邪道であるという声もあるかもしれないが、今回は時短のため使用した。
  3. 圧力調理の終わった鍋から豚脂、豚肉を取り出す。ゲンコツ残り1本分、ネギ、生姜を加え、水を鍋いっぱいまで追加して時間の許す限りひたすら煮込む。ゲンコツからは8時間ほどはだしが出続けるそうなのでできればそれぐらい煮込むと良いのであろう。野菜に関しては2時間程度で取り出す。また途中水分が少なくなってきたため、何度か追加した。なお今回の鍋の容量は3.7リットル、煮込み時間は4〜5時間程度であったと思う。

チャーシュー

  1. 醤油、みりんを鍋で沸騰させ、火を止める。
  2. タッパーに移し、圧力調理の終わった豚肉を漬け込む。豚肉全体が漬からないため、30分程度毎に上下を入れ替える。
  3. 辛くなり過ぎないように2時間ほど漬け込んだら取り出す。

  1. 重曹、塩を水に溶かす。
  2. 強力粉に混ぜながら少しずつ加え、全体に行き渡らせる。
  3. 一つにまとまるように捏ねる。
  4. ジップロックに入れてそれを更にビニール袋に入れ、足で踏んで捏ねる。
  5. 捏ねる工程が終わったら、一つにまとめてラップをして1時間程度生地を休ませる。
  6. 生地を5分割して、麺棒で薄くのばし、包丁で細く切っていく。極力細く切るつもりでいいが、二郎的な極太麺に仕上げるためにはある程度太く切ってもいいようだ。

仕上げ

  1. 鍋に取っておいた豚脂を一度火にかけて溶かしておく。
  2. スープをカセットコンロで保温しておく。
  3. チャーシューを切っておく。
  4. にんにくをみじん切りにしておく。
  5. 麺を茹でる。今回の麺は4分程度がちょうど良かったようだ。時間は好み、麺により適宜調整する。
  6. 麺と同時に、別の鍋でキャベツ、もやしを茹でる。キャベツ2分、もやし10秒程度。
  7. 茹で上がる前に、丼にかえし、スープ、豚脂を入れる。
  8. 茹で上がった麺を湯切りし、丼に入れる。箸でスープとなじませる。
  9. 麺の上に野菜、にんにく、チャーシューを盛り付ける。コールがアブラ、カラメの場合、豚脂、かえしを上からかける。
  10. 食す。

総評

  • はじめての挑戦であり、とても食べられないものにならないかと心配であったが、十分旨かった。
  • 味の素を用意していたが使わなかった。二郎的なジャンク感を出すためには加えたほうが良かったかもしれないが、単体の仕上がりとしては加えなくても十分だった。
  • ラーメンとしての旨さを追求するには鶏ガラも加えたほうが良かったかもしれない。
  • 当初から予想されていたが3.7リットルの圧力鍋では容量不足だった。提供中にややスープが足りない感があり、少し水を追加することになった。やはり最低でも6〜10リットル程度の寸胴鍋が欲しい。
  • 麺も及第点だがまだ課題が残る仕上がりだった。麺打ちについては更なる研究が必要。
  • 麺の手打ちに必要なスペースを十分確保することができなかった。自分で打ってみることにより麺打ち職人があれだけ広いスペースを使っている理由がわかった。
  • 5人で強力粉600gは少し多いかと思ったが、食べてみれば問題なかった。
  • 今回は肉のハナマサどっきり市場池袋西口店にてゲンコツの調達を行った。肉のハナマサ池袋店にも行ったが、購入単位が5人分に対して大きすぎたため適さなかった。

以上。

Faradayでawsの認証ヘッダを付けるミドルウェア書いた

rubyでs3からファイルをダウンロードするときはAWS SDK for ruby使えば簡単にできるんだけど、既にFaradayで取得処理が構築されてる部分でS3にも対応させたいところが出てきたのでAWSの認証ヘッダを付けるためのミドルウェアを書いてみた。

tarhashi/faraday_middleware_aws_auth

酒飲みながら作成しててまだ対応してない部分があったり、本物のS3にはまだ接続を試してなくてRiak CSでしか動作確認してなかったりだけど一応単純なgetだけはできた。

使うときはこんな感じで使う。

conn = Faraday::Connection.new(:url => 'http://host_name') do |builder|
  builder.use Faraday::Request::AwsAuthorization, {:access_key_id => "your_access_key_id", :secret_access_key => "your_secret_access_key"}

  builder.response :logger
  builder.adapter Faraday.default_adapter
end

response = conn.get "/foo/bar"
puts response.body