ブログ

【SAP BTP】ネットワーク不調? OData通信エラー時の対処法

この記事をSNSでシェア!

はじめに

まず初めに、私がSAPの開発を行う中で、思ったことを言わせてください。
日本語の記事が少なすぎる。
SAP BTPのサービスを活用していく中で、発生したトラブルや課題の対応・解決手段の模索方法について、調べても出てくるものは英語ばかり。
それでも出てくるならまだいい方で中には何もヒットしない問題に直面することもしばしば・・・
そんな問題解決の一助にもなればと思い、この場にメモとして残します。

今回はその第一弾として、OData通信時にネットワークエラーが頻発する処理への対応方法について執筆しました。

OData通信エラー

事象概要

SAP OData通信の処理で画面が固まってしまい、そのまま待っていると「取得処理が失敗しました。」というメッセージが表示される事象が発生しました。
更にこの事象は特定の地域でのみほぼ毎回発生し、その地域以外では正常に動作するというものです。

事象詳細

ブラウザの開発ツールで処理を観測したところ、ODataの通信処理($batch)で、レスポンスが返ってこないまま「HTTP 504 Gateway Timeout」のエラーとなってしまうようです。
実施後のアプリケーションログを確認してみても「Error: connect ECONNREFUSED」とあり、どうやら接続に失敗しているようです。
※OData通信時のPGは次を参照

OData通信処理(修正前)
  var oModel = this.getView().getModel("demoService");
  var key= "key";
  oModel.read(
    "/testTable(" + key+ ")", {
      success: function(data) {
        return true;
      },
      error: function(error) {
        return false;
      }
    }
  );

原因調査と対策

エラー発生個所の特定

タイムアウトといっても、OData通信のどの部分で不具合が生じているのか、もう少し詳細を調べる必要がありました。
そのため、次の3つの工程に分けて、処理がどのフェーズで失敗しているのか分析することにしました。

  1. フロントエンドからのリクエストがDBに届いているか
  2. DB内部での処理(SQL)は正常に実行されているか
  3. DBからフロントエンドへのレスポンスが返却されているか

上記を分析するため、次の内容を確認しました。

  • フロントエンドから投げているリクエストのパラメータおよびリクエスト時のタイムスタンプを
    ブラウザの開発ツールから確認
  • DB側のログに1のパラメータ、タイムスタンプと一致するリクエストが残っているか、
    またそのリクエストが正常に終了しているか

この結果、DBに関連するログが残っていないことを確認しました。
これによりフロントエンドからのリクエストが届いていない、つまりネットワークの不調によるエラーである可能性が高いと結論付けし、対策を練ることとしました。

対処方法

フロントエンドから直接ODataを呼び出すという処理は、そもそもパフォーマンスが悪いため、この処理をもっと軽くすることができないかを検討しました。
その検討の結果、フロントエンドからバックエンドの処理を呼び出して、バックエンドからODataのデータを読み込むように処理を分散させることで、アプリケーションにかかる負荷が軽減できるのではと考え、次のようにPGを修正しました。
※今回バックエンドの処理はJavaで実装

OData通信処理(修正後)
  var _this= this;
  var key = "テーブルのキー項目";
  
  $.ajax({
    url: _this.{endpoint} + "/getTestTable?parm=" + key,  //バックエンドメソッドを指定
    type: 'GET'
    }).then(function(data) {
      return true;
    }).catch(function(error) {
      return false;
    }
  );
  Edm edm;
  
  @GetMapping("/getTestTable")
  public ResponseEntity<Object> getTestTable (@RequestParam("parm") String parm)  throws Exception {
  
    ODataFeed feed = getOdata("getTestTable", parm);
    return 
  }
  
  //OData取得(GETリクエスト)処理  
  private ODataFeed getOdata(String servieName, String parm) throws 
    EntityProviderException, EdmException, UnsupportedOperationException, IOException,
    URISyntaxException{
 
        URIBuilder uriBuilder = new URIBuilder("{endpoint}" + servieName);
        uriBuilder.addParameter(key, parm);
        uriBuilder.addParameter("$format", "json");
        URI uri = uriBuilder.build();

        HttpGet getRequest = new HttpGet(uri);
        HttpResponse httpResponse = getHttClient().execute(getRequest);
        
        if(edm == null) {
            oDataReadMetadata();
        }
        EdmEntityContainer entityContainer = edm.getDefaultEntityContainer();
        return EntityProvider.readFeed("application/json" 
            , entityContainer.getEntitySet(servieName)
            , httpResponse.getEntity().getContent()
            , EntityProviderReadProperties.init().build());
    }
    
      

結果

処理落ちが発生していた地域でのアクセスが安定して、事象が大幅に改善しました。通信エラーによる処理落ちは、ほとんど発生しなくなりました。
また、正常に動いている地域でも、処理に1分ほどかかる場合がしばしばあったのだが、この対応を入れて以後は即座に処理が完了するようになるという副産物がありました。

最後に

今回はSAPのサービスを開発するにあたって発生した、課題の中でも対処に困ったことに焦点をあてて紹介をしました。
この記事が少しでもエンジニアの助けになれば幸いです。
最後まで閲覧いただきありがとうございました。

投稿者プロフィール

木村裕亮
木村裕亮
2014年入社
ビジネスソリューション事業部
2021年からSAP Business Technology Platformを基盤としたシステムのエンジニアとして開発業務を行っています。
この記事をSNSでシェア!