コンテンツへスキップ

Brokerへのレビューコメントの送信

Image

当社の書店メインダッシュボードには、読者が他のユーザーのコメントを表示し、テキスト入力エリアから自分のコメントを送信できるコメントセクションがあります。ボタンをクリックするとコメントが投稿されるというシンプルなプロセスに見えますが、その基礎となるメカニズムは堅牢なイベント駆動アーキテクチャによって実現されています。

どのようなKnative機能について学習しますか?

  • Knative Eventing Broker
  • Knative Eventing Sink
  • Knative SinkBinding

成果物はどのようなものですか?

Image

簡単に言うと、ユーザーがフロントエンドの送信ボタンをクリックすると、コメントがイベント表示サービスに表示されます。

実装

ステップ0:基本を理解する

Image

マイクロサービスとREST APIの世界では、リクエストをサービス間の通信の主要な方法として参照することがよくあります。しかし、イベント駆動アーキテクチャでは、最小単位はイベントです。Knative EventingはCloudEvents仕様に準拠しているため、先に進む前にこの概念を理解することが不可欠です。先に進む前に、CloudEventsの詳細をこちらで学習してください!

ステップ1:Book Review Serviceの理解

Image

Book Review Serviceは、イベント駆動アーキテクチャで重要な役割を果たすNode.js APIサーバーです。イベントを受信して適切に処理する方法を理解することが不可欠です。

Image

主要概念:BrokerとSinkBinding

コードに進む前に、2つの重要な概念を明確にしておきましょう。

  • Broker:イベント駆動アーキテクチャの中心的な役割を果たし、イベントを正しい宛先にルーティングします。
  • SinkBinding:このKnative Eventingコンポーネントは、Brokerのアドレスを環境変数K_SINKに自動的に挿入するため、Node.jsサーバーは手動で更新することなく常に正しいアドレスを取得できます。

順を追ってより深く理解できるようになります。

Image

node-server/index.jsファイルの/add関数を見てみましょう。ユーザーがフロントエンドからコメントを送信すると、最初にこのエンドポイントで受信されます。

app.post('/add', async (req, res) => {
  try {
    const receivedEvent = HTTP.toEvent({headers: req.headers, body: req.body});
    const brokerURI = process.env.K_SINK;

    if (receivedEvent.type === 'new-review-comment') {
      const response = await fetch(brokerURI, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/cloudevents+json',
          'ce-specversion': receivedEvent.specversion,
          'ce-type': receivedEvent.type,
          'ce-source': receivedEvent.source,
          'ce-id': receivedEvent.id,
        },
        body: JSON.stringify(receivedEvent.data),
      });
    }
  } catch (err) {
    console.error(err);
  }
});

イベントの受信/addエンドポイントは、フロントエンドからイベントを受信します。CloudEventsのSDKを使用して、受信リクエストをCloudEventオブジェクトに変換します。

const receivedEvent = HTTP.toEvent({headers: req.headers, body: req.body});

Brokerアドレスの決定:Brokerのアドレスはクラスタ内で動的に割り当てられます。Node.jsサーバーは、このアドレスを環境変数K_SINKから取得します。

const brokerURI = process.env.K_SINK;

環境変数にアドレスを伝えたのは誰か疑問に思うかもしれませんね?それはKnative SinkBindingです。

イベントフィルタリング:サービスはイベントの種類をチェックします。new-review-commentであれば、Brokerにイベントを転送します。

if (receivedEvent.type === 'new-review-comment') {
  // logic that forwards the event, see below
}

イベント転送ロジック:適切なCloudEventヘッダーを使用して、イベントがBrokerに転送されます。

const response = await fetch(brokerURI, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/cloudevents+json',
    'ce-specversion': receivedEvent.specversion,
    'ce-type': receivedEvent.type,
    'ce-source': receivedEvent.source,
    'ce-id': receivedEvent.id,
  },
  body: JSON.stringify(receivedEvent.data),
});

Image

その他の関数の調査

Node.jsサーバーには、同様のパターンに従う他の関数があり、詳細なコメントで機能が説明されています。

  • /insert:CloudEventsを受信し、ペイロードをPostgreSQLデータベースに挿入します。
  • /comment:データベースからコメントを転送するために、フロントエンドとWebSocket接続を作成します。

ステップ2:Brokerの作成

Image

Brokerはイベント駆動アプリケーションにおけるルーターとして機能し、イベントを受信して正しい宛先にルーティングします。

  • 1:node-server/config/200-broker.yamlという名前の新しいYAMLファイルを作成し、次の内容を追加します。
node-server/config/200-broker.yaml
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
    name: bookstore-broker
  • 2:YAMLファイルを適用します。
kubectl apply -f node-server/config/200-broker.yaml

次の出力が表示されます。

broker.eventing.knative.dev/bookstore-broker created

または、Brokerを作成するには、Knative CLI knを使用します。

kn broker create bookstore-broker

次の出力が表示されます。

Broker 'bookstore-broker' successfully created in namespace 'default'.

検証

Brokerを一覧表示するには、次のコマンドを実行します。

kubectl get brokers

ステータスがTruebookstore-brokerというBrokerが表示されます。

NAME               URL                                                                                 AGE     READY   REASON
bookstore-broker   http://broker-ingress.knative-eventing.svc.cluster.local/default/bookstore-broker   7m30s   True    
トラブルシューティング

問題が発生した場合は、次のコマンドを使用して診断します。

kubectl describe broker bookstore-broker

ステップ3:Node.jsサーバーとBroker間のSinkBindingの作成

Image

アプリケーションでKubernetesサービスに接続するためのURLをハードコーディングすると、制限的で柔軟性に欠けます。SinkBindingは、KubernetesサービスのURLをアプリケーションに動的に挿入します。

SinkBindingの詳細については、こちら仕様スキーマを参照してください!

SinkBindingの作成

  • 1:node-server/config/300-sinkbinding.yamlという名前の新しいYAMLファイルを作成し、次の内容を追加します。
node-server/config/300-sinkbinding.yaml
apiVersion: sources.knative.dev/v1
kind: SinkBinding
metadata:
  name: node-sinkbinding
spec:
  subject:
    apiVersion: apps/v1
    kind: Deployment
    selector:
      matchLabels:
        app: node-server
  sink: # In this case, the sink is our Broker, which is the eventing service that will receive the events
    ref:
      apiVersion: eventing.knative.dev/v1
      kind: Broker
      name: bookstore-broker
  • 2:YAMLファイルを適用します。
kubectl apply -f node-server/config/300-sinkbinding.yaml

次の出力が表示されます。

sinkbinding.sources.knative.dev/node-sinkbinding created

検証

以下のコマンドを実行して、sinkbinding を一覧表示します。

kubectl get sinkbindings
node-sinkbinding という sinkbinding が、READY ステータスがTrueで表示されるはずです。

NAME               SINK                                                                                AGE     READY   REASON
node-sinkbinding   http://broker-ingress.knative-eventing.svc.cluster.local/default/bookstore-broker   2m43s   True    

ステップ 4: イベント表示サービスの作成

Image

イベント表示は、Knative Eventing のデバッグツールであり、イベントの一時的な送信先(別名シンク)として使用できます。

イベント表示サービスの作成

  • 1: node-server/config/100-event-display.yamlという名前の新しいYAMLファイルを作成し、以下の内容を追加します。
node-server/config/100-event-display.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: event-display
spec:
  replicas: 1
  selector:
    matchLabels:
      app: event-display
  template:
    metadata:
      labels:
        app: event-display
    spec:
      containers:
        - name: event-display
          image: gcr.io/knative-releases/knative.dev/eventing-contrib/cmd/event_display
          ports:
            - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: event-display
spec:
  selector:
    app: event-display
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP
  • 2:YAMLファイルを適用します。
kubectl apply -f node-server/config/100-event-display.yaml

次の出力が表示されます。

deployment.apps/event-display created
service/event-display created

検証

以下のコマンドを実行して、pod を一覧表示します。

kubectl get pods

event-display-XXXXXXX-XXXXXというpodが"実行中"ステータスで表示されるはずです。

NAME                                  READY   STATUS    RESTARTS   AGE
bookstore-frontend-7b879ffb78-9bln6   1/1     Running   0          91m
event-display-55967c745d-bxrgh        1/1     Running   0          4m44s
node-server-644795d698-r9zlr          1/1     Running   0          4m43s

ステップ 5: ブローカーとイベント表示を接続するトリガーの作成

Image

トリガーは、CloudEvent の属性に基づいて、イベントを正しい送信先に転送できます。これは、ブローカーとイベント送信先の接続役です。

トリガー内のフィルタは、**フィルタ条件に基づいてイベントをフィルタリングします。** フィルタ条件は、トリガーのYAMLファイルで指定します。**フィルタを指定しない場合、トリガーはブローカーが受信したすべてのイベントを転送します。**

Image

KnativeにはChannelという概念もあり、一般的に、フィルタなしのブローカーとトリガーは、ChannelとSubscriptionと同じように扱うことができます。

ブローカーとトリガーの詳細については、こちらをご覧ください!

トリガーの作成

Image

ここでは、すべてのイベントをイベント表示に送信するトリガーを作成します。

Image

  • 1: node-server/config/200-log-trigger.yamlという名前の新しいYAMLファイルを作成し、以下の内容を追加します。
node-server/config/200-log-trigger.yaml
# This Trigger subscribes to the Broker and will forward all the events that it received to event-display.
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: log-trigger
spec:
  broker: bookstore-broker
  subscriber:
    ref:
      apiVersion: v1
      kind: Service
      name: event-display
  • 2:YAMLファイルを適用します。
kubectl apply -f node-server/config/200-log-trigger.yaml

次の出力が表示されます。

trigger.eventing.knative.dev/log-trigger created

検証

以下のコマンドを実行して、トリガーの一覧表示します。

kubectl get triggers
log-triggerというトリガーのREADYステータスがTrueになっているはずです。

NAME                BROKER             SUBSCRIBER_URI                                                       AGE     READY   REASON
log-trigger         bookstore-broker   http://event-display.default.svc.cluster.local                       6m2s    True    

検証

Image

以下のコマンドで、イベント表示のログを開きます。

kubectl logs -l=app=event-display -f
検証

UIのコメントボックスに何かを入力して送信ボタンをクリックします。コメントは、以下の出力と共にイベント表示サービスに表示されるはずです。

☁️  cloudevents.Event
Validation: valid
Context Attributes,
specversion: 1.0
type: new-review-comment
source: bookstore-eda
id: unique-comment-id
datacontenttype: application/json
Extensions,
knativearrivaltime: 2024-05-19T05:27:36.232562628Z
Data,
{
    "reviewText": "test"
}

次のステップ

Image

先に進む前に、検証テストに合格していることを確認してください。

MLワークフローのデプロイへ移動: 感情分析

サイトトラフィックを理解するために、アナリティクスとCookieを使用しています。当サイトのご利用に関する情報は、その目的でGoogleと共有されます。詳細はこちら。