情シスは何度でも甦るさ。

OracleDB/Ruby好きの情シス部員がお送りします

WindowsでJRubyでsinatraでRest API

既存システムとのリアルタイム連携

既存システムのリプレースにあたり、販売管理システムの在庫データをリアルタイムに覗きたいという要望がでてきた。

社内システムの連携は基本はファイルベースでバッチ処理で行っているのだが、それではリアルタイムという要件に合致しない。

なので、ここは、販売管理システムにAPI生やすのが良さそうだな。と考え至る。

販売管理システムの開発・保守してるベンダーにその旨を告げると、

「レスト?」「エーピーアイ?」

あぁ、ダメだ。人のこと言えないけど、これは、無理だ。

自分で作るか。ならば、Ruby、キミに決めた!

ただ、単純にSQLでSELECTして返すだけなので、自分でAPI作る方が、まだましか。お金かからんし。 とりあえず、動けばいいし、問題が出たらそん時考えるべ。ということで、自分のスキル的にはRubySinatraでちゃちゃっとプロトタイプ作ってみよう。と思ってみたが、

あ、うちの会社OS Windows縛りあるわ。

Windows Server で Rubyのサービス動かすのは、地雷源をコサックダンスしながら通り抜けるようなものだ。

という程度の認識はあったので、悩む。うーん。。。

帰り道、電車の窓から外を眺めたら、一羽の鳥が。

f:id:ryoben:20171223161432p:plain

「はっ、その手があったか!」

Windows上で、JRubySinatraまで

前置き長かったが、WindowsJavaのWebアプリなら普通に動くだろ。ということで、JRuby試してみる。 JRuby触ったこと無いから、色々検索してみるが、欲しい情報はなかなかないので、手探りでやることに。 なるべく、CRubyを操作するのと同じ流れを意識する。

事前準備
JDKをインストール
そもそも入れてたので、不要だったが。バージョンは既存のシステムの影響でJDK7(古っ)

Jrubyをインストール
Jrubyのサイトから JRuby 9.1.15.0 Windows Executable (x64) を選択してインストール。

bundler をインストール

 jruby -S gem install bundler

jrubyフォルダを作成し、移動して、Gemfile作成。

cd jruby

jruby -S bundle init

Gemfile を開いてsinatraを追加

 gem "sinatra"

bundle install

jruby -S bundle install --path vendor/bundle

app.rbを新規作成

require 'sinatra'

get '/' do
  'Hello Sinatra on Jruby'
end

ここで、 jruby -S bundle exec jruby app.rb

で動くかと想いきや、エラーにもならず、沈黙するのみ。 ので、rackupで動かすことに。

config.ru を新規作成

require 'sinatra'
require File.expand_path '../app.rb', __FILE__

run Sinatra::Application

起動

jruby -S bundle exec rackup

動いた。

f:id:ryoben:20171225141932p:plain

DBに接続する *1

MSのサイトからjdbcのドライバを落としてきて、解凍して中のjarファイルをコピってくる。

JDKのバージョンによって、2種類あるので、自分の環境に適した方のファイルをjrubyフォルダ直下にコピる(JDK9はないみたい・・・)

mssql-jdbc-6.2.2.jre7.jar
mssql-jdbc-6.2.2.jre8.jar

Gemfileに追記

gem "activerecord-jdbcmssql-adapter"

bundle install

jruby -S bundle install

動作検証も兼ねてapp.rb にDB接続のコードをハードコーディング。

app.rb 全書き換え

require 'activerecord-jdbcmssql-adapter'
require './mssql-jdbc-6.2.2.jre7.jar'

# define hash of connection properties
config = {
  url: 'jdbc:sqlserver://192.168.0.1\インスタンス名;databaseName=データベース名',
  adapter: 'jdbc',
  username: 'ユーザー名',
  password: 'パスワード',
  driver: 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
}

# establish connection
ActiveRecord::Base.establish_connection( config )

# define model and inherit from ActiveRecord Base
class Stock < ActiveRecord::Base
  # override table name as necessary
  self.table_name = 'M_STOCK' #テーブル名
end

get '/' do
# query model table, examples:
  stock = Stock.first #何も考えず1件取得
  "倉庫コード:" + stock.WH_CODE + "  数量:" + stock.STOCK_QT.to_s
end

で、起動して、アクセスして、テーブルの値が取れてればOK。
f:id:ryoben:20171225234222p:plain

データ取れた。

接続設定を外部ファイルに切り出したり、ロジックをmodelに切り出したりは、やっとく。

API設計する

ココらへん読んで、URLのエンドポイントについては/stock とし、条件はパラメータとして設定する。 (バージョンはとりあえず、含めてない)
今回でいうと、倉庫と商品コードという条件がパラメータがあるので、以下のようなイメージとなる

localhost:9292/stocks?shop=999999&product=1755

Jsonについては、データを配列として返す。
検索結果の件数とかは、Jsonに書くのではなく、HTTPレスポンスヘッダーに書くのが流行りらしいのでそうする。
sinatraでは、以下のようにセットするとレスポンスヘッダーを返してくれる。

response.headers['X-Stock-Count'] = stock_count.to_s

Jsonの描画については、DBのカラム名Json上の定義名にギャップがあるので、to_jsonなどは使わず、viewsフォルダの配下にerbファイルを作成して値をセットするようにした。

エラーについては、ココらへんにある通り、httpのステータスコードを設定して返す。さらに、Json上でもシンプルなメッセージをセットして返すことにした。

ロットリングは、社内でしか使わない仕組みなので今のとこ対応しない。

warに固めてTomcat上で動かす

まず、この時点でのフォルダ構成はこんな感じになってる。

jruby
├app
│ └app.rb  ・・・main処理
│   
├config
│ └database.yml ・・・データベースの接続情報を外出し
│   
├lib
│ └mssql-jdbc-6.2.2.jre7.jar  ・・・sqlserver用のjdbcドライバ
│   
├log  ・・・ アプリケーションログ用フォルダ
│   
├models
│ └stock.rb ・・・ビジネスロジックを記述
│   
├vendor 
├views
│ ├errors.erb ・・・ エラーを返すJsonのテンプレート
│ └stocks.erb ・・・ stockを返すJsonのテンプレート
│   
├config.ru ・・・ 起動用スクリプト
├Gemgile
└Gemfile.lock

DBの接続情報は外出しして、環境によってDev環境かProductionかを自動で変わるようにした。

で、warblerを使って、warファイルを作成していく。

Gemfileに追加

gem "warbler"

bundle install実行

jruby -S bundle install

完了後、warblerのconfigファイルを作成する。

jruby -S bundle exec warble config

デフォルトで config/warble.rb が作成されるので、これを編集する。以下の記述を追加

  config.dirs = %w(app config lib views models log) #warに含むフォルダを指定。gemファイルのフォルダは不要
  config.bundle_without = []  # bundler用のおまじない

war作成

jruby -S bundle exec warble

で、実行フォルダに、jruby.war (フォルダ名.war)が作成される。

次にTomcatをダウンロード&インストール。
公式サイトから、32-bit/64-bit Windows Service Installer を選択してダウンロード。 今回は、Java7なので、8.x系を選択。 インストールは、exeを実行して、次へ次へで。

インストール完了後、管理画面を使うために、conf/tomcat-users.xml を編集。以下の記載を追記して、TOMCAT再起動。

  <role rolename="manager-gui"/>
  <user username="tomcat" password="tomcat" roles="manager-gui"/>

http://localhost:8080 にアクセスして、Manager Appを選択し、でID/Passに先ほど設定ファイルに追記した 値 を入力する。
デプロイ画面に遷移するので、war ファイルを選択し、アップロード&配備ボタン実行!

そして、いざアクセス
http://localhost:8080/jruby/stocks?shop=999999&product=2075

にブラウザでアクセスすると、以下のJsonがちゃんと返ってきた。

{
  "shop": 999999,
  "stocks": [
    {
      "product": "207554013",
      "color": "47",
      "size": "38",
      "count": 1
    },
    {
      "product": "207554013",
      "color": "47",
      "size": "40",
      "count": 1
    }
  ]
}

レスポンスヘッダーにも、ちゃんと件数が表示されてた。

Content-Length   1608
Content-Type    application/json
Date    Wed, 10 Jan 2018 09:43:21 GMT
X-Content-Type-Options  nosniff
X-Stock-Count   2

めでたしめでたし

AWSとOracle Cloudのサービス比較

今、クラウドにするならどこ?

と聞いたら、情シス的には、ほぼ100%AWSと答える。なぜなら、情シスには技術力はあまりないので、みんなが使ってるやつに乗っかりたいからである。

ただ、そうはいかないケースもある。既存の取引先とか、今のインフラの環境とかもろもろの事情で、Oracleクラウドも検討せなあかんときもある。

さらに、コストメリットでいうと、AWSより安いってラリーが言い切ってるし、現にOracle DBの費用だけの勝負ならオラクルクラウドの方が安い気もする。

でもさ、AWSのあの機能はOracle Cloudにあるの?

という疑問。いや、そもそも情シスごときが使いこなせないサービスも山ほどあるんだけどさ、でも、やっぱり今の世の中AWSと比較しないと判断がしづらいよね。

というわけで、AWSの主なサービス・機能でOracleクラウドで対応するサービスを洗い出してみました。

カテゴリー サービス AWS Oracle Cloud
ストレージ オブジェクトストレージ S3 Object Storage
永続ストレージ EBS Block Volumes
ファイルストレージ Elastic File System File Storage
アーカイブ Glacier Archive Storage
オンプレからのデータ転送 Storage Gateway Database Backup(oracleDBのみ)
コンピューティング 仮想OS EC2 Compute
サーバレス処理 Lambda ない。出ると噂
リソースの自動拡張 Auto Scaling Auto Scaling
データベース フルマネージドDB RDS Database Cloud Servis(DBCS)
KeyValueストア DynamoDB NoSQL Database Cloud Service*1
インメモリキャッシュ Elastic Cache Oracle Application Container Cloud Service(キャッシュ利用)
DWH基盤 Redshift Database Exadata Cloud Service
ネットワーク 仮想プライベートクラウド VPC Virtual Cloud Network(VCN)
CDN CloudFront ない
DNS Route53 DNS
専用線接続 Direct Connect FastConnect
ロードバランサ Elastic Load Balancing Load Balancing
開発者ツール ソースコントロール CodeCommit Developer Cloud Service
ビルドとテスト CodeBuild Developer Cloud Service
デプロイ自動化 CodeDeploy Developer Cloud Service
管理者ツール モニタリング CloudWatch Infrastructure Monitoring、Application Performance Monitoring
構成管理ツール CloudFormation、OpsWorks Orchestration
分析 MR EMR Big Data Cloud Service、Big Data SQL Cloud Service
ストリーミング Kinesis Event Hub
メッセージング メッセージキュー SQS Messaging
モバイル通知 SNS ない
Eメール配信 SES Email Delivery*2
セキュリティ ID管理 IAM Identity and Access Management(IAM)
ソフトウェア マーケットプレイス Marketplace Marketplace
デスクトップ仮想化 仮想デスクトップ Workspace ない
アプリ配信 AppStream ない
移行 データベース移行 Database Migration Service ない?
サーバ移行 Server Migration Service Ravello Cloud Service

第一印象としては、結構対応してきてるなぁという感じ。
実際使えるかどうかは別だが、急ピッチで機能追加もしており、Oracleの本気度は伝わってくる。

いや、でも、やっぱAWSがいいなぁ。

なお、これを調べて一番胸にぐっときたのは、Developer Cloud ServiceのCI機能として、ハドソンの名前があったこと。
誰か、もうやつを引退させてやってくれよ・・・。

*1:本番リリースはまだ

*2:本番リリースはまだ

iPhoneを企業導入することになってMDMとか運用管理とかやってみた

前提

  • ユーザー企業の情シス
  • 社員、店にiPhoneを配布することになった
    • 社員配布数:100端末以上
    • 店配布数:数百
  • 検証のため、一部先行して導入
  • iPhoneは、キャリアから調達(Docomo
  • キャリアのMDMサービスを使用(あんしんマネージャー)  
     

全社展開に向けて、運用管理を考えなきゃ。

検証当初に困ったこと

  • キャリア提供のMDMは機能不足な気が
    • iOSのユーザーによるアップデートを無効にできない
    • サポートへの問い合わせに時間がかかる。手段がTELしかなくて、ログの文言をいちいち口頭で伝えるのが面倒
    • アプリ配信時にユーザーにApple IDのパスワードを入力させなければならない 
       
       

そもそも、キャリアの提供するMDM機能ってイケてるのか?

色々調べた結果

キャリアの提供するMDMはイケてる

  • あんしんマネージャーはVMWare社のAirWatchという製品を提供
    • この製品によりVMWareは、ガートナーにリーダーと評価されてる
    • Softbankでも提供している模様。auは多分違う
  • そもそもAppleが操作を許可してないことはMDMからも操作できない(iOSのアップデートは無効化できない)
  • サポートは時間がかかるが丁寧で確実ではある
  • アプリインストールの自動化はAppleが提供する企業向けプログラムMDMを組み合わせれば実現可能

f:id:ryoben:20171113115150p:plain:w480
エンタープライズ モビリティ管理のガートナー マジック クアドラント(2017)

Appleが提供する企業向けプログラム

  • Device Enrollment Program(DEP) ※AirWatch対応
    • 端末の初期設定(キッティング)の自動化
    • アプリ配布のサイレント・インストール、 iOSの更新。
  • Volume Purchase Program(VPP) ※AirWatch対応
    • 企業向けAppStore
    • アプリライセンスの一括管理
    • AppleIDをユーザーが意識せずにインストール可能
  • Apple Developer Enterprise Program
    • AppStore(VPP含む)通さずにアプリ配布が可能(自社サーバ経由)
    • 開発ツールの提供やAppleのサポートがある
    • 大企業でAppを内製してる企業向けなので不要
  • AppleCare for Enterprise
    • 企業向け端末保証。キャリアの保証があるので不要

ビジネス - プログラム - Apple(日本)

Device Enrollment Program(DEP)

  • 初期設定の自動化
    • iPhoneを箱から出して、最初にやる設定作業を自動化できる。
      • これがないとUSBでPCにつなげて設定する必要がある
      • Apple Storeやキャリアから購入すると、端末にDEPの設定をした状態で出荷が可能
    • 端末側でのプロファイルの削除の無効化が可能
  • アプリの配布
    • アプリのサイレントインストールが可能になる
    • iOSの更新もできる  
       

Docomoから購入する場合は、ある程度設定済みで納品されるので、効果は薄い(ZEROではない)

参考: mdm-richard.blogspot.jp

Volume Purchase Program(VPP)

  • 企業向けAppStore
    • 組織に対してライセンス数を購入する(有料無料問わず)
    • 購入したライセンスを端末に摘要する
    • 法人のクレジットカードが必要
  • AppleIDをユーザーが意識せずにインストール可能
    • インストール時にAppleIDのパスワードが入力不要 → ITリテラシーが低いとパスワード入力は意外とつまづく
    • なぜか、パスワード2回入力が必要
    • 電波の関係か、ちゃんとパスワード2回入力しても、インストールできないことも
    • うちの会社では、初めてのアプリ配信では、20%しかアプリのインストールに成功せず
    • プッシュ配信でのインストールだったので、失敗すると再度プッシュしてあげる必要がある(成功するまでプッシュを繰り返す毎日)

まとめ

  • キャリアのMDMだけでも、運用管理は可能
    • ITリテラシーが低い場合は、VPPは有効化した方がよさげ
      • ただ、Apple側への申請が結構大変
        • DUNS番号の登録でかなり時間が取られる。
  • たまにちゃんと動かないこともある
    • プロファイルでアプリ削除を無効にしたはずなのに、削除できちゃった
    • 手動削除したら、アプリをプッシュできなくなっちゃった  
       

iOSも結構な勢いでバージョンアップするので、MDM側もそれに追いつくのが大変。細かい不具合は許容するしかない。
まだ、うちも検証中だけど、スモールスタートして運用手順を確立してから全社に拡大していった方が良い。

なお、BYODで行う場合は、システム部門は下手にデバイス管理すると、結構死ねる気がする。使う側も個人端末に監視エージェントとか入れられるの嫌だろうし。そこは、端末を管理せずに、N/Wとアプリ側でうまいこと制限した方が得策な気が。