13871 words
69 minutes
SpringBoot2徹底活用

現場至上主義SpringBoot2徹底活用#

理解したこと#

  • Gradleを使ったビルドができる

書籍情報#

  • 著者

    • 廣末 丈士/宮林 岳洋 著、高安 厚思 監修
  • 定価

    • 3,456円(本体価格 3,200円)
  • 発売日

    • 2018年11月30日
  • ISBN

    • 978-4-8026-1185-5
  • 目次

    • 第1章 Spring Bootの構成
    • 第2章 Webアプリケーションにおける共通処理
    • 第3章 データアクセス
    • 第4章 セキュリティ
    • 第5章 画面開発
    • 第6章 API開発
    • 第7章 チーム開発
    • 第8章 運用
    • 第9章 (Spring Bootアプリケーションが想定している)システム構成
    • 第10章 Spring5/Spring Boot2の新機能
    • 第11章 ローカル開発環境の構築について
    • 第12章 サンプルアプリについて
  • サンプルプログラム

第1章 Spring Bootの構成#

1.1 SpringBootの基礎#

  • SpringBootとは「Spring Frameworkベースのアプリケーションを手軽に作成することができるフレームワーク」

    • それ自体で完結するフレームワークではない
    • Spring MVCやSpring Batchなどの様々なフレームワークを組み合わせて素早く簡潔にアプリケーションを開発する機能を提供
    • SpringBootの中にTomcatが同梱されており、デフォルトでjarファイルをして、java -jarコマンドで引数に指定すると組み込まれたtomcatが立ち上がり開発したアプリケーションを実行できる
  • 代表的な特徴

    • スターター
      • 依存関係をシンプルに定義するためのモジュール
    • ビルドツール
      • バージョン解決など、開発を効率化するためのプラグイン
    • コンフィグレーションクラス
      • XMLではなく、アノテーションとJavaで設定が書ける
    • オートコンフィグレーション
      • デフォルトのコンフィグレーションが適用されて、必要なところだけを設定すればよくなる
    • メインアプリケーションクラス
      • Javaコマンドで組み込みのTomcatを起動できる
    • 設定ファイル
      • プロパティを外部ファイルに定義でき、動作使用を簡単に変更できる

スターター#

  • 一連の依存関係をセットとしてそろえるためのモジュール

  • 必要なライブラリを準備したり、それぞれのバージョンを選定したりする煩わしい作業から解放される

  • たとえば、spring-boot-starter-webを1つ依存関係に追加するだけで、SpringMVCやTomcatなど、Webアプリケーションに必要なライブラリがセットになって追加される

  • 以下はスターターの例

    • spring-boot-starter-web : SpringMVC Tomcatが依存関係に追加される
    • spring-boot-starter-jdbc : SpringJDBC Tomcat JDBC Pool が依存関係に追加される
  • スターターリファレンスページ

  • 自分でスターターを作成する際は、*-spring-boot-starterという命名規則が定められていることに注意

ビルドツール#

  • Spring Bootの推奨ビルドツール

    • ApacheMaven
    • Gradle
  • 本書ではGradle

    • メリット
      • スクリプトを記述するタイプのビルドツールのため、Antのようにタスクを自由に記述することができる
      • マルチプロジェクト構成の場合は、サブプロジェクトに対して一括設定して、必要に応じて個別に設定することができるため、記述量がMavenよりも少なくなる
      • Mavenの場合は、特殊な処理が必要になった時に独自プラグインを実装する必要があるのに対し、Gradleはスクリプトを書くだけで対応できる
  • Maven

    • Mavenを利用する場合、spring-boot-starter-parentプロジェクトを親プロジェクトとして継承することで、プラグインのデフォルト設定、依存ライブラリのバージョンの定義、Javaコンパイラー準拠レベル、文字コードを引き継ぐことができる
  • 親プロジェクト設定

<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
</parent>
  • Gradle

    • Spring Boot2.0.xはGradle4.0以降に対応している
    • GradleはMavenと違って、設定を引き継ぐための親プロジェクトが存在しないため、単に、スターターを依存関係として追加します
    • spring-boot-gradle-pluginというGradleプラグインが用意されており、実行可能なJarファイルを作成するためのタスクを利用できる
  • ビルドスクリプトの処理内容

    1. spring-boot-gradle-plugin をビルドスクリプトの依存関係に追加する
    2. spring-boot-gradle-plugin と dependency-management プラグインを利用することを宣言
    3. Javaコンパイラー準拠レベルをデフォルトの1.8から11に変更
    4. 文字コードはUTF-8であることを指定する
    5. スターターをアプリケーションの依存関係に追加する
    6. テスト用のスターターをアプリケーションの依存関係に追加する

依存関係の管理#

  • すべてのライブラリのバージョンを1つずつ指定するというような作業をする必要はない
  • 依存関係に定義されているライブラリも一緒にバージョンアップする
  • Spring Bootのバージョンを上げる場合は、Project Wikiに載っているリリースノートを確認すること

コンフィグレーションクラス#

  • Spring BootはJavaベースのコンフィグレーションが好まれる

  • 従来通りXMLファイルに記述できるが、推奨されるのは@Configurationアノテーションを付与したクラスによるコンフィグレーション

  • MVCの設定のこと?再度確認する

オートコンフィグレーション#

  • Spring Bootは設定を変更しなければ、あらかじめ敷かれたレールに沿って動作するようになっている

メインアプリケーションクラス#

  • SpringBootのアプリケーションを起動するメソッドを呼び出すクラス

  • Javaアプリケーションのエントリポイントとなるmainメソッドの中で、SpringApplicationクラスのrunメソッドを呼び出すと、組み込みのTomcatが立ち上がり、SpringIoCコンテナの初期化が行われる

  • ※再読

設定ファイル#

  • アプリケーションを起動すると、次の場所にあるapplication.properties設定ファイルを読み込む

    1. カレントディレクトリの/configサブディレクトリ
    2. カレントディレクトリ
    3. クラスパスの/configパッケージ
    4. クラスパスのルート
  • 上から順番に優先度が高くなる

  • プロファイルという単位で別々の設定を持たせることも可能

  • 設定ファイルはyml形式でもOK

  • application.ymlを配置することで使用可能

  • 設定ファイルの値を参照するのも簡単

Colum 外部設定ファイルの種類#

  • 環境変数

  • システムプロパティ

  • コマンドライン引数

  • いろんな渡し方がある

  • けど、アプリケーションプロパティしか使わないのではと思う

アプリケーションの起動#

  • コマンドラインで起動 gradle bootRun
  • InteliJ IDEAを使って起動する

1.2 Spring BootによるWebアプリケーション開発#

  • Intelij IDEA 起動

    • Cntl + Shift + A -> compiler.automake.allow.when.app.runningON にすることでファイル変更時に自動更新する
  • リソースの除外

    • 静的リソースの変更は単に再読み込みするだけで再起動は不要
    • デフォルト設定では、
      • /META-INF/maven
      • /META-INF/resources
      • /resources
      • /static
      • /public
      • templates
      • に含まれるファイルへの変更は再起動がかからないようになっている
// 再起動のトリガーから除外するファイルを設定する
spring.devtools.restart.exclude=static/**,public/**
  • LiveReload
// LiveReloadを無効化する
spring.devtools.livereload.enabled=false

Restart vs Reload#

  • JVM hot-swapping をよりよいものにしたい場合

    • JRebel(有償)または、Spring Loaded(無償の内部で利用されている) の利用を検討する
  • もう一つの方法として、Dynamic Code Evolution VM(DCEVM) HotSwapAgentを使ったJVM hot-swapping がある

    • JDKにパッチをあててクラスの再定義機能を強化してくれる
    • Spring Loadedでは対応していないクラス追加に対してもhot-swappingが働く
  • DCEVM + HotSwapAgentの導入方法

  • Intelij IDEA プラグイン設定

    • HotSwapAgent をインストール
    • Settingより設定する

1.3 サンプルプロジェクトの構成#

マルチプロジェクト#

  • 本書で用いるサンプルプロジェクトは複数のモジュールで構成されるマルチプロジェクト
  • メリット
    • ビルドスクリプトを共通化することができるので記述量が減る
    • ローカル・リモートリポジトリにアーティファクトをアップロードしなくてもソースコードの変更が反映される
    • それぞれのプロジェクトを関連付けてタスクを実行できる

アプリケーション・アーキテクチャ#

  • プレゼンテーション層
    • プレゼンテーション層は、入力された値を受け取って、値をチェックしたり、値の変換を行ったりする層
    • WebモジュールのFormクラス、FormValidatorクラスが該当
  • アプリケーション層
    • プレゼンテーション層から受け取った値をドメイン層に渡す層で、WebモジュールのControllerが該当する
    • ビジネスロジックは含まれないが、画面遷移先を制御したり、セッションを用いて、次画面に値を渡したりといった処理を行う
  • ドメイン層
    • ドメインオブジェクトを持ち、ビジネスロジックを処理するメインの層で、ドメインモジュールのServiceクラスが該当する
    • ドメインオブジェクトはすべての層から利用されるが、逆にドメイン層はほかの層に依存してはならない点に注意する!
  • インフラストラクチャ層
    • インフラストラクチャ層では、ドメイン層から渡されたデータを永続化する層
    • ドメインモジュールのRepositoryクラスが該当する
    • アプリケーション層の影響を受けないように、汎用的な部品としてつくるようにすること!

サンプルプロジェクトのビルドスクリプト#

  1. Spring Bootのバージョンを拡張プロパティにセット
  2. テストコードはSpockフレームワークを利用するため、Groovyを扱えるようにする
  3. すべてのサブプロジェクトにおいて spring-boot-gradle-plugin を利用できるようにする
  4. すべてのサブプロジェクトにおいて dependency-management プラグインを利用できるようにする
  5. Javaコンパイラー準拠レベルを11に変更する
  6. src/main/resources をクラスパスに追加して、開発中の変更がすぐに反映されるようにする
  7. リソースファイルの出力先をソースファイルの出力先に変更する
  8. コンパイルの前に、リソースファイルの出力を行うようにする
  9. Domaの依存関係にあるバージョン違いの Spring Boot を除外する
  10. Spring Session モジュールを使ってセッション情報をデータベースに格納する
  11. Gradleのプロジェクトプロパティを bootRun の引数に渡せるようにする
// メインアプリケーションクラスを持たないモジュールの場合(build.gradle)
bootJar {
enabled = false
}

Lombokを利用する#

  • ボイラープレートコードの削減のため
  • アプリケーションの実行時には不要なので、スコープはcompileOnlyに設定
  • valが使用できる
    • MEMO: これを使うと長い型を3文字でかけるよっていうことらしい

第2章 Webアプリケーションにおける共通処理#

  • サンプルプロジェクトにおける共通処理、その実装方法について説明
種別説明
バリデーション単項目・相関チェックを効率よく実施する
オブジェクトマッピング入力値を他のエンティティに効率よく詰め替える
ログ出力共通的に処理の開始・終了をログ出力する
ファイルダウンロードCSV、Excel、PDFなどのファイルをダウンロードする
ファイルアップロードアップロードされたファイルを、Domaを使ってデータベースに保存する
メール送信本文をテンプレート処理してメールを送信できるようにする

2.1 バリデーション#

  • Spring MVC では単項目チェックを行うためのBean Validatorが用意されている
  • 相関チェックのためのアノテーションはないので、効率よく相関チェックを行うために共通処理を実装する
  • Spring Bootでは spring-boot-starter-validationスターターを依存関係に追加することで、Bean Validation 2.0 と Spring Validatorが利用できる
  • バリデーションのポイント
    • メッセージの設定
    • バリデーションの種類
    • 単項目チェック
    • 相関項目チェック

メッセージの設定#

  • Bean Validator はメッセージを外部ファイルで管理するためのMessageSourceを内包している

  • デフォルトでは文字コードがUTF-8 になっていないので、エラーメッセージを表示する際に文字化けてしまう

  • application.yml

# 共通の設定を定義する
spring:
messages:
# メッセージ定義ファイルのパスを含めて設定する
basename: messages,ValidationMessages
cache-duration: -1
encoding: UTF-8 # P40. デフォルトのままだと文字化けするため指定

Colum メッセージを定義するファイルを分割する#

  • application.ymlのbasenameにカンマ区切りで複数指定可能
    • ValidationMessage:バリデーションのエラーメッセージを定義する
    • PropertyNames:エラー項目の項目名を入力フォームごとに定義する
    • messages:バリデーションとは関係ないシステムメッセージなどを定義する

バリデーションの種類#

  • バリデーションの種類

    • クライアントサイド
    • サーバーサイド
  • 本書はサーバーサイドのバリデーションについて説明

  • 単項目チェック:Bean Validation APIで提供されるアノテーションを利用できる

  • 相関項目チェック:org.springframework.validation.Validatorインターフェースの実装クラスを作成するか、自作のアノテーションを実装する

単項目チェック#

  • javax.validation.constraintsパッケージに定義されている
アノテーションチェック内容
Min,DecimalMin数値の最小値を下回らないこと
Max,DecimalMax数値の最大値を超えないこと
NotNullNULL値ではないこと
Pattern正規表現を満たすこと
NotBlank値があること(空白を許さない)
NotEmpty値があること(空白を許す)
Digits数値であること
Past過去であること
Future未来であること
  • spring-boot-starter-validationスターターは Bean Validationの実装ライブラリーとして、Hibernate Validatorを依存関係に追加しているので、Hibernateで定義されたアノテーションも使うことができる
アノテーションチェック内容
CreditCardNumber正しいクレジットカード番号であること
LengthNULL値ではないこと
Range範囲内の値であること
SafeHtml妥当なHTML書式であること
URL正しいURLであること
  • 参考URL

  • Formオブジェクトに@NotEmptyなどのアノテーション付与

  • Controller@PostMapping("/new")を付与したメソッドの引数に@Validatedを付与し、Formオブジェクトを第一引数に指定

  • チェック結果が、第二引数のBindingResultに入るので結果をチェックする

Column PRGパターンについて#

  • PRGパターンでは、Post-Redirect-Getメソッドを組み合わせて、以下の流れで登録処理を行う実装パターン
  1. 保存ボタンを押したとき、POSTメソッドを使い、サーバーにリクエストする(P
  2. 入力値をDBに保存するといった一連の処理を行い、詳細画面にリダイレクトする(R
  3. GETメソッドで詳細画面が表示される(G
  • サンプルプロジェクトはほぼすべての機能において、PRGパターンを適用している
  • メリット
    • ブラウザの戻るボタンを押しても、フォーム再送信のダイアログを表示しないようにすることができる

相関項目チェック#

2.2 オブジェクトマッピング#

  • ModelMapperを使用した詰め替え例の紹介

  • Dozerなどもあるのでお好みで使用すること

  • Strictモードにしないと意図しない詰め替えが発生する可能性があるので注意

  • MEMO: ここはOrikaを採用することにしたので割愛

2.3 ログ出力#

  • MDCを使ってログに値を埋め込む設定

    • コントローラに関数名を返却する処理を埋め込む
    • リクエストごとに乱数を生成して埋め込む(リクエストトラッキング)
  • ログローテーションの設定について

2.4 ファイルダウンロード#

ファイルの出力処理を共通処理にするとソースコードの記述量を削減市、統一された方法に揃えることで微妙な動作の違いを生まない用にすることができます。

ファイルダウンロード機能は、エンタープライズのアプリケーション開発に限らず、とてもよくある機能の1つ

org.springframework.web.servlet.Viewインターエースを実装することで、汎用的なロジックで様々なファイルダウンロードに対応できる用になる

PDFファイルのダウンロード#

帳票出力の代表的なライブラリとして、JasperReportsがある JasperReportsは、.jrxmlという拡張子のXMLファイルで帳票のレイアウトをテンプレートとして定義して帳票を出する際に対象データを引数に渡すことで帳票を出力します。 テンプレートファイルはJasperSoftStudioというEclipseベースの帳票デザインツールを使って作成

SpringMVCには、JasperReportsをサポートするViewクラスが提供されていたが、SpringFramework5から機能が除外されている

そのため、JasperReportsライブラリを直接使ってPDF出力するPDFViewクラスを実装して、引数にデータを渡すだけでPDF出力ができるようにします。

CSVファイルのダウンロード#

CSVファイルのダウンロードは、jackson-dataformat-csvを利用するとシンプルに実装することができる

  • CsvViewクラス
  • Entityクラス
  • Controllerクラス

Excelファイルのダウンロード#

Excelファイルのダウンロードの場合は、org.springframework.web.servlet.view.document.AbstractXlsxViewを利用 AbstractXlsxViewはApachePOIに依存しているのでバージョンまで指定して依存関係を記述します PDFファイルの場合と同様で、ファイル名に日本語文字が含まれると文字化けが生じてしまうので、子クラスを作成して対応

2.5 ファイルアップロード#

ファイルダウンロードと同様によく実装する機能の1つ

SpringBootでは、アップロードファイルのサイズ上限などの設定を適切に行わないと、オートコンフィグレーションによるデフォルトの動作仕様では要件を満たせないこともありえるので注意が必要 SpringBootでは、ServletAPI3.0で利用できるjavax.servlet.http.Partを内包するMultipartResolverがオートコンフィグレーションされるので、なにもしなくてもMultipartFileインターフェースを使ってファイルを受け取ることができる

ファイルサイズの設定#

  • 1ファイルのサイズ上限は1MBで、1リクエストで受け付ける上限は10MBになっている
spring:
servlet:
multipart:
max-file-size: -1 # デフォルトは1MB -1だと無制限
max-request-size: 20MB # デフォルトは10MB

ファイルの取扱#

ファイルのデータベースへの格納#

  • TODO: 後で画像保存する処理実装する

2.6 メール送信#

  • MEMO: 省略

第3章 データアクセス#

本chapterでは、O/RマッパーとしてDomaを使った実装方法を説明 Domaは2way-SQLと呼ばれるSQLテンプレートを利用できるので、SQL分の見通しがよくなるという特徴がある

実行時にSQLテンプレートとJavaソースコードとの不整合を検知して間違いを指摘する機能も備わっていて、とても使い勝手がよいO/Rマッパーです

3.1 スターター#

  • 2way-SQLとは
    • SQLのコメントに条件分岐を記述することで、プログラムのSQLテンプレートとしての利用と、囲うせずにそのままツールでの利用という2通りの使い方が可能になっているSQL文

3.2 Domaの使い方#

3.3 エンティティ共通処理#

すべてのエンティティにシステム固有のシステム制御項目(作成者、作成日時、更新者、更新日時、削除者、削除日時)を用いて、エンティティを取り扱うときに、すべてのテーブルに共通のルールを適用する場合の共通処理について説明

エンティティ基底クラス#

エンティティ基底クラスを用意し、共通的に使うフィールドを定義することができる

@Entityアノテーションにリスナーを指定すると、更新・登録・削除のタイミングで共通的な処理を実行することができる

  • TODO: 共通項目実装

3.4 ページング処理#

  • DOMAはページング処理を行うための仕組みとして検索オプションを提供している

  • TODO: 要実装

3.5 排他制御#

楽観的排他制御#

データ不整合を保険的に防ぐ方法 複数人が同じデータを編集してしまった場合に、先に保存したほうの編集内容が後から保存した内容で上書きされてしまうといったことを防ぐことができる

Domaを使って楽観的排他制御を行うには以下の条件を満たす必要がある

  • エンティティのフィールドに@Versionアノテーションが付与されている

  • Daoインターフェースに付与したアノテーションのignoreVersionをtrueにしていない

  • テーブルに数値型の改定番号カラムが定義されている

  • 流れ

    1. Formオブジェクト二改定番号のフィールドを定義する
    2. コントローラに@SessionAttributeアノテーションを付与する。
    3. 編集画面の初期表示処理で改定番号を含めてデータを取得して、Formオブジェクトに詰め替える
    4. 更新処理で、更新対象データを取得して、そのデータをFormオブジェクトの値で上書きする
    5. Daoの更新処理を呼び出す(ここで排他制御がかかる
    6. 不要になったFormオブジェクトをセッションからクリアする
  • TODO: 楽観的排他制御について深堀り、実装→悲観的排他制御だけでアプリとしては回せそう

  • Column セッション情報の格納先について

    • 楽観的排他制御の説明の中でSessionAttributeを使ってFormオブジェクトをセッション情報に保存する方法を紹介しました。サンプルプロジェクトでは、SpringSessionモジュールを依存関係に追加しているので、SpringBootによるオートコンフィグレーションが行われます。SpringSessionには、以下の格納先に対するオートコンフィグレーションが用意されています。
      • JDBC
      • Redis
      • Hazelcast
      • MongoDB
    • セッション情報の格納先を変更したい場合は、設定ファイルにリスト3.11を記述することで変更することができます。
      • redisにする場合:spring.session.store-type=redis
  • TODO: セッションの格納先はREDISにする

悲観的排他制御#

データベースの行ロック機能を使った排他制御で、在庫数のような頻繁に同時更新がかかるようなデータの整合性を担保する方法として利用される

Domaでは、悲観的排他制御を行うための仕組みも用意されていて、ページング処理の説明と同じ用に検索オプションを使う

悲観的排他制御を行うときに注意すべきなのは、検索結果が0件になるような条件で検索すると、行ロックではなくテーブルロックがかかる点です!!! 処理時間が長い処理でテーブルロックがかかってしまうと、処理の滞留が発生してしまい、システム全体が不安定な状態二なることもあるので注意する

3.6 論理削除#

DBのレコードを削除するのではなく、削除フラグによってレコードの削除を表すという方法

更新機能による実現#

  • @Update(excludeNull = true) // Nullの項目は更新対象にしない

エンティティリスナーによる共通処理#

  • リスナーの中のpreUpdateメソッドの中で、メソッド名が論理削除のメソッド名と一致するかを確認する

論理削除レコードの除外#

  • 論理削除を行うことをアプリケーション内で統一している場合は、データ取得のSQLに、論理削除フラグによる削除データの除外が行われる用にする必要がある

  • Column 参考文献

第4章 セキュリティ#

本chapterでは、SpringSecurityを使った認証・認可とそれらにまつわる課題を解決する実装方法を説明

4.1 スターター#

compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity5', version: '3.0.4.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-security'

4.2 認証#

認証情報の取得#

  • UserDetailsServiceをimplementsして実装する方法
  • TODO: 権限周りが実装できていないので見ておく

ログイン機能#

ログイン機能のコントローラを実装します。 デフォルトでも組み込みのログイン画面を表示することが可能ですが、ほとんどの場合において画面を変更する必要があるので、Thymeleafテンプレートを使ってログイン画面を表示する用に実装し、それ以降の処理はSpringSecurityと連携するようにします。

  • TODO: タイムアウト処理やログイン成功処理など実装の必要があればサンプルを基に実装する
    • /authorize にfowardできなくて、formオブジェクト経由のエラーチェックが実装できなかった

4.3 RememberMe#

一般的なWebサービスでは、ログイン画面に「ログインしたままにする」というチェックボックスがあることがしばしばある 一定期間内であればセッションがタイムアウトしても自動ログイン処理が行われる機能が提供されるので、何度もログイン画面でパスワードを入力する不便さを解消することができる

ログイン記録の永続化#

  • TODO: 自動ログイン機能は必要になれば実装しておきたい
    • 合わせて不要なレコードを削除する機能も実装する必要がある

4.4 認可#

管理機能を備えたWebアプリケーションにおいては、ログインユーザーごとに権限を付与して、特定のユーザーのみが操作することができるように制御することがよくある このようなアクセス制御を行う場合は、以下の要件が満たされていると汎用的に使えるためとても便利

  • 要件

    • システムを利用するユーザーは、複数のロール(役割)を持つことができる
    • 特定リソースの操作を識別する単位として権限を定義することができる
    • ロールは、複数の権限を持つことができる
    • システムの移動中にロールの持つパーミッションや対象のリソースを変更することができる
  • SpringSecurityを使った認可の実装方法としては、アノテーションを使う方法と、JavaConfigでURLベースの条件式をていk技する方法がある

  • これらの方法では、システムの稼働中に新たに役割に権限を追加したり、することが困難

  • 認証処理の中でデータベースからロール権限を取得して、コントローラのメソッドレベルでの認可制御を行うようにしている

権限管理データをロード#

権限とメソッドの紐付け#

認可制御のインターセプター#

  • TODO: 権限管理はあとで見直す

4.5 CSRF対策#

// 以下を追加するとformにhiddenでcsrfトークンが埋め込まれる
http.csrf()
.csrfTokenRepository(new CookieCsrfTokenRepository());

4.6 二重送信防止#

  • 二重送信防止するためのチェック方法

    • JavaScriptでボタンを連打できないようにする
    • PostRedirectGetパターンを適用
    • トークンを使った送信済みチェックをする
  • TODO: ここで紹介されているやり方だと、二重送信防止チェックをするのは、UPDATEが伴う処理のみに限定できる

    • ページ遷移や検索処理で二重送信が行われた場合は除外できるという仕組みになっている
    • ここの実装方法の方がより現実的なので後で真似る

第5章 画面開発#

5.1 Thymeleaf#

SpringMVCといえばJSP一択だったが、HTML5に準拠した形で管理できる方が望ましい

  • メリット
    • Spring推奨
    • HTML5準拠
    • デザイナとの分業がしやすい
    • ブラウザで直接参照できる

5.2 Formバインディング#

  • FormBeanの定義方法とバリデーション方法

5.3 事前評価#

アプリケーションで扱うデータは特定の変換処理をかけたいことがよくある Thymeleafでは事前評価をサポートしている

事前評価の実装例#

  • 表示する言語を翻訳する例が紹介されている
  • FormBeanの値と、実際に表示したい値が異なる場合に有用だと思う
  • <p th:text="${@myapp.translator.Translator@translateToEnglish(textVar)}">some text here ...</p>

5.4 テンプレート共有#

テンプレートの部品化#

  • includeとreplaceの話

テンプレートの共通化#

レイアウトという機能でテンプレートの共通化をサポートします HTMLのレイアウトやJavaScriptおよびCSSのインクルードを一元管理できる 本機能を用いてテンプレートの共通化を採用することでソースコードの保守性や品質も向上するため、積極的に導入すべき機能

compile('nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.3.0') {
exclude group: "org.codehaus.groovy", module: "groovy"
}
@Configuration
public class WebConfig extends WebMvcConfigurer {
@Bean
public LayoutDialect layoutDialect() {
return new LayoutDialect();
}
}
  • レイアウト機能を利用するために、xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"を指定する

  • layout:fragment="任意の文字列"で各ページで差し替えるエリアを指定する

  • MEMO: Spring徹底入門でも紹介されていたが、画面の全体像がわかりづらくなりやすいためincludeを用いることにする

5.5 Thymeleafのその他の機能#

エスケープなしのテキスト#

  • 通常、クロスサイトスクリプティング対策のためSpringはタグ文字列をエスケープして表示している

  • 場合によってはエスケープしないで、文字列を表示したいケースがある

  • <p th:utext="#{home.welcom}">Welcom to our grocery store!</p>

  • このutextを利用する場合は、XSSの脆弱性を含まない用に注意が必要

日付操作拡張#

Thymeleafでは、Date/TimeAPIをデフォルトでサポートしていないため拡張ライブラリーを使用する必要がある

// https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-java8time
compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-java8time', version: '3.0.4.RELEASE'
<input class="form-control" type="text" name="holidayDate"
th:value="${(value != null) ? #temporals.format(value, 'yyyy/MM/dd') : '' }" />

※その他にもThymeleafは各種の拡張機能をサポートしている

5.6 静的コンテンツ管理#

BtoCのアプリケーションを構築する際、UI/UXの向上が欠かせないため、クライアントサイドライブラリを有効活用する必要がある JavaScriptやCSSを適切に管理していない状況では、次の問題が発生することがありました。

  • JavaScriptやCSSが適切にバージョニングされていないため、ブラウザキャッシュにより、リリース時に古いバージョンが提供されてしまう。

  • JavaScriptやCSSライブラリが構成管理されていないため、安易な外部ライブラリの利用により障害が発生してしまう

  • 本節では、Webアプリケーションの静的コンテンツについて

    • 配置場所
    • キャッシュ制御
    • アクセス制御
    • クライアントライブラリの構成管理方法
      • を解説!!

静的コンテンツの配置場所#

SpringBootでは、SpringMVCのオートコンフィグレーションに以下の設定がされており、デフォルトでは次の4点のパスに静的コンテンツを配置できる

  • /resources/
  • /static/
  • /public/
  • /META-INF/resources/

キャシュ制御#

キャッシュする時間は、application.(properties|yml) や ResourceHandlerRegistryのオーバーラードで調整

spring:
resources:
# cache-period: 86400 # 1日間キャッシュさせる
chain:
strategy:
content:
enabled: true # 静的コンテンツのキャッシュ無効設定 MD5ハッシュが計算される バージョン管理戦略と呼ばれるらしい
paths: /**
  • TODO: バージョン管理戦略を実施した場合のキャッシュの挙動を確認しておく

アクセス制御#

Faviconなどの画像ファイルやクライアントライブラリは未認証、認証にかかわらずアクセスできる必要がある SpringBootでは、SpringSecurityのオートコンフィグレーションにリストの設定がされており、デフォルトで次の5点のパスはpublicアクセス可能

しかし、SEOに必要なrobots.txtやsitemap.xmlは含まれないため、これらのファイルをPublicアクセス可能とするには、JavaConfigで設定を上書きする必要がある

  • デフォルトで許可されている5点

    • /css/
    • /js/
    • /images/
    • /webjars/
    • favicon.ico
  • TODO: SEO対策に必要な知識を習得しておく必要がある

private static final String[] STATIC_RESOURCES = {
"/favicon.ico", "/css/**", "/js/**", "/img/**", "/lib/**", "/font/**"
};
@Override
public void configure(WebSecurity web) {
// セキュリティ対策が不要なリソースがある場合、SpringSecurityの処理を適用しないようにする
// web.ignoring().antMatchers("/resources/static/**");
web.ignoring().antMatchers(STATIC_RESOURCES);
}

クライアントライブラリの構成管理#

サーバサイドエンジニア中心のチーム構成だとフロントライブラリの管理が抜けてしまうことがよくある

本項では、WebJarsを用いてクライントライブラリを管理する方法を紹介

  • Dependenciesの追加方法を説明
// https://mvnrepository.com/artifact/org.webjars/webjars-locator-core
compile group: 'org.webjars', name: 'webjars-locator-core', version: '0.45'

第6章 API開発#

金融機関でのAPI公開の動きが急激に加速しているように、APIというキーワードはビジネス領域でもよく目にする用になってきている システム開発でも迅速に機能をリリースしていくためにはAPI連携は書かせず、API連携の重要度は日に日に高まってきている

6.1 Spring でのAPI開発#

MSA(Micro Service Architecture)開発やSPA開発ではAPI連携が必須 一方小売業界ではオムニチャネルといった言葉が生まれている

チャネルの違いを意識しないようにするには、バックエンドのサービスをAPI化し、PC/スマホ/他サービスなどの複数のチャネルから透過的に利用できるようにする必要がある

API仕様#

リソース実装#

コントローラ実装#

エラーハンドリング実装#

@RestControllerAdviceアノテーションを指定して作成

6.2 SpringでのAPI連携#

現在のシステム開発でアジリティを追求するためにはAPI連携は欠かせません

RestTemplate#

SpringではRestTemplateというRESTクライアントを提供している RestTemplateを用いると、Javaオブジェクトとレスポンスボディの変換も容易に実現できる

ユーザー一覧取得APIへの連携#

ユーザー作成APIへの連携#

6.3 API開発効率の最大化#

API開発でクライアント側でモックを用意して実装をすすめる必要がある

API定義をExcelなどのドキュメントで管理し、Excelなどのドキュメントに基づきクライアント側でモックの準備をすすめると、仕様の認識齟齬が発生することが多くなってしまいます。

またAPIの仕様変更時の連携のオーバーヘッドも大きくなってしまいます。

本節では、現在の開発での必須要素であるAPI連携をより円滑にすすめるためにAPI管理にSwaggerを用い、API開発の効率を上げる方法を説明

Swaggerとは#

OpenAPI仕様に基づくAPI開発ツールのフレームワークであり、APIのライフサイクル全体に渡って、設計から文書の管理、テストおよびデプロイまでを可能にします。

  • 大きな利点は以下の4つ

    • OpenAPI準拠
    • YAMLを用いた宣言的な記法
    • コード自動生成
    • エコシステムの充実(SwaggerHub)
  • OpenAPI準拠

    • マイクロソフト、Googleなどの大手の企業を含むOpenAPIInitiativeがLinuxFoundationの協力のもとで結成され、APIの記述のために採用したのがSwagger
    • API管理のデファクトスタンダードと呼ばれるほど普及している
  • YAMLを用いた宣言的な記法

    • SwaggerはAPI定義をYAML(JSON)により宣言的に記載できます。
    • また、定義したYAMLからSwaggerUIというツールを用いると、HTMLベースの定義書やモックを作成できます。
    • SwaggerUIを利用し、APIを公開すると、クライアント側は動く仕様としてAPIを参照できるため、API連詠によるコミュニケーションコストを低下させることができます。
  • コード自動生成

    • Swaggerには、Swagger CodegenというSwaggerUIで公開されたAPI仕様を基にコードを自動生成するツールがある

TODO: Dockerを用いてSwaggerCodegenを用いたスタブサーバーの起動例 確認しておく

  • エコシステムの充実(SwaggerHub)
    • SwaggerCodegenを用いてスタブサーバーを起動し、開発チームで共有する方針も悪くないですが、ホスト環境の管理やAPI仕様の変更の都度、コードの再生成および再起動が必要になります。
    • Swaggerはエコシステムも充実しており、SwaggerHubというAPI管理のプラットフォームがあります。
    • SwaggerHubはSwaggerを使ったモックサーバーやテスト環境などAPI管理に関するサービスをまとめて提供しているため、APIの管理工数を下げることが可能です。
    • SwaggerHubはAPIドキュメントの編集/表示、モックサーバーの立ち上げ、SwaggerCodegenの機能などをブラウザベースで提供しています。

TODO: SwaggerHubは一回使ってみる必要あり!!! →お金かかるから断念… チーム開発に有用かも?

Springでの利用(SpringFox)#

SwaggerでのAPI管理がデファクトスタンダードになっていること、Swaggerを利用することのメリットを説明しました。 本項では、SwaggerをSpringで利用する方法を説明します。

Springでは、SpringFoxを用いるとAPIドキュメントの自動生成が可能 SpringFoxはSwaggerUIの提供もサポートしているため、APIを用いたチーム開発を円滑にすすめることができる 次の手順に従い、SpringFoxの利用方法を説明

  • 依存関係の設定
  • 共通設定カスタマイズ
  • 個別エンドポイントのカスタマイズ
  • 静的ドキュメント生成
  1. 依存関係の設定
// https://mvnrepository.com/artifact/io.springfox/springfox-swagger2
compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
// https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
  1. 共通設定カスタマイズ(JavaConfig)
@Configuration
@Import({ ThymeleafConfig.class, // Thymeleafを使用することを明示
GoogleAutoConfiguration.class })
@EnableSwagger2
public class AppConfig implements WebMvcConfigurer {

APIControllerのみグルーピングする方法を紹介

  1. 個別エンドポイントのカスタマイズ

アノテーションでAPIごとの説明を追加できる

  1. 静的ドキュメント生成

SwaggerUIを動的に生成する方法は、API連携開発の効率を上げてくれるため、開発フェーズでは導入しておくと効果的

しかし本番サービス稼働後に上述の手順を有効化しておくと、SwaggerUIの外部公開制御が必要になります

本項では、別のアプローチとして、SwaggerのAPI定義から静的ドキュメントを生成する方法を紹介

  • 依存関係の設定

  • テストクラスの追加

  • HTML変換

  • 依存関係の設定

    • SwaggerからAsciiDocへの変換をサポートしているSwagger2Markupというライブラリがある
    • Swagger2MarkupをSpring向けにカスタマイズした、springfox-staticdocsを依存関係に追加する
  • テストクラスの追加

    • テストコードを作成し、CIサイクルに含めておくと、静的なドキュメントのAsciiDocが自動生成される
  • HTML変換

    • HTMLへの変換はasciidoctorを利用する

TODO: HTMLへ変換するCI構築する

Spring REST Docs#

Springでのドキュメント生成の自動化には、Spring REST Docsを採用する方法もある

  • 利点

    • テストをパスしないドキュメントは作成されないため、「動く仕様書」として信頼できる。
    • asciidoctorを用いた簡潔な記法
  • 手順

    • 依存関係の設定
    • 雛形生成
    • テストコード生成

第7章 チーム開発#

システム開発では、1人ですべての作業を簡潔させることはできません。

最近のシステム開発で主流となってきている機能ごとに分割して開発する手法のMSA(MicroServieceArchitecture)開発でも、5~8人でのチーム開発(Two Pizza Team)が良いとされています。

7.1 インフラの構成管理#

ローカルPC、検証環境、本番環境(オンプレミスもしくはクラウド)など、プログラムは様々な環境で動く可能性があります。

本節では、特定の環境にロックインされないようにする方法を紹介 旧来のシステム開発では、Excelなどで作成された手順書を用いて、半日~2日かけて開発環境を構築することが当たり前でした しかし最近では、Infrastracture as Code(IaC)やDockerをはじめとするコンテナ技術が広く普及してきたことにより、上述のような方法を採用することはとても効率的とは言えません

Docker#

「私のローカル環境では再現しません」をなくそう 秘伝のたれ的な作業が影響して、このような環境差異によるトラブルが発生しがち

コンテナ技術のDockerを用いて、環境構築手順をコード化してGithubなどにコミットし、環境の使い捨てができる状態にしておくことで、上述のようなトラブルを抑制できる

  • メリット

    • インフラ構築手順のコード化(Dockerfile)
    • 環境依存性による問題の排除
    • 廃棄容易姓
  • Column クラウドベースの統合開発環境(AWS Cloud9)

    • ここ数年、ブラウザのみでコードを記述、実行、デバッグできる統合開発環境の利用が活発化している
    • ブラウザベースの統合開発環境の有名なサービスとして、AWS Cloud9がある
    • AWS Cloud9を利用すると、開発には非力なマシン(ipadなど)でも、いつでもどこでも開発が可能
  • インフラ構築手順のコード化(Dockerfile)

    • 開発に関わる全ての文書は構成管理の対象とすることが望ましい
    • チーム開発では、アプリケーションプログラムは必然的に構成管理の対象となりますが、設計文書やインフラ構築手順は構成管理の対象外になってしまうことがある
    • インフラ構築手順のコード(Dockerfile)をSCMにコミットすることで、利用しているディストリビューション、設定ファイルの状態がコードで明確化されるため、インフラに関わるトラブルを抑制できる
  • 環境依存性による問題の排除

  • 廃棄容易姓

  • Column Tweleve-Factor App

    • コンテナ開発が活発になってきているのと同時に、クラウドアプリケーション開発のベストプラクティスの1つとして、The Twelve-Factor Appが取り上げ垂れることが多くなってきています。
    • The Twelve-Factor Appは、Herokuのプラットフォーム開発での治験をプラクティスに落とし込んだもので、コードベース、依存関係、プロセス、並行性、廃棄容易姓、開発/本番一致などの12の要素から構成されます。
    • アプリケーションをThe Twelve-Factor Appに適用させることができれば、コンテナベースの開発に適用していることになるため、オンプレミス、クラウドなどの実行環境に関わらずアプリケーションをデプロイできます。

TODO: The Twelve-Factor Appについて深堀り

  • Windows10proではHyper-Vを有効化することでDockerを利用できます。
  • ここでは、Windows10 Pro以外でDockerを利用する方法を紹介します
  • VagrantとVirtualBoxでDocker環境を構築

TODO: VagrantとDockerのコマンドについて説明しているので再度理解した上で読んで見る SpringBootで利用するための設定についても記載があるので組み込んでおく

7.2 データベースの構成管理#

  • データベースの構成管理をするための、OSSのDBマイグレーションツールのFlywayを紹介

Flywayの利用#

  • SpringBootで利用するための設定
    • 依存下院系の設定
    • プロパティ設定
    • マイグレーションファイルの準備

7.3 メンテナブルなテストコード#

テストコードは重要 本節では、GroovyベースのテスティングフレームワークのSpockを用いてテストコードの可読性を上げる方法を紹介

Spock#

言語仕様に、RSpecやScalaなどのよい点を取り入れており、大きく次の3点の利点がある

  • 可読性
  • データ駆動テスト
  • Power Assertions

TODO: SpringでのSpockの利用方法を紹介 GroovyやScalaなどをキャッチアップする必要がありそう

7.4 ドキュメント生成ツールの活用#

  • 設計書が適切に管理できていない例

    • 詳細設計書がそもそもない
    • Textファイル、Excel、Wikiなどにドキュメントが散乱している
    • Excelなどで納品ドキュメントとして管理されているが、ソースコードと乖離している、および設計書がないプログラムがある
  • 本節では、チーム開発で共有するドキュメントについて述べる

  • ドキュメント管理ツールのSphinxを紹介

Sphinx#

  • Sphinxはドキュメントを簡単に作ることができるようにするツール

  • セットアップ

    • Pythonを利用しているため、Pythonの実行環境が必要
    • Dockerを用いた方法を紹介

TODO: 後ほど実施

  • Sphinxの特徴
    • テキスト(MarkDown)形式
    • CIとの相性がよい
    • 様々な出力形式をサポート

7.5 ソースジェネレータ#

SpringMVCに基づいた画面開発では、1つの機能を追加するために、多岐にわたるファイルの作成が必要 画面開発のたびに発生するファイル作成作業を効率化することで開発生産性を向上させることができる

通常のプロジェクト開発では多くの画面を開発する必要があり、大規模なプロジェクトだと数百画面もの開発が必要になってくる プロジェクト開発で必要になってくる画面開発にかかる以下のコストを削減することで、開発生産性をさらに向上させることができる

  • 開発メンバー参画の際のパッケージ構成のベストプラクティスの共有
  • 新規画面開発の際の必要なソースコード一式の作成作業

この方法論は古くから知られており、有名なプロダクトとしては、YEOMANやAngularJSでも同様のツールセットが用意されている → AngularCliのことか

ここでは、Thymeleafを用いて、Gradleのカスタムプラグインとして、ソースジェネレータを作成する方法を紹介

ソースジェネレータプラグインの導入#

  • 次の手順で導入
    • GradlePluginの実装
    • GradlePluginの利用

TODO: 余裕があればソースコード生成の自動化を組めたら

  • メンバー全員に自動生成の仕組みが浸透していない状態で導入すると、ごちゃごちゃするのであまりおすすめできないらしい

第8章 運用#

システム開発は、「開発を完了させること」=「業務やサービスの提供が滞りなく進むこと」ではない システムは、システムトラブルなどの望まない状態を排除・軽減し、利用者に継続的に使われていくことではじめて価値を生んでいきます。 IPAによると、運用コストはシステム開発の全体の3/4以上のコストを占め、運用の重要性が高まってきている

8.1 環境ごとの設定管理#

Spring Profiles#

開発/本番環境の柔軟な切り替え

環境ごとの設定管理#

ファイルを分ける方法を記載→理解しているので飛ばす

8.2 アプリケーションサーバー設定#

本設では、SringBootで提供している組み込み型のWebサーバー(Embedded Web Servers)を配備するサーバーの設定方法を紹介

実行可能Jar#

以下を加えることでビルド時に依存下院系のあるライブラリを梱包したJarを容易に作成できる

bootJar {
launchScript()
}

アプリケーションサーバーの設定及びリリース#

  • systemdを用いたアプリケーションサーバーの設定

TODO: jarファイルの生成とDocker組み合わせまでできたらやってみる

8.3 アプリケーションの状態確認#

システム開発では、利用者に見える機能開発や画面デザインが優先されてしまい、SLAの検討が後回しになることが少なくありません。

本設では、SpringBootでのアプリケーションの状態の確認方法について紹介

SpringBootActuator#

SpringBootには、Actuatorという安定運用に寄与する強力な機能があるActuatorを有効にすると、HTTPやJMX経由でアプリケーションの状態を確認でき、自前でヘルスチェックのエンドポイントを実装する必要はなくなる

  • SpringBootActuatorを有効化する
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator
compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.3.0.RELEASE'

上記の設定だけで、デフォルトではシャットダウンを除く全てのエンドポイントが有効になります

主要なエンドポイント#

  • Beans

    • アプリケーションに登録されたBeanの一覧を取得します。Curlでのリクエスト例を紹介
  • Environment

    • アプリケーションで利用している環境変数の一覧を取得
  • Health

    • アプリケーションのヘルスチェック。AutoConfigurationの状態をもとにデータベース接続やDiskFullのチェックを実施します
  • HeapDump

    • ヒープダンプファイルをHTTPエンドポイントから取得できる
  • Mappings

    • アプリケーションのエンドポイントとリクエストパスのマッピング情報を出力します。SpringFoxなどを導入しなくてもアプリケーションのエンドポイントの詳細な情報が取得できる
  • Metrics

    • アプリケーションの現在の状態を出力
  • Thread Dump

    • スレッドダンプを取得します
  • Prometheus

    • インフラサービス監視ツールのPrometheusへ連携するメトリクスを出力するエンドポイント
    • 2018/10現在、Prometheusエンドポイントを有効にするためには、ライブラリを追加する必要があるらしい
  • Column Prometheusとは

    • サーバーやインフラなどのメトリクスを取得できるOSSの統合監視ソリューション
    • Prometheusはインストールや設定が容易で、かつ十分な機能を持ち管理しやすいという特徴を持ちます。
    • Go言語で開発されており、バイナリと設定ファイルを用意するだけで利用できる他、Zabbixなどと異なり、データを格納するデータベースを別途用意する必要もありません。
    • また、DockerやKubernetesといったコンテナ/クラスター管理ツールとの連携機能もあり、容易に監視対象を設定できるため、マイクロサービス開発を推進している企業での導入が増加

エルスチェックのカスタマイズ#

Actuatorのデフォルトのヘルスチェックも強力ですが、ヘルスチェックをカスタマイズすることも可能

システム独自のチェックをすることができる

HealthIndicatorインターフェースを実装するBeanを登録することで実現できる

SpringBootActuatorのセキュリティ制御#

アプリケーションの機密情報を取得できるため、システム管理者以外からのアクセスは遮断する必要がある

Spring Boot 2系では、/info, /health以外のエンドポイントはデフォルトで認可ありとなります。 認可なしにしつつ、Listenポートの変更及び接続元IPを制限する設定は以下

8.4 アプリケーション監視#

システムを運用していくためには、アプリケーション状態の可視化およびアプリケーション異常を迅速に検知する必要がある

クラウドを用いた開発が普通(ニューノーマル)となった現在では、監視設計についてもクラウドに適したものにしていく必要があります。 本設では、システム運用に欠かせないアプリケーション監視について、Prometheusを用いる方法を説明

Prometheus#

  • メリット
    • 導入の敷居の低さ
    • クラウドネイティブ時代に適した設計
    • オープンソース

なお、本番環境のトータルの運用コストを見据える場合は、有償の監視サービスのMackerelやDatadogも検討対象にしてみる

Prometheusの導入#

  • インストール方法は次の3つ

    • バイナリのダウンロード
    • Docker
    • ソースビルド
  • PrometheusのDownloadページよりターゲットOSのファイルをダウンロードし、展開するだけでインストールは完了

Prometheusのサービスディスカバリー#

Prometheusにはサービスディスカバリ機能が備わっており、サービスの拡張に自動で追従します。 例えば、AWS EC2を利用している場合、サーバーの増減に自動で追従します

Springアプリケーションとの連携#

  • SpringActuatorとPrometheusは連携できる
  • 設定する方法を記載

メトリクスの可視化#

単体でもメトリクスの可視化はできるが、Grafanaと連携すればより強力にビジュアライズできる

  • ダウンロード
    • バイナリのダウンロード
    • パッケージマネージャインストール

アラート通知#

Prometheusは複数のコンポーネントで構成されており、アラート通知もオプション構成となっている

  • AlertManagerのインストール

    • アラート通知を実現するためには、Prometheus本体のPush通知を処理するAlertManagerのインストールが必要
    • バイナリファイルをダウンロードして展開する
  • Slack通知設定

    • 本書では、Slack通知の設定方法を説明
    • AlertManagerはメール、HipChatなどの連携をデフォルトでサポートしています

TODO: このあたりは見返して設定していきたい

8.5 リクエスト追跡#

本番環境では、可用性要件を考慮の上、アプリケーションサーバーを冗長化することが多く行われます。 また並行性を考慮するとアプリケーションサーバーは状態をNoSQLやRDBに保持させるステートレス構成とし、 スケールアウト及びスケールイン構成とすることも多く行われます。

アプリケーションが多層で連携する場合、各層でリクエストを処理するサーバーが不定となるため、ユーザーの行動履歴をトレースするためには、リクエスト追跡の仕掛けを導入する必要があります。本節では、リクエスト追跡の方法としてnginxを用いる方法を紹介

nginxトレース#

静的コンテンツ配信の最適化やプロキシ用途でnginxを導入することは多く行われる

nginxは以下の用に設定すると、リクエストIDがCookieに付与される

userid on;
userid_name uid;
userid_domain example.com;
userid_path /;
userid_expires 365d;

nginxとのトレースIDの統合#

前項では、ミドルウェア(nginx)でリクエスト追跡IDを発行する方法を紹介 リクエスト追跡を切れ目なく実現するために、nginxとリクエスト追跡IDの統合の方法を紹介

リクエスト追跡機能は横断的関心事(cross-cutting concerns)のため、SpringAOPで実装する方針が望ましいと言えます

  • RequestTrackingInterceptor.javaに実装した内容のことを説明していた

  • Column ログ集約ソリューション

    • 複数台構成のアプリケーションをステートレスにと持つことを望ましい構成とすると、各アプリケーションサーバーにSSH接続してログを確認する方法では運用が大変
    • 上述の課題に対応するためには、ログ集約の仕組みを導入する方法がよい
    • ログ集約のソリューションとしては、商用のSplunk、DatadogやOSSのFluentd、Logs、AzureではLogAnalyticsなどの仕組みがある。アプリケーションを複数台で運用する際はこれらのソリューションの導入も検討してみて

TODO: OSSのFluentdは使ってみたい

8.6 レイテンシ分析#

リクエスト追跡が可能な構成で、かつ応答遅延が発生した場合は、ボトルネック箇所を特定し対応を検討する必要がある また、MSA開発では、多層、多数のサービスが連携するため、サービスのどこがボトルネックであるか特定できる仕組みの導入が望ましいと言えます。

本節では、SpringエコシステムであるSpringCloudプロジェクトのSpringCloudSleuthを用いてレイテンシ分析する方法を紹介

Spring Cloud Sleuth#

FrontentとBackendで同じIDを出力して処理を追うことができますよっていう説明 RestTemplateを使用する必要があるみたい

ここでレイテンシが図られる様子 Zipkinで可視化できるみたい

8.7 無停止デプロイ#

BtoCサービス開発の場合、サービスに影響をおよぼさず無停止でアプリケーションをデプロイする必要が多くあります。 特に利用者が多い場合は、必須の要件となります。

本節では、オンプレミスの条件付きで、無停止でアプリケーションを更新する方法を紹介

ローリングデプロイ#

ローリングデプロイ作業フロー#

  • Step1. アプリサーバー#1へのデプロイ
    • プロキシサーバーからアプリサーバー#1へのリクエスト振り分けを停止
    • アプリサーバー#1のアプリケーションをデプロイ

ローリングデプロイ作業手順#

TODO: nginxの設定ファイルの変更方法も記載しているので後で参考にして設定しておきたい

8.8 コンテナオーケストレーションツールへのデプロイ#

コンテナをデプロイする基盤としてのコンテナオーケストレーションツールは、激しい開発競争が繰り広げられましたが、Kubernetesがデファクトスタンダードとなっている

本節では、SpringBootアプリケーションを、Dockerコンテナを用い、コンテナオーケストレーションツールのKubernetesを用いてデプロイする方法を紹介

コンテナイメージの作成#

TODO: Kubernetesを使ったコンテナ管理…後でDockerを一通り使い倒した後確認する

第9章 (Spring Bootアプリケーションが想定している)システム構成#

どんなにアプリケーションコードが優れていても、システム・アーキテクチャ設計が適切でないと安定的にサービスを提供できません。本ChapterではSpringBootで作成したアプリケーションを中心とした本番環境のシステム・アーキテクチャ構成について検討します。

9.1 システム・アーキテクチャ考察#

データベースを用いるSpringBootで作成したアプリケーションの場合、1つの仮想サーバーにアプリケーションおよびデータベースを構築することで、最小限の構成によるサービスの提供は可能

クラウドネイティブが常識となった現在では、クラウドベンダーが提供するマネージドサービスの特性を理解し、適切なアーキテクチャ設計を行う必要があります。

システムが必要とする要件#

  • 要件
    • 可用性:稼働率は99.9%以上を目標とすること
    • 拡張性:スループットの増加に対して、サービスが低下しない性能を維持するための資源の追加が容易に行えること
    • 完全性:データの操作にはACIDを保証し、データの堅牢性を実現すること

システム要件の検討#

  • 可用性

    • システム構築ではSLAが明記されることが普通
    • サービス品質がSLAの保証値を著しく下回った場合には、ペナルティが発生することもあります。
    • SLAに可用性99.9%と記載されている場合、数値として年間にして9時間弱、月間にして44分弱以内の停止しか許さないシステム構成を検討する必要がある
  • 拡張性

    • システム構築では、サービス特性によりシステムへの負荷がばらついたり、突発的な高負荷が発生したりすることがあります。
    • 可能な限りシステムリソースのスケールアウト及びスケールインできるように設計することが望ましいと言えます。
  • 完全性

    • システム構築では、システムじの状態をRDBなどのデータストアに保管することが普通
    • システムで保管した情報資産が正当な権利を持たない人により変更されていないことを確実にしておくよう設計する必要があります。また、データの消失を防ぐための対策も実施していく必要があります
  • コスト

    • Capter8で解説したように、運用コストはシステム開発全体の3/4以上のコストを締めます。
      • システムリソースの運用コスト(ハードウェアコストやライセンスコストなど)
      • システム運用のコスト(人件費など)

9.2 システム・アーキテクチャ案#

AWSを利用したアーキテクチャ例を記載している

構成要素一覧#

可用性#

拡張性#

コスト#

9.3 構築チュートリアル#

Teraformを利用した環境構築を紹介している

第10章 Spring5/Spring Boot2の新機能#

2017年にリリースされたSpring5,2018年にリリースされたSpringBoot2の新機能のうち、 今後重要になると考えられるWebFluxについて説明

10.1 WebFlux#

HTTPを利用したシステムの範囲が拡大し、同時アクセスが増えていくにつれて、Webアプリケーションにおけるコンピュータリソースに対して待ちが多いことがわかってきました。 そのため非同期処理を用いたWebアプリケーションが求められる様になりました。その解決案の1つとしてリアクティブプログラミングが選ばれ、Srping5/SpringBoot2においてはWebFlux飛ばれるリアクティブプログラミングを用いたWebプログラムを書くことができるようになりました。 このプログラムは同期ではないのでブロックされることなく、実施されてI/O待ちのような状態にはならず、I/Oが発生したタイミングで実施されることになります。

TODO: 実装ハードル高そう。色々考えること多いので後で見返す

第11章 ローカル開発環境の構築について#

第12章 サンプルアプリについて#

SpringBoot2徹底活用
https://tutttuwi.github.io/posts/2020-06_springboot2徹底活用/
Author
Tomoaki Tsutsui
Published at
2020-06-07
License
CC BY-NC-SA 4.0