---
# System prepended metadata

title: '**29Jan2024 - Anypoint Platform Architecture: Integration Solutions**'
tags: [MuleSoftTraining]

---

# **29Jan2024 - Anypoint Platform Architecture: Integration Solutions**
###### tags: `MuleSoftTraining`

[TOC]
# Module 0: 準備

## Mimeoから次の資料を確認
- :star: APAIntSols4.4_**studentFiles**_16nov2021.zip (受講者ファイル)
-  APAIntSols4.4_studentSlides_16nov2021.zip　(受講者スライド)
-  APAIntSol4.4_studentManual_JA_16nov2021.pdf(受講者マニュアル)

## アカウントとソフトウェアの準備
[こちら](https://salesforce.quip.com/bFrfAZE3riXy) をご参照ください。

1. [Anypoint Platform トライアル (試用) アカウント](https://salesforce.quip.com/QQN7Acqju0il)
2. [Anypoint Studio 7.14.0 (最新版)](https://www.mulesoft.com/lp/dl/studio)
   - コース開始前にダウンロードとインストールを行い、ソフトの起動をお試しください。
   - よくあるエラーとトラブルシューティングは[こちら](https://salesforce.quip.com/n2iFAKKHMM1A)からご確認ください。
3. [Mule Runtime 4.4 (最新版)](https://www.mulesoft.com/lp/dl/mule-esb-enterprise)
4. [Advanced REST Client](http://install.advancedrestclient.com/install)
   - [Postman] (https://www.postman.com/downloads/)など、他の REST API クライアントアプリケーションも使用可能です。
5. [Java 8/11 (Adopt OpenJDK)](https://salesforce.quip.com/5B2PAV46QbB5)
  - `java -version`
6. [VisualVM](https://visualvm.github.io/)
7. [Apache JMeter](https://jmeter.apache.org/download_jmeter.cgi)
8. [Anypoint CLI](https://docs.mulesoft.com/jp/runtime-manager/anypoint-platform-cli#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
- `npm install -g anypoint-cli@latest`
- `anypoint-cli`
  - 注1: [Node.js](https://nodejs.org/ja/download/) のインストールが必要になります。
  - 注2: [Git](https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB) のインストールが必要になります。


![anypoint-cli](https://i.imgur.com/y1zQltD.png)
9. [Apache Maven](https://dlcdn.apache.org/maven/maven-3/3.8.4/binaries/apache-maven-3.8.4-bin.zip)
- bin ディレクトリに Path を通す
- `mvn -version`

## ディレクトリの準備
- MuleSoft_Training_IntSol_07mar2022
  - exportedApps
  - installs
  - performance
  - resources
    - :star: APAIntSols4.4_**studentFiles**_16nov2021.zip (受講者ファイル)
    -  APAIntSols4.4_studentSlides_16nov2021.zip　(受講者スライド)
    -  APAIntSol4.4_studentManual_JA_16nov2021.pdf(受講者マニュアル)
  - workspace
  - mule
    - mule-4.4.0-node1
    - mule-4.4.0-node2
    - mule-ee-distribution-standalone-4.4.0.zip (予備)

# Module 1: インテグレーションソリューションアーキテクチャの紹介
## Catalyst Knowledgehub
catalyst.mulesoft.com (knowledgehub.mulesoft.com)
- [CloudHub Usecase](https://knowledgehub.mulesoft.com/s/article/CloudHub-Infrastructure-Use-Cases)
- 日本語の資料も
  - https://knowledgehub.mulesoft.com/s/global-search/%40uri#q=JP 

## Catalyst Git Repository
https://github.com/mulesoft-catalyst

例:) 監査ログ (audit log) を splunk に集約したい
  - [catalyst](https://knowledgehub.mulesoft.com/s/article/Retrieve-Audit-Logs-Aggregate-and-Send-Them-to-Splunk)
  - [github]( https://github.com/mulesoft-catalyst/audit-log-aggregators)
  - [mulesoft doc]( https://docs.mulesoft.com/jp/access-management/audit-logging)

## 機能要件 FRs vs 非機能要件 NFRs
 FR -> what 何を実現するか
 NFR -> how どうやって実現するか (reliability, availability, security ..)

 - [User Story](https://www.atlassian.com/ja/agile/project-management/user-stories)
 - [Epic, Stories]( https://www.atlassian.com/ja/agile/project-management/epics-stories-themes)
![Epic, Stories](https://i.imgur.com/lmwTOo8.png)

## Architecture Document Template 
https://knowledgehub.mulesoft.com/s/article/Anypoint-Platform-Architecture-Template

### Q.アーキテクチャドキュメントテンプレート は実際にどのように運用されている？
- MuleSoft の Solution Atchitect チームが、プロジェクトの初期設計を担当する場合、このテンプレートをもとにドキュメントを生成することがある。
- パートナー企業がドキュメントを生成する場合、かつ、 MuleSoft の Solution Atchitect チームもプロジェクトの初期に参加する場合、ドキュメントで不足している部分を、このテンプレートの内容をもとに捕捉的にサポートする場合がある。

※ API-led アーキテクチャにフォーカスしたドキュメント [Solution Design Template](https://knowledgehub.mulesoft.com/s/article/Solution-Design-Template) もあります。

いずれの場合も、このドキュメントテンプレートは参考として使い、これらをそのまま使用するとは限らない。

## UML
 - [UML](https://www.uml-diagrams.org/uml-25-diagrams.html)
 - [Qiita記事](https://qiita.com/taku_maru/items/80d39f2f043489033076)

# Module 2: Anypoint Platform コンポーネントと機能の理解

[Anypoint Platform ホスティングオプションの比較](https://docs.mulesoft.com/jp/general/intro-platform-hosting)

## コントロールプレーン vs ランタイムプレーン
### コントロールプレーン
アプリケーションや　Muleランタイムを管理・監視・デプロイするためのコンポーネント群
- :star: MuleSoft-hosted (anypoint.mulesoft.com) - US East
- MuleSoft-hosted (eu1.anypoint.mulesoft.com) - EU (Germany)
- [Anypoint Private Cloud Edition (PCE)](https://docs.mulesoft.com/jp/private-cloud/3.0/)
- [Goverment Cloud(US-only)](https://docs.mulesoft.com/jp/general/intro-platform-hosting)

![比較表](https://i.imgur.com/zdRfHe7.png)

### ランタイムプレーン
アプリケーションやMuleランタイムのデプロイ先となるホスティング環境

- :star: **CloudHub (MuleSoft-hosted)**
  - MuleSoft が管理する AWS 環境
  - CloudHub ワーカー = EC2 インスタンス
  - クラウドベースの key-value ペアストレージ: Object Store v2
  - クラウドベースの永続化 VM キュー: Persistent Queue
  - スケーリング
    - CHワーカーの数を増やす = スケールアウト
    - CHワーカーの性能を良くする = スケールアップ
    - [自動スケーリング](https://docs.mulesoft.com/jp/runtime-manager/autoscaling-in-cloudhub) は ELA 契約のみ
  - ロードバランサー
    - SLB(共有ロードバランサー)
      - HTTP 80 -> 8081
      - HTTPS 443 -> 8082 
    - DLB(専用ロードバランサー) 
      - HTTP 80 -> 8091
      - HTTPS 443 -> 8092 
      - VPC に構成する
- Customer-hosted Mule ランタイム
  - クラスター構成 / 非クラスター構成 
  - オンプレミス
  - VM
  - プライベートクラウド (AWS, Azure, GCP..)
- Runtime Fabric(RTF）　
  - クラスター構成 
  - RTF-VM
    - EC2 etc... 
  - RTF on self-managed k8s
    - GKE, AKS, EKS etc... 

Q. ランタイムプレーンに何を選択するかによって、ライセンスや運用費用に差は生じるのでしょうか?
- Hybrid / RTF > Platinum or Tatanium ライセンス契約が必要
  - https://www.mulesoft.com/anypoint-pricing
- どの契約においても Core 数の概念がある（On-Premise Core vs Cloudhub vCore）
  - https://help.mulesoft.com/s/article/How-to-Transfer-Mulesoft-on-Premise-Core-Licenses-to-Cloudhub-vCore-Licenses-or-Vice-Versa 
- CloudHub： 0.1 vCore, 0.2 vCore, 1 vCore...
- RTF: https://docs.mulesoft.com/jp/runtime-fabric/1.6/deploy-resource-allocation#vcpu-%E3%81%AE%E5%89%B2%E3%82%8A%E5%BD%93%E3%81%A6
- Customer-hosted Mule ランタイム: 1 Runtime - N apps

## Mule App
- Javaベースのアプリケーション。Anypoint Studioで(ローコード)開発が可能。
- XMLで構成したアプリケーションをMavenを使用して jar にパッケージングする。
- 1つの Mule アプリケーションは、1つ以上のフローで構成される。

## Flow
- 関数やメソッドのように、再利用可能な単位のロジックの塊(スコープ)
- 関数のように、受け取ったいインプットが、さまざまなロジックを経て(Transform Message など)、アウトプットとしてリターンされる
- フローから別のフローを呼び出すことも可能(Flow Reference)

## Mule 4 Event 
Mule Event: Mule アプリケーションが扱うデータオブジェクト(Javaオブジェクト)

![MuleEvent](https://i.imgur.com/xyC2AHg.png)

- Mule Message
   - Attributes (属性、メタデータ)
     - Headers
     - Query Params
     - etc... 
   - **Payload (データの本体)**
 - Variables (vars, 変数)
 - :warning: (Error) ``<Object> エラー発生時``
   - errorType ``<Object>`` >> HTTP:BAD_REQUEST
     - namspace (名前空間)``<String>``
       - e.g HTTP 
     - identifier ``<String>``
       - e.g. BAD_REQUEST (識別子) 
   - description ``<String>``
     - エラーの説明 


## API-led Connectivity (API 主導の接続性)
1. Experience API(EAPI)
  - API クライアント毎の違いを吸収する(データ型、フォーマット, セキュリティ..) 
2. Process API(PAPI) 
  - ビジネスロジック
3. System API(SAPI)
  - バックエンドのデータを取得・更新・作成
  - 統一のデータ型への変換を行うことも(SAP Customer <-> SFDC Customer)

※データ型の変換の話は, Module 6 でより多く触れます!

## Spec-Driven Development（仕様駆動型開発）
- どちらのツール、どちらの言語でもOK！
   - RAML 0.8/1.0
   - OAS 2.0(a.k.a Swagger)/3.0 
- なぜ？
  - その API の役割や機能について合意をとる
  - フィードバックをもらって改善する
  - データ型、エンドポイント名、フィールド名、パラメータ (必須 or not)、などについての事前確認 
  - 仕様通りのバリデーションを自動で適用
  - Studio にインポートして、土台となるスケルトン (インタフェースフロー)を自動で生成する
    - ApiKit 
  - Exchange に公開したタイミングで
    - API ポータルが自動生成される
    - 仕様をもとにドキュメントが自動生成されます
    - API コンソールが自動生成される
      - Anypoint Studioでも参照可能 
    - コネクタの自動生成 (REST Connect)
    - モッキングサービスが自動生成される (プロトタイプ)
      - [シミュレーションヘッダー](https://docs.mulesoft.com/jp/design-center/apid-behavioral-headers)機能で、より実際に近いモック呼び出しが可能
        - MS2-Delay
        - MS2-Example
        - MS2-Error-Rate
  ![MS2-Delay](https://i.imgur.com/fDGcJFw.png)

Q. デフォルトのモッキングサービスのURLだと外部からサービスから呼び出すURLはどのように発行するのでしょうか？CurlでURLを叩くと「{"errorType":"ServiceError","message":"No OrganizationId Header"}」とでてしまいます。
- 設定+鉛筆アイコン > Make Publicを有効にします。有効期限を設定することも可能です。
![Make Public](https://i.imgur.com/bM2309m.png)

## Semantic Versioning 
![nodejs](https://i.imgur.com/ZZ7nWmG.png)

Node.js
- Devlopment: 奇数バージョン
- Stable: 偶数バージョン

Major version . Minor version . Patch version  - https://semver.org/lang/ja/

**2**.2.1 vs **3**.0.0(ブレーキングチェンジ->後方互換性が保てない変更)

1.**0**.0 vs 1.**1**.0(機能追加)

2.2.**1** vs 2.2.**2**(バグ修正)

## API の管理・保護
![autodiscovery](https://i.imgur.com/H8oSWNJ.png)

### Basic Endpoint(埋め込み型)
![Basic Endpoint](https://i.imgur.com/VnkEFXN.png)

+アプリケーションの数を抑えられる
+vCoreの消費を抑えられる($$$)
+追加のネットワークホップがない=追加のレイテンシーがない
-Studio での作業が必要（autodiscovery ID の設定）
-Mule アプリケーションしか保護できない

### Endpoint with Proxy(APIプロキシアプリケーション型)
![Endpoint with Proxy](https://i.imgur.com/F0A4Mn1.png)
+Non Mule アプリケーションの保護
+Studio での作業が不要
+APIプロキシとAPI実装の明確な分離
+複数のAPIプロキシで、1つの実装を保護することにより、コンシューマー/クライアントごとに適用するポリシーを変える
-URLが複数ある (APIプロキシ+API実装) = 複雑
-アプリケーションの数が増えてしまう
-vCoreを消費してしまう($$$)
-ネットワークのホップが増える->レイテンシーの増加(?)

### [Service Mesh](https://docs.mulesoft.com/jp/service-mesh/1.1/)

 [what is service mesh](https://www.mulesoft.com/resources/api/what-is-a-service-mesh)

![service mesh](https://i.imgur.com/JMZJECK.png)

![ServiceMesh](https://i.imgur.com/w1kJ1jU.png)

Q.Service Mesh ではコアを消費するか?
![ServiceMesh](https://i.imgur.com/exYjSLo.png)

Yes, コアを消費します。管理する API のサイズによって、コアのサイズは変わります。

##  [Flex Gateway](https://www.mulesoft.com/platform/api/flex-api-gateway)
> Anypoint Flex Gateway is ultrafast, designed to manage and secure APIs running anywhere. Built to integrate seamlessly with DevOps and CI/CD workflows, Anypoint Flex Gateway delivers the performance required for the most demanding applications while providing enterprise security and manageability across any environment.

- [video](https://share.vidyard.com/watch/Mr9r3ARNRHbgYrsBaTsBTo)
- [blog](https://blogs.mulesoft.com/news/introducing-universal-api-management-on-anypoint-platform/)
- [page](https://www.mulesoft.com/platform/api/flex-api-gateway)

## AsyncAPI
[AsyncAPI](https://www.asyncapi.com/)
[blog](https://blogs.mulesoft.com/news/anypoint-platform/event-driven-architecture-asyncapi/)

Q. 埋め込み型の場合、デプロイ先によってポリシーの細かい条件が変わる場合、Studioで毎回変更する必要があるとい認識でよいですか?Sandboxと本番で変えるなどを想定しています。
- 異なる環境でのAPIの管理は、異なるAPIインスタンスを構成できます(=異なるautodicovery IDが生成される)
![differentInstance](https://i.imgur.com/eNcQGOm.png)
- autodiscovery IDは、プレースホルダー（${}）を使用することで、デプロイのタイミングで動的に切り替えることが可能です。

![studio](https://i.imgur.com/R0UOEyb.png)

![${autodiscoveryId}](https://i.imgur.com/9MGSls5.png)

# Module 3: Mule アプリケーションを使用したインテグレーションソリューションの設計

## フローの処理
左から右へ(コードの上から下へ) **同期的**に処理を行う

## 非同期の処理を行うプロセッサ・スコープ・コネクタの例
- Async スコープ
- Scatter-Gather　ルーター
- VM コネクタ
- JMS コネクタ 
- Logger -> デフォルトは Async Logger 
- Batch Job
- Parallel For Each
- etc..
 
## Mule SDK > コネクタ・モジュールの開発
https://docs.mulesoft.com/jp/mule-sdk/1.1/

- Java SDK
- XML SDK
  - RAML や OAS からコネクタを自動生成する、REST Connect にも使用される

### mule-db-connector
https://github.com/mulesoft/mule-db-connector
    
## Maven3の始め方
https://maven3.kengo-toda.jp/
    
## Exchange: stable vs development
- stable
  - 安定版
  - API Manager での管理や、Anypoint Studioでの開発が可能
- developlemt
  - 開発中
- deprecated
  - 非推奨
![stablevsdevelopment](https://i.imgur.com/FzedRAG.png)

## REST Connect コネクタの使用
displayNameを変更することで、より直感的な表示名にすることができる(日本語も可能)
![getSpots](https://i.imgur.com/Zg2BjCv.png)

呼び出し先の設定
![config](https://i.imgur.com/gpDQKBB.png)

![/spots->CH](https://i.imgur.com/ZHLzP8N.png)

## APIKit
RAMLから土台となるスケルトンフロー、バリデーションを自動で生成するためのツール。API Consoleも自動生成される。
- API Consoleがあることによって、APIのテスト呼び出しが簡素化される(ARCなしでもテストが可能)
-　仕様・ドキュメントの確認も可能
## Rest Connect コネクタ
- RAMLから自動生成されるコネクタ。Exchangeに公開されたタイミングで生成される。
- パラメータやリソース名、メソッド、認証情報などAPI呼び出しにかかわる複雑さをコネクタに隠蔽する

## ドメインプロジェクト
Customer-hosted Muleランタイムのみで構成可能
![domain-project](https://i.imgur.com/Zw2yzNQ.png)

## Scheduler の挙動
![Scheduler](https://i.imgur.com/gOa8tDz.png)

- CloudHub
  - 複数のワーカーがあっても、 どちらかワーカーで実行
  - CloudHub では "1"
  - Cron は **UTC** のタイムゾーンを使用する
- スタンドアローン & RTF
  - Cluster構成をとっていない場合
    - それぞれのノードで Scheduler が実行
  - Cluster構成をとっている場合
    - 1つのノードで実行される (= primary ノード)

## DataWeave 
- [Playground Library](https://developer.mulesoft.com/learn/dataweave/)

```
%dw 2.0 // dw のバージョン 省略可能
output application/csv header=false,separator="\t"
// 出力データ型 -> output jsonでもOK

// https://docs.mulesoft.com/dataweave/2.4/dataweave-formats-csv#reader_properties
---
// String, Number, Boolean, Null, Date
// Object, Array

/** 
 * output application/xml
 * xml は親タグが必要。配列を () で囲んで宣言する。
 * parentTag:{([{
 *     hello:"world"
 * },
 * {
 *     hello:"world2"
 * }])
 * }
*/

[{
  hello:"world",
  hello2:"worldX"
}, 
{
  hello:"world2",
  hello2:"worldY"
}]
```
## Error Handler
### Error Handlerスコープ
https://docs.mulesoft.com/jp/mule-runtime/4.4/error-handling

0. **Mule**デフォルトエラーハンドラー
 - *カスタマイズ*などは不可
 - 汎用的に処理 (Propagate)
1. アプリケーション/グローバルエラーハンドラ
![app-error-handler](https://i.imgur.com/y2ecwln.png)

 - 個別のエラーハンドラー(2.フロー, 3.Tryスコープ/プロセッサ)が設定されていないときだけ、このハンドラーで処理がされる
 - Global Elements  > Create > Configuration > Default Error Handler で設定
 **Default** は、アプリケーションのデフォルト(=Application/Global Error Handler)の意味であり、「0.Mule デフォルトエラーハンドラー(カスタマイズ不可)」のことではない
![apperrorhandler](https://i.imgur.com/MO2bmKH.png)

2. フローレベルエラーハンドラ
![flow-level-error](https://i.imgur.com/4fgXTPL.png)

3. Try/プロセッサレベルエラーハンドラ
![try-error](https://i.imgur.com/yBs9apL.png)

### Error Handler の種類
1. On Error Propagate
 - デフォルトの処理(**Mule**デフォルトエラーハンドラで使用)
 - "エラーをエラー"として処理
 - エラーオブジェクトを伝播して、呼び出し元に伝える
 - エラーを Continue 処理すると、Transactionはロールバックされる

2. On Error Continue
 - まるで"エラーが起きていないかのように"処理
 - 自分のエラーを他の処理に影響がないように、"エラーを飲み込む"
 - エラーが起きても他の処理を継続する (=continute)
 - エラーを Continue 処理すると、Transactionはコミットされる
![Transaction](https://i.imgur.com/J7JH48Y.png)

## ルーター
### Choice
  - if, else-if, else...
### Scatter-Gather
  - 非同期,マルチスレッドですべてのルートの処理を行う
    - トランザクション処理は例外 
  - エラーが起きた際には、MULE:COMPOSITE_ERROR がスロー
  - 処理結果を結合したオブジェクトがリターンされる
```
{
"payload" : {
  "0" : {
   "attributes" : {
   "properties" : { … }
   "headers" : { … }
  …
  },
  "payload" : {
      "firstRoute" : "First Payload"
    }
  }
  "1" : {
   …
   "payload" : {
     "secondRoute" : "Second Payload"
   }
 }
 …
}
```
- First Succesful
  - 上から順番に実行 > いずれかのルートで処理に成功したら完了 
    - 1(失敗)> 2(成功)> ~~3(処理されない)~~ 
- Round Robin
  - 順番に実行
    - 1 > 2 > 3 > 1 > 2 > 3 > 1 ....

## ルーターエクササイズ
- 2 番目の API が、最初の API のレスポンスを必要とする (... HTTP Request 1 -> HTTP Request 2-> ...)
  - A. **ルーターを使用しない**! 
  - A. vars (変数)に HTTP Request 1の結果を入れておくことで、payload を上書きしない (もしくは、 HTTP Request 2の結果を target variable に保存することで、HTTP Request 1のpayload を上書きしない)
![1](https://i.imgur.com/CNldxkX.png)

- 各APIはそれぞれのレスポンス (注文、顧客) に依存しないが、結果を統合する必要がある
  - A. **Scatter-Gather**
![2](https://i.imgur.com/vAMvNul.png)

- 2 つの Address Validation (住所バリデーション) API エンドポイントで同一の機能を実行するが、そのうちの1つはフォールバックオプションになる
  - A. **First Successful**
![3](https://i.imgur.com/NEIzhka.png)

- リージョンに応じて Inventory (在庫) API の異なるリージョンエンドポイント(ANZ, Japan) を使用する必要がある
  - A. **Choice**
![4](https://i.imgur.com/gYlV1T3.png)

- 各種保険会社からの Insurance Quote (保険の見積もり) API を呼び出し、結果を統合してソートする必要がある
  - A. **Scatter-Gather** -> **Dataweave** 
![5](https://i.imgur.com/GOzTHxF.png)

# Module 4: 適切な Mule 4 イベント処理モデルの選択
## Mule 4 - 3つのイベント実行・処理のタイプ
- CPU_LITE
- CPU_INTENSIVE
  - この種の処理は自動的には予測できない
![CPU-intensive](https://i.imgur.com/KIwnyNi.png)
- IO_INTENSIVE(Blocking）

```
@Execution(CPU_INTENSIVE)
public void computeFlightPlan() {
  ... 
}
```

## DEDICATED: Mule 4.1, 4.2 
3つの実行モデルごとに、別々のスレッドプールが用意されていた。(CPU_LITE, CPU_INTENSIVE, **IO_INTENSIVE**)

scheduler-pool.conf

IO_INTENSIVE(Blocking) `maxSize=max(2, cores + ((mem - 245760) / 5120))`
```
# The maximum number of threads to allow in the I/O pool.
# Supports Expressions
# Only applies when org.mule.runtime.scheduler.threadPool.strategy=DEDICATED
#org.mule.runtime.scheduler.io.threadPool.maxSize=max(2, cores + ((mem - 245760) / 5120))
```

CPU_INTENSIVE `size=2*cores`
```
# The number of threads to keep in the cpu_intensive pool, even if they are idle.
# Supports Expressions
# Only applies when org.mule.runtime.scheduler.threadPool.strategy=DEDICATED
#org.mule.runtime.scheduler.cpuIntensive.threadPool.size=2*cores
```

CPU_LITE `size=2*cores`
```
# The number of threads to keep in the cpu_lite pool, even if they are idle.
# Supports Expressions
# Only applies when org.mule.runtime.scheduler.threadPool.strategy=DEDICATED
#org.mule.runtime.scheduler.cpuLight.threadPool.size=2*cores
```

## UBER スレッドプール: Mule 4.3+ 
`org.mule.runtime.scheduler.threadPool.strategy=UBER`

![uber](https://i.imgur.com/mVcu7a6.png)

scheduler-pool.conf
UBER スレッドプール
```
# The maximum number of threads to allow in the uber pool.
# Supports Expressions
# Only applies when org.mule.runtime.scheduler.threadPool.strategy=UBER
org.mule.runtime.scheduler.uber.threadPool.maxSize=max(2, cores + ((mem - 245760) / 5120))
```

## mule ランタイムの起動
bin ディレクトリで
Mac: `./mule`
Windows: `mule.bat`

## mule ランタイムの停止
https://docs.mulesoft.com/jp/mule-runtime/4.4/starting-and-stopping-mule-esb#mule-%E3%81%AE%E5%81%9C%E6%AD%A2
    
bin ディレクトリで
Mac: `./mule stop`
Windows: `mule.bat stop`

## Tanuki Wrapper
https://wrapper.tanukisoftware.com/doc/japanese/introduction.html

> Wrapper は、JVM プロセスをモニタリング（監視）し、 もし JVM がクラッシュしたり、ハングアップした時には、自動的に再起動させます。 この処理は、Wrapper が「問題がある」と判断した場合に実行され、所要時間はほんの数秒です。 さらに、JVM のコンソール出力をモニタリング（監視）して、 ある一連の文字列に反応して、JVM を再起動したりシャットダウンするように、Wrapper の設定を変更することもできます。
    
![wrapper](https://i.imgur.com/SyrpVBZ.png)

```
# Initial Java Heap Size (in MB)
wrapper.java.initmemory=1024

# Maximum Java Heap Size (in MB)
wrapper.java.maxmemory=1024
```
Q. visualVM - Cannot find Java 1.8 or Higher
https://github.com/oracle/visualvm/issues/112

It works.

`visualvm.exe --jdkhome "C:\Program Files\AdoptOpenJDK\jdk-8.0.242.08-hotspot"`

`visualvm.exe --jdkhome "C:/Program Files/AdoptOpenJDK/jdk-8.0.242.08-hotspot"`

`visualvm.exe --jdkhome "C:/Program Files/AdoptOpenJDK/jdk-8.0.242.08-hotspot/"`

It does not work...

`visualvm.exe --jdkhome "C:\Program Files\AdoptOpenJDK\jdk-8.0.242.08-hotspot\"`

## Runtime Manager Agent
Mac: `./amc_setup -H 9910f194-0c5c-4e86-9a44-aa9094116f64---662992 node1`

Windows: `./amc_setup -H 9910f194-0c5c-4e86-9a44-aa9094116f64---662992 node1`

Q. Runtime Manager AgentのProxy 設定
https://docs.mulesoft.com/jp/runtime-manager/rtm-agent-proxy-config#mule-agent-yml-%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE-amc_setup-%E3%81%AE%E5%AE%9F%E8%A1%8C

`-P proxy-host proxy-port proxy-user proxy-password`
    
## レコードの処理
- For Each
  - シングルスレッド
  - 同期処理 
  - デフォルト batch size = 1
    - [1, 2, 3].. > 1 > 2 > 3.. 
  - batch size = 2
    - [1, 2, 3].. > **1,2**  > 3.. 
  - For Each スコープの中で payload を変更しても、Mule Event の payloadに影響はない
```
INFO  2022-02-02 13:34:45,079 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 1
INFO  2022-02-02 13:34:45,091 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 2
INFO  2022-02-02 13:34:45,097 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 3
INFO  2022-02-02 13:34:45,108 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 4
INFO  2022-02-02 13:34:45,116 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 5
INFO  2022-02-02 13:34:45,122 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 6
INFO  2022-02-02 13:34:45,130 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 7
INFO  2022-02-02 13:34:45,141 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 8
INFO  2022-02-02 13:34:45,151 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 9
INFO  2022-02-02 13:34:45,157 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].forEach.CPU_LITE @cc46f1] [processor: forEach/processors/2/processors/0; event: 72531310-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 10
```
- Parallel For Each
  - マルチスレッド
  - 非同期処理 
  - 各レコードの値を変更可能
```
INFO  2022-02-02 13:33:57,974 [[MuleRuntime].uber.06: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 2
INFO  2022-02-02 13:33:57,974 [[MuleRuntime].uber.09: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 5
INFO  2022-02-02 13:33:57,974 [[MuleRuntime].uber.08: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 4
INFO  2022-02-02 13:33:57,975 [[MuleRuntime].uber.01: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 1
INFO  2022-02-02 13:33:57,980 [[MuleRuntime].uber.07: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 3
INFO  2022-02-02 13:33:57,984 [[MuleRuntime].uber.10: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 6
INFO  2022-02-02 13:33:58,001 [[MuleRuntime].uber.11: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 7
INFO  2022-02-02 13:33:58,005 [[MuleRuntime].uber.12: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 8
INFO  2022-02-02 13:33:58,007 [[MuleRuntime].uber.13: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 9
INFO  2022-02-02 13:33:58,008 [[MuleRuntime].uber.14: [mod04-foreach_pararrelforeach_batchjob].parallelForEach.CPU_LITE @1e52b5e4] [processor: parallelForEach/processors/2/processors/0; event: 55d97e40-83e1-11ec-91c7-0028f8083c74] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: 10
```
- Batch Job
  - マルチスレッド
![visualVM](https://i.imgur.com/0gw7Lg4.png)
  - 非同期処理
  - pararell (並列に) 処理を行う
  - 変数は、各レコードに固有のもの
    - レコード1 vars.hoge = true (レコード1 の vars.hoge は、そのまま BatchStep A, B, C で参照・変更可能
    - レコード2 vars.hoge = false(レコード2 の vars.hoge は、そのまま BatchStep A, B, C で参照・変更可能)
    ※これらの変数は、各 Batch Step を超えて参照・変更ができる
    ※Batch Job スコープの完了後は、各変数を参照することはできない
  - Batch Step
    - Batch Job の処理のスコープ
    - それぞれの Step は、それぞれの条件に基づいて、レコードを受け入れる (acceptPolicy, acceptExpression)
      - e.g. acceptExpression: ```#[vars.hogeFlag==true]```             acceptPolicy: ONLY_FAILURES (処理に失敗したレコードだけを処理する Batch Step)
![DLQ](https://i.imgur.com/xeTfBzx.png)
                
  - Batch Aggregator 
    - Bulk Insert など、まとめて処理を行う
    - 2種類の設定
      1. Fixed Size (固有のサイズ)
    ![fixedsize3](https://i.imgur.com/Qw22kYk.png)
      2. Streaming 
  ![aggregator](https://i.imgur.com/KSxiggt.png)

  - maxFailedRecords
    - 失敗したレコードを許容する数 (デフォルト 0)

  - batchBlockSize
    - 各スレッドがどのくらいの単位で、各レコードをまとめて処理するか (デフォルト100)
e.g.  1000  レコード
1-100(100単位)
101-200(100単位)
201-300(100単位)
  ...
901-1000(100単位)
     
  - onComplete フェーズでの payload
  サマリーレポート
```
  {
    "onCompletePhaseException": null,
    "loadingPhaseException": null,
    "totalRecords": 2000,
    "elapsedTimeInMillis": 8909,
    "failedOnCompletePhase": false,
    "failedRecords": 1,
    "loadedRecords": 2000,
    "failedOnInputPhase": false,
    "successfulRecords": 1999,
    "inputPhaseException": null,
    "processedRecords": 2000,
    "failedOnLoadingPhase": false,
    "batchJobInstanceId": "9d6a7e50-5bd0-11ec-8902-a483e7ab0cd9"
  }
```
## エクササイズ 4-2： MySQLとSaaSシステムの同期
![e4-2](https://i.imgur.com/3XWvYgp.png)

- MySQL データベースを SaaS CRM システムと同期させる必要がある
- CRM システムはできるだけ早く更新しなければならない 
- このインテグレーションでは、各レコードの監査と追跡もサポートする必要がある
- 失敗したレコードの後処理が行えるように、人が操作できるようにしておく必要がある 
- Mule アプリケーションは、単一の 0.2 vCore CloudHub ワーカーへのデプロイを想定して設計されている (1 GB のヒープメモリ）

1. On Table Row(DBコネクタ)
 - 自動のウォーターマーク設定
 - Transform Messageでsalesforceにデータを入れる前準備を行う
 - Salesforce コネクタ
 - Error Handler?

2. Scheduler
 - Object Storeでウォーターマークを設定/取得
 - DBコネクタ > Select
 - Batch Job
 - Batch Aggregator で一括処理(Salesforce コネクタ)
 - 失敗した処理用のBatch Stepを使用して、DLQキューに詰め込む

3. データベース更新時に更新レコードをRESTでうけとりキューに格納する。
キューから取り出しながらCRMに連携

## エクササイズ 4-3：一方向 (one-way) のファイル転送ユースケースに適した Mule イベント処理を設計する
![4-3](https://i.imgur.com/hRRENIS.png)

- 1日に何回かランダムに、顧客の財務データが含まれた新しいソースファイルを、ファイルサーバー上の特定のディレクトリにアップロードする
- Mule アプリケーションはすぐにファイルを処理し、ターゲットの MySQL データベースに結果を送信する必要がある 
- 各ファイルに約100万件の顧客データレコードが含まれている
- 各レコードの監査と追跡機能が不可欠
- 失敗したレコードの後から処理が行えるように、人が操作できるようにしておく必要がある 
- Mule アプリケーションは 単一の 0.2 vCore CloudHubワーカーへのデプロイを想定して設計されている(1 GBのヒープメモリー)

1. On New Updated File 
- For Each
- Queue
- Queue から取り出して処理
2. On New Updated File 
- Batch Job
  - Batch Jobの読み込みフェーズでエラーが発生しないかを確認。ファイルを分割（e.g ２００,000*5）する必要がある可能性。
- エラー専用のBatch Step + Queue

3.　On New Updated File
- For Each(batch sizeを設定)
  - デフォルトの1で100万件を処理するのは厳しいか?
- DBコネクタのBulk Insert
- Error Handler

4.　On New Updated File
- Parallel For Each
- Error Handler


# Module 5: 適切なメッセージトランスフォーメーション(変換)とルーティングパターンの選択
DataSenseがメタデータの読み込みと変換をサポート
![datasense](https://i.imgur.com/OUhassZ.png)

## データ変換の複雑性 : Common Data Model (共有データモデル) の有効活用
- N\*N(-1) => **O(N^2)**
N=6 6×5 -> 30
N=7 7×6 -> 42
- 2N => O(N)
![complexity](https://i.imgur.com/cMRlO2R.png)

## バリデーションモジュール
- fail fast (障害を早期に発見可能) になるようにバリデーションをかける
- isNotNull? isNumber?  etc...
https://docs.mulesoft.com/jp/validation-connector/1.4/validation-examples
- ALL 
  - 全部の検証が通るとOK
  - [1,2,3] > 2でこけても、3も実行 > VALIDATION:MULTIPLE のエラーを吐く
  - 3つ中,2つでこけた例:
```
Message               : test is not a valid email address
value was expected to be null
Element               : testFlow/processors/1 @ test:test.xml:14 (All)
Element DSL           : <validation:all doc:name="All" doc:id="89e83d21-a4aa-4b47-acf6-bdb9a7a632ff">
<validation:is-email doc:name="Is email" doc:id="081b258d-75e8-4db5-a64a-f4532faeb54a" email="#[payload]"></validation:is-email>
<validation:is-null doc:name="Is null" doc:id="2c6a2c24-964e-488f-b97e-acf6786df0e6" value="#[payload]"></validation:is-null>
<validation:is-not-null doc:name="Is not null" doc:id="678c7c2c-20f7-423f-8032-61f22b01a7d1" value="#[payload]"></validation:is-not-null>
</validation:all>
Error type            : VALIDATION:MULTIPLE
FlowStack             : at testFlow(testFlow/processors/1 @ test:test.xml:14 (All))

```
- ANY 
  - 1つでも検証が通るとOK 

### Common Data Modelのイメージの一例
1. データの取得: **GET**
=== API クライアント === 
    ↑ ↓
EAPI //クエリパラメータ? URL パラメータ?ヘッダー?
    ↑ ↓
PAPI //ビジネスロジック、オーケストレーション
    ↑ ↓
SAPI //各システム固有のデータ型(システム毎の違いを吸収)からデータを取得
->Common Data Model(該当する場合)へ変換
=== バックエンドシステム ===

2. データの作成: **POST**
=== API クライアント ===
	↑ ↓
EAPI //各クライアント固有のデータ型? フォーマットは? (JSON  etc...) 
-> Common Data Model (該当する場合)　(API クライアントごとの違いを吸収)
    ↑ ↓
PAPI //ビジネスロジック、オーケストレーション
  	↑ ↓
SAPI //Common Data Model(該当する場合)
->各システム固有のデータ型への変換 (システム毎の違いを吸収)
=== バックエンドシステム ===

3. API-led のパターンに当てはまらない場合
=== データソース,Queue === 
    ↓
E/PAPI（そもそもAPIでない)
//JSON, CSV,  XML ... 
->Common Data Model+ビジネスロジック,オーケストレーション
    ↓
SAPI //Common Data Model(該当する場合)　
-> 各システム固有のデータ型への変換 (システム毎の違いを吸収)
=== バックエンドシステム ===

## EIP
https://www.enterpriseintegrationpatterns.com/

https://docs.mulesoft.com/jp/mule-runtime/4.4/understanding-enterprise-integration-patterns-using-mule

## DDD
[DDD難民に捧げるDomain-Driven Designのエッセンス](https://www.ogis-ri.co.jp/otc/hiroba/technical/DDDEssence/chap1.html)

# Module 6: Mule アプリケーションのテスト戦略の設計
> Untested code is broken code.

## MUnit テスト
### エラーが出た場合
Xml -> テスト名をクリックして、詳細なエラーを表示させる
![Munit!](https://i.imgur.com/AS9LXFb.png)

### Assert (アサート, 検証)
- [Assert Equals](https://docs.mulesoft.com/jp/munit/2.3/assertion-equals-processor)
![assert](https://i.imgur.com/6wSaIxC.png)

- [Assert Expression](https://docs.mulesoft.com/jp/munit/2.3/assertion-expression-processor)
- [Assert That](https://docs.mulesoft.com/jp/munit/2.2/munit-matchers)

### Spy 
[Spy](https://docs.mulesoft.com/jp/munit/2.3/spy-event-processor) プロセッサでは、イベントプロセッサのコール前後で何が起きているかを監視できます

## MUnit テストのパラメータ化 
yaml と組み合わせて、複数のテストケースを作成

```
hello: # test case 1
  inputPayload: "hello" # ${inputPayload} 
  expectedPayload: "Hello back!" # ${expectedPayload}
goodbye: # test case 2
  inputPayload: "goodbye" # ${inputPayload}
  expectedPayload: "Goodbye!" #  ${expectedPayload}
default:  # test case 3
  inputPayload: "default" # ${inputPayload}
  expectedPayload: "I do not understand that" #  ${expectedPayload}
 ```

### Set Event to Behavior エリア
- Value (値): `${inputPayload}`
- Media Type (メディアタイプ): `text/plain`

###　Assert Equal to Validation エリア
- Actual (DataWeave 式モード): `payload`
- Expected (リテラルモード): `${expectedPayload}`
- Message (リテラルモード): `Payload did not match expected`

## MUnit Test Tags
`mvn clean test -Dmunit.tags=aTagName`
https://docs.mulesoft.com/jp/munit/2.3/munit-test-concept#%E3%82%BF%E3%82%B0%E5%B1%9E%E6%80%A7%E3%81%AE%E3%83%86%E3%82%B9%E3%83%88

    
# Module 7: デプロイメント戦略の決定と開発
## CloudHub ゼロダウンタイムのデプロイ
![zerodowntime](https://i.imgur.com/GRYL6aa.png)

## VisualVMでスタンドアローンMuleランタイムのメモリの変化を確認する
193行目 default => 1024　
ここではメモリの最小を変更
`wrapper.java.initmemory=512`

197行目 default => 1024　
ここではメモリの最大を変更
`wrapper.java.maxmemory=512`
- プロセスを確認
チェックポイント: メモリは 512 MBに変わっている？

##  Domain プロジェクト
1つのランタイムで複数のアプリケーションを実行する際に、設定を共有させることが可能
例: appA と appB のどちらもが、domainX の HTTP Listner Config を参照する => ポートの競合が解消！
※ Customer-hosted Mule ランタイムでのみ可能な構成
※ CloudHub や RTF はマイクロサービスとして 1Mule=1Appなので、そもそもドメインプロジェクトの必要がない。
※1 Mule <=> N 個の App の構成が可能、ではあるが、アプリケーションの数が増えると、Mule バージョンのアップデートや再起動に際しての影響範囲が広くなるため、注意が必要。

## RTF (Self-managed k8s)
1. RTF on Self-managed k8s
資料: https://docs.mulesoft.com/jp/runtime-fabric/1.9/index-self-managed
- EKS, AKS, GKE などの管理型 k8s サービスで実行
- 1 に比べて専門知識が必要
    
![RTF-ON-Selfmanaged-k8s](https://i.imgur.com/pij59zy.png)


## Gold vs Platinum & Titanuim
Platinum & Titanuim　では、CloudHub vCore から Customer-hosted ランタイム Core への振替が可能 (サポートケースを作成)
資料: https://help.mulesoft.com/s/article/How-to-Transfer-Mulesoft-on-Premise-Core-Licenses-to-Cloudhub-vCore-Licenses-or-Vice-Versa

## エクササイズ: デプロイメントオプションの比較
- API呼び出しとメッセージングに関する全てのメタデータを含む、オンプレミス処理の制約
  - コントロールプレーン: Anypoint PCE
  - ランタイムプレーン: スタンドアローン（RTFはPCEで選択不可）
- 市場投入(time-to-market)の期間
  - コントロールプレーン: MuleSoft-hosted Anypoint Platform
  - ランタイムプレーン: **CloudHub**
- IT 運用の労力の削減
  - コントロールプレーン: MuleSoft-hosted Anypoint Platform
  - ランタイムプレーン: **CloudHub**
- オンプレミス/DCデータソースへのアクセス
  - コントロールプレーン: MuleSoft-hosted Anypoint Platform
  - ランタイムプレーン: **CloudHub** [(VPN,VPC Peering, Transit Gateway, DirectConnect)](https://docs.mulesoft.com/runtime-manager/vpc-connectivity-methods-concept), RTF, スタンドアローン
- 複数の Mule アプリケーション間の分離
  - コントロールプレーン: MuleSoft-hosted Anypoint Platform
  - ランタイムプレーン: CloudHub, RTF, スタンドアローン(1 Mule <-> n 個のアプリケーションが可能)
- Mule ランタイムのチューニング
  - コントロールプレーン: MuleSoft-hosted Anypoint Platform
  - ランタイムプレーン: スタンドアローン(必要性を考慮)
- ランタイムプレーンの拡張性 (scalability)
  - コントロールプレーン: MuleSoft-hosted Anypoint Platform
  - ランタイムプレーン: CloudHub(CloudHub の枠組みの中で拡張は可能), RTF, スタンドアローン 
- スケーリング -> 水平(スケールアウト/イン) & 垂直(スケールアップ/ダウン)
  - コントロールプレーン: MuleSoft-hosted Anypoint Platform
  - ランタイムプレーン: CloudHub(オートスケーリング: ELA契約のみ), RTF
    - [RTF](https://docs.mulesoft.com/jp/runtime-fabric/1.4/deploy-resource-allocation)
    - [CH+ELA](https://docs.mulesoft.com/jp/runtime-manager/autoscaling-in-cloudhub)
- 新規リリースのロールアウト(ゼロダウンタイムでのデプロイメント)
  - コントロールプレーン: Anypoint Platform(US/EU)
  - ランタイムプレーン: CloudHub, RTF
    - [RTF 本番設定](https://docs.mulesoft.com/jp/runtime-fabric/1.7/architecture#%E6%9C%AC%E7%95%AA%E8%A8%AD%E5%AE%9A)

# Module 8: 適切なステート(状態)の維持と管理のオプション設計
・デプロイの設定によって異なる状態の保持管理オプション
![デプロイの設定によって異なる状態の保持管理オプション](https://i.imgur.com/tQjGhp0.png)

## エファメラルなストレージ
![ephameral](https://i.imgur.com/tir7b1S.png)

## 信頼性/アクセススピード/共有可能性
![tradeoff](https://i.imgur.com/i4wu7im.png)


## CloudHub - Persistent Queue (クラウドの永続化キュー)
https://help.mulesoft.com/s/article/Mule-Batch-Process-and-CloudHub-Persistent-Queues
※ Batch 処理ではパフォーマンスに影響あり!!! 
以下のコマンドで「VM のpersistent queue を有効にしつつ、batch queue では persistent queue を使用しない」という設定が可能
`batch.persistent.queue.disable=true`

## Object Store on CloudHub
- Object Store V2 の制限
資料: https://docs.mulesoft.com/jp/object-store/#object-store-%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E3%83%A1%E3%83%A2

制限に引っかかるもの (10TPS/100TPS, 30 days TTL )や、再起動で失われても良いもの、共有しなくても良いものは Object Store V2 ではなく non persistent の使用を検討

Object Store はキーバリューペア
```
{ 
  "persistent": "cloudHubValue"
}
```

- Store Object Store V2
  - エンドポイント: /object-store/**storePersistent**?key=**persistent**&value=cloudHubValue

- Retrieve ObjetStore V2
  - エンドポイント: /object-store/**retrievePersistent**?key=**persistent**
retuens `"cloudHubValue"`

- Store NP (Non Persistent: 非永続的な) ObjetStore
  - エンドポイント: /object-store/**storeNonPersistent**?key=**nonPersisten**t&value=cloudHubValue

- Retrieve NP ObjetStore
  - エンドポイント: /object-store/**retrieveNonPersistent**?key=**nonPersistent**
  

- [ ] 再起動後、CloudHub Object Store V2 の データは残っている?
  - [ ] /object-store/retrieveNonPersistent?key=nonPersistent 
returns `null!`
  - [ ] /object-store/retrievePersistent?key=persistent
returns `cloudHubValue!`

## Clustered Mule ランタイム (HZ IMDG)
### mule.bat -M-Dhttp.port=9081 でポートのコンフリクトを避ける!


![cluster](https://i.imgur.com/SzU5kiD.png)


## cluster profile (performance/reliable[デフォルト])

HZ を使わないオプション: `mule.cluster.storeprofile=performance`
https://docs.mulesoft.com/jp/mule-runtime/4.4/mule-high-availability-ha-clusters#%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9%E3%83%97%E3%83%AD%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E8%A8%AD%E5%AE%9A

    
> Unicast servers must be in the Running state.

Unicastで実行する場合は、まずmuleランタイムを実行する

1. .mule/mule-cluster.propertiesを削除
2. ランタイムを起動する

Mac
- ./mule -M-Dhttp.port=9081
- ./mule -M-Dhttp.port=9082

Windows: 
- mule.bat -M-Dhttp.port=9081
- mule.bat -M-Dhttp.port=9082

3. Unicastでお互いを検知させる
![unicast](https://i.imgur.com/9hHF22C.png)

![unicast2](https://i.imgur.com/v0lpf1y.png)
https://help.mulesoft.com/s/article/Unicast-Cluster-shows-Communication-Issues-Detected

![unicast3](https://i.imgur.com/HP2o6BV.png)
    
4. テスト！
## stateful-playground.jar(cluster) 
- 1.Store Persistent 
  - http://localhost:**9081**/object-store/storePersistent?key=persistent&value=Cluster-persistent!

- 2.Retrieve Persistent
  - http://localhost:**9081**/object-store/retrievePersistent?key=persistent
  - http://localhost:**9082**/object-store/retrievePersistent?key=persistent
    - `Cluster-persistent!`
    - 複製がされている! 
    
- 3.Store Non Persistent (非永続的)
  - http://localhost:9082/object-store/storeNonPersistent?key=nonPersistent&value=Cluster-non-persistent!

- 4.Retrieve NonPersistent(非永続的)
  - http://localhost:9082/object-store/retrieveNonPersistent?key=nonPersistent
  - http://localhost:9081/object-store/retrieveNonPersistent?key=nonPersistent
    - `Cluster-non-persistent!`
    - 複製がされている! 

- 5. 再起動後の挙動を確認する: 全ての値が再起動後も取得可能(HZ IMDGで複製済み)
  - http://localhost:**9081**/object-store/retrieveNonPersistent?key=nonPersistent
  - http://localhost:**9082**/object-store/retrieveNonPersistent?key=nonPersistent
  - http://localhost:**9081**/object-store/retrievePersistent?key=persistent
  - http://localhost:**9082**/object-store/retrievePersistent?key=persistent

6. primary nodeは変更される
![primarynode](https://i.imgur.com/PA9cBcB.png)

- JMS: primary node only
https://docs.mulesoft.com/jms-connector/1.8/jms-performance#cluster-configuration-optimization
    
- Schedulerはprimary nodeのみで動く
non primary node
![non primary node](https://i.imgur.com/02oZN0w.png)
primary node
![primary node](https://i.imgur.com/pbCthVo.jpg)
    
## スタンドアローンランタイム Object Store
- persistent(永続的)
  - .mule > <appname> > objectstore に保存されていく
- transient(一時的)
  - メモリ

###  stateful-playground.jar(スタンドアローン) 
- 1.Store Persistent 
  - http://localhost:8081/object-store/storePersistent?key=persistent&value=Standalone!

- 2.Retrieve Persistent
  - http://localhost:8081/object-store/retrievePersistent?key=persistent
`Standalone!`

- 3.Store Non Persistent (非永続的)
  - http://localhost:8081/object-store/storeNonPersistent?key=nonPersistent&value=Standalone!

- 4.Retrieve NonPersistent(非永続的)
  - http://localhost:8081/object-store/retrieveNonPersistent?key=nonPersistent
`Standalone!`


- [x] 再起動後、 スタンドアローンの Object Store のデータは残っている？？
  -  http://localhost:8081/object-store/retrievePersistent?key=persistent 
     - standaloneValue!!! (persistent = ディスクに書き込む) 
  -  http://localhost:8081/object-store/retrieveNonPersistent?key=nonPersistent 
     - null(non persistent  = メモリに保持する = 再起動に耐えられなかった...) 
    
## CloudHub Persistent Queue(永続化キュー) 
- SQS の仕組みを使用したクラウドベースの永続化キュー(ワーカー間で共有可能 && リスタートに耐える)
- **Batch Queue に、永続化キューを使用するとパフォーマンスに影響がある** 
- オプトアウト
`batch.persistent.queue.disable=true`

https://help.mulesoft.com/s/article/Mule-Batch-Process-and-CloudHub-Persistent-Queues
    
## Cache スコープ
Object Store を使用して、一定期間キャッシュを使用する仕組み 

## Idempotent Message Validator　スコープ 
Object Store を使用して、同一の ID を持つデータが、重複して処理されないようにする仕組み

Q.1. CloudHubの複数ワーカー構成
2. RTFの非クラスタ構成(pod/replica)
3. RTFのクラスタリング構成
の3つを比較したときに、アプリケーションの状態管理の観点では、1.と2.は同じであり、2.と3.はhazelcastでOSとVMを共有できる違いがあるという理解であってますか？であれば、1.と3.の違いも2.と3.の違いと考えてよいですか？
    
A. Yes! -> 1と3の違いは 
1. OS V2,クラウドベースのpersistent Queueが使用可能
3. persistent gateway(psql)でOSを共有可能にすることができる

# Module 9: 効果的なログと監視(モニタリング)の設計
## CloudHub log
100MB or 30 days
https://docs.mulesoft.com/runtime-manager/custom-log-appender#create-your-log4j-configuration

## Anyoint Monitoring Log
https://help.mulesoft.com/s/article/Anypoint-Monitoring-Log-FAQ
> What are the storage limits for Anypoint Monitoring logs?
For Titanium Subscription, you will get 200 GB per production core. Please note that the storage is shared across globally, meaning that if you only have one production core, you will get **200 GB** of storage that is shared across all apps. This storage is also shared across both logs and metrics usage.

## JMeter + Proxyの起動方法 まとめる
`.\jmeter.bat -H proxyHost -P proxyPort`
    
    
# Module 10: 効率的で自動化されたソフトウェア開発ライフサイクル(SDLC)の設計
##  maven 
https://maven.apache.org/download.cgi

- ライフサイクル
https://maven3.kengo-toda.jp/primer/build-lifecycle

- Mule Maven Plugin 
https://docs.mulesoft.com/jp/mule-runtime/4.3/mmp-concept
https://docs.mulesoft.com/jp/mule-runtime/4.3/deploy-to-cloudhub
    
- Connected App
https://docs.mulesoft.com/jp/access-management/connected-apps-overview

## Anypoint CLI
https://docs.mulesoft.com/jp/runtime-manager/anypoint-platform-cli

1. インタラクティブモード
- `npm install -g anypoint-cli@latest`

- `anypoint-cli --username=XXX --password=YYY --organization=ZZZ --environment=Sandbox`

※ スペースがある場合は""で囲む(`--organization="MuleSoft Training"`)
※ !などがある場合は、`\`でエスケープ
`--password=\!MuleSoft2020`
    
例: Runtime Manager アラートの一覧を取得
`runtime-mgr cloudhub-alert list`

例: Runtimeのサーバーの名前を変更
`runtime-mgr server list` // ID を取得
`runtime-mgr server describe 13634800`　// 詳細情報の表示
`runtime-mgr server modify 13634800 --name nodex` // node1 -> nodex

2. スクリプティングモード

## Anypoint Platform API
### Anypoint Platform APIのレート制限
https://help.mulesoft.com/s/article/Anypoint-Platform-REST-API-Rate-Limit#:~:text=Anypoint%20platform%20detects%20usage%20based,from%20an%20individual%20client%20IP.
> As a guidance, it is recommended that applications do not exceed 15 requests per second from an individual client IP.

> Should an API Rate Limit be exceeded, the Anypoint Platform will reject requests with a 503 Service Unavailable or 503 Service Temporarily Unavailable HTTP Response Code.

## Anypoint Platform REST API の呼び出し方
1. `https://anypoint.mulesoft.com/accounts/login` に POST リクエストを送信します。  Body には以下の内容を設定してください。

content-type: application/json
```
{
  "username": "REPLACE_HERE!",
  "password": "REPLACE_HERE!"  
}
```

2. 403 Forbidden 「invalid csrf token」エラーが表示された場合は、Advanced REST Client の _csrf クッキーを削除します。
> Request > Web session > Cookie manager 
![cookie-manager](https://i.imgur.com/y4i9lva.png)

![403](https://i.imgur.com/vI58kwq.png)

3. 再度リクエストを送信すると 200 OK と access_token が返されます。
```
{
  "access_token": "824767b4-1e87-4b56-9896-99878491f5f2",
  "token_type": "bearer",
  "redirectUrl": "/home/"
}
```
    
4. このアクセストークンを Authorization ヘッダーに使用して、 Anypoint Platform API を呼び出すことが可能になります。
例: `Authorization: bearer 80566d46-3827-463c-b624-c36bae02d0df`

![authorization](https://i.imgur.com/YacDP8w.png)

Access Managent API `https://anypoint.mulesoft.com/accounts/api/me`
    
[Anypoint Platform API](https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/)
  
※ curl: `curl -X POST https://anypoint.mulesoft.com/accounts/login -H "Content-Type: application/json" -d '{"username":"testuser1111", "password":"!MuleSoft2020"}`

※ Postman のクッキーの削除
postman のsendボタンの下にcookieを編集する機能がありました。そちらでクッキー消して出来ました。

### Access Managemnt API
https://anypoint.mulesoft.com/accounts/api/users/me

# Module 11: Mule アプリケーションにおけるトランザクション(TX)　管理設計
※ TX = トランザクション
すべてのメッセージ処理は単一スレッドで行う
    
https://docs.mulesoft.com/jp/api-manager/2.x/configure-autodiscovery-4-task
```INFO  2022-02-04 11:30:45,811 [agw-policy-set-deployment.01] com.mulesoft.mule.runtime.gw.policies.deployment.DefaultPolicyDeployer: Applied policy rate-limiting-2521374 version 1.3.5 to API COVID-19 SAPI-v1-v1:17609769 (17609769) in application covid19-api```
        
## シングルリソース TX
単一のデータソースで実行するトランザクション(e.g 単一DBの単一テーブル)

## XA TX 
複数のデータソースを跨いだトランザクション
bitronix XA マネジャー
<bti:transaction-manager doc:name="Bitronix Transaction Manager" doc:id="15009545-b62f-4210-972d-df654f3a5f6c" />

## XA トランザクションハンズオンの呼び出し例
`/init` -> 2つテーブルを作成(orders, orders2)
`/drop` -> テーブルをドロップ
`/select` -> セレクト
`/doStuffAsXA?id=1&haveError=false&customerName=MaxMule`
 -> エラーなし XA TX 

`/doStuffWithoutTransaction?id=2&haveError=false&customerName=MaxineMule`
 -> エラーなし 

`/doStuffAsXA?id=3&haveError=true&customerName=MaxMule`
 -> エラーあり トランザクションあり

`/doStuffWithoutTransaction?id=4&haveError=true&customerName=MaxineMule`
 -> エラーあり トランザクションなし
 
#### Saga Pattern
- イベントコリオグラフィーパターン
- オーケストレーターパターン 

## JMS には TX と ACK の仕組みがある(どちらか、を選択)
[ACK]( https://docs.mulesoft.com/jp/jms-connector/1.7/jms-ack) 
1. AUTO (デフォルト)
   - 完了、もしくは On Error Continue で ACK
      
2. IMMEDIATE 
   - 受け取ったら ACK (信頼性...?)
   - Mule 3 では NONE と呼ばれていた

3. MANUAL 
   - ACK オペレーションをフローの中で設定

4. DUPS_OK
   - まとめて ACK  (重複の可能性)

# Module 12: 信頼性(reliability)目標に向けた設計
## Reliablity Pattern
- 再接続戦略
- 再デリバリーポリシー(メッセージ)
- Transaction(LocalTX/XATX)
- エラー処理
- First Successful

### Messaging Queue
![message queue](https://i.imgur.com/PhECdcp.png)

### Until Successful
Until Successful + Try + On Error Continueで、「エラーの種類に応じて、リトライするかどうか」を判断する(4XX系のエラーであれば、OnErrorContinueでUntil Successfulから抜け出す、など)
- On Error Continue はエラーを飲み込むため「Successした」と判断させることができる
![on error continue](https://i.imgur.com/8Z5YrER.png)
