インターネット上のDataSnapサーバへRestAPI(httpsではなくhttp)を発行する
下記のとおり簡単なサンプルプログラムをFMXで作成したのですが、
iOS及びAndroidの場合、RESTRequest.Executeを実行後、10KB程度のJSONデータを取得するのに
8秒もかかってしまいます。(NetHTTPRequest.Getでも同様)
同じサンプルプログラムでターゲットプラットフォームを
Windowsに切り替えて実行すると1秒もかからず、取得できます。
Wi-Fiの問題ではないかと思い、「HTTPBot」というiOSアプリのRestAPIクライアントで
実行するとWindowsと同様1秒もかからず、取得できました。
Delphiのバージョンは最新の「Embarcadero® Delphi 11 バージョン 28.0.44500.8973」です。
ちなみに自社のホームページのURLで実行するとHTMLは47KB程度ですが
1秒程度で取得できました。
状況的にDataSnap側の問題ではないように思うのですが、
FMXのマルチデバイスアプリで何か通信の問題があるのでしょうか?
<サンプルプログラム抜粋(URLは伏せてあります)>
procedure TForm1.Button1Click(Sender: TObject);
var
RESTClient: TRESTClient;
RESTRequest: TRESTRequest;
RESTResponse: TRESTResponse;
begin
RESTClient := TRESTClient.Create(nil);
RESTRequest := TRESTRequest.Create(nil);
RESTResponse := TRESTResponse.Create(nil);
RESTRequest.Client := RESTClient;
RESTRequest.Response := RESTResponse;
try
RESTClient.BaseURL := 'http://xxx.xxx.xxx.xxx:8080/';
RESTClient.Params.AddHeader('Content-Type', 'application/json; charset=utf-8');
RESTClient.Params.AddHeader('ID', '1');
RESTClient.Params.AddHeader('Password', '1');
RESTRequest.Method := rmGET;
RESTRequest.Resource := 'api/v1/test/datalist';
RESTRequest.Response := RESTResponse;
RESTRequest.Execute;
memo1.Lines.Add(RESTRequest.Response.JSONValue.ToString);
finally
RESTResponse.Free;
RESTClient.Free;
RESTRequest.Free;
end;
end;
TRESTClientは使ったことがないのですが
HTMLではなくてJSON形式のデータを要求する場合は
コンテンツタイプを指定するパラメータに
application/json
を指定する必要があるかと思います。
指定しない場合はHTML形式のデータが返ってくると思って
待機してしまうので時間がかかっているものと思われます。
追加情報ですが
RESTRequest.AcceptEncoding:='gzip, deflate, br';
を入れると圧縮されて、速くなるみたいです。
takeさん、mamさん
ご回答大変ありがとうございます。
残念ながら、下記のContetType、AcceptEncodingのロジックを
それぞれ入れて試しましたが、現象は変わらずでした。
DataSnap側の問題の可能性も考えてみたいと思います。
①
RESTClient.ContentType := 'application/json';
②
RESTClient.Params.AddHeader('Content-Type', 'application/json');
③
RESTRequestParameter := RESTRequest.Params.AddItem;
RESTRequestParameter.ContentType := ctAPPLICATION_JSON;
RESTRequestParameter.name := 'Content-Type';
RESTRequestParameter.Value := 'application/json';
④
RESTRequest.AcceptEncoding:='gzip, deflate, br';
チェックした覚えがないのに解決になってしまいました。
まだ未解決の状態です。
この辺は参考になりませんか?
RESTデバッガが付いてるの知らなかった・・・
Delphi Community Edition Meet up ! - REST 編
https://qiita.com/CYonezawa/items/e20c3018c6eb6e1200a0
【Delphi】REST クライアントライブラリを使う
https://qiita.com/ht_deko/items/eb3f987c50012109e781
takeさん、ありがとうございます。
参考にはなりませんでした。
DataSnap側から問題切り分けをしてみたいと思います。
解決するまで経過報告させていただきます。
経過報告なります。
DataSnap側ではOracleDBからデータを取得し、JSON形式で返却していました。
問題切り分けのため、下記メソッドのとおり、返却するJSONデータを予めファイルに保存しておき、
APIのリクエストを受信時に当該ファイルの中身をそのまま戻り値に設定して試しましたが、
やはり8秒ほど時間がかかりました。
今後、下記を試してみたいと思います。
①RestAPIのリクエスト時のパラメータ等に違いがないかどうかをサーバ側で確認する。
②httpではなくhttpsで通信してみる。
※最初のご質問に一部訂正がありました。申し訳ございません。
10KB程度のJSONデータではなく、116KBでした。ファイルを抜き出したとき、欠けていました。
<DataSnap側のRestAPIのメソッド>
function test.datalist(Key: String): TJSONValue;
begin
Result := TJSONValue(TJSONObject.ParseJSONValue(TFile.ReadAllText(ExtractFilePath(Application.ExeName) + 'datalist.json')));
end
経過報告なります。
②httpではなくhttpsで通信してみる。
⇒nginx経由ですが現象同じでした。遅いです。
レスポンスヘッダの内容や返り値にエラーを示すものが含まれていませんか?
タイムアウトかなにかが起きているものと思われます。
tateさん
エラーを示すものは含まれていません。
DataSnap側では遅延なく処理を終えていますので、
クライアント側に問題があるのだと思います。
エンバカデロ・テクノロジーズ社に問い合わせてみます。
下記の様に書かれていました。
AParameter := RESTRequest.Params.AddItem;
AParameter.ContentType := ctAPPLICATION_JSON;
AParameter.name := 'Content-Type';
AParameter.Value := 'application/json';
JSON取得に この方法でだめなら
RESTRequest.Params.AddHeader('Content-Type', 'application/json');
はどうですか?
さらに強制的にしていする場合は
RESTRequest.Body.Add(AJSONString, ctAPPLICATION_JSON);
のようにしましょう
RESTRequest.AddParameter('Content-Type'、'application / json'、TRESTRequestParameterKind.pkHTTPHEADER、[poDoNotEncode]);
tateさん
何れも試してみましたが、だめでした。
色々とお調べいただいて、本当にありがとうございます。
感謝いたします。
エンバカデロ・テクノロジーズ社には問い合せをしました。
何らか結果が出ましたら、ご報告いたします。
取り急ぎ、ご報告ですが、
問題切り分けのため、jsonファイルにhtmlタグをつけて、HTMLファイルにし、WEBサーバ上で
直接ダウンロードするだけに単純化しました。
RESTRequest.Executeは速く、
memo1.Lines.Addの実行でやたらと遅いことがわかりました。
http通信ではなく、TStream系の問題がありそうです。
ただし、jpgなど画像をダウンロードし、700KBの画像をTImageに表示するのは速いです。
RESTClient.BaseURL := 'http://xxx.xxx.xxx.xxx:8080/';
RESTRequest.Resource := 'datalist.html';
RESTRequest.Execute;
memo1.Lines.Add(RESTRequest.Response.JSONValue.ToString);
エンバカデロ・テクノロジーズ社からはまだ返答がない状態です。
ただ、RESTRequestの問題ではなく、下記のTMemoのLines.Addで遅いことがはっきりしました。
通常そのような使い方はしませんので、本件、CLOSEさせていただきます。
memo1.Lines.Add(RESTRequest.Response.JSONValue.ToString);
実際は、RESTRequestでJSONデータを取得後、TGridPanelLayoutへの表示で非常に時間が掛かっていたのですが、
描画前後にBeginUpdate、EndUpdateを実行すると問題ない速度になりました。
RESTRequest実行前後でどこで時間が掛かるのか、TMemoでログを表示して遅い部分を判断していたのですが、
実行イベントが一通り完了してから、ログが表示されていたので、RESTRequestの実行に問題があると
誤認したことが問題でした。お騒がせ致しました。
ツイート | ![]() |