• このエントリーをはてなブックマークに追加

  • ドワンゴのプロダクト開発インターンシップ(第2クール) を終えて

    2017-10-27 14:532

    ドワンゴ 技術コミュニケーション室の小枝です。

    インターンシップシーズン後半、エンジニア志望の学生さん向けに開いていた「プロダクト開発インターン」の第2クールが終了しました。 (第1クールの様子はこちら

    14cdbc46efadc03291d1e528b293449a9bbab87b

    第2クールの参加者は8名だったため、2人チーム4組に分かれてそれぞれ開発を行い、3チームの機能がfriends.nicoのプロダクトとしてサービスリリースされました。

    各チームの成果

    チームWRP

    このチームの選んだ課題は『ユーザーが自由に絵文字を追加できる』ようにしたいというものでした。

    開発初期は「マイ絵文字」機能として、ユーザーが自由に絵文字を追加できる機能を開発していましたが、開発中に本家マストドンにCustom emojiという機能が追加されてしまいました。

    このままマイ絵文字の開発を続けても将来的に大きな負債になると予想されるため、『ユーザーのプロフィールアイコンを絵文字のフォーマットで表示する書式[:@username:]の追加』という形に企画のピボットを行い、機能名も「ユーザープロフィール絵文字」に変わりました。

    ユーザープロフィール絵文字機能は画像リソースの登録画面がいらず、既存のユーザー名サジェスト機能を流用できたため、少ない工数で実現可能かつシンプルで使いやすい仕様になり、9/28にサービスリリースされました。

    81bb2182c2822fc8676b575b85b23efc0e26394d

    4faf3e203a74d7dd83582187f4100fe5c2dc4abd

    3d17d5f6b7a7190908d65ce74062e508988a1ced

    チームsuits

    このチームはfriends.nicoを始めた際に、「このインスタンスはどんな文化なのか、どう慣れていったら良いのか」がわからないという不満に着目し、アカウント登録時に表示されるチュートリアルを『よりfriends.nicoという文化にフォーカスしたチュートリアル』に変更する ということにチャレンジしました。

    e418e50df627e1592f98e3d297b510100718b5cd

    9e73dfc812208131d68ae733ee28a75abea9149e

    0fe2b23db266dcaf842d735e2f7926c9428deb0a

    29ae475961f76119139b61744a73a9b8f5980b86
    新しいチュートリアルでは、独自機能であるニコるの使用方法やユーザーの初トゥートを促すステップを用意し、ユーザーの能動的なアクションに対する恐怖心を早期に取り除けるよう設計されています。 また重要度の低い機能の説明をあえて省くことによりユーザーの混乱を避け、よりfriends.nicoの魅力を理解しやすいチュートリアルに仕上がりました。 社内デザイナチームの協力も受けて開発は順調に進み、9/27にサービスリリースされました。

    チームUK

    このチームは画面を見ていないときでもマストドンのタイムラインを追いたいという思いから、『マストドンのトゥートを読み上げるデスクトップアプリ(Tootalk)』の作成に挑戦しました。

    前期のPHPチームと同じくElectronのフレームワークを使い、ゼロベースからのアプリ開発を行いました。 Tootalkはマストドンから取得したテキストデータを読み上げ用のフィルターを通して正規化し、WebSpeechAPIを通して発声させる仕組みになっています。

    惜しくもインターン期間中にリリースすることはできませんでしたが、最終週には社内デモができる形までは辿リついていました。

    3a4783ce875822d866bd0a93d9465104dc498bb9

    72085ea8e812da289f4fed79d6c950b4443ee12e

    チームaneula

    このチームは「自分の名前を含んだトゥートや、自分の興味関心がある話題が出た際に見逃さないようにしたい」という想いから、『キーワードハイライティング&Push通知』の機能を開発し、9/29にサービスへリリースされました。

    ユーザーはキーワード管理画面でハイライティング及びPush通知したいキーワード(自分の名前や気になる話題など)を入力します。 ブラウザが登録されたキーワードを含むメッセージ(トゥート)を受信すると、画面上で該当キーワードがオレンジ色にハイライト表示され、Push通知(Web Notifications)が送られます。

    2fbdb9069669078d21753f968bdaef188d19d3a5

    6b01621666059b3c54b79c0244756a5d968f9bd0

    6e473299a453dbbf0554282afdaac68525b25f5d

    終わりに

    以上、ドワンゴのインターンシップ第2クールの様子をお届けしました。 インターン生からの感想では、「コミュニティマネジメントの概念が勉強になった」、「サービスの文化や理念を深く知ることが機能開発には欠かせないことを実体験から学べて良かった」などのコメントが多く、サービスの文化にフォーカスした開発について多く学んでいただけたようです。

    27260661c8026d6dba3695a5ec28b5c84f5f8ae3

    インターンシップ最終日には、全ての機能がサービスイン(読み上げアプリも手元で実行)されたfriends.nicoの様子を皆で眺めながら懇親会を行いました。 自分たちで考え作り上げたプロダクトが実際にユーザーに使われている風景を見て、プロダクトを開発するということやサービスを育てるということの魅力を体感してもらえたのではないでしょうか。

    bba46774cb899da05d8ea19432c27d9dd375acfc

    8341b03efb2f876d3221daf8c5d4bd2ef3a56880

  • ニコニコ生放送におけるdockerの活用事例

    2017-10-23 13:161

    はじめに

    はじめまして。ニコニコ生放送でマイクロサービスチームのグループリーダーを務めています、 ビビる(@vivil@friends.nico) です。以前歌舞伎座.techニコニコ生放送フロント レガシーシステムの改善の発表をさせていただきました。

    ニコニコ生放送(以下「生放送」)ではバックエンド・フロントエンドのサーバーを建てる環境として、2016年からDocker Swarmを採用し始めています。ここではその際に得た知見等を書いていきます。 ご意見・ご質問等あればコメント・トゥート等でお声をおかけ下さい。

    何故docker化を始めたの?

    マイクロサービス化の機運

    生放送は肥大化したモノリシックなサービスが2つ並列運用されており、それぞれロジックを保有する見通しの悪い状態になっていました。 そこで、各種のロジックをマイクロサービスとして切り出すことで、サービス全体の見通しを良くする為にマイクロサービス化を進めることになりました。

    ポータビリティ

    生放送は機材の関係で色々な環境で動くのが要求されるため、フロントエンド/バックエンドともにポータビリティ性の高いコンテナ化が求められ、技術的にはDockerが妥当であろうという結論に達しました。

    フロントエンドの分離

    フロントエンドサービスをScalaから脱却する / バックエンドサービスはScalaを引き続き使う

    従来、フロントエンドエンジニアはサーバーサイドも触る必要があったため、Scala/TypeScript/SCSS/Rakeを理解している必要がありました。(一部PHPが必要なこともありました)   フロントエンドエンジニアが複数言語を覚える負荷を下げるため・Scalaのコンパイル時間を減らす為に、サーバーサイドをTypeScriptで書きたい要望が出ました。
    一方、バックエンドサービスに関しては利便性等を考慮して、引き続きScalaを利用していく方針の為、それぞれ独立した環境で実行できるDockerを利用することになりました。

    スケーラビリティの向上

    超会議や人気アニメ一挙放送など、多数の来場者が予想される際にはインスタンスを増やして、たくさんの方に視聴していただけるようにし、人が少ない時間帯はスケールダウンさせて、別用途に利用する等、柔軟に対応出来るようにしたい意図がありました。

    なんでSwarmなの?

    2016年当時、Dockerのクラスタリング技術としてはKubernetes or Swarmの二択であり、

    • Docker公式のSwarmのほうが後々廃れにくいだろう
    • 知見が社内にほぼない状態だったので、挑戦していきたい

    と考えたため、Swarmを選定しました

    サービス構成

    マシン数

    現状70台以上のサーバーでクラスタを組んで運用されています。

    構成

    Blue-Green Deploy

    フロントエンドサービスについて、 Blue-Greenの2系統準備しています。 Coldインスタンスにデプロイして動作確認後、Hotとスワップすることで無停止で新バージョンの動作確認/デプロイを行うことが出来ます。

    また、問題が発覚した際、従来のScalaベースのシステムでは数十分デプロイに時間がかかっていたのが、Blue-Greenデプロイを実装した現在では3分程度でロールバックできるようになりました。

    監視

    コンテナについてはcAdvisor -> Prometheus -> Alertmanager -> Slack の流れでアラートを飛ばすようにしています。

    Web上でも、Grafanaを使ってPrometheusの情報をリアルタイム監視できるように整えています。

    ホスト単位での監視はインフラチームが構築したZabbixで行っています。

    Swarmについての知見

    以下に、半年以上Swarmを本番運用して得られた知見を紹介します。

    未解決

    Dockerのバージョンアップで不具合が出ることがある

    無停止で更新すると、Ingressネットワークが不通になったり、jobが不安定になったりと不具合が出ることがあったため、Dockerのバージョンアップは一度サービスを止めてメンテナンスを行っています。

    vip/ingress network周りが不安定になることがある

    現在進行系で不安定になることがあります。ネットワークが極稀に数秒詰まったりします。安定稼働に向けて引き続き改善を進めています。

    解決済み

    アクセス元IPの取得ができない

    Swarmの仕様上、アクセス元IPがSwarmのvipになっていた問題がありました。ネットワーク設定をhostmodeにすることで、解決しました。

    カーネルパラメータ

    Docker機材にはカーネルパラメータのチューニングが必要でした。(未だに試行錯誤はしています)

    具体的に一部事例を紹介させていただくと、コンテナを多数建てるとホストマシンのARPキャッシュが溢れる事があったため、GCの閾値を上げています。

      "net.ipv4.neigh.default.gc_thresh1": 4096
      "net.ipv4.neigh.default.gc_thresh2": 8192
      "net.ipv4.neigh.default.gc_thresh3": 8192
    

    個人的な感想

    以下は個人的な感想です。

    Docker / Swarm 使ってみてどうだった?

    色々アプリケーションを追加する必要なく、Dockerさえ入れられれば立ち上げられるので、とても便利でした。

    アプリケーション開発者も、サーバー側の心配をせずにアプリケーション実装に集中できるので楽になったと思います。(特に、この変更によってフロントエンドエンジニアはTypeScript/SCSSに集中できるようになり、効率が上がったと言われています)

    今まで1つのモノリシックサービスのデプロイを週に3回やる、と言うかたちから、毎日特定のサービスのみ複数回更新できる、というかたちになったので、更新頻度をあげられるようになったのは良かったと思っています。

    今後はどうする?

    マイクロサービスをどんどん増やす方針なので、より使いやすいプラットフォームになるよう、改善を進めていきたいと考えています。

    10月16日から開催されているDockercon EU 17で、Kubernetesの公式サポートが発表されました。
    今後、KubernetesとSwarmがどうなっていくのか、ますます目が離せないとても刺激的な状況です。

    エンジニア募集中です

    コンテナ技術は技術の進歩が速い刺激的な分野です。ドワンゴでは、最新の技術を使ってニコニコ生放送というサービスをよりよくしていくことに興味のあるエンジニアを募集しています。この記事を読んで興味を持った方は、ぜひこちらよりご応募ください。生放送チームのエンジニアがお待ちしています!
  • CodeIQ感謝祭「ドワンゴからの挑戦状」についての解説

    2017-09-26 15:15
    ドワンゴ 技術コミュニケーション室の塩谷( @kwappa / @kwappa@friends.nico )です。

    9/16に開催された「学びの秋!エンジニア最先端に触れて学ぶITフェス」というイベントにドワンゴも企業として出展し、私も職務経歴書についての講演を行ってきました。ご清聴いただいた皆様、ありがとうございました!

    さて、企業ブースでは「ドワンゴからの挑戦状」と題したプログラミング課題を用意し、正解者には先着順でアスキードワンゴの技術書をプレゼントする企画を実施しました。「ヒントが欲しい」「解き方を教えてください」という要望も多かったので、解法をJavaScriptによるサンプルコードを添えて紹介します。
    fdc86074325d0845df1fcb641327b7596e9950bf

    解答と解説

    Q1 : 101

    力技で解くなら、2525から1までのループを回し、その数と2525および5252の剰余を求め、いずれも0になる最初の数、ということになります。
    let a0
    for (let i = 2525 ; i > 0 ; i --) {
      if (2525 % i === 0 && 5252 % i === 0) {
        a0 = i
        break
      }
    }

    最大公約数を求める有名な方法に「ユークリッドの互除法」があり、そちらを使えばより計算量少なく求めることができます。

    x <= y , x > 0 , y > 0 の場合、以下のコードで最大公約数が求められます。互いに素な場合は1が返ります。

    function gcd(x, y) {
      let r
      while (y > 0) {
      r = x % y
      x = y
      y = r
      }
      return x
    }
    const a1 = gcd(2525, 5252)


    Q2 : 2859870693

    漸化式なので、設問通りの演算をする関数を再帰的に呼び出せばn項めを求めることができます。ですが、Q3とQ4が同様の数列を利用する問題になっているため、ここで全要素を演算した配列を生成した方が楽でしょう。

    2 ^ 32 はこのあとも使うので、ここで定義してしまいましょう。ES2016からは 「2 ** 32」 と書くこともできます。

    const TWO_POW_32 = Math.pow(2, 32)
    let arr = [a1]
    for (let i = 1 ; i <= 1000 ; i ++) {
      arr[i] = (arr[i - 1] * 2525 + 5252) % TWO_POW_32
    }
    const a2 = arr[1000]


    Q3 : [2355222565, 3890716245, 434637493, 1285940997, 3265016661, 5746901]

    文字コードをindexとして先ほどの配列から取り出し答えとなる配列にpushしていく、という戦略が考えられます。

    文字列を配列に分解するにはスプレッド演算子が使えます。 以前は `'dwango'.split('')` という書き方をすることが多かったようです。

    const a3 = [...'dwango'].map(v => arr[v.charCodeAt(0)])

    Q4 : 2110379477

    ソートして取り出すだけの問題です。500番目はちょうど真ん中なので、昇順 / 降順を間違えても解答は変わらないというボーナス問題です。

    JavaScriptの場合は単純に `Array#sort` でソートすると文字列として辞書順でソートされてしまうので、比較関数を書いて数値でソートする必要があります。

    const sortedArr = arr.sort((a, b) => a - b)
    const a4 = sortedArr[500]

    問題 : 3322

    JavaScriptではreduceというメソッドで畳み込み演算を行うことができます。Q3で作った配列に残りの値を連結した配列を作り、すべての値を合計し、2 ^ 32との剰余を求め、先頭4文字を取り出してみましょう。
    const answerArr = a3.concat([a1, a2, a4])
    const answer = ((answerArr.reduce((a, x) => a + x))% TWO_POW_32).toString().slice(0, 4)

    蛇足

    筆者の趣味でRubyによる解答例も掲載しておきます。 Integer#gcd とか Array#sum (2.4から)など便利メソッドがあることをコードレビューで教えてもらいました。

    a1 = 2525.gcd(5252)
    puts "Q1 : #{a1}"

    arr = [a1]
    1.upto(1000) { |idx| arr[idx] = (arr[idx - 1] * 2525 + 5252) % 2 ** 32 }
    a2 = arr[1000]
    puts "Q2 : #{a2}"

    a3 = "dwango".each_byte.map { |idx| arr[idx] }
    puts "Q3 : #{a3}"
    a4 = arr.sort[500]
    puts "Q4 : #{a4}"

    answer = (a3.concat([a1, a2, a4]).sum % 2 ** 32).to_s[0..3]
    puts "Answer : #{answer}"

    まとめ

    当日会場では「5分で解けた」から「難しすぎてギブアップ」まで、さまざまな感想をいただきました。みなさまはいかがだったでしょうか。

    ドワンゴではエンジニアを積極的に採用しています。「解けた!」という方で、お仕事をお探しの方は、経験者採用の募集情報もぜひご覧ください!