マイクロサービスを10分で作る-郵便番号検索サービス-Apache Camel


今回は試しに郵便番号から住所情報を検索できるサービスを作ってみる。

マイクロサービスとは

このブログがよくまとまっていると思う
http://techlife.cookpad.com/entry/2014/09/08/093000

良い点

  • 共通で利用できるサービスだったら言語関係なく呼べばいいだけなので便利!
  • もしサービスが古くなって作り直しとなっても、作り直しの範囲が小さくなる。

悪い点

  • サービスの数が増えるので、運用するサービスが増える。

今回のサンプル限定で考えると

良い点

  • 各個別のアプリで郵便番号DBを持たなくて済む
  • 郵便番号テーブルの最新化が1箇所で済む
  • 郵便番号検索プログラムを個別のアプリで作らなくて済む
  • 検索プログラムにバグがあっても、検索サービスだけ修正すればいいだけ。

Apache Camelを使って作る事

英語の記事なので読める人だけ。
http://java.dzone.com/articles/apache-camel-micro%C2%ADservice

Apache Camelとは

Apache Camel ™ is a versatile open-source integration framework based on known Enterprise Integration Patterns.

ということで、色んなシステムと統合できるフレームワークであり、メッセージ流通なフレームワーク。
Apache Camel (Java)を使うと開発が楽になる7つの理由

ちなみに、Camelが提供しているコンポーネント一覧はこんな感じ
https://twitter.com/davsclaus/status/506728047928942592/photo/1
全ては既存のOSSのライブラリをラップして動いているだけだけ。
とうとう170コンポーネント以上になったという事らしい。

環境

  • Tomcat7, 8
  • Java7, 8
  • Apache Camel 2.14.0
  • MySQL

完成したものを動かしてみる

作り方は下のほうに書くので、どういう動作結果になるかをまず見せる。

下記のURLにアクセスすると

アクセス結果

{"id":100000000,"ken_id":13,"city_id":13101,"town_id":131010000,"zip":"100-0000","office_flg":false,"delete_flg":false,"ken_name":"東京都","ken_furi":"トウキョウト","city_name":"千代田区","city_furi":"チヨダク","town_name":"","town_furi":" ","town_memo":"(該当なし)","kyoto_street":"","block_name":"","block_furi":"","memo":"","office_name":"","office_furi":"","office_address":"","new_id":0}

という結果が帰ってくる。

Webブラウザで状態確認もできる

hawtio-default-1.4.19に関してはデプロイの所に記述。
tomcatにデプロイするhawtioというツールでcamelの状態を確認できる。
アクセス方法は下記のような感じ
http://localhost:8080/hawtio-default-1.4.19

1つめのルート定義を確認。
http受信返信(rest)の処理

2つめのルートを確認。
郵便番号テーブルからデータを取得し、結果レコードの1番目を返す。

アクセスしてみる

データが流れた部分に1が付いた

情報がないデータにアクセスしてみる
http://localhost:8881/address/zip?zip=999-0000

データが流れた部分に1が付いた
振り分けられたようですね

トレース機能をONにして、流通データを追跡

start traceボタンをクリックして、データを流してみる。
データが流れた結果を後で確認できるのがトレース機能。

処理速度を確認

テーブルにインデックスを設定していない為、検索に平均20ミリ秒もかかっている事が分かる・・・

作り方

DBの作成 - 1分

ここからsqlをダウンロード
http://jusyo.jp/sql/document.html

mysqlに突っ込む

mysql -u ユーザー名 -p データベース名 < ファイル名

プロジェクトを作成する - 1分

いろいろ設定 - 4分

pom.xmlはこんな感じ
https://github.com/d7kuro/post/blob/master/pom.xml

web.xmlはいつものコピペ
https://github.com/d7kuro/post/blob/master/src/main/webapp/WEB-INF/web.xml

spring.xmlはいつものコピペ
https://github.com/d7kuro/post/blob/master/src/main/resources/spring.xml

spring-db.xmlはいつものコピペ
https://github.com/d7kuro/post/blob/master/src/main/resources/spring-db.xml

spring-camel.xmlはrestConfigurationが付いた。ここでrestのport番号が決まっている

src/main/resources/spring-camel.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring-2.14.0.xsd
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       ">

    <!-- ルートの自動登録(サブディレクトリも検索される) @Componentが対象 -->
    <context:component-scan base-package="post" />

    <!-- SQLコンポーネントの全共通デフォルト値を設定 -->
    <bean id="sql" class="org.apache.camel.component.sql.SqlComponent">
        <property name="dataSource" ref="ds_mysql" />
    </bean>

    <!-- camelルート -->
    <camelContext xmlns="http://camel.apache.org/schema/spring"
        id="post">
        <contextScan />
        <restConfiguration component="jetty" host="0.0.0.0"
            port="8881" bindingMode="json" >
        </restConfiguration>
    </camelContext>

</beans>

プログラムを作る - 3分

郵便番号検索用ルートを作成

src/main/java/post/route/api/AddressRoute.java
package post.route.api;

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.sql.SqlConstants;
import org.springframework.stereotype.Component;

/**
 * 000-0000形式の郵便番号からjsonデータを返す
 */
@Component
public class AddressRoute extends RouteBuilder {

    public static final String CLASSNAME = AddressRoute.class.getSimpleName();
    public static final String IN = "direct:in" + CLASSNAME;

    @Override
    public void configure() throws Exception {
        from(IN).routeId(CLASSNAME)

        // SQL実行
        .to("sql:SELECT * FROM ad_address WHERE zip = :#zip ")

        // 見つからなかった時の処理
        .choice()
        .when(header(SqlConstants.SQL_ROW_COUNT).isEqualTo(0))
            .setBody(constant(null))
        .otherwise()
            // 結果データ作成(List<Map>の0番目のデータを返却)
            .setBody(simple("${body[0]}"))
        .end()
        ;
    }

}

HTTP受信用ルートを作成

package post.route;

import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;

import post.route.api.AddressRoute;

/**
 * HTTP受信 <br>
 * 返却値は自動的にjsonに変換される 
 * 
 */
@Component
public class HttpRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        rest("/address")
        .get("/zip").to(AddressRoute.IN);
    }

}

ビルド・デプロイ - 1分

warファイルを作成

maven clean package を実行
target/post-1.warができる。

ブラウザでCamelの状態を確認・操作できるツールを入手

hawtio-default-1.4.19.warをダウンロード
( http://hawt.io/getstarted/index.html からダウンロード)

tomcatにデプロイ

  • post-1.war
  • hawtio-default-1.4.19.war

上記のファイルを下記のフォルダにコピーするだけ
tomcat/webapps/

全体のソースコード
https://github.com/d7kuro/post