2019年6月の記事一覧

いよいよRaksul Hack Weekが始まります!

こんにちは。エンジニアマネージャーの石川です。普段は、印刷ECサイトで提供している集客支援(ダイレクトメール、新聞折込、ポスティング等)の開発に携わってます。

前回、ハコベルの加藤よりHack Weekの紹介をさせていただきましたが、いよいよHack Week #2の開催が来週となりました。

Hack Weekは、エンジニア、デザイナ、PM、普段ラクスルの事業を支えているTECHチームが参加するハッカソンイベントです。自分たちでアイディアを出し合い、1週間かけて開発を行います。

本日は、前回の記事以降に行われたチームビルディングイベントの様子をご紹介したいと思います!

チームビルディングイベントを開催しました

Hack Week開催まで3週間を切った5/22、Hack Week pre-eventと称して、チームビルディングを目的としたイベントを開催しました。

前回の記事では、 Hack Week Lunch を実施の様子をご紹介しましたが、今回はチームビルディングイベントということもあり、美味しい食事とお酒を楽しみながら、自由な雰囲気でコミュニケーションを取りやすいイベントを目指しました。

まずはIceBreak

Hack Weekでは、普段は違うチームで開発をしているメンバーと一緒に開発ができる良いチャンスでもあります。

今回のイベントでは、普段のチーム以外のメンバーともぜひ交流を深めてほしい。

そこで、冒頭の時間をIceBreakタイムとして簡単なゲームを実施しました。

まずは隣にいる人と話すきっかけを持ってもらうこと、声を出して話して見ることで、緊張をほぐしてもらうことが目的です。

2人ペアを組んでもらい、簡単なゲームを通して15分ほど会話を楽しんでもらいました。

会場の雰囲気も和んできたところで…ラクスルビールで乾杯をしてイベントスタートです!

チームビルディングタイム

「こういう面白いことやろうと思ってるんだけど、フロントやってくれませんか?」

と、熱いプレゼンをするメンバー

「まだ何をやるか決めてないんですが、何やるか決めました?」

と、すこし不安な思いを抱えながらの参加となったメンバー

それぞれの想いが入り混じりながら、チームビルディングタイムがスタートしました。

それぞれの想いを胸に、イベントスタートです!

最初はみんな手探りでしたが、それぞれが持ち寄ったアイディアを語り合いながら食事とお酒を楽しみ、それぞれのテーブルで様々な議論が交わされました。

身振り手振りを交えて熱い議論を交わします。

チームビルディングイベントの結果は?

イベント開催をきっかけに、16のチームが結成されました!

チームビルディングイベント中に結成されたチームも合ったようですが、イベントの翌日以降に改めて話して結成したチームも多く見られたようです。

チームビルディングイベントに参加してみて

私自身も、ラクスルに入社して4ヶ月。

社内にまだまだ知り合いが少ないので少し不安な気持ちでの参加でしたが、自己紹介から始まり、お互いの事業の紹介をしたり、温めていたアイディアの話をしたり、Hack Weekに対する不安が解消され「いよいよ始まるんだな!」と期待が膨らむイベントになりました。

いよいよRaksul Hack Weekが始まります!

いよいよ来週からRaksul Hack Weekが始まります。

それぞれの16チームのテーマも出揃いました。

テーマは、普段関わっている事業に関するもの、最新の技術を使ったもの、様々です。

次回は、Hack Week開催後に結果をお届けしようと思います。

ラクスルではエンジニアを引き続き募集しております!

ラクスルでは、一緒に事業を盛り上げてくれる仲間を引き続き募集しております。

エンジニア一人一人が事業に対して高い解像度を持ち、事業に関わることができる。全職種一丸となって事業を成長させていける、そんな職場です。

ただ開発をするだけではなく、事業を一緒に創っていきたい方、ぜひ弊社オフィスに遊びにきてください!

 

 

gRPC Client Interceptor入門 with Ruby

こんにちは。サーバサイドエンジニアの三瓶です。印刷ECサイトの ラクスル の開発保守を担当するチームに所属しています。

ラクスルでは Raksul Platform Project (RPP) と称して技術負債の返済活動を継続的に行っているのですが、その流れの一環として印刷ECチームでは巨大化したアプリケーションから商品仕様に関わる部分を別サービスとして切り出す、という作業を最近行いました。

この切り出したサービスでは通信方式として gRPC を、言語としてはRubyを採用しています。

実際に導入してみて、gRPCはまだドキュメントも多くはないと感じたので、本記事ではgRPCが備える機能の1つである Interceptor についてチュートリアル形式でご紹介したいと思います。言語はもちろんRubyを使います。

※ gRPC導入に至った背景や経緯について興味のある方は弊社エンジニアの二串のスライドをご参照ください

Interceptorとは何か

Interceptorとは、RPCコールの前後に任意の処理を差し込める機能・レイヤーのことです。Railsアプリケーションに馴染みがある方は Rack Middleware のようなものを想像してもらうと理解しやすいかと思います。

Interceptorを使えば、認証やロギング、データのフィルタリングなど各通信で共通の処理をひとまとめにできます。
実際に、我々のプロジェクトではリクエストを一意に特定するためのIDをmetadataに付与するInterceptorやリクエストしたメソッド・パラメータ・処理時間をログに残すInterceptor、例外をCatchしてSentryに通知するInterceptor等を自作して、本番環境で稼働しています。

以下はClient → Server間の通信に2つのInterceptorが介在したときのイメージ図です。

作成するClient Interceptorの仕様を決める

ClientのInterceptorと一口に言っても、以下のパターンが考えられます。

  • リクエスト処理の「前」に差し込む。リクエストデータに何か手を入れたい場合など
  • リクエスト処理の「後」に差し込む。レスポンスデータに何か手を入れたい場合など
  • リクエスト処理の「前後」に差し込む。両方に手を入れたい場合や処理全体に何かをしたい場合など

このうち、今回はリクエストの「前」に差し込んでリクエストデータを大文字化する UpcaseInterceptor と、リクエストの「前後」に差し込んで処理時間を計測する PerformanceLoggingInterceptor の2つを作ってみることにします。

以下、それぞれのインターセプターの簡単な仕様です。

  • UpcaseInterceptor
    • リクエストの前に差し込む
    • リクエストオブジェクトに name というキー名のデータあればその値を大文字化する
  • PerformanceLoggingInterceptor
    • リクエストの前後に差し込む
    • リクエスト全体にかかった時間を計測し、標準出力へ出力する
    • 時間は小数点第3位以下を四捨五入する

また、動作の流れは次の図のようになります。赤い線の箇所でインターセプターの処理を挟みこむイメージです。

Client Interceptorを実装する

※ 注意:gRPCのRuby実装では、IntercptorのAPIインターフェースは EXPERIMENTAL という扱いのようです。そのため、今後のバージョンアップで今回紹介するものとはAPIインターフェースが変わっている、ということがありえますのでお気をつけください。

Interceptorを実装するのはとても簡単で、今回の仕様であれば数行で作れてしまいます。

UpcaseInterceptor

UpcaseInterceptorの実装は次のようになりました。

# upcase_interceptor.rb
class UpcaseInterceptor < GRPC::ClientInterceptor
  def request_response(request: nil, call: nil, method: nil, metadata: nil)
    request.name = request.name.upcase
    yield
  end
end

いくつかポイントとなる部分を説明します。

(1) GRPC::ClientInterceptor を継承する

インターセプタークラスは GRPC::ClientInterceptor クラスを継承する必要があります。
継承しない場合、GRPC::InterceptorRegistry::DescendantError 例外が発生します。

(2) 通信方式に合わせてメソッドをオーバーライドする

メソッドは利用する通信方式に合わせてオーバーライドします。gRPCには以下4つの通信方式があり、それぞれに対応するメソッドがあります。

  • Unary RPC : #request_response
  • Server streaming RPC : #server_streamer
  • Client streaming RPC : #client_streamer
  • Bidirectional streaming RPC : #bidi_streamer

今回は、1リクエストに対して1レスポンスが返ってくる一番シンプルな通信方式であるUnary RPCを使うため、request_response メソッドをオーバーライドしています。

※ 各通信方式の詳細が気になる方は https://grpc.io/docs/guides/concepts/ をご参照ください

(3) yieldで次の処理を呼び出す

次にメソッドの中ですが、yield を呼び出すことで次のインターセプターまたはリクエスト処理の本体を呼び出すことになります。
UpcaseInterceptorはリクエスト実行の前に呼び出したいので、yield をコールする前に変換処理をしています。

PerformanceLoggingInterceptor

同様に、処理時間を計測して出力するPerformanceLoggingInterceptorは次のようになりました。

# performance_logging_interceptor.rb
class PerformanceLoggingInterceptor < GRPC::ClientInterceptor
  def request_response(request: nil, call: nil, method: nil, metadata: nil)
    start_time = Time.now.to_f
    resp = yield
    request_time = Time.now.to_f - start_time

    puts "duration: #{request_time.round(3)} sec"
    resp
  end
end

PerformanceLoggingInterceptorはリクエスト処理の全体を計測したいため、リクエストの前後に処理を差し込みます。
前述のとおり、リクエスト処理は yield を呼び出すことで伝播されていくため、その前後を囲う形で時間を取れば良いということになります。

返り値は yield で受け取ったレスポンスオブジェクトをそのまま返します。

Interceptorを使う

それでは、作成した2つのInterceptorを実際に使ってみましょう。
gRPC公式のチュートリアル Ruby Quick Start にあるHelloWorldアプリケーションに、今回作成したインターセプターを組み込んで動かしてみます。

Client Interceptorは、Stub と呼ばれるクライアントオブジェクトを初期化するときに引数として渡します。

# greeter_client.rb
require 'grpc'
require 'helloworld_services_pb'

# ★ 作成したインターセプターをrequireする
require_relative './performance_logging_interceptor'
require_relative './upcase_interceptor'

def main
  stub = Helloworld::Greeter::Stub.new(
    'localhost:50051',
    :this_channel_is_insecure,
    interceptors: [UpcaseInterceptor.new, PerformanceLoggingInterceptor.new] # ★ ここでインターセプターを設定する
  )

  # 省略..
end

main

interceptors 引数に渡す順序でインターセプターの実行順序が決まります。
配列の末尾から先頭へと順に実行されるため、上の書き方の場合、PerformanceLoggingInterceptorUpcaseInterceptor の順で実行されることになります。当初のイメージ図の通りの順序ですね。

それでは実行してみましょう。
まず、比較対象としてインターセプターを使わなかった場合の結果を見てみます。

$ bundle exec ruby greeter_client.rb
"Greeting: Hello world"

チュートリアルの通りであれば、上のように “Greeting: Hello world” という結果が出力されると思います。

次にインターセプターを有効化した状態で実行してみます。

$ bundle exec ruby greeter_client.rb
duration: 0.002 sec
"Greeting: Hello WORLD"

UpcaseInterceptor によって “world” が大文字化されて、PerfomanceLoggingInterceptor によって実行にかかった時間が出力されました!

まとめ

以上、簡単ではありますが、RubyでのgRPC Client Interceptorの仕組みや使い方についてのご紹介でした。

アプリケーションを本格的に運用するにつれて様々な要求が発生してくるかと思いますが、Interceptorが役に立つ・解決手段となるケースもあるのではないかと思います。そのようなときにこの記事が参考になれば幸いです。