【B4】Delphi/C++テクニカルセッション「DataSnapユースケース研究」
多層技術の概要と最適化、実践テクニック
エンバカデロ・テクノロジーズ
エヴァンジェリスト 高橋智宏

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

アジェンダ• DataSnapの基礎– プロトコル– サーバーメソッド• 現実的な構成例– DMZ + ロードバランス– ライフサイクル• DB接続のレイヤ– 親クラス– FireDAC• デモ– マルチデバイス対応• Tips– HTTPSを利用するには?
– バイナリデータの送受信– サーバーメソッドの非同期呼び出しは?

2

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

1
3

DataSnapの基礎

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

DataSnapとは?
• 2層のC/SGUI, 業務ロジック
SQL文 etc…
アクセスDB

GUIアプリドライバ• 3層構造

業務ロジック
SQL文 etc…

GUI
TCP/IP
HTTP(s)DataSnap
プロトコル

DataSnapサーバ

アクセスDB

4

DataSnap

GUIアプリ

RDBMS

ドライバ

RDBMS

検討事項
• 特にセキュリティ面と運用面– RDBMSの「ユーザー名」と「パスワード」の管理– ネットワーク上、直接RDBMSに接続出来てしまう– dbExpress/dbGo/FireDACなどのDBコンポーネント• コンポーネントのアップデート  全端末への再配布– RDBMSのネイティブクライアントライブラリ• サポートされているプラットフォームは??
• インストーラ• モジュールのアップデート  全端末への再配布– ビジネスロジックやSQL文がクライアント側に存在• アプリケーションのアップデート  全端末への再配布– ファイアウォール
etc…
Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.
本文書の一部または全部の転載を禁止します。

5• TCP/IP

DataSnapプロトコル– デフォルト211番ポート– SSL, IPv6 は未サポート• HTTP– デフォルト80番ポート– HTTPSもサポート

クライアントからのリクエストのサンプル{"method":"connect","params":"drivername":"DATASNAP","port":"211","communicationprotocol":"tcp/ip","hostname":"127.0.0.1","DriverUnit":"DbxDatasnap",....]}{"method":"execute","params":[{"fields":[1,false,"Dbx.MetaData","GetDatabase"]}]}{"method":"reader_close","params":[1,0]}{"method":"disconnect","params":[0]}• RPC形式– サーバーメソッド• 要は、RDBMSのストアドプロシージャと同じ扱い!!
• パラメータ & 戻り値

サーバーからのレスポンスのサンプル– in, var, out, return• 組み込みの非同期呼び出しは無い– インスタンスのライフサイクル• Server, Session, Invocation– Callback, Filter, Event• データフォーマット
– JSON(JavaScript Object Notation){"result":[0,"DataSnap",2]}{"result":[{"rows":[0]},{"data":[1,`]},{"table":[{"fields":[0,false,1,0,true]},{"columns":[13,["QuoteChar",26,0,0,0,16,0,0],["ProcedureQuoteChar",26,0,0,0,16,0,0],["MaxCommands",6,0,0,0,0,0,0],["SupportsTransacti
ons",4,0,0,0,0,0,0],["SupportsNestedTransactions",4,0,0,0,0,0,0],["SupportsRowSetSize",4,0,0,0,0,0,0]...
...
...

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.
本文書の一部または全部の転載を禁止します。

6

サーバーメソッドとは?
• リモートプロシージャコール(RPC)– http://ja.wikipedia.org/wiki/RPC• サーバーメソッドの実装 & エクスポート– 引数の型– 戻り値– 例外は?
– クライアント用プロキシは?

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.
本文書の一部または全部の転載を禁止します。

7

サーバーメソッドで扱える型•基本型––––––––––––––––––

AnsiString
Boolean
Byte
Currency
TDateTimeTDBXDate
TDBXTime
DoubleInt64
Integer
LongInt
OleVariantSingle
ShortInt
SmallInt
String(UnicodeString)
WideString
TStream• DBXValue型••••••••••••••••••••TDBXAnsiStringValueTDBXAnsiCharsValueTDBXBcdValueTDBXBooleanValueTDBXDateValueTDBXDoubleValueTDBXUInt8ValueTDBXInt8ValueTDBXInt16ValueTDBXInt32ValueTDBXInt64ValueTDBXJSonValueTDBXReaderValueTDBXSingleValueTDBXStringValueTDBXTimeStampValueTDBXTimeValueTDBXWideCharsValueTDBXWideStringValueTDBXStreamValue• テーブル型•••

TDataSet
TParams
TDBXReader• JSON型•••••TJSONArrayTJSONNumberTJSONObject
TJSONStringTJSONValue

基本型

NULLサポート無し。
varや戻り値もOK

DBXValue型

NULLサポートあり。
varや戻り値はNG

テーブル型

varや戻り値もOK

配列型(array of …)

サポートされません。
TJSONArrayを使う

Copyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.
本文書の一部または全部の転載を禁止します。

82
9

現実的な構成例

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

システム構成例• 複数のDataSnapサーバーをロードバランス
GUI

DMZ
HTTPS

HTTP

リバースプロキシ
DataSnap
プロトコル

ApacheNginx
ロードバランサ etc…

DataSnapサーバ

FireDAC

DataSnap

GUIアプリ業務ロジック
SQL文 etc…

RDBMS

TCP/IP
社内端末

10

ドライバ

DB管理者等

ロードバランスすると…
• サーバーメソッド用クラスのライフサイクルとの兼ね合い– Session (デフォルト)• クライアントアプリケーションからの接続とインスタンスが結びつく• ステートフル– ステート(セッション情報)のリプリケーションは??

– Invocation• サーバーメソッドの呼び出しごとにインスタンスの生成&破棄を繰り返す• ステートレス

リクエスト
レスポンス

クライアント11

ロードバランサクラス
インスタンスクラス
インスタンスクラス
インスタンスクラス
インスタンスクラス
インスタンス接続
クエリー実行
切断

DataSnapサーバ

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

RDBMS

3
12

DB接続のレイヤ

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

サーバーメソッドクラスの構造• 親クラス– TComponent, TDataModule, TDSServerModule• データアクセス– IBExpress– dbExpress– dbGo(ADO)– FireDAC
etc…

• 親クラスをTComponentで、データモジュールをプーリング?
• コネクションプーリング– 独自実装– FireDACCopyright ©2009 Embarcadero Technologies, Inc. All Rights Reserved.
本文書の一部または全部の転載を禁止します。

13

DBアクセスモジュールの設計• FireDACで使用する主なコンポーネント– TFDConnection– TFDTable / TFDQuery など– TFDPhysIBDriverLink など– TFDGUIxWaitCursor (ProviderプロパティはConsole)• データモジュール– データベースアクセスをカプセル化– サーバーメソッドの処理とデータベース処理を分離

サーバー
メソッド群

データモジュールRDBMS

DataSnap
クライアントアプリ
14

DataSnap
サーバープロセス

デモ- 複数デバイス対応 -15

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

サーバー & クライアントの例• サーバー– Delphi 64bit スタンドアロン– TCP/IP + HTTP
– TComponent(親) + データモジュール– FireDAC• クライアント– Delphi VCL– Delphi iOS– Delphi Android– C++Builder OS X
16

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

Tips

17

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

HTTPSを利用するには?
• リバースプロキシでHTTPSを処理し、HTTPのDataSnapにリダイレクトする– http://blogs.embarcadero.com/teamj/2013/10/29/4096/

DataSnap

GUIアプリ

HTTPS

HTTP

リバースプロキシ
DataSnap
プロトコル

DataSnapサーバ• DataSnap単体でもOpenSSL(Indyで利用)を使用したHTTPS接続を受付可能– http://blogs.embarcadero.com/teamj/2013/10/30/4103/• Windows ServerのIISを利用する– ISAPI(DLL)モードでDataSnapサーバーを実装– IIS自体でHTTPSを処理する• クライアントは、プロトコルにhttpsを指定するだけでOKバイナリデータの送受信• TStreamを使う– 高速– もちろん、TJSONAarrayにByte配列を入れる方法もOKですが…
Server側

Client側

function TTestServer.Download(…): TStream;var
memStream: TBytesStream;
begin
Result := nil;
FileName := …;
if FileExists(FileName) then
begin
memStream := TBytesStream.Create;memStream.LoadFromFile(FileName);
Result := memStream;
end;
end;

procedure TForm1.BtnClick(Sender: TObject);var
stream: TStream;b: Byte;mem: TBytesStream;
begin
stream := TestSV.Download('xyz.jpg');
mem := TBytesStream.Create;
while stream.Read(b, 1) = 1 do
mem.Write(b, 1);…
mem.Free;end;

19

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。

サーバーメソッドの非同期呼び出しは?
• VCL(Windows)向けなら OmniThreadLibrary が便利– http://code.google.com/p/omnithreadlibrary/– 最新版は 3.03a で、Delphi 2007〜XE5 (32bit/64bit)をサポート• VCL以外(FireMonkey, iOS, Android)は– TThreadの派生クラスとSynchronizeメソッドなどを組み合わせる
20

本文書の一部または全部の転載を禁止します。本文書の著作権は、著作者に帰属します。