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

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

JenkinsのSlaveが原因不明で切断されるのを力技で解決する

Jenkins

R&D事業部の岩原です。

今回は、クラッシュフィーバーのJenkinsの構成と、長い間悩まされ続けていた問題の解決案をご紹介したいと思います。

クラッシュフィーバーのJenkins構成

以前書いた記事に似た構成ではありますが、
大体こんな感じになってます。

f:id:m_iwahara:20161028160827p:plain

EC2上にJenkinsマスターを建て、スレーブとして社内MacMini2台とEC2を1台ぶら下げているような構成です。
MacMiniはそれぞれiOS用とAndroid用のアプリビルド&配布用サーバーへのアップロードを行うようにし、EC2はツールのデプロイ用にしています。
よくある構成ですね。

しかし、この構成にしてからずっと悩まされ続けている問題がありました。
その問題は、題名にもありますが「社内のSlaveが原因不明で切断される」というものです。

社内Slave切断問題

運用してしばらくすると、社内のMac MiniのスレーブがConnection Resetを吐いてよく切断されてしまう事象がよく発生していました。
吐き出されるログは以下の様なものでした。

10 27, 2016 5:26:29 午後 hudson.remoting.SynchronousCommandTransport$ReaderThread run
重大: I/O error in channel channel
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:209)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
    at hudson.remoting.FlightRecorderInputStream.read(FlightRecorderInputStream.java:82)
    at hudson.remoting.ChunkedInputStream.readHeader(ChunkedInputStream.java:72)
    at hudson.remoting.ChunkedInputStream.readUntilBreak(ChunkedInputStream.java:103)
    at hudson.remoting.ChunkedCommandTransport.readBlock(ChunkedCommandTransport.java:39)
    at hudson.remoting.AbstractSynchronousByteArrayCommandTransport.read(AbstractSynchronousByteArrayCommandTransport.java:34)
    at hudson.remoting.SynchronousCommandTransport$ReaderThread.run(SynchronousCommandTransport.java:48)

この状態になると、マスター側は接続していると認識しているが、スレーブ側は切断した扱いになってしまい、
ジョブのビルドが上手くいかなくなりました。
初めは、Jenkinsのバージョンが古いからか?と思いましたが、EC2側のスレーブは切断されたことが無かったので、
社内環境的な問題かと推測しましたが、未だに原因不明です。

このままではおちおち家に帰っていられないので、対処療法的に対応することにしました。

対応

Slave起動のスクリプト化

まず取り掛かったのは、Slave起動のスクリプト化です。
Slaveの処理はフォアグラウンドで動く&切断されるまで処理が戻ってこないので、それを利用して無限ループ化することにしました。
ただし、その場合再接続してもマスター側がSlave接続エラー状態になるまで「すでに接続しているよエラー」がマスターから帰ってきてしまうので、
再接続前にSlaveの切断をしてから再接続を行うようにしています。Slaveの切断はJenkins-cliを利用して行います。
また、規則性などの調査のため、Slaveの処理が終了した際はSlackへ通知をするようにしてから、再接続を行うようにしています。
こちらはシェルスクリプトで書くことにしました。
大体こんな感じです。

[JenkinsのURL]、[SSH秘密鍵へのパス]、[Slave名]、[シークレットキー]、 [SlackのInComming WebhookのURL]、[Jenkinsのログインユーザー名]、[Jenkinsのトークン]あたりは秘密情報なので伏せさせてもらいます。
Jenkinsに認証を掛けているため、Jenkins-cliではSSH秘密鍵、Jenkins WebAPIではAPIトークンを使用しています。
スクリプトと同じディレクトリに「slave.jar」、「jenkins-cli.jar」、「jenkins_slave_job_restarter.py(後述)」が存在している前提です。

#!/bin/bash
while :
do
java -jar jenkins-cli.jar -s [JenkinsのURL] -i [SSH秘密鍵へのパス] disconnect-node [Slave名]
java -jar -Dorg.jenkinsci.plugins.gitclient.Git.timeOut=120 slave.jar -jnlpUrl [JenkinsのURL]/computer/mac_slave/slave-agent.jnlp -secret [シークレットキー]
sleep 60
curl -X POST --data-urlencode 'payload={ "username": "[Slave名]", "text": "私は死にました(´・ω・`)", "icon_url": "http://mirrors.jenkins.io/art/jenkins-logo/48x48/logo.png"}' [SlackのInComming WebhookのURL]

python jenkins_slave_job_restarter.py [Jenkinsのログインユーザー名] [Jenkinsのトークン] [Slave名]

done

上記に出てくる[jenkins_slave_job_restarter.py]は後ほど紹介します。

スレーブで実行していたジョブの再実行

再接続時、Slaveで実行していたジョブは、切断されたことが検知できていないので、実行され続けてしまいます。
このままでは終了しないので、いったん該当Slaveのジョブのビルドを中断し、再度実行し直すようにします。
こちらはJenkins-cliでは出来ないので、JenkinsのWebAPIを使用します。
こちらはJsonなどを扱うのでPythonで書くことにしました。

[JenkinsのURL]は秘密情報なので伏せさせてもらいます。

# -*- coding: utf-8 -*-

import sys
import json
import urllib2
import base64

import os
import traceback

JENKINS_URL_BASE = "[JenkinsのURL]"

def start_job(user, pw, job_url):
    try:
        url = os.path.join(job_url, "../build")
        auth_header = 'Basic ' + base64.b64encode('{}:{}'.format(user, pw)).strip()
        headers = {'Authorization': auth_header}

        req = urllib2.Request(url, "\r\n" ,headers )
        urllib2.urlopen(req)
        return True
    except Exception as e:
        print(e)
        print(traceback.format_exc())
        return False

def stop_job(user, pw, job_url):
    try:
        url = os.path.join(job_url, "stop")
        auth_header = 'Basic ' + base64.b64encode('{}:{}'.format(user, pw)).strip()
        headers = {'Authorization': auth_header}

        req = urllib2.Request(url, "\r\n" ,headers )
        urllib2.urlopen(req)
        return True
    except Exception as e:
        print(e)
        print(traceback.format_exc())
        return False

def get_node_info(node_info_list_json, node_name):
    computer_list = node_info_list_json["computer"]
    node_info = [computer for computer in computer_list if computer["displayName"] == node_name]
    return node_info

def get_node_info_list(user, pw):
    url = os.path.join(JENKINS_URL_BASE, "computer/api/json?pretty=true&depth=1")
    auth_header = 'Basic ' + base64.b64encode('{}:{}'.format(user, pw)).strip()
    headers = {'Authorization': auth_header}

    req = urllib2.Request(url, "\r\n" ,headers )
    r = urllib2.urlopen(req)
    return json.loads(r.read())

def main(args):
    if len(args) < 4:
        print("引数が足りない")
        return 0
    user = args[1]
    pw = args[2]
    node_name = args[3]
    node_info_list_json = get_node_info_list(user, pw)
    node_info_json_list = get_node_info(node_info_list_json, node_name)
    if len(node_info_json_list) < 1:
        print("ノードが見つかりませんでした")
        return 0
    node_executors_list = node_info_json_list[0]["executors"]
    for executors in node_executors_list:
        if executors["currentExecutable"] is None:
            print("ビルドジョブなし")
            continue
        job_url = executors["currentExecutable"]["url"]
        ret = stop_job(user, pw, job_url)
        if not ret:
            print("ジョブの停止に失敗したわ")
            continue
        ret = start_job(user, pw, job_url)
    return 0


if __name__ == "__main__":
    args = sys.argv
    sys.exit(main(args))

ざっくり解説

Slaveで実行されているジョブを取得するためには、まずはSlaveのリストを取得する必要があります。
Slaveのリストは「computer/api/json」で取得できますが、depth=1を追加することで、さらに深い情報を取得することができ、Executor(ビルド実行状態)も合わせて取得できます。
あとは、コードを読んでいただければなんとなく理解できるかと。
なお、JenkinsのWebAPIはPython用の口もありますが、evalしてオブジェクト化するようなので、なんとなく避けました。

まとめ

上記で書いたシェルスクリプトとPythonスクリプトを組み合わせれば、SlaveがConnection Resetで突然切断されても、

Slave切断

Slaveで実行されているジョブの停止&開始

Slaveの再接続

を行うことができるようになります。

あくまでも対処療法なので、いつか原因を突き止めたいのですが、当面の間はしのげるかと思います。

ワンダープラネットでは、この問題を根本解決出来るような人やJenkinsおじさんを探してます(´・ω・`)

Apple WatchでSpriteKitを使ってアニメーション

iOS

R&D事業部の近藤です。

今回はSpriteKitについてです。
SpriteKitとはiOS 7で登場した2Dゲームを作るためのフレームワークです。
2016年9月のWWDCで発表のあったwatchOS 3が公開され、Apple WatchにもSpriteKitが対応しました。
これがApple Watchに対応したことにより、Apple Watch上でオブジェクトのアニメーションやパーティクルなど、よりリッチな表現をすることができるようになりました。
今回はApple WatchでのSpriteKitの使い方と、Xcode 8で新しく追加されているSpriteKit関連の機能を交えて紹介しようと思います。
f:id:HidehikoKondo:20161024175354p:plain

SpriteKitに対応したWatchAppのプロジェクトの作成

まずはiPhoneのアプリをプロジェクトを作る

「SingleViewApplication」で作りましょう。
プロジェクト名などは好きなように設定してください。 f:id:HidehikoKondo:20161024180500p:plain

WatchAppのTARGETを追加する

プロジェクトができたら、WatchAppのターゲットを追加します。
「NEW」→「Target...」をメニューから選択。 f:id:HidehikoKondo:20161024180616p:plain

「watchOS」のタブから「Game App」を選択してターゲットを追加する。
f:id:HidehikoKondo:20161024180635p:plain

storyboardを開くと、SpriteKitのシーンが配置された状態になっていることがわかります。
このシーンにオブジェクトを配置していくことでゲームの画面を作っていきます。 f:id:HidehikoKondo:20161024180706p:plain

シーンを編集する

シーンにオブジェクトを配置する

「GameScene.sks」でシーンを編集します。
初期状態では定番の「Hello World」のラベルが表示されています。いらないので消しておきましょう。
f:id:HidehikoKondo:20161024182214p:plain

座標は画面の中央がx:0 y:0となっています。
f:id:HidehikoKondo:20161024183026p:plain

まずはColorSpriteをシーンに配置してみましょう。
このオブジェクトにSKActionを設定してアニメーションさせてみます。
f:id:HidehikoKondo:20161025153300p:plain

SKActionがGUIで設定する

SKActionとはオブジェクトにアニメーションをさせるためのクラスです。
(SKActionの詳細は『SpriteKitのSKActionでオブジェクトをアニメーションしてみよう』を参照)

Xcode 8からはこれをGUIで設定できるようになりました。
Object Libraryの一覧の下の方にSKActionの項目があります。
アクションを設定したいオブジェクトのタイムラインにドラッグ&ドロップすると、そのアクションを設定することができます。

f:id:HidehikoKondo:20161025190346p:plain

アクションをループする場合はアクションをクリックするとループボタンが出てくるので、これを押すとループ無限ループになります。 「+」と「ー」のボタンはループする回数を指定できます。
f:id:HidehikoKondo:20161025191253p:plain

アクションのパラメータは右側のウィンドウから設定することができます。
f:id:HidehikoKondo:20161025202711p:plain

「Animate」ボタンを押すことで、設定したアニメーションの再生され、シミュレーターや実機に転送しなくても動作確認ができます。
f:id:HidehikoKondo:20161025195754p:plain

実行すると赤いスプライトが回転アニメーションが再生されます。
f:id:HidehikoKondo:20161025193141g:plain

こんな感じでお手軽にアクションを設定することができます。
今回は回転するだけの設定を行いましたが、MoveやFadeのアクションを組み合わせてより複雑なアクションを設定することもできます。
以前はコードでSKActionクラスのsequenceやgroupを組み合わせて複雑なコードを書く必要がありました。
これらの設定をXcodeの画面上で全て設定することができるようなり、とっても簡単になりました。

パーティクルも動くぞ!

f:id:HidehikoKondo:20161025193938g:plain
まさかと思いましたが、パーティクルも普通に動いてしまいます。
ただし電池消費が激しそうなのと、あまりたくさん使うとApple Watchの処理が追いつかなくなるので、使いすぎには注意しましょう。

Object Libraryに「Emitter」というオブジェクトがあるので、これでパーティクルを表示できます。
(パーティクルのパラメータや設定については『SpriteKitでパーティクルを表示してみよう』を参照)

手首から燃えあがる炎。
なんだか攻撃魔法が放てそうなこの中2病感・・・(笑)
VRコンテンツとかに組み合わせられないだろうか?

使ってみた感想

Apple Watchアプリはいままでパラパラ漫画のようなアニメーション程度しかできず、リッチな表現をするのは困難でしたが、SpriteKitにより複雑なアニメーションが作りやすくなりました。

そしてSKActionのGUIでの設定はめっちゃ便利です!
以前はSKActionでオブジェクトにアニメーションを設定するのに、パラメータの調整・コードの修正・実行をひらすら繰り返していましたが、GUIで設定から確認までできるようになったことで調整作業がとても楽チンになりました。

ゲーム開発において、ゲームエンジンといえばCocos2d-xやUnityが主流となっていてSpriteKitはすっかり影の薄い存在となっていますが、Apple WatchでSpriteKitが使えるようになったことにより、その存在価値も上がったように思います。
これからApple Watchアプリを作る機会があったら活用していきたいと思います。

ソースコード静的解析

今回のブログ担当の渋谷と申します。
今回は「ソースコードの静的解析」というテーマでブログを書かせていただきます。

ソースコード静的解析とは

ソースコードの文脈だけを見て機械的に問題を指摘してくれるツールです。

なぜこれを使う?

バグや意図しない動作の原因になる問題の検出を行うためですね。

とくに、コンパイルエラーや警告にはならないが結果的に未定義の動作になる場合はデバッグしにくいバグを生む原因になってしまいやすいです。

それの検出を行い、修正をするのが主な目的になります。

どんなものがある?

自分の知っているもので有名どころを幾つか挙げてみます。

  • 無料
    • cppcheck
    • clang Static Analyzer
    • splint(C++ では使えません…)
  • 有料
    • Coverity(オープンソースのプロジェクトに限り、無料で使える Coverity Scan というものがあります。また、C#なども対応されているようです。)
    • Klocwork

以下、自分で使ったことがあるものを紹介いたします。(自分の所感を大いに含みます)

cppcheck

名前の通り、C++のソースコードの静的解析を行うことに特化したオープンソースのツールです。
Windows 番は GUI もあったり、 mac だと Homebrew で楽にインストールできたりと、導入も使用も楽で使いやすいです。その上静的解析ツールの中ではかなり高速に動作するのも特長です。
コンパイラに依存しないスタンドアローンのツールなので C++ を使用しているプロジェクトなら簡単に導入できるのもいいところですね。

clang Static Analyzer(scan-build)

clang に付属している静的解析ツールです。
cppcheck がテキストでの出力であるのに対して、 HTML のリッチな形式で出力してくれるのが大きなポイントです。どのようにしてどんなことが起こるかも手順を一緒に出力してくれるので、レポートを確認した後に修正を行いやすいです。
また、Objective-C の静的解析にも対応しています。
コマンドラインから使える他、 Xcode からも使えます(Product -> Analyze)。また、 Xcode で設定したオプションを保持したままコマンドラインから使うことも可能です。(mac では Xcode の Analyze 機能を使うことが推奨されていますが…)

検出の例

以下のコードは C++ を使う人なら問題大有りだとわかりますが、コンパイルエラーになりません。
(本番のコードはこんなに単純じゃないとかいうツッコミはなしでお願いいたします…)

#include <iostream>

int main()
{
    using namespace std;
    
    int* a = nullptr;
    cout << *a << endl;
}

cppcheck だと以下のように出力してくれます。

[nullptr.cpp:7]: (error) Null pointer dereference: a

最後に

これらのツールは必ずしも完璧なものではありませんが、起こりがちなヒューマンエラーなども検出してくれます。
うまく使用すれば、効率良く品質の良いコードを書いていけると思います。 jenkins おじさんに組み込んでみるのも良いと思います。
こうしたツールを利用したりして質の高いコードを書くことが、質の高いプロダクトにつながっていくと思っています。

おまけ

より安全性の高いソースコードを書くためのコーディングルールがあります。

https://www.jpcert.or.jp/sc-rules/

どちらかというと業務用ソフトウェアに適用されるものかもしれませんが、私たちが作成しているプロダクトにも応用しても効果が大きいものと思っています。

GitHubの新機能「Projects」の活用アイデア

GitHub アジャイル

ネイティブアプリケーション事業部サーバエンジニアの桐島です。

ワンダープラネットでは、開発の様々なシーンでGitHubを活用しており、 GitHubは日々の開発に無くてはならない存在となっています。

また、GitHub好きのエンジニアが多く、 GitHub shopから大量にグッズ購入した結果、想定外の関税の支払いに泣かされたり等、 GitHubをフル活用していると思います。

約1ヶ月前、そんなGitHubに「Projects」という新機能が追加されました。

今回は、Projectsの活用方法を書いてみたいと思います。

GitHub Projectsとは

Projectsは、以下画像の様にかんばんボードを作れる機能です。

issueなどの優先度/状態を視覚化することが可能となります。

f:id:s-krsm:20161024020637p:plain

GitHub Projectsの特徴

GitHub Projectsは、かんばんツール(ZenHub, waffle.ioなど)と比較されますが、 それらかんばんツールには無い、Projectsの特徴的な機能は以下となります。

  • issue, pull reqとは別に、「note」を作成可能(noteは作成後に、issueに変換可能)
  • 1つのリポジトリにおいて、複数のかんばんボードを作れる
  • 各々のかんばんボードのフェーズ(ToDo/WIP/Doneなど)の内容/数は、かんばんボード毎に設定できる

また、公式サイト には、 Projectsについて「Manage your ideas.」と説明してあります。

これらを考慮すると、Projectsは、ZenHubやwaffle.ioとは設計思想が異なる様に思えてきます。

GitHub Projects = 個人のタスク管理ツール

GitHub Projectsは「あるプロジェクトに参加しているメンバの、個人のタスク管理ツールである」と考えると、 別の活用方法が見えてきます。

  • リポジトリに参加しているメンバ1人につき、1つのProjectを作成
  • メンバは各々のProjectにて、各人が行うタスク(issue,PR)を管理する
  • アイデアは各人のProjectにnoteとして残す
  • 他メンバとnoteについて話し、noteを削除するか、issue化するか決める
  • 完了したタスクは、開発の区切りのタイミング(sprint期間が1weekであれば、一日の始まり)にProjectからremoveする

この運用により得られるメリットは以下が考えられます。

  • マネージャは、sprint期間中に各々のメンバが行っているタスク、及びメンバが設定している優先度をProjects上で確認可能となる(メンバの、タスクに対する認識はProject上に現れる)
  • 各メンバは、個人用の別のタスク管理ツールを使用することなく、GitHub上だけでタスク管理が可能となる(マイルストーン、及び自分のタスクの両方を管理できる。しかも他メンバと簡単に共有できる)
  • 1つのcard(issue, PR, note)は複数のProjectに紐付け可能であるため、複数人で対応しているcardの各メンバの対応状況/認識が明確になる

まとめ

以下の運用が良いのでは、というアイデアでした。

  • かんばんツール(ZenHubやwaffle.io) = マイルストーンの管理
  • GitHub Projects = メンバ一人ひとりの個人のタスク管理

Projectsは、ZenHubやwaffle.ioと競合するツールではなく、 併用することで補完し合うツールであると思います。

非エンジニアがSlackというハイカラなツールを使ってみた

Slack

こんにちは。クラッシュフィーバーチーム所属の大脇です。エンジニアではありませんのでプログラミングはほぼ行いません。

 

そんな非エンジニアの私が、ここ最近社内の業務ツールとして導入された「Slack」というハイカラなツールを使ってみた感想をお伝えします。

 

◆第一印象は・・・

「げ、なんか画面が英語ばっかりでとっつきにくそう・・・名前も「スラック」ってなに?おいしいのそれ」とすぐにブラウザ閉じ・・・という、ネガティブな出会いでした。

 

f:id:wp_tomoyan:20161012192912j:plain

◆Slackとは

Slackをググってみると「企業内コミュニケーションツール」「チャットツール」とあります。チャットでコミュニケーションを行うツールはこれまでも別のツールを使っていましたのでなんとなくイメージはつきました。が、今までは100%日本語だったので安心だったのが、今回は英語。なんで英語ばっかりのツールに変えるのか・・・という言葉は飲み込み笑顔で導入、大人なので。

 

◆実際に使い始めてみると・・・

いざ使い始めてみると、宛先の指定の仕方やトピックの引用の仕方に違いはあるものの、社内でこれまで使っていたチャットツールと、それほど大きく違わないこともわかり一安心しました。 

f:id:wp_tomoyan:20161013215114p:plain

トピックごとにチャンネル(チャットルーム)も分けられていて、飲み会専用のチャンネルもあったりします。

 

◆Slackの良い点・便利な点

使い始めてみると良い点も見えてきます。

Slackの気に入っている点は、「リアクションをつける」ことができる点です。同僚から仕事の返信が来た時にf:id:wp_tomoyan:20161012204351j:plainアイコンをつけるだけで相手に感謝の気持ちを簡単に伝えることができます。これまでMSOutlookしか使ったことのなかった私は、メールによる返信で「ありがとう」と文字ベースが基本だったため、入力不要ですし、これは新鮮でした。

f:id:wp_tomoyan:20161012205150j:plain

 

また、ユーザーが自分の好きなアイコンを追加できるのも楽しいです。 

f:id:wp_tomoyan:20161012192328j:plain

 

社内にはたくさんのパブリックチャンネル(社員なら誰でも見ることのできるチャットルーム)があり、チャンネル内で流れる情報はすべて社内的にオープンな情報です。よくある部外秘的なものはありません。(一部情報を除く)

弊社のバリューに「360度オープンであれ」というものがあるのですが、それを達成できるツールだということを実感しました。(ちなみに弊社CEOがSlackを導入しようとしたのもそれが理由)

嗚呼、メールの引用の>>>マークとは無縁の世界、便利さが少しづつわかってきました。

 

Slackは他にも、Trelloといったタスク管理できる外部ツールとの連携や、bot、スニペットなどの機能で活用の幅が広がるらしいので、これからももっとSlackライフを楽しみたいと思います。

 

#ちなみに社内では●岡●造さんのbotがあり、「●造」と呼びかけると熱いメッセージを自動的に返してくれるのがお気に入りです。 

f:id:wp_tomoyan:20161013215817j:plain

キャラクターイラストができる道程

開発

アートディレクターの磯部です。 

 

皆さんはキャラクターイラストができるまでにどのような道筋を

辿っているかご存知でしょうか。

今回はクラッシュフィーバーのキャラクターが

どのような工程を経て、作られているのかをご紹介したいと思います。

  

1.テーマを決める

まず最初に作るキャラクターのテーマを決めるミーティングを開きます。

おとぎ話、神話、戦国…イラストのモチーフとなりそうなテーマから

季節やキャラクターのバランスを考慮し、ユーザー様が興味をもって

いただけるようなテーマを決めます。

 

2.キャラクターの指示書をかく

テーマが決まったら、キャラクターの指示書を書きます。

指示書とはキャラクターの設計図のようなもの。

年齢・性別・性格・体格・ポーズ・攻撃方法等々…

どんなキャラクターにしたいかを、具体的に文章で書きます。

キャラクターの根幹を決めるとても大切な作業です!

 

3.イラストレーター様にご依頼をする

外部パートナー様を経由し、指示書をイラストレーター様に渡していただきます。

イラストは月に何10体も増えていくので社内ですべて描くのは大変!

そこで外部パートナー様に指示書を読んでいただき、

指示書のイラストを描く事が得意なイラストレーター様にご依頼していただきます。

メカが得意なイラストレーター様にはメカを、

女の子が得意な方には女の子の絵を…といった感じです。

 

4. 赤入れをする

イラストレーター様に描いていただくイラストは、3段階に分けて弊社のチェックをはさみます。

  1. ポーズラフ  構図とポーズを決める。
  2. 詳細ラフ   配色とデザインを決める。
  3. 着彩     光や影をいれ、ゲーム画面にのせられる段階まで仕上げる。

f:id:wp_isobe:20161009154301p:plain ▲左からポーズラフ・詳細ラフ・着彩 

あがってきたイラストに修正依頼を出す作業を赤入れと言います。

参考資料を渡し、文章で直して欲しい箇所をご依頼します。

弊社内で絵を描いて直接修正を行う場合もあります。

 

構図、配色、デザイン が、一定のクオリティを満たしているか

社内レビューを交えながら慎重に進めていきます。

 

5. イラストをご納品いただく。

イラストに汚れやミスがないかを、ゲームの画面にあてはめて最終チェックをします。

問題がなければイラストをご納品いただきます。  

 

まとめ

個人プレーと思われがちなイラスト制作ですが、

実はとても多くの方のご協力と、チームプレーあってのものなのです。

 

クラッシュフィーバーが始まって1年以上になりますが、

いまでもキャラクターのイラストが世に出るときはドキドキしますね。

ユーザー様の反応が良かったときには、ほっと胸をなでおろしています…!

 

これからもドンドン素敵なキャラを追加していくのでお楽しみに!

GatlingとnginxのDockerコンテナを構築する

Docker

ネイティブアプリケーション事業部の山内です。

ワンダープラネットでは、プロダクトローンチ前あるいはローンチ後にサーバーの負荷テストを実施してボトルネックを探り、パフォーマンスチューニングを実施しています。Apache BenchJMeterVegetaなど様々な無償ツールがありますが、社内ではGatlingが人気です。負荷テストの結果が静的ファイルにも出力され、グラフや表をブラウザで確認できて便利です。


f:id:crux-one:20160928170606p:plain

今回は、Docker上にGatlingとnginxを動かすコンテナを用意し実際に負荷テストを実施、テスト結果をブラウザで閲覧するまでの一連の流れをご紹介します。

環境

・MacBook Pro (El Capitan 10.11.6)

Docker for Mac Version 1.12.1-beta26.1 (build: 12100)

docker-compose.ymlの作成

適当な場所にディレクトリを作成し、その中に docker-compose.yml ファイルを作成します。

version: '2'
services:
  gatling:
    build: ./gatling
    container_name: gatling
    restart: always
    stdin_open: true
    tty: true
    volumes:
      - /usr/local/bin
    command: /bin/sh

  nginx:
    build: ./nginx
    container_name: nginx
    restart: always
    stdin_open: true
    tty: true
    volumes_from:
      - gatling
    ports:
      - "80:80"

Dockerfileの作成

Gatlingを実行するコンテナを次のように定義します。Gatlingは執筆時点(2016年10月6日現在)での最新の安定版 2.2.2を使います。

FROM dockerzone/lubuntu-desktop
ENV LANG C.UTF-8

# Install JDK8
RUN apt-get update && \
apt-get install -y unzip wget software-properties-common python-software-properties && \
add-apt-repository -y ppa:webupd8team/java && \
apt-get update && \
echo "oracle-java8-installer shared/accepted-oracle-license-v1-1 select true" | sudo debconf-set-selections && \
apt-get install -y oracle-java8-installer

# Donwload and Unzip Gatling
RUN cd /usr/local/bin/ && \
wget -N https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/2.2.2/gatling-charts-highcharts-bundle-2.2.2-bundle.zip && \
unzip -f /usr/local/bin/gatling-charts-highcharts-bundle-2.2.2-bundle.zip

Gatlingのテスト結果はresultsディレクトリに出力されます。今回はブラウザで結果を閲覧できるようにnginxのドキュメントルートを変更します。デフォルトでは /usr/share/nginx/html ですが、Gatlingの結果が出力される /usr/local/bin/gatling-charts-highcharts-bundle-2.2.2/results に置換するよう命令を記述しています。

FROM nginx
ENV LANG C.UTF-8

# Change DocumentRoot so that we can browse gatling result
RUN sed -i 's/root   \/usr\/share\/nginx\/html;/root   \/usr\/local\/bin\/gatling-charts-highcharts-bundle-2.2.2\/results;/' /etc/nginx/conf.d/default.conf

構成

docker-compose.yml、Dockerfileは次のような構成になります。

# tree
.
├── docker-compose.yml
├── gatling
│   └── Dockerfile
└── nginx
    └── Dockerfile

2 directories, 3 files

ビルド

docker-compose.ymlファイルのあるディレクトリに移動してビルドします。初回ビルドには少し時間がかかります。

# docker-compose build

コンテナの起動

ビルドが終わったらコンテナを起動させます。

# docker-compose up
Creating network "gatling_default" with the default driver
Creating gatling
Creating nginx
Attaching to gatling, nginx

-dオプションを付けるとコンテナをバックグラウンドで起動できます。

# docker-compose up -d

Dockerコンテナの確認

docker psコマンドでコンテナのステータスを確認することができます。ここでは2つのコンテナのSTATUSがUpになっていることを確認します。

# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
fe2366bda6b6        gatling_nginx       "nginx -g 'daemon off"   3 minutes ago       Up 3 minutes        0.0.0.0:80->80/tcp, 443/tcp   nginx
bfce0b54d4fb        gatling_gatling     "/opt/init /bin/sh"      13 minutes ago      Up 3 minutes        22/tcp, 5901-5999/tcp         gatling

Gatlingの実行

docker execコマンドでGatlingのテストを実行することができます。コンテナのIDは適宜指定します。 今回はGatlingのコンテナのIDが bfce0b54d4fb なので、次のようなコマンドを実行します。bfce0b54d4fbコンテナ内の gatling.sh を実行する、というような意味です。

# docker exec -it bfce0b54d4fb /usr/local/bin/gatling-charts-highcharts-bundle-2.2.2/bin/gatling.sh

gatling.sh実行後にコンパイルが走り、テスト(シミュレーション)を選択することができます。

GATLING_HOME is set to /usr/local/bin/gatling-charts-highcharts-bundle-2.2.2
07:30:33.006 [WARN ] i.g.c.ZincCompiler$ - Pruning sources from previous analysis, due to incompatible CompileSetup.
Choose a simulation number:
     [0] computerdatabase.BasicSimulation
     [1] computerdatabase.advanced.AdvancedSimulationStep01
     [2] computerdatabase.advanced.AdvancedSimulationStep02
     [3] computerdatabase.advanced.AdvancedSimulationStep03
     [4] computerdatabase.advanced.AdvancedSimulationStep04
     [5] computerdatabase.advanced.AdvancedSimulationStep05

テスト結果の閲覧

テスト実行後、/usr/local/bin/gatling-charts-highcharts-bundle-2.2.2/results/ ディレクトリ配下に結果が出力されます。

Reports generated in 1s.
Please open the following file: /usr/local/bin/gatling-charts-highcharts-bundle-2.2.2/results/basicsimulation-1475739367052/index.html

今回は、resultsディレクトリ配下に basicsimulation-1475739367052 が出力されたので、ブラウザから http://localhost/basicsimulation-1475739367052/ にアクセスすることで結果を閲覧することができます。(1475739367052は結果出力時のUNIXタイムです。)

まとめ

今回はGatlingとnginxの2つのコンテナを構築し、テスト結果をブラウザで閲覧する流れをご紹介しました。2016年はDocker for Mac、Docker for Windowsなどの登場によりVirtual Boxを使うことなく簡単にコンテナを構築できるようになりました。急成長中のDocker、今後も目が離せません。