Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MicroProfileのススメ~ なぜぼくはコレを使うのか~

MicroProfileのススメ~ なぜぼくはコレを使うのか~

JJUG CCC 2023 Spring登壇資料

荻原利雄

June 05, 2023
Tweet

More Decks by 荻原利雄

Other Decks in Programming

Transcript

  1. 2 荻原 利雄(オギワラ トシオ) • 所属 / 職種 - 株式会社豆蔵

    - ビジネスソリューション事業部 - 主幹ソフトウェアエンジニア • プロフィール - オブジェクト指向とともにエンタープライズな Javaアプリを作りつづけて25年のアラフィフエ ンジニア - ここ数年は大規模基幹システムを支える JakartaEEフルスタックなフレームワークの開発 を行っている • 使っているMicroProfile実装 ‐ 業務:WebSphere Liberty(だけどMicroProfileは使っ ていない) ‐ 社内技術調査等:Oracle Helidon extact-io 豆蔵デベロッパーサイト 豆蔵デベロッパーサイトで連載中! 逆張りのMicroProfile
  2. お断り • 本資料はMicroProfile 5.0(+ Jakarta EE 9.1)をベースに作成しています • 最新はMicroProfile 6.0(+

    Jakarta EE 10)ですが機能的に大きな違いはありません • MicroProfile 5.0をベースにしているのはHelidonの最新が、、モゴモゴ • JakartaEEの各仕様名はJavaEE時代から変更されていますが、表記が長くな るのと発表者が呼びなれないため、JavaEE時代の旧称を使用しています <例> • Jakarta RESTful Web Services → JAX-RS(Java API for RESTful Web Services) • Jakarta Persistence → JPA(Java Persistence API) 4
  3. 速習JakartaEEこれだけ知っておいて - CDIの基本 - 8 CDI(Contexts and Dependency Injection)とは •

    指定されたサライフサイクル(Scope)に応じてBeanオブジェ クトをCDIコンテナで管理してくれる • Interceptorをバインドすることでメソッド呼び出しに対し 割り込みを掛け、任意の処理を追加することができる • 他にも色々あるがこの2つを理解しておけばとりあえずOK なにか見覚えが・・ SpringFrameworkのDI x AOPとやってくれることは同じです CDI SpringFramework ほぼ同じ
  4. 速習JakartaEEこれだけ知っておいて - Springで理解するCDI - 9 import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @ApplicationScoped

    public class Foo { private Bar bar; @Inject public Foo(Bar bar) { this.bar = bar; } } import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class Bar { } <CDIで実装した場合> import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class Foo { private Bar bar; @Autowired // 省略も可。あと@Injectも使える(使おうと思えば・・ public Foo(Bar bar) { this.bar = bar; } } import org.springframework.stereotype.Component; @Component public class Bar { } <Springで実装した場合> 極論するとアノテーションが違うだけで基本機能としてできることは同じ ライフサイクルはSingleton ライフサイクルはSingleton
  5. 速習JakartaEEこれだけ知っておいて - JAX-RSの基本 - 10 JAX-RS(Java API for RESTful Web

    Services)とは • JakartaEEのRESTリクエストを処理する仕様 • HTTPメソッド(GET、POST、PUT、DELETEなど)に対応するアノ テーションを使用して、リソースの作成、更新、削除などの操 作を定義する • パスパラメータやクエリパラメータなどのリクエストパラメー タを取得したり、JSONやXMLなどメッセージボディの形式が異な るデータを処理することもできる なにか見覚えが・・ SpringMVCのRestControllerと守備範囲は同じ CDI Spring Framework ほぼ同じ
  6. 速習JakartaEEこれだけ知っておいて - Springで理解するJAX-RS - 11 import jakarta.enterprise.context.ApplicationScoped; import jakarta.ws.rs.GET; import

    jakarta.ws.rs.Path; import jakarta.ws.rs.QueryParam; @ApplicationScoped @Path("/hello") public class HelloController { @GET public String hello(@QueryParam("name") String name) { return String.format("Hello %s!", name); } } <JAX-RSで実装した場合> import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/hello") public class HelloController { @GetMapping public String hello(@RequestParam("name") String name) { return String.format("Hello %s!", name); } } <SpringWebで実装した場合> 極論するとアノテーションが違うだけで基本機能としてできることは同じ
  7. JakartaEE(≠MicroProfile) vs SpringFramework • Springはmainメソッドから起動できるがJakartaEEはアプリケーションサーバ上で動作させる必要がある ➢ 百歩譲ってCDIコンテナはJavaSE環境で動作させられるのでまだよいが、JAX-RSはアプリケーションサーバにデ プロイして動かす必要がある。なのでデバックがめんどくさい・・ • Springは設定ファイルでBeanの実装を切り替えることができるがCDIはできない

    ➢ beans.xmlのalternativesが有効なのはアーカイブ内だけ。warから依存jar内の実装を変えるなどアーカイブの 外から実装を変えることはできない ➢ (他の手段で工夫すればやりようはあるが)レイヤ間の実装をモックに切り替えたテストがしづらい 12 基本機能は同じといったが、Springならできるのに・・と思うことは少なから ずあるのは事実。よって、機能面での単純比較であればモノとしてはSpringの 方がよいのは確か(個人の感想です) ≦ だって、オレ標準だからさぁー
  8. MicroProfileの仕様体系-JakartaEE 14 JakartaEE Spec部 CDI DIコンテナ+Interceptor JAX-RS RESTリクエスト処理 Jakarta Annotaions

    @Priorityや@PostConstructなど のSpec間の共通アノテーション JSON-P JSON処理関連(具体でいうとこれ らの実装としてjacksonがある) JSON-B JSON-Processing:JSONの読み書き JSON-Binding:JSONのオブジェクトバインド JakartaEE Specで含まれるのはREST機能を実現する 必要最小限のスペックのみ REST基盤 共通アノテーション オブジェクトのJSON(de)serialize message bodyのwrite/readで利用
  9. MicroProfileの仕様体系-MicroProfile固有 15 MicroProfile Spec OpenTracing OpenTracingに参加させるインテグレー ション機能(Jaeger連携) Metrics ヒープサイズやGC回数などのメトリック スの公開方法(Prometheus連携)

    Fault Tolerance サーキットブレーカやRetry、Timeoutな どのフォールトトレラント機能 Health サービスの死活監視に関するいわゆる ReadinessとLivenessに関する仕様 Config 環境変数やシステムプロパティ、設定 ファイルなど異なる設定源の統合 JWT Auth 標準Claimの定義とJWT認証 OpenAPI ソースからOAS(OpenAPI Specification) ドキュメントを生成 RestClient インタフェースを定義するだけでREST呼 び出しを可能にする 可観測性 回復性 可搬性 可用性 実装容易性 MSAは複数の要素から構成される(このため) ✓ ボトルネックや障害箇所の特定が困難となるため可観 測性がより重要となる ✓ 部分的障害が発生することを前提に機能を継続させる 回復性が重要となる ✓ またそのためにはシステムの健全性を確認できる必要 がある MSAはそれ自身の目的からスケール容易であることが求め られる ✓ スケール容易にするためコンテナ化が前提となるため、 コンテナの可搬性が求められる ✓ スケールできるようにステートレスな認証方式が求め られる MSAではRESTが多用される(このため) ✓ RESTの実装が容易であることが求められる マイクロサービスアーキテクチャ(MSA)に求められる非機能 マイクロサービスアーキテクチャで必要となる 非機能要件に対する対応 赤字:後ほど個別に紹介するSpec
  10. 改めてMicroProfileとは-ここまでの理解をもとに 16 JakartaEEのCDI+JAX-RSを基盤とし、マイクロサービスなREST アプリケーションを作りやすく運用しやすくするための仕様の セット(なのでUIに関する仕様は含んでいない) MicroProfileとは 余談:なぜJakartaEEと別なのか(私見) • 端的に言うとリリースサイクルが異なるから •

    JakartaEEはその利点の1つとしてJ2EEからの膨大な過去資産に対する下位互換性を重んじる 傾向にあり、リリースは慎重に行われる • 一方、MicroProfileが対象にしているマクロサービス界隈はトレンドの移り変わりが早く早 期のリリースが求められる。それと引き換えに後方互換に対する優先度は低くならざるを得 ない • 事実、JakartaEEはリリース間隔がMicroProfileに比べて長いが、破壊的変更は滅多に含まれ ない。これに対し、MicroProfileはリリース間隔は短いが破壊的変更が含まれることがある (最近ではMetrics3.0で多数の破壊的変更が入れられた)
  11. おまけ:MicroProfile 5.0と6.0の違い 17 引用:https://microprofile.io/ 引用:https://devm.io/java/jakarta-ee-ten-release MicroProfile 6.0 JakartaEE10 CoroProfile CDIを構成する

    細かいSpecを明 記しただけで今 までと同じ OpenTracingから置き換え ✓ 分散トレーシングに準拠する仕様がOpenTracingからOpenTelemetryに変更 ✓ 一部のSpecバージョンは上がっているが、実質的なSpecレベルの追加はない
  12. MicroProfileの実装形態 21 <JakartaEEアプリケーションサーバ> ◼ 2つの実装形態がある <MicroProfileフレームワーク> ✓ アプリケーションサーバに内包される MicroProfileの実装を利用する ✓

    JakartaEEアプリと同じようにwar形式でアプリ ケーションサーバにデプロイする ✓ アプリの動作にはアプリケーションサーバが必要 ✓ jarのライブラリ形式で提供されるMicroProfile実装を アプリケーションのdependencyに追加して利用する ✓ nettyなどの組み込みのHTTPサーバを内包しているため、 アプリケーションサーバは不要で動作する ✓ 利用イメージとしては組込みTomcatを使ったSpringBoot と同じ 代表ケースを記載しています。MicroProfile実装固有な実行形式もあります。詳細等は利用する MicroProfile実装のマニュアル等を確認ください
  13. おまけ:OpenLibertyの例-実装方法 22 @ApplicationScoped @Path("/hello") public class HelloController { @GET public

    String hello(@QueryParam("name") String name) { return String.format("Hello %s!", name); } } <アプリのコード> ※Servletアプリと同様にmainメソッドの実装は不要 JakartaEEアプリケーションサーバ <dependency> <groupId>jakarta.enterprise</groupId> <artifactId>jakarta.enterprise.cdi-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.ws.rs</groupId> <artifactId>jakarta.ws.rs-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.eclipse.microprofile.config</groupId> <artifactId>microprofile-config-api</artifactId> <scope>provided</scope> </dependency> ✓ MicroProfile実装に対する依存はアプリケーションサーバに内包さ れているため不要 ✓ 代わりにコンパイルを通すために仕様(api)だけの依存をprovidedス コープで追加する <pom.xml(主なdependency部分)>
  14. おまけ:OpenLibertyの例-ビルド~実行 23 JakartaEEアプリケーションサーバ <!– MicroProfile6.0のすべての機能を有効化する例 --> <featureManager> <feature>microProfile-6.0</feature> </featureManager> <!--

    MicroProfile6.0の必要な機能だけを有効化する例 コンテナ化する際のフットプリントを小さくできる --> <featureManager> <feature>cdi-4.0</feature> <feature>restfulWS-3.1</feature> <feature>jsonb-3.0</feature> <feature>jsonp-2.1</feature> <feature>mpConfig-3.0</feature> </featureManager> 機能の有効化:サーバー構成を定義するOpenLiberty独自のserver.xmlに利用する機能を宣言 ✓ その他のビルドから実行までの方法は普通の Servletアプリと同じ ✓ IBM Liberty Developer Tools(LDT)プラグインを インストールすることでEclipseから(デバッグ)実 行することができるようになる(操作方法は EclipseのWTPと同じ) <IBM Liberty Developer Toolsの操作イメージ> 引用:Libertyの始め方 – Qiita@TTakakiyo(Takakiyo Tanaka) in IBM
  15. おまけ:Helidonの例-実装方法 24 @ApplicationScoped @Path("/hello") public class HelloController { @GET public

    String hello(@QueryParam("name") String name) { return String.format("Hello %s!", name); } } package jaxrs; public class HelloMain { public static void main(String[] args) { // Helidonの起動 io.helidon.microprofile.cdi.Main.main(args); } } <dependencies> <dependency> <groupId>io.helidon.microprofile.bundles</groupId> <artifactId>helidon-microprofile-core</artifactId> </dependency> ... </dependencies> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>libs</classpathPrefix> <mainClass>jaxrs.HelloMain</mainClass> </manifest> </archive> </configuration> </plugin> <アプリのコード> <pom.xml(一部抜粋)> これだけで推移的依存により必要な依存が追加される mainメソッドから起動 mainClassとclasspathをMANIFESTファイルに設定した ExecutableJarの作成 MicroProfileフレームワーク
  16. おまけ:Helidonの例-ビルド~実行 25 target ├─jjug-mp-sample.jar <-- mainClassを持つアプリのExcutableJar ├─libs <-- 依存ライブラリ(Helidonの実体) │

    ├─aopalliance-repackaged-3.0.3.jar │ ├─helidon-common-3.2.1.jar │ ├─helidon-common-configurable-3.2.1.jar │ ├─helidon-common-context-3.2.1.jar │ ├─helidon-common-crypto-3.2.1.jar │ ├─helidon-common-http-3.2.1.jar │ ... $ mvn clean package $ java -jar target/jjug-mp-sample.jar 1. mavenでアプリをビルド ビルド結果 2. javaコマンドでアプリを起動 maven-dependency-pluginの copy-dependenciesゴールで runtimeとcompileスコープのjarが ./target/libにコピーされる 3. 起動イメージ MicroProfileフレームワーク
  17. MicroProfileの実装形態によるメリデメ 26 メリット デメリット アプリケーションサーバ ✓ MicroProfileと一緒にアプリケーショ ンサーバが持つJakartaEE仕様を使え る(その典型がJPA) ✓

    既存のJakartaEEアプリに MicroProfile機能を追加できる ✓ 実行にアプリケーションサーバ が必要 ✓ デバックがめんどくさい ✓ MicroProfile仕様としてMultiモ ジュール(1VM複数war)の扱い が分かりづらい*1 ✓ コンテナ化しづらい MicroProfileフレーム ワーク ✓ JavaSE環境で動作する ✓ デバックがしやすい ✓ コンテナ化しやすい ✓ MicroProfileに含まれない JakartaEE仕様が使えるかは MiroProfileの実装次第*2 ✓ 既存のJakartaEEアプリはその ままでは動作しない(Servletは 含まれていない) *1:MicroProfileにcontext-rootの概念は基本ない *2:多くの実装でJPAは独自拡張としてサポートされている
  18. MicroProfileフレームワーク JakartaEEアプリケーションサーバ(warデプロイ形式) 主なMicroProfile実装 27 IBM陣営 ✓ 最新のMicroProfile6.0に対応して いるのは現時点でOpenLibertyのみ ✓ ここに挙げたOpenLiberty以外は

    MicroProfile5.0に対応 ✓ OpenLibertyは常にMicroProfileの 最新仕様に追従するスタンス ✓ 図からもIBM陣営はMicroProfileに 積極的なことがうかがえる ✓ LauncherはJakartaEEアプリケー ションサーバではないが、アプリ ケーションをwar形式にする必要が ある。warをuber JARに変換して Javaコマンドから起動することが できる ✓ PayaraMicroも同様なことができる
  19. 典型的なJakartaEEフルスタックなWebアプリ JSF(+CDI) CDI JPA(+CDI) MicroProfile Config-登場背景 • JakartaEEには設定ファイルに対する共通的な仕様が定義さ れていない •

    web.xmlやbeans.xml, persistence.xmlなど仕様ごとに必要 な設定ファイルが存在する(徐々にアノテーションでも定 義できるようになってはきてはいる) • アプリケーション全体レベルでの設定の見通しが悪く、設 定漏れや配置漏れも起きやすくハッキリいって不便 (Springのapplication.ymlが裏山) 29 Configに対する2つのモチベーション 多すぎる設定ファイル CloudNativeへの追従 • マイクロサービスアーキテクチャのbest practiceとして知 られるThe Twelve-Factor Appの“Ⅲ 設定”では「設定を環 境変数に格納する」ことを推奨している • これまでJakartaEEの仕様でこれを実現できるものはなかっ た(SpringBootでは普通にできるけど) web.xml persistence.xml beans.xml orm.xml presentation faces-config.xml business beans.xml integration beans.xml 多すぎ、散らばりすぎ、勘弁して・・ 引用:Twelve-Factor Appを噛み砕いてみた - Qiita @supreme0110 ✓ 設定はコードや設定ファイルに含めず、環境変数で設定す るようにしましょう。 ✓ なぜならコードに含めてしまうと環境ごとにビルドが必要 になり、設定ファイルの場合は環境ごとにファイルが必要 となりスケールしにくくなるためです。 ✓ 環境変数であればOSが異なっても取得方法は基本的に統一 できます -Ⅲ 設定-
  20. MicroProfile Config-機能概要 30 MicroProfile共通仕様としての設定機能 • MicroProfileの各仕様はMicroProfile Configから設 定を読み込むことで統一されている • よってJakartaEEのように仕様ごとに設定ファイルが

    増えることなく集約されている 必須サポートな設定ファイルの策定 • MicroProfile Config準拠のランタイムが必須でサ ポートすべき設定ファイルとして /META-INF/microprofile-config.properties を定義 • MicroProfile Configを拡張することでYAMLなど独 自の設定ファイルもMicroProfile Config配下で扱 うことができる 優先度付けされた設定とマージ • 設定源ごとにデフォルトで優先度が定義されており、 実行時に優先度に応じて設定が上書きされる • 優先度は設定ファイルにごとに変更することもでき る 集約・一元化によるJakartaEEの問題の解消! <デフォルトの優先度> 環境変数の優先度:300 microprofile-config.propertiesの優先度:100 Twelve-Factor Appの実現!
  21. MicroProfile Config- APIでの取得(1/2) 31 name = mamezou foo.bar.baz = Hello

    public static void main(String[] args) { // Configインスタンスの取得 Config config = ConfigProvider.getConfig(); // propertiesファイルの設定値の取得(キー名区切りなし) String name = config.getValue("name", String.class); // propertiesファイルの設定値の取得(キー名区切りあり) String baz = config.getValue("foo.bar.baz", String.class); // どこにも設定されていない設定値 Optional<String> address = config.getOptionalValue("address", String.class); // システムプロパティの設定値の取得 String version = config.getValue("java.version", String.class); // 環境変数の設定値の取得 Optional<String> envUserName = config.getOptionalValue("USERNAME", String.class); // 取得値の出力 System.out.println("name:" + name); System.out.println("foo.bar.baz:" + baz); System.out.println("address:" + address.orElse("empty")); System.out.println("java.version:" + version); System.out.println("USERNAME:" + envUserName.orElse("no def")); } name:mamezou foo.bar.baz:Hello address:empty java.version:11.0.5 <-- 使用しているJDKのバージョンが出力されます USERNAME:ogiwara <-- Windowsでは自分のログインIDが出力されます 1. 設定ファイル(/META-INF/microprofile-config.properties) 2. ソースコード 3. 実行結果 ✓ MicroProfile ConfigだけはCDIコンテナが起動 しない状態でも利用することができる ✓ よって、CDIExtensionなどアプリケーションの 初期化時にも安全に設定情報を取得することが できる(できなとそれはそれで缶切りは缶詰の 中状態で困るのですが・・)
  22. MicroProfile Config- APIでの取得(2/2) 32 @ApplicationScoped public class CdiSampleBean { //

    Field InjectionによるConfigインスタンスの取得 @Inject private Config fieldConfig; // Field Injectionによる設定項目ごとの取得 @Inject @ConfigProperty(name = "name") private String name; // Field Injectionによる設定項目ごとの取得(型変換あり) @Inject @ConfigProperty(name = "age") private int age; // Field Injectionによる設定項目ごとの取得(デフォルト値設定あり) @Inject @ConfigProperty(name = "address", defaultValue = "empty") private String address; ... ✓ ConfigオブジェクトはInjectionで取得するこも とも可能。むしろこっちが基本 ✓ (行数の関係でField InjectionにしているがCDI でもコンストラクタインジェクションが今風) ✓ 特定の設定項目だけを取得することもできる ✓ intやdouble, Classなど基本的な型に対するコン バーターはbuilt-inコンバーターとして標準で提 供されている ✓ enumやLocalDateなどbuilt-inにない型はインタ フェースを実装することで独自コンバーターを作 ることもできる ✓ 設定がない場合のデフォルト値も定義することが できる
  23. MicroProfile OpenAPI-APIの利用(1/2) 35 @GET @Path("/{id}") @Produces(MediaType.APPLICATION_JSON) Person get(@PathParam("id")long id); paths:

    /api/persons/{id}: get: operationId: get parameters: - in: path name: id schema: format: int64 type: integer responses: '200': content: application/json: schema: $ref: '#/components/schemas/Person' components: schemas: Person: properties: age: format: int32 type: integer id: format: int64 type: integer name: type: string type: object REST動作に必要なJAX-RSアノテーションのみ (OpenAPIのアノテーションなし) /openapiで返されるOAS ✓ MicroProfile OpenAPIのアノテーションを付けなくてもメ ソッド定義を解析し最低限のOAS情報を生成してくれる ✓ よって、メソッド定義から読み取れないAPIの情報を MicroProfile OpenAPIのアノテーションで追加すればよい ✓ なので、スクラッチからOAS情報を作成するのは手間がか かるが、メソッド定義さえあればかなりの部分のOAS情報 を生成することができる
  24. MicroProfile OpenAPI-APIの利用(2/2) 36 @GET @Path("/{id}") @Produces(MediaType.APPLICATION_JSON) @Operation( operationId = "get",

    summary = "Person情報を取得する", description = "指定されたIDに対するPerson情報を取得する") @Parameter( name = "id", description = "PersonのインスタンスID", required = true, schema = @Schema( implementation = Long.class, minimum = "0", maximum = "9999999")) @APIResponse( responseCode = "200", description = "成功") @APIResponse( responseCode = "404", description = "該当なし", content = @Content(mediaType = "text/plan", example = "Not Found")) Person get(@PathParam("id")long id); paths: /api/persons/{id}: get: operationId: get summary: Person情報を取得する description: 指定されたIDに対するPerson情報を取得する parameters: - description: PersonのインスタンスID in: path name: id required: true schema: format: int64 maximum: 9999999 minimum: 0 type: integer responses: '200': description: 成功 content: application/json: schema: $ref: '#/components/schemas/Person' '404': description: 該当なし content: text/plan: example: Not Found components: ~ 前頁と同じため省略 ~ /openapiで 返されるOAS MicroProfile OpenAPIのアノテーションで情報を追加 :MicroProfile OpenAPIアノテーションを追加した部分 :MicroProfile OpenAPIアノテーションにより付加された部分
  25. なぜMicroProfileを使いだしたか-きっかけ • SpringなどのOSSが使えない環境(プロジェクト)もある程度存在 するから • なぜならば金融システムや社会インフラを担うシステムなどでは、 アーキテクチャ選定において以下のことが求められる場合がある • 長期間に渡り大きな変更なく使い続けられることが可能なことを見込めな いといけない

    • 障害や不具合発生時にその責任の所在や対応先が明確になっている必要が ある • 内部で利用しているモジュールも含め脆弱性(CVE)への管理・対応がしっ かりしている必要がある • これらの条件から利用可能なものは自ずとベンダーサポートが受 けられる製品に限られてくる 39 きっかけは単に上記を満たし、かつモダンでかつマイクロサービスな基盤になり得るものを 探すと消去法でMicroProfileしかなかっただけだった(消極的理由)
  26. MicroProfileが良く分かってきた今は • モダンでベンダーサポートが必要となるシビアなプロジェクトでは文句な くうってつけ • 最初はサポートに入っていなくても後から必要になった際にその選択肢が取れるだけでも安心 • バックエンドのAPI構築プロジェクトであれば、むしろSpringよりも利点を 感じる •

    オープンなプロセスで揉まれてリリースされるため、とりあえず出してみた的な仕様はなく、マ イクロサービスで必要なものがそれなりに揃っている(なので選択に迷わない、ハズれない) • 今回紹介したConfigのようにMetricsとRestClient, OpenTracingとRestClient、MetricsとFault Toleranceなどそれぞれの仕様間が使いやすくインテグレートされている 40 ✓ ベンダーによりサポートの熱量は異なる。こちらも知っている基本的なことしか回答してこないベンダーやそ もそも回答をよこさないベンダーも存在する。ベンダーサポートの親切度や技術レベルも重要な要素 ✓ 親切でレベルが高いサポートであっても、こちらが問題解決に有益な情報を提供できるかも重要となる。この ため、問題解決に至る時間にはサポートを受ける側の力量に依るところもあることは理解しておく必要がある ベンダーサポートは銀の弾丸ではない