gRPCについて調査

gRPCとか使って、マイクロサービスを構築したかった。 調査メモ。

grpc /

grpc /

ruby と go のtutorial やって、ruby のクライアント側と、goのサーバー側立てて連絡させてみた。 tutorial 通りやれば簡単だった。

要は、同じ.protoファイルを元に、それぞれの言語毎にクラス(rubyだったら)生成して、それを普通に使えば良いって感じだった。 調べてたらめっちゃ難しそうだったけど、やってみると簡単だった。

最終的には、Railsをクライアント側にしたいので、Railsに入れてみようとしたが、libフォルダに、protoファイルから作ったクラスをおいて、必要なところでそのクラスを呼べば良いだけだった。

で、Go部分は普通にAPI作るイメージで、チュートリアル通りやればできた。

今後の流れとしては、 1. Goを触ったことないので、勉強して、GoでgRPCサーバ作る 2. Envoy を用いて、ルーティングをいい感じにできるようにする。 3. ECSにあげてみる ところまではとりあえず頑張りたい。

最初は、gRPC gateway が必要なのかなって思ってたけど、BFF構成だと、rubyはgRPC読めるし必要なさそう。

Next + Rails の開発構成考えてみた

考えたきっかけ

新規サービス作るにあたって、構成考えてみた。
将来的にはアプリ化するということで、それを見越して、API + SPA の形にしてみた。 下の画像のイメージ。 正直、静的ファイルはCDNに置いた方がよくない?って感じだけど、Dockerの勉強も兼ねて。

f:id:okadak1990:20181212233035p:plain

開発用

version: '2'
services:
  app:
    build: .
    image: rails_dev
    volumes:
      - .:/app
    ports:
      - "3000:3000"

  nginx:
    build: nginx
    image: nginx_dev
    ports:
      - "80:80"
    volumes_from:
      - app
    depends_on:
      - app

  # railsディレクトリの中に、frontendというフォルダ名で、nuxtをぶっこんでる。
  nuxt:
    image: nuxt_dev
    build: frontend
    ports:
      - '4000:4000'
    volumes:
      - ./frontend:/frontend
      - node-modules-data:/frontend/node_modules

volumes:
  node-modules-data:

本番用

version: '2'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile_dev
    image: rails

  nginx:
    build: nginx
    image: nginx
    ports:
      - "80:80"
    volumes_from:
      - app
    depends_on:
      - app

docker-compose 一回で開発環境も、本番環境も起動できるようになった。 dockerすごい...けど、少人数開発ならlocalだけで良いのでは?と思ったりもする。

the twelve factor app をみてみた

どうやったら全体の開発最適できるか考える必要があって、有名とのことだったので読んでみたメモ

 

だが、

とにかく分かりづらいTwelve-Factor Appの解説を試みる

こちらがとても分かり易かった。

 

 

一応まとめたので、メモ

https://12factor.net/ja

 

1. コードベース

  1アプリケーションは、1レポジトリにしよう!

2. 依存関係

  bundler とか使って、ライブラリの依存関係を明示しよう

3. 設定

  デプロイ毎に違う設定は環境変数に入れておこう。

  config/setting.yml とかに入れたら基本ダメっぽい。  

4. バックエンドサービス

  DBとかストレージサービスは、本体のサービスと疎結合であるべき

5. ビルド、リリース、実行

  上記3ステージは、分けられるべき。

6. プロセス

 ステートレスなプロセスとして実行し、メモリやディスクが将来使えるということを仮定しない。

 セッションとか使いたいなら、Redisとかにデータを格納すべき。

7. ポートバインディング

 それぞれのアプリケーションは、WEBに公開できるために、HTTPをサービスとして公開して、ポートにリクエストが来るようにする。

8. 並行性

 スケールアップする際は、複数台立ち上げればOKってすること

9. 廃棄容易性

 簡単にデプロイと、停止できるようにしよう! 

10. 開発 / 本番一致

 開発環境と本番環境のギャップを小さく保とう。

 開発環境でビルド完了 = そのビルドしたもので本番反映できるみたいにする。

11. ログ

 ログは標準出力に吐き出す

12. 管理プロセス

 infracture as code 的な感じ? 

 

今自分が作ってるアプリケーションは、テスト環境、本番環境でどっちもビルドしてるので、さっさとDocker環境に持っていって、Docker build時に、npm build して、コンパイルされたイメージを、クラウドに持って行って、それをそのままスタートするって感じにしたいなー。

となると、build時に、環境によって変数が違う部分をまずなんとかしなきゃいけない...

textareaに、入力した文字に色をつけたい。

jquery.mentionsInput

という機能で現在、実装されているものをVueで書き換えたかった。

何をやりたいかというと、コメント欄にメンション機能をつけて、そのメンションに対して、色付けしたいという要望。

色付けする = HTMLなので、textareaを普通に使っただけでは実装できなくて、めっちゃ辛かった。

 

 

色々調べたところ、最終ゴールとしては、contenteditableを用いて、twitterのようなUIを目指すのが良さそう。

ただ、闇が深そうだったので、一旦下記を参考にして、違う方法で実装した。

 

markus.oberlehner.net

 

textarea層とHTML層の2層作って、textarea層の背景色をtransparentにして、その下に配置したHTML層の色を上手く当てることで、限られた部分だけの色つけを可能にした。できたら、Twitterみたいに文字色も変えたかったけど、限られた部分だけ色付けするっていうのが、結構厄介だったので、一旦断念。

jqueryの方もこの方法を使ってる。

 

正直、満足いくUIにできなかったので、時間ある時、contenteditableを使ってみたいと思う。

レコメンド技術調査

レコメンドの方法には、2種類ある。

コンテンツに基づくフィルタリング

例)とある検索結果をユーザが指定すると、それに近い検索結果ページをレコメンドしてくれる。

基本の考え方としては、

コンテンツ側:コンテンツの特徴量を抽出して、モデル化する。

ユーザー側:コンテンツの特徴量に関する嗜好情報を抽出して、ユーザプロファイルを作成する。

このコンテンツモデルと、ユーザプロファイルを比較して、レコメンドが行われる。

 

コンテンツに基づくフィルタリングは三種類の方式に分けられる。

ルールベース方式

人手で、フィルタリングのルールを設計する方式。

メモリベース方式

コンテンツモデルとユーザプロファイルの両方をベクトル化して、ベクトル空間上での距離で、レコメンドするかを判断する。

モデルベース方式

過去の行動履歴から、興味傾向をモデル化し、ユーザプロファイルする。

学習には時間がかかるが、レコメンド時は高速な処理が可能

 

協調フィルタリング

アイテムの内容を見ず、ユーザがアイテムにどのような評価値をつけたかの情報をみる。対象ユーザと好みの近いユーザを特定して、その近いユーザの好みのものをレコメンドする。

ユーザベース方式(メモリベース)

ユーザ集合とアイテム集合を用意して、それぞれの予測評価値を出して、対象ユーザと全てのユーザ間の類似度を計算する。その類似度の高いユーザが評価をして、かつ対象ユーザが評価をしていないアイテムについて、嗜好の予測値を計算し、その順番でレコメンドしていく。

アイテムベース方式(メモリベース)

二つのアイテムに対して、同じユーザが近い評価値をつけている時、アイテムの類似度は高くなる。あとは、上と同じように、嗜好の予測値を計算し、その順番でレコメンドしていく。

モデルベース方式

ユーザやアイテム間の関係をあらかじめ一般化して、モデル化する。

代表的なのは、クラスタリング手法、ベイジアンネットやあ、EMアルゴリズムなどの確率モデル、マルコフモデルなどの時系列モデルを用いる手法。

クラスタリングをもちいる手法では、ある特徴を有するユーザ集合(あるいはアイテム集合)を事前にクラスタ化して、その特徴を表す代表的なベクトルを生成しておく。

推薦時は、その数個のユーザ集合グループとの類似度を計算するだけで良い。

アルゴリズムには、K-means法や、凝集法などが用いられる。

 

指標

正確さの指標

precision(精度) : 推薦リストの中に、好きなアイテムがどれだけ含まれるか。

recall(再現率) : 好きなアイテムの中に、推薦リストのものがどれだけ含まれるか。

正確さ以外の指標

 coverage:どれだけのアイテムが予測の対象か(誰も評価していないアイテムは強調フィルタリングだと、推薦できない)

novelty(新規性):初めてユーザが見る好みのアイテムがどれだけあるか

serendipity(意外性):ユーザ本人だけでは、予測発見が難しかった意外性のあるアイテムをどれだけ推薦できたか

diversity(多様性):推薦アイテムの類似度がどれだけ低いか

discovery ration(発見性):推薦リストに知らないアイテムがどれだけあるか?

 

課題

内容に基づくフィルタリング

メリット

新しいアイテムも推薦対象に含まれる

 

デメリット

メタデータがないコンテンツには高い推薦を見込めない

意外性の高い推薦を行うことが難しい

 

協調フィルタリング

メリット

コンテンツを解析する必要がない

 

デメリット

sparsity問題:扱うアイテム数に対して、評価をつけたアイテム数が少なすぎると、推薦の質が低くとどまる

first-rater問題:新しいアイテムは誰か一人でも評価しないと、推薦候補に入らない。

 

筆者の構築したシステム例

C-baseMR

モデルベースのコンテンツに基づくフィルタリングシステム

ユーザプロファイルをを評価値データから構築後、ユーザが自由にユーザプロファイルを編集することができるシステム。

これによって、ユーザに自分の嗜好の理解と、音楽特徴の理解が支援できた。

 

参考

嗜好抽出と情報推薦技術 土方嘉徳 2006

http://soc-research.org/ja/wp-content/uploads/2014/08/IFSurvey4IPSJ.pdf

Nuxt Meetup #6 でLTした

他の方が発表されてた内容が参考になったので、メモ

- appolo というGraphQLクライアントライブラリが良いらしい。

- k8s 使ってる人に話聞くと、自分たちに本当に必要なのかって感じだったらしい。

  - Blue Green したいだけなら、Code deploy とかでもできるし

  - 当たり前だけど、何をしたいか考えて、docker使いたいだけなら、ECSでOK。

- vuetify は良い感じらしい。element-ui はレスポンシブできないところがNG。

  - けど、やっぱりカスタマイズの話になってくると、辛くなる。

- Vuex は、global に持ちたいstateを管理する場所であり、Axios とかのAPIは、できるだけコンポーネント内に抑え込めるような設計の方が良さそう。

 

LTしたスライドはこちら

RoomClip の Nuxt.js 移行の話 - Speaker Deck