[Cloud] Microservices From Dev To Deploy, Part 2: Node/Express and Fn Serverless

原文はこちら。
https://blogs.oracle.com/developers/microservices-from-dev-to-deploy%2c-part-2%3a-nodeexpress-and-fn-serverless

前回のエントリで、Lydiaという創業者が運営するTechCorpという架空の会社を紹介しました。彼女はインターネット・ホームページのすばらしき日々を取り戻そうとしています。
Microservices From Dev To Deploy, Part 1: Getting Started With Helidon
https://blogs.oracle.com/developers/microservices-from-dev-to-deploy-part-1-getting-started-with-helidon
https://orablogs-jp.blogspot.com/2018/10/microservices-from-dev-to-deploy-part-1.html
Lydiaの会社のグローバルチームはすばらしい開発者で構成されており、彼らは彼女のビジョンをマイクロサービス・アーキテクチャで実装しています。すでに我々はLondonのChrisのチームと東京のMichikoのチームの情報を知っています。これらのチームは天気および名言のサービスをHelidonというOracleが作ったマイクロサービス・フレームワークで構築しました。
Helidon
https://helidon.io/
ChrisのチームはHelidon SEをGroovyから利用し、MichikoのチームはHelidon MPとJavaを選択しています。このエントリでは、MurielleとそのBangaloreのチームがNode.jsとExpressを使って株価サービスを作成し、DominicとそのMelbourneのチームがJavaとFn Project(サーバーレス・テクノロジー)を使ってランダムに猫の画像を出すサービスの構築といううらやましい作業をしているところを見ていきます。
Fn Project
https://fnproject.io/
Helidonを使えば関数型スタイルとMicroprofileスタイルのサービスの両方を簡単に実装できます。 しかし、個人的に5年前に考えていたことではありますが、NodeJSの人気は無視できません。Stack Overflowの最近の調査によると、プログラミング、スクリプト、マークアップ言語の中で最も人気のある技術としてJavaScriptを選択した回答者は69%を超えており、かつ、回答者の49%以上が「フレームワーク」カテゴリの最上位にNodeを位置づけています。
Stack OverFlow Developer Surveys - Most Popular Technologies
https://insights.stackoverflow.com/survey/2018#technology
これは、人々がフロントエンドでJavaScriptを使用するのは当然として、ますますバックエンドでJavaScriptを活用しようとしているということです。そのため、Murielleのチームは、ExpressとNodeを使用して株価サービスを構築することにしました。

このサービスを作成するためのExpressについて深掘りはしませんが、株価の取得方法を簡単に見てみましょう。
var express = require('express');
var router = express.Router();
var config = require('config');
var fetch = require("node-fetch");

/* GET stock quote */
/* jshint ignore:start */
router.get('/quote/:symbol', async (req, res, next) => {
  const symbol = req.param('symbol');
  const url = `${config.get("api.baseUrl")}/?function=GLOBAL_QUOTE&symbol=${symbol}&apikey=${config.get("api.apiKey")}`;
  
  try {
    const response = await fetch(url);
    const json = await response.json();
    res.send(json);
  } catch (error) {
    res.send(JSON.stringify(error));
  }

});
/* jshint ignore:end */
module.exports = router;
(非同期呼び出しで)fetchを使っています。このメソッドは株価APIを呼び出し、URLパラメータを使って受け取ったティッカーシンボルを渡して、株価をJSON文字列としてAPI呼び出し元に返します。ローカルでサービスを実行したときの様子は以下の通りです。

Murielleのチームは、将来的にサービスを拡張して履歴データ、暗号通貨のルックアップなど、ビジネスが必要とするものすべてを提供できますが、現時点では、受け取ったティッカーシンボルに基づいて現在の株価を返します。チームは今後のデプロイのためにDockerfileとKubernetesの設定ファイルを作成しています。

MelbourneのDominicのチームは、サーバーレス・テクノロジーをこれまでよく使ってきています。彼らは優先機能、つまりランダムな猫の画像を提供する機能を任されており、サーバーレス(テクノロジー)を使ってこの機能を提供すべきで、Fnを使ってサービスの構築に着手しようと考えています。

マイクロサービスアーキテクチャではサーバレスを考慮する必要はありませんが、サーバーレスを使えば、柔軟性に富み、スケーラブル、集中性、迅速なデプロイが可能という、マイクロサービス・アプローチの目標を達成できるでしょう。DominicのチームはサーバーレスとFnに関して調査を完了し、作業準備が整ったので、開発者はローカルFnサーバーをインストールし、Javaのクイックスタートに従ってfunctionのテンプレートを作成しました。
Serverless with Fn Project
https://developer.oracle.com/opensource/serverless-with-fn-project
Install Fn
https://fnproject.io/tutorials/install/
Introduction
https://fnproject.io/tutorials/JavaFDKIntroduction/
プロジェクトの準備完了後、Dominicのチームはfunc.yamlファイルを修正して、プロジェクトの設定、特にapiBaseUrlとapiKeyを設定しました。
schema_version: 20180708
name: cat-svc
version: 0.0.47
runtime: java
build_image: fnproject/fn-java-fdk-build:jdk9-1.0.70
run_image: fnproject/fn-java-fdk:jdk9-1.0.70
cmd: codes.recursive.cat.CatFunction::handleRequest
format: http
config:
  apiBaseUrl: https://api.thecatapi.com/v1
  apiKey: [redacted]
triggers:
- name: cat
  type: http
  source: /random
CatFunctionクラスは基本的なもので難しくはありません。@FnConfigurationで注釈を付けられたsetUp()メソッドは、YAMLファイルの設定情報を含むfunctionコンテキストにアクセスし、関数の変数を初期化します。handleRequest()メソッドはUnirestというクライアントライブラリを使用してHTTP呼び出しを行い、すばらしい猫の画像へのリンクを含むJSONを返します。
public class CatFunction {

    private String apiBaseUrl;
    private String apiKey;

    @FnConfiguration
    public void setUp(RuntimeContext ctx) {
        apiBaseUrl = ctx.getConfigurationByKey("apiBaseUrl").orElse("");
        apiKey = ctx.getConfigurationByKey("apiKey").orElse("");
    }

    public OutputEvent handleRequest(String input) throws UnirestException {
        String url = apiBaseUrl + "/images/search?format=json";
        HttpResponse<JsonNode> response = Unirest
                .get(url)
                .header("Content-Type", "application/json")
                .header("x-api-key", apiKey)
                .asJson();
        OutputEvent out = OutputEvent.fromBytes(
                response.getBody().toString().getBytes(),
                OutputEvent.Status.Success,
                "application/json"
        );
        return out;
    }
}
functionのテストのため、ローカルのFnサーバーにデプロイして…
fn deploy --app cat-svc –local
動作確認すると…
curl -i \
-H "Content-Type: application/json" \
http://localhost:8080/t/cat-svc/random
以下のような結果が返ってきます。
HTTP/1.1 200 OK
Content-Length: 112
Content-Type: application/json
Fn_call_id: 01CRGBAH56NG8G00RZJ0000001
Xxx-Fxlb-Wait: 502.0941ms
Date: Fri, 28 Sep 2018 15:04:05 GMT
[{"id":"ci","categories":[],"url":"https://24.media.tumblr.com/tumblr_lz8xmo6xYV1r0mbi6o1_500.jpg","breeds":[]}]
うまく動作しました。Dominicのチームは昼食前に猫のサービスを作成し、残りの時間はランダムに表示される猫の画像を見て過ごしました。

さまざまなテクノロジーを使い、4チーム全てが任されたサービスの実装が完了しました。フロントエンドからサードパーティAPIを直接呼び出すのではなく、バックエンドにこのような簡単なサービスを実装する必要性​​を自問していらっしゃるかもしれません。理由はいくつかありますが、一部を見ていきましょう。

サーバーベースのバックエンド経由でこの機能を実装する理由の1つとして、サードパーティのAPIが信頼性が低かったり、レート制限があったりする可能性があります。独自のバックエンドを介してAPIをプロキシすることで、チームはキャッシュや独自に設計したレート制限を活用できるます。サードパーティAPIへのリクエストや、制限付きで管理できたり管理不可のサービスの潜在的なダウンタイムやレート制限の回避をする必要はなくなります。

第二に、チームはデータをクライアントに送信する前に制御できる、という点です。条件やビジネスニーズにより、他のサードパーティまたはユーザーデータでデータを補うことがAPI内で可能であれば、クライアント到達前にデータの追加、変更によってクライアントのCPU、メモリ、帯域幅の要件を削減できます。

最後に、ブラウザによるCORSの制約は、サーバーからAPIを呼び出すことで回避できます(CORS制約の結果ブラウザからのHTTP呼び出しをブロックを経験している場合には、このメリットは理解いただけると思います)。

TechCorp はこれでプロジェクトの最初のマイクロサービス開発のスプリントを完了しました。次回のエントリでは、4個のサービスをローカルのKubernetesクラスタにデプロイする方法と、Angularで作成するフロントエンドを深く見ていきます。

0 件のコメント:

コメントを投稿