Main Content

MATLAB 関数実行のための RESTful API

MATLAB® 関数実行のための MATLAB Production Server™ RESTful API を使用すると、MATLAB データ型およびプロトコル バッファーの JSON 表現を使用してリモート サーバー上で MATLAB 関数を評価できます。プロトコル バッファーのサポートは、Java® クライアント API および .NET クライアント API でのみ提供されています。

MATLAB Production Server RESTful API を使用するクライアント コードを JavaScript® などの Web ベースの言語で記述して、HTML ページに組み込むことができます。その後、これらの Web ページを使用してリクエストを送信し、MATLAB Production Server インスタスからレスポンスを取得できます。Web ベースのアプリケーションは JavaScript で記述されたクライアント コードに適している可能性がありますが、Java、Python、C++、.NET をはじめとする任意の HTTP 対応プログラミング言語を使用してクライアント アプリケーションを開発することもできます。

クライアント プログラムが異なるドメインからリクエストを行う場合、JavaScript を使用するプログラマは、オリジン間リソース共有 (CORS) がサーバー上で有効になっているかどうかを確認する必要があります。サーバー上で CORS を有効にするには、サーバー管理者が main_config サーバー構成ファイルの cors-allowed-origins プロパティに適切な値を設定する必要があります。

RESTful API の特性

MATLAB 関数実行のための RESTful API は、MATLAB Production Server との通信に HTTP リクエスト/レスポンスモデルを使用します。このモデルには、リクエスト メソッド、レスポンスコード、メッセージ ヘッダー、およびメッセージ本文が含まれます。RESTful API には以下の特性があります。

  • HTTP メソッド (POST、GET、および DELETE) がクライアントとサーバー間の通信の基本モードを形成します。

  • 一意の Uniform Resource Identifier (URI) が、サーバーによって作成されるリソースを特定します。

  • メッセージ ヘッダーが、リクエストの "コンテンツ タイプ" などのメタデータを伝達します。

    • API は application/json を HTTP Content-Type ヘッダーとしてサポートします。

    • また、MATLAB 関数実行のための RESTful API は、Java クライアント API および .NET クライアント API を介してのみ、application/x-google-protobuf を HTTP Content-Type としてサポートします。

  • リクエストのメッセージ本文には、サーバーに送信される情報が含まれます。

    • JSON をデータ シリアル化形式として使用する場合、デプロイされたアーカイブ内に含まれる MATLAB 関数への入力は JSON で表現され、メッセージ本文内にカプセル化されます。詳細については、MATLAB データ型の JSON 表現を参照してください。

    • データ シリアル化にプロトコル バッファー (protobuf) を使用する場合、Java クライアント ライブラリおよび .NET クライアント ライブラリにより、protobuf メッセージを proto 形式に基づいて内部的に作成して対応するバイト配列を返すためのヘルパー クラスが提供されます。このバイト配列をリクエストのメッセージ本文に使用します。

  • レスポンスのメッセージ本文には、リクエストに関する状態や結果などの情報が含まれます。

    データ シリアル化に protobuf を使用する場合、Java クライアント ライブラリおよび .NET クライアント ライブラリにより、protobuf のレスポンスを逆シリアル化するためのメソッドとクラスが提供されます。

  • API はサーバーの同期モードと非同期モードの両方をサポートします。

メモ

以下の例および図では、JSON をデータ シリアル化形式として使用しています。

同期実行

同期モードでは、クライアントがリクエストを POST 送信すると、元のリクエストの処理を完了するまで、サーバーのワーカー プロセスが以降のすべてのリクエストをブロックします。処理が完了すると、ワーカーは自動的にクライアントにレスポンスを返します。リクエスト処理中にブロックするのはワーカーであるため、使用可能な他のワーカーが存在する場合、サーバーは他の同期リクエストを処理のために受け入れることができます。サーバーに対して同期リクエストを行ってレスポンスを待機するには、POST Synchronous Requestを使用します。

次の図は、RESTful API が同期モードでどのように機能するかを示しています。

When the server receives a request in synchronous mode, it blocks all other requests till it finishes processing the current request.

例: RESTful API と JSON を使用した魔方陣の同期実行

この例では、 JavaScript を使用した実装と Python® を使用した実装の 2 つの別々の実装を示すことで、RESTful API と JSON を使用する方法を説明します。この例を実行すると、サーバーは 25 個のコンマ区切り値のリストを返します。これらの値は、列優先形式で表されている、デプロイされた MATLAB 関数 mymagic の出力です。関数 mymagic の MATLAB コードは次のとおりです。

function out = mymagic(in)
out = magic(in);
end

この例を実行するには、デプロイされた MATLAB 関数 mymagic が含まれている MATLAB Production Server インスタンスを実行する必要があります。デプロイ可能なアーカイブを作成する方法の詳細については、MATLAB Production Server 用のデプロイ可能なアーカイブの作成を参照してください。サーバーのセットアップの詳細については、コマンド ラインを使用したサーバー インスタンスの作成を参照してください。

JavaScript の実装

RESTful API の JavaScript 実装を使用して、HTML ページの <script> </script> タグ内にスクリプトを含めます。この HTML ページを Web ブラウザーで開くと、サーバーによって関数 mymagic の値が返されます。JavaScript コードが機能するためには、サーバーで CORS が有効になっている必要があります。CORS を有効にする方法の詳細については、cors-allowed-originsを参照してください。

組み込み JavaScript を含むサンプル HTTP コードは次のとおりです。

<!DOCTYPE html>
<html>
    <head>
        <title>Magic Square</title>
        <script>
            var request = new XMLHttpRequest();
            //MPS RESTful API: Specify URL
            var url = "http://localhost:9910/ctfArchiveName/mymagic";
            //MPS RESTful API: Specify HTTP POST method
            request.open("POST",url);
            //MPS RESTful API: Specify Content-Type to application/json
            request.setRequestHeader("Content-Type", "application/json");
            var params = { "nargout": 1,
                           "rhs": [5] };
            request.send(JSON.stringify(params));
            request.onreadystatechange = function() {
                 if(request.readyState == 4) 
                 {	 //MPS RESTful API: Check for HTTP Status Code 200
                    if(request.status == 200) 
                    {	  result = JSON.parse(request.responseText);
                       if(result.hasOwnProperty("lhs")) {
                       //MPS RESTful API: Index into "lhs" to retrieve response from server
                       document.getElementById("demo").innerHTML = '<p>' + result.lhs[0].mwdata; }
                    }
                       else if(result.hasOwnProperty("error")) {
                       alert("Error: " + result.error.message); }
                 }
            };
        </script>
    </head>
    <body>
        <p>MPS RESTful API and JSON EXAMPLE</p>
        <p> >> mymagic(5)</p>
        <p id="demo"></p>
        <p> # output from server returned in column-major format </p>
    </body>
</html>

Python の実装

import json
import http.client

conn = http.client.HTTPConnection("localhost:9910") 
headers = { "Content-Type": "application/json"}
body = json.dumps({"nargout": 1, "rhs" : [5]})
conn.request("POST", "/mymagic/mymagic", body, headers)
response = conn.getresponse()
if response.status == 200:
   result = json.loads(response.read())
   if "lhs" in result:
     print("Result of magic(5) is " + str(result["lhs"][0]["mwdata"]))
   elif "error" in result:
     print("Error: " + str(result["error"]["message"]))

MATLAB 関数を MATLAB Production Server にデプロイし、RESTful API と JSON を使用して呼び出すエンドツーエンドのワークフロー例については、RESTful API、JSON、および JavaScript を使用した Web ベース ツールの作成を参照してください。

非同期実行

非同期モードでは、クライアントは複数のリクエストを POST 送信でき、いずれの場合もサーバーは、新しいリソースを作成して各リクエストに対応する一意の URI を返すことでレスポンスします。この URI はレスポンスメッセージの本文内にカプセル化されます。クライアントは、サーバーが返す URI をクエリや結果の取得などに使用できます。

次の表は、非同期モードの RESTful API 呼び出しの一覧です。

呼び出し目的
POST Asynchronous Request

サーバーに対して非同期リクエストを行う

GET Representation of Asynchronous Request

サーバーに対して行われた非同期リクエストがどのように表されるかを表示する

GET Collection of Requests

リクエストのコレクションを表示する

GET State Information

リクエストの状態情報を取得する

GET Result of Request

リクエストの結果を取得する

POST Cancel Request

リクエストをキャンセルする

DELETE Request

リクエストを削除する

次の図は、RESTful API が非同期モードでどのように機能するかを示しています。この図は、すべての RESTful API 呼び出しに対応しているわけではありません。呼び出しの完全なリストについては、上記の表を参照してください。

Asynchronous request processing.

例: RESTful API と JSON を使用した魔方陣の非同期実行

この例では、JavaScript を使用した非同期実装に RESTful API と JSON を使用する方法を説明します。この例を実行すると、サーバーは 100 個のコンマ区切り値のリストを返します。これらの値は、列優先形式で表されている、デプロイされた MATLAB 関数 mymagic の出力です。関数 mymagic の MATLAB コードは次のとおりです。

function out = mymagic(in)
out = magic(in);
end

この例を実行するには、デプロイされた MATLAB 関数 mymagic が含まれている MATLAB Production Server インスタンスを実行する必要があります。デプロイ可能なアーカイブを作成する方法の詳細については、MATLAB Production Server 用のデプロイ可能なアーカイブの作成を参照してください。サーバーのセットアップの詳細については、コマンド ラインを使用したサーバー インスタンスの作成を参照してください。

組み込み JavaScript を含むサンプル HTTP コードは次のとおりです。

<!DOCTYPE html>
<html>
    <head>
        <title>Magic Square</title>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
        <script>
            // MPS RESTful API (Asynchronous): Specify URL
            var hostname = "http://localhost:9910";
            var mode = "async";
            var clientID = "client100";
            var ctfName = "mymagic";
            var matlabFuncName = "mymagic"
            var url = hostname + "/" + ctfName + "/" + matlabFuncName + "?mode=" + mode + "&client=" + clientID;
            // Specify arguments
            var params = {
                "nargout": 1,
                "rhs": [100],
                "outputFormat": {"mode": "small"}
            };
            $.ajax(url, {
                data: JSON.stringify(params),
                //MPS RESTful API (Asynchronous): Specify Content-Type to application/json and Specify HTTP POST method
                contentType: 'application/json',
                method: 'POST',
                dataType: 'json',
                success: function(response) {
                    // Print Request URI to webpage
                    $("#requestURI").html('<strong>Request URI: </strong>' + hostname + response.self);
                    pollUsingUp(response);
                }
            });
            // Polling Server using UP
            function pollUsingUp(request) {
                setTimeout(function() {
                    var newSeq = parseInt(request.lastModifiedSeq) + 1;
                    var queryURI = hostname + request.up + "?since=" + newSeq + "&ids=" + request.id;
                    $.ajax({
                        url: queryURI,
                        method: 'GET',
                        dataType: 'json',
                        success: function(response) {
                            //Poll again if no data about the request was received.
                            if (response.data.length == 0) {
                                pollUsingUp(request);
                                return;
                            }

                            var requestResource = response.data[0];
                            // Print "state" of request
                            $("#state").html('<strong>State: </strong>' + requestResource.state);


                            if (requestResource.state != "READY" && requestResource.state != "ERROR") {
                                //Keep polling if the request is not done yet.
                                pollUsingUp(requestResource);
                            } else {
                                var requestURI = hostname + requestResource.self;
                                var responseURI = hostname + requestResource.self + "/result";
                                // Get result.
                                $.ajax({
                                    url: responseURI,
                                    // MPS RESTful API (Asynchronous): Specify HTTP GET method
                                    method: 'GET',
                                    dataType: 'json',
                                    success: function(response) {
                                        if (response.hasOwnProperty("lhs")) {
                                            $("#demo").html('<p>' +
                                                response.lhs[0] + '</p>');
                                            //Uncomment the next line if using JSON large representation
                                            //response.lhs[0].mwdata + '</p>');

                                        } else if (response.hasOwnProperty("error")) {
                                            alert("Error: " + response.error.message);
                                        }
                                        // MPS RESTful API (Asynchronous): Specify HTTP DELETE method
                                        $.ajax({
                                            url: requestURI,
                                            method: 'DELETE'
                                        });
                                    }
                                });
                            }
                        }
                    });
                }, 200);
            }
        </script>
    </head>
    <body>
        <p><strong>MPS RESTful API and JSON EXAMPLE</strong></p>
        <p> >> mymagic(5)</p>
        <p id="requestURI"></p>
        <p id="state"></p>
        <p id="demo"></p>
        <p> # output from server returned in column-major format </p>
    </body>
</html>

HTTP クッキーの管理

Azure® での MATLAB Production Server のデプロイでは、サーバーにデプロイされた MATLAB 関数を呼び出すために HTTPS エンドポイント URL が提供されます。Azure アプリケーション ゲートウェイは、クッキーを使用することで同じサーバー上にユーザー セッションを維持する、クッキーベースのセッション アフィニティを提供します。クライアント プログラムからリクエストを受信すると、アプリケーション ゲートウェイは Set-Cookie HTTP レスポンスヘッダーに、リクエストを処理するバーチャル マシン (VM) に関する情報を設定します。

非同期リクエストの実行

非同期リクエストを使用して、サーバーにデプロイされた MATLAB 関数を実行するクライアント プログラムは、後続のすべてのリクエストにおいて Cookie HTTP リクエスト ヘッダーに Set-Cookie ヘッダーの値を設定する必要があります。これにより、最初のリクエストを処理するのと同じサーバー VM が、そのセッションの後続のすべてのリクエストを処理するようになります。

同期リクエストの実行

同期リクエストを使用して、サーバーにデプロイされた MATLAB 関数を実行するクライアント プログラムは、Cookie HTTP リクエスト ヘッダーに Set-Cookie ヘッダーの値を設定してはならず、Cookie の値が以前に設定されている場合は、それをクリアする必要があります。これにより、同期リクエストが負荷分散されて、同じサーバー VM によって処理されないようにします。

Azure 上の MATLAB Production Server のアーキテクチャおよびリソースの詳細については、Architecture and Resources on AzureおよびArchitecture and Resources on Azureを参照してください。

関連するトピック