EatSmartシステム部ブログ

ウェブサイトの開発や運営に関する情報です。

Javaの単体テストJunit入門

こんにちは、EatSmartの新人エンジニアです。弊社のサービスの一つであるカロリーチェックAPIの開発を行った際にJava単体テストを行ったのでその流れを振り返ってみたいと思います。

JUnitとは


Javaユニットテストの自動化を行うためのフレームワーク

ユニットテストを書くことで正しく動作しているかを検証することができます

気を付けたいポイント


  • 「前提条件、実行、検証」がわかりやすいコードを書く
  • ユニットテストし易いように対象のクラスを作る
  • 想定されうるケースをできるだけ作る
  • プログラム単体の振る舞いを確認する
    ex) 引数のデータの組み合わせが正しいか、例外が発生した際の振る舞いが正しいか

今回の開発環境


開発環境
サーバー Tomcat
IDE Eclipse
標準API JavaEE
フレームワーク Spring boot
テスト Junit 4
ビルドツール Apache Maven

利用手順(Eclipseで利用の場合)


  1. サンプルプログラムを作成する
  2. テスト用のソース・フォルダーを作成する
  3. Junitへのビルドパスを追加する
  4. テストクラスを配置する
  5. テストを実行する

テスト作成ルール


JUnitで利用するアノテーション


アノテーション 機能
@Before 全てのテスト実行前に行われる処理
@After 全てのテスト後に行われる処理  
@BeforeClass テストメソッド実行前に一度だけ行われる処理
@AfterClass テストメソッド実行後に一度だけ行われる処理
@Test テストメソッドを知らせる


今回使用したアノテーション

アノテーション 機能
@JsonIgnore フィールドが変換対象外になる
@JsonProperty Jsonのプロパティ名を変更する
@JsonInclude 値がnullの場合は出力しない

サンプルコード

テスト対象のSample.javaは次の通りです。
<使用したアノテーションの設定>

  • @JsonIncludeで値がnullの場合は結果を出力しない
  • @JsonIgnoreでxml/jsonの出力をしない

import java.math.BigDecimal;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;

public class Sample {

    @JsonInclude(JsonInclude.Include.NON_NULL)
    private BigDecimal rowNumber;
    private String foodName;
    @JsonIgnore
    private BigDecimal standardAmount;
    private String standardAmountUnit;
       
       @JsonProperty(value="contentsAmount")
       @JacksonXmlProperty(localName="contentsAmount")
    public String getContentsAmountStr() {
        if (contentsAmount == null) {
            return "0";
        }
        return FormatUtil.format(contentsAmount, 2, "#########");
    

上のサンプルに対するJUnitは次のようになります

  • テストメソッドはassertTrueで設定
  • テストに成功すればグリーンで返ってくる
import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;

public class SampleTest {

    @Before
    public void setUp() throws Exception {
        TestUtil.initialize();
    }

    @Test
    public void testXml_OK() throws Exception {
        //結果取得
        SamplelBean bean = new SampleBean();
        bean.setFoodCode("00");
        bean.setNutritionProvideKbn("01");
        SampleBean ret = new SamplelAction().xml(bean);

        //パラメーター設定
        Map param = new HashMap();
        param.put("foodCode",bean.getFoodCode());
        param.put("nutritionProvideKbn",bean.getNutritionProvideKbn());

        //検証
        assertTrue(TestUtil.validate(ret,"/calorie/detail",param));

    }

Google Map APIについて

クスパでは料理教室の所在地をGoogle Map APIを利用して表示していますが、2018年6月にGoogle Map APIのサービスが見直され、Google Maps Platformというサービスに変更されました。その際に調査したことなどを記載したいと思います。

Google Maps Platformの変更点

Google Maps Platformの大きな変更点としては、API等を利用する場合、利用アカウントに(クレジット カードの)決済情報を設定しないと利用できない点です。

GoogleMapPlatform 既存ユーザー用ガイド

User Guide  |  Google Maps Platform  |  Google Cloud

Google Maps Platform利用までの流れ

手順としては、「APIキーの取得」「APIの設定と有効化」があり、利用までの大まかな流れを記載します。

APIキーの取得
APIの設定と有効化
  • (上記で作成した)プロジェクトを選択

  • 「Maps JavaScript API」を有効にする※「Maps JavaScript API」利用の場合

  • 利用するAPIの追加

  • 認証情報の設定

  • APIアクセス制限の設定(リファラー設定等)

Google Maps Platformの料金体系について

今回のリニューアルにより、大幅に料金体系が見直されました。 変更点としては、いままでは「個別のAPIごとに」無償枠があり超過分だけを支払う形態でしたが、 Google Maps Platformでは「Google Maps API全体での無償枠」を超えた分だけ支払う形に変更されました。 Google Maps Platformの無償枠は毎月$200となり、(2018/10/26に調査した時点の)各APIの無償枠内での利用数は以下の通りです。

マップ(Maps)
API 月額無償枠(200$)
Mobile Native Static Maps 無制限のロード
Mobile Native Dynamic Maps 無制限のロード
Embed 無制限のロード
Embed Advanced 最大14,000のロード
Static Maps 最大100,000のロード
Dynamic Maps 最大28,000のロード
Static Street View 最大28,000のパノラマ
Dynamic Street View 最大14,000のパノラマ
ルート(Routes)
API 月額無償枠(200$)
Directions 最大40,000件のコール
Directions Advanced 最大20,000件のコール
Distance Matrix 最大40,000の要素
Distance Matrix Advanced 最大20,000の要素
Roads - Route Traveled 最大40,000件のコール
Roads - Nearest Road 最大40,000件のコール
プレイス(Places)
API 月額無償枠(200$)
Autocomplete - Per Character 最大70,000文字
Autocomplete without Places Details - Per Session 最大11,000セッション
Autocomplete(included with Places Details) - Per Session 無制限のコール
Query Autocomplete – Per Character 最大70,000文字
Places Details - Basic 最大11,000件コール
Places Details - Basic + Contact 最大10,000件コール
Places Details - Basic + Atmosphere 最大9,000件コール
Places Details - Basic + Contact + Atmosphere 最大8,000件コール
Places Photo 最大28,000件コール
Find Place - Basic 最大11,000件コール
Find Place - Basic + Contact 最大10,000件コール
Find Place - Basic + Atmosphere 最大9,000件コール
Find Place - Basic + Contact + Atmosphere 最大8,000件コール
Places - Nearby Search - Basic + Contact + Atmosphere 最大5,000件コール
Places - Text Search - Basic + Contact + Atmosphere 最大5,000件コール
Geocoding 最大40,000件コール
Geolocation 最大40,000件コール
Time Zone 最大40,000件コール
Elevation 最大40,000件コール

今後の対応

クスパでは、Static Maps(静的地図の表示)/Geocoding(住所から緯度経度を検索)をメインに利用しており、現状は無償枠内で利用しておりますが、今後のトラフィック増に伴い月額利用料が増額する可能性がある為、下記対応も検討していきたいと思います。

  • Static Mapsから地図埋め込みによるロード数削減

  • 無償の地図API(Leaflet等)の利用

leafletjs.com

Javaの開発環境を構築する(Windows編)

イートスマートの新人エンジニアが、今回はJavaの開発環境の構築について、業務を通して行ったので 流れを簡単に振り返ってみたいと思います。以下の書籍を参考にしました。

スッキリわかるJava入門 第2版 (スッキリシリーズ)

スッキリわかるJava入門 第2版 (スッキリシリーズ)

Javaで開発するために必要なもの

JDK

JDK とは、Javaのアプリケーション開発に必要なソフトウェアのキット(コンパイラ、デバッガなどが揃っている)です。現在は、Oracleがより多くの開発者に使ってもらうためにJDKの配布、アップデートを繰り返してしています。JDKと対比されるJREは、Javaの実行環境のみであり、簡単に言うとJDKJavaの開発、JREJavaの実行のイメージになります。

Eclipse

Javaの開発に必要な統合開発環境(エディタ、コンパイラインタプリタが揃ったもの)になります。Eclipseは、エディタで行われるような文字のカラーリング、キー入力の予測変換、デバッグの支援など多様な機能が搭載されています。Java以外のRubyPythonといったプログラミング言語にも用いることができます。

今回の環境について

Windows 10 (64bit版)

JDKの導入

JDKのダウンロード元:https://www.oracle.com/technetwork/java/index.html
上記のURLより、JDKをダウンロードします。ダウンロードページにて、Java SE8u~(アップデートのタイミングによって~は異なります。)と書かれたものを選択します。ライセンス契約に同意し、今回であれば環境がWindows64bit版なので、Windows x64と書かれたものを選択します。ダウンロード実行後、セットアップに移ります。

JDKのセットアップ

こちらは、画面の案内に従って進行していきます。注意点として、JDKのインストール先を覚えておく必要があります。
例) C:¥Program Files¥Java¥jdk1.8.0_181
ここまでは、指示通りに進めば問題がないかと思います。

設定で躓いたのが、環境変数の設定になります。 コントロールパネル>システム>システムのプロパティ>環境変数から以下のように設定をします。 <ユーザー環境変数>
変数名: JAVA_HOME
変数値: C:\Program Files (x64)\Java\jdk1.8.0_181
JAVA_HOMEの環境変数が既に<システム環境変数>の方にある場合には、そちらが優先して 読まれる場合があるので、参照元を確認し不要であれば削除します。 コマンドプロンプトで設定する場合には、 一旦閉じて、設定を反映させます。
再び、コマンドプロンプトを開き以下のコマンドが通れば 設定完了になります。
C:\Users\eatsmart>java -version
結果:java version "1.8.0_181"

C:\Users\eatsmart>javac -version
結果:javac 1.8.0_181

Eclipseの導入

続いて、Eclipseを導入していきます。今回、Eclipse拡張機能を追加し、日本語化を行ったパッケージであるPleiadesをダウンロードして行いました。Pleiadesには、Eclipse本体に加えて、日本語化のプラグインJRE(Java実行環境)、その他便利なプラグインが含まれています。
Pleiadesのダウンロード:http://mergedoc.osdn.jp/

Eclipseの起動について

上記URLよりダウンロードしたzipファイルを開き、eclipseと書かれたフォルダの中のeclipse.exeを開きます。 ワークスペースディレクトリがデフォルトで設定されているので、そのまま「OK」を押せばEclipseが立ち上がります。上記の流れでJavaの開発環境が整いました。
画面のカスタマイズなどもできますので、普段使っているエディタのように文字のカラーや背景色の設定を自由にできます。 alt

参考URL: http://hatehate-masaki.hatenablog.com/entry/2017/01/18/235633

番外編~VSCodeを使ったJavaの環境構築

最近になって、VSCodeJavaサポートが充実してきているようなので、Mac環境にてVSCodeを使って環境を構築してみました。 f:id:eatsmart:20181019003953p:plain

以下、参考にした記事になります。

簡単に流れをざっとご紹介しましたが、快適なJavaライフを送るために参考になればと思います。

DockerコンテナでJenkinsを稼働させる

今回は、イートスマートのサービスのビルド・デプロイに利用しているJenkinsについて書きます。 DockerコンテナでJenkinsを稼働させるための手順をまとめました。 現在はJenkins以外にも同様のツール・サービスが多数ありますが、手元のサーバ上で手軽に利用できるのがお大きな利点ではないかと思います。

Jenkinsについて

Jenkinsは、継続的インテグレーションを行うため に利用するツールです。 主な用途は以下となります。

アプリケーションのビルド

Javaやその他の言語で造られたアプリケーションのビルドを行います。 ビルドを行う手順はJenkins上に直接記述することもできますが、バージョン管理を行うためスクリプトにまとめておき、Jenkinsではそのスクリプトを実行するのみとしています。

バッチの実行

定期的に実行したいバッチを「ビルド・トリガ」の「定期的に実行」を利用して処理しています。 以前はCronを利用していましたが、Jenkinsへ移行することで

  • スケジュールの管理
  • 状況の把握
  • 結果の把握

が容易になりました。 アプリケーションのビルドも同様ですが、「ビルド後の処理」へ失敗時にシステム部メンバーへメールで通知する設定を行っています。 また、手順もスクリプトにまとめてバージョン管理を行っています。

サービスの監視

インフラ・サービスの監視はZabbixを利用していますが、補助的にJenkinsでも行っています。 サービスごとに監視用のスクリプトを用意して、バッチと同様に失敗時に通知を行っています。

Dockerコンテナで稼働させる

今年の3月にインフラをデータセンターからさくらインターネットクラウド・専用サーバへ移行しました。 この時、Jenkinsをはじめ上記のZabbixやタスク管理に利用するRedmine、バージョン管理に利用するsvn/gitbucket等も同様に移行しましたが、すべてDockerコンテナにしています。

Dockerイメージを作成する

以前の環境ではJava6を利用してビルドを行っていました。移行のタイミングでバージョンアップすると問題が発生した場合に切り分けが難しいので、Dockerコンテナも同じバージョンにしました。 公式のイメージもありますが、上記の理由で以前の環境を再現することにりました。

FROM java:6

Java6のイメージをベースにしました。

ADD jenkins.war /var/
ADD apache-ant-1.7.0-bin.tar.gz /var/
ENV PATH $PATH:/var/apache-ant-1.7.0/bin

JenkinsのwarとJavaアプリケーションのビルドに利用するAntのjarをコピーし、パスを通します。

RUN apt-get update \
  && apt-get install -y zip \
  && apt-get install -y rsync

デプロイに利用するコマンド(zip,rsync)をインストールします。

ENTRYPOINT ["java", "-Duser.timezone='Asia/Tokyo' -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Xmx1024m", "-jar", "/var/jenkins.war"]

Jenkinsを起動します。タイムゾーンエンコードを指定してます。 また、大きめのアプリケーションのビルドとテストを行うので、メモリの指定も追加しています。

実際はサービスごとの細かな設定も追加していますが、これらの内容でイメージを作成しました。

Dockerコンテナを起動する

Dockerイメージができたら起動します。起動には、以下のようなオプションを指定しています。

--env="JENKINS_HOME=/var/jenkins/jenkins_home/" \
-v /var/jenkins/jenkins_home:/var/jenkins/jenkins_home \

Jenkinsのジョブやワークスペースの保存先をしています。 保存先をホストサーバとすると、バックアップ等扱いやすくなります。

--env="TMPDIR=/dev/shm" \

長期間かどうさせるとサーバのメモリが不足し、Jenkinsの動作が不安定になることがありました。 Zabbixで確認すると、アプリケーション自体が利用するメモリが増加するのではなく、「cached」や「slab_cache」とよばれるメモリが増加していました。 以下の記事を参考に、tmpfsを利用するための設定となります。

qiita.com qiita.com

この設定を行うことで、最大5GB程度あったスワップが200MB程度に収まるようになりました。

-v /etc/localtime:/etc/localtime:ro \

ホストサーバと同じタイムゾーンで稼働させるための設定です。

-v /root/.ssh:/root/.ssh:ro \

デプロイsshを利用する際に、ホストのものを利用します。

アプリケーションのビルド

Antを利用するプロジェクトは、Dockerコンテナ内でビルドすることができるようになりました。 これ以外のMavenGolang等のプロジェクトは、Jenkinsとは別のコンテナを利用しています。

  • Mavenを利用するプロジェクト

Mavenコンテナを利用してビルドします。 /root/.m2ディレクトリの保存先をホストサーバすることで、ダウンロードにかかる時間を短縮できます。

docker run -i --rm --name maven -v <プロジェクトのルート>:/target -v /root/.m2:/root/.m2 -w /target maven:3.3.3-jdk-8 mvn package
  • Golanのプロジェクト

プロジェクトのルート用意したビルド用のスクリプト(build.sh)を利用します。 ビルド用のスクリプトではgo get/go buildを行います。

docker run  -v <プロジェクトのルート>:/go/src/project/ golang:latest \ sh /go/src/project/build.sh

まとめ

以上、イートスマートでのJenkinsの利用方法を書きました。 利用を開始してから6年近く経ちますが、ジョブの数・実行時間も増え、キューにジョブが溜まることも増えました。そのため、バッチの実行に関しては、別のツールへの移行を検討しているところです。

webpackを使ったVue.jsのモジュール開発

前回の続きで、今度はクライアント側でVue.jsを使い、前回作ったNode.jsのAPIからデータを取得して表示するページを作りたいと思います。

eatsmart.hatenablog.com

インストール

まず、プロジェクトのフォルダを作り、初期化します。

$ npm init

次に、webpack系のライブラリをインストールしました。

$ npm i -D webpack webpack-cli webpack-dev-server

その次に、Vue.jsをインストールしました。

$ npm i --save vue

その後、css系のライブラリと、js系のライブラリをインストールしました。 vue-loaderは最新版をインストールすると、

vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.

というエラーが出て、こちらhttps://github.com/symfony/webpack-encore/issues/311を参考に、ver14を使うようにしました。

# vue
$ npm i -D vue-loader@14 vue-template-compiler css-loader sass-loader
# babel
$ npm i -D babel-loader @babel/core @babel/preset-env babel-preset-es2015
# ajax通信用
$ npm i -D axios

設定

まず、開発用サーバーとビルドの設定をpackage.jsonに追加します。

  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "test": "echo \"Error: no test specified\" && exit 1",
+    "dev": "webpack-dev-server --hot",
+    "build": "webpack -p"
  },

次に、webpack用の設定ファイル(webpack.config.js)を作成します。

module.exports = {
    // エントリポイントとなるファイル
    entry: './src/index.js',
    // ビルド先設定
    output: {
        filename: 'bundle.js',
        path: `${__dirname}/dest`,
    },
    module: {
    // ローダー設定
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.(css|sass|scss)$/,
        loader: 'sass-loader',
      },
    ]
  },
  resolve: {
    extensions: ['.js', '.vue'],
    alias: {
      vue$: 'vue/dist/vue.esm.js',
    },
  },
  // 開発サーバ設定
  devServer: {
    contentBase: 'dest',
  },
}

実装

いよいよVue.jsでの実装ですが、まずエントリポイントとしてsrcフォルダのindex.jsを以下のようにしました。 componentsフォルダのTimeineの内容を#appに出力します。

import Vue from 'vue'
import Timeline from './components/Timeline'

new Vue({
    el: '#app',
    components: { Timeline },
})

次に、src/componentsフォルダのTimeline.vueファイルに実体を実装します。

Vue.jsではHTMLのtemplateとjsの処理を同一ファイルに記述します。 jsの処理としては、APIサーバーからtimelineの一覧を取得し2件表示し、「もっと見る」で2件づつ追加するようにします。

  • はじめにAPIサーバーから一覧を取得する
  created:function(){
    var items = this.items;
    axios.get(ENDPOINT_TIMELINE_LIST+'?name='+this.name)
    .then(function(res) {
      for(var i=0;i<res.data.length;i++){
        items.push(res.data[i]);
      }
    });
  },
  • 「もっと見る」の処理
  computed:{
    showCount:function() {
      return this.first + this.count * this.step;
    },
    hasMore:function() {
      return (this.showCount < this.items.length);
    }
  },
  methods: {
    more:function() {
      this.step++;
    }
  }
}
  • 処理をバインドするテンプレート
<template>
<div class="snsWrap">
  <div class="feedBox" v-for="(item, index) in items">
    <span v-show="index < showCount" v-html="item"></span>
  </div>
  <button v-if="hasMore" v-on:click="more">もっとみる</button>
</div>
</template>

確認

開発サーバーはnpm run devで起動できます。

$ npm run dev

> timeline@1.0.0 dev /XXXXX/XXXX
> webpack-dev-server --hot

ℹ 「wds」: Project is running at http://localhost:8081/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from dest
⚠ 「wdm」: Hash: 8fa2fd3d7a6fca1710e3
Version: webpack 4.20.2
Time: 1760ms
Built at: 2018-10-06 17:20:11
    Asset     Size  Chunks                    Chunk Names
bundle.js  254 KiB       0  [emitted]  [big]  main
Entrypoint main [big] = bundle.js

・・・

WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
  bundle.js (254 KiB)

WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
  main (254 KiB)
      bundle.js

と起動でき、ブラウザでhttp://localhost:8081/にアクセスする事で、動作の確認ができました。

ビルド

jsファイルのビルドは、npm run buildでできます。

$ npm run build

> timeline@1.0.0 build /XXXXX/XXXX
> webpack -p

Hash: d77cd19e816f5c62ca5c
Version: webpack 4.20.2
Time: 3393ms
Built at: 2018-10-06 18:33:39
    Asset     Size  Chunks             Chunk Names
bundle.js  104 KiB       0  [emitted]  main
Entrypoint main = bundle.js
 [1] (webpack)/buildin/global.js 509 bytes {0} [built]
[31] ./src/index.js + 4 modules 5.5 KiB {0} [built]
     | ./src/index.js 129 bytes [built]
     |     + 4 hidden modules
    + 30 hidden modules

となり、destフォルダにbundle.jsが出力されます。

最終的に、コンテンツのHTMLにbundle.jsを組み込む事で、以下のページができました。

mognavi.jp

まだ理解できていなくてオマジナイ的な所も多いですが、とりあえずシンプルな形での実装ができました!

RailsでMinitestを実行する

EatSmartの新人エンジニアです。現在、社内向けツールの開発をRuby on railsを用いて行っています。 今回、テストコードを書くにあたりMinitestを使用したので実装内容を振り返ってみいたいと思います。

テストに関する知見が浅いのでこちらの本を読みました。

テスト駆動開発

テスト駆動開発

簡単に「テスト駆動開発について」話します。

テスト駆動開発とは

・機能そのものが存在しない状態でテストだけを先に書きそのテストを通すことを目的に最小限の実装を行う

・このサイクルを繰り返すことによりプログラムを作成する開発手法のこと

【3つのステップから構成される】

◆レッド

1 プロダクトコードを書く前にテストコードを書きそれが失敗することを確認する ・大切なことは実装コードが一切なにも書かれていなくてもとにかく先に書くこと

◆グリーン

2 テストに成功するようにテストコードを書く

・どんな手段であったとしてもとにかく成功させる

リファクタリング

3 プログラムの振る舞いを変えないようにプロダクトコードの重複などを整理する ・意味のあるソースコードにもっていく

なぜテストコード書くのか?

◆コマンド一発で速く、かつ楽に動作確認ができる

◆今後、メンテナンスをすることになる他の開発者のために書く

・コードを書いた人の意図や頭のおく

◆将来、Railsやライブラリのアップデートするときのために書く

使用したライブラリ

gem 'minitest'

gem 'minitest-doc_reporter'

実際のコード

【コントローラーの単体テスト

require'test_helper'  #デフォルト設定
require 'minitest/autorun'  #ファイルを実行するだけでテストが実行される

class FoodcategoriesControllerTest < Minitest::Test

    def test_category_search0
        c = FoodcategoriesController.new
        c.category_search0('01')
        xml_result = c.instance_variable_get('@xml_result')
        p xml_result

        status = c.instance_variable_get('@status')
        assert_equal(status, '0')

        largecategoryname = c.instance_variable_get('@largecategoryname')
        assert_equal(largecategoryname, 'お菓子')

        largecategorycode = c.instance_variable_get('@largecategorycode')
        assert_equal(largecategorycode, '01')
    end
end

インスタンス変数を確認するメソッド

instance_variable_get

レシーバが持っているインスタンス変数の値を返す

def test_category_search0
        c = FoodcategoriesController.new
        c.category_search0('01')
    
    xml_result = c.instance_variable_get('@xml_result')
    p xml_result

        largecategoryname = c.instance_variable_get('@largecategoryname')
        assert_equal(largecategoryname, 'お菓子')

end

テスト実行コマンド

$rake test TEST=test/controllers/foodcategories_controller_test.rb

テスト結果は以下のように返ってきました

Minitest::Result
 list0 


2 tests run in 10.833853009 seconds.
Errors: 0  | Failures: 0  | Skips: 0

ImageFluxの導入について

イートスマートでは複数のサービスを運営していますが、各サービスで画像を扱う際に、オリジナル画像から独自でサムネイル画像を作成しています。 その場合、サイトリニューアル時に、速度低下やディスク使用量、ディスクI/O負荷等の懸念がありました。 それらを解消する為に、CDNでキャッシュし、画像の加工を柔軟に扱う目的で、今回ImageFluxを導入することにしました。

CDNとは

コンテンツ・デリバリー・ネットワーク(Contents Delivery Network)の略で、ウェブコンテンツを配信するのに最適化されたネットワークのことを意味します。 Webサイトにある画像や動画・CSSなどの静的コンテンツを、Webサイトが管理されている「サーバー」とは、別の(CDN)サーバーにキャッシュし、そのサーバーで代わりに配信することで負荷分散され、Webサイトの表示速度向上が見込めます。

ImageFluxとは

ImageFluxとは、オリジナル画像をベースに画像の拡大・縮小/切り抜き/フォーマット変換等を、URLパラメータ指定することで生成してキャッシュし、代わりに配信してれるクラウドサービスです。

www.sakura.ad.jp

導入の目的

  • サイトリニューアルを行う際、画像サイズの変更等を容易行える

  • サイト速度向上が見込める

  • サムネイル画像を独自で持たないことで、ディスク使用量の削減が見込める

  • (サムネイル画像を作成しない事で)サーバーのディスクI/O負荷を軽減できる 等

導入して分かったこと(2018/9/20時点)

  • 画像は、JPEGPNG、GIFに対応

  • 拡張子と画像形式が一致していない場合の扱い
    画像判別には拡張子を利用しておらず、対応画像(JPEGPNG、GIF)であれば問題ないそうです。
    ※拡張子が無くても問題なし

  • 対応外(BMP等)の画像について
    対応外の画像が入力された場合、ステータスコード500を返すそうです。
    ※対応外の画像は、ImageFluxを通さない対処が必要です。

  • ImageFluxでSSL通信を採用する場合、独自ドメインのみ対応

  • WebPの対応ブラウザは ChromeOperaの2種類で、どちらもiOSへは未対応とのことでした。
    ChromeAndroid)、Android ブラウザへは対応

導入手順

導入手順について簡単に記載します。

  1. 契約書の記載、送付

  2. SSL証明書発行
    SSL証明書ですが、Let's Encryptは(3ヶ月更新の為)運用負荷が掛かりNGでとのことでした。結果、JPRSドメイン認証型(972円/1年)を採用しました。

  3. SSL証明送付
    発行した証明書をImageFlux担当者に送付して、ImageFlux側で証明書を設定してもらいます。

  4. ImageFluxアカウント発行
    ImageFlux側の作業が完了するとアカウントが発行されます。
    ※ImageFlux+SSLを採用した場合、発行迄に5営業日程掛ります。

  5. オリジン設定
    ImageFluxの管理コンソールにログインして、オリジンサーバーの追加を行います。
    ※オリジンサーバーを追加すると、ImageFlux側のドメインが発行されます。

  6. DNS設定
    DNSに、5)で発行されたImageFluxのドメイン(CNAME)を設定します

今回は導入迄ですが、導入結果について改めて報告できたらと思います。