Architecture Bookmarks 2020

2020年にArchitecture系の読んだ記事とかのなかでメモしておきたいもののまとめ。

目次

Software/System Architecture

How to Design a Web Application: Software Architecture 101

- ソフトウェアアーキテクチャは主要なコンポーネントの関係、連携方法を表し、後で設計変更やリファクタリング避ける為に慎重に検討する必要がある
- アーキテクチャを選択すると、パフォーマンス、フォールトトレランス、スケーラビリティ、および信頼性への対処方法が決まる
- ソフトウェアデザインはモジュールの責務、クラスのスコープなどのコードレベルの設計を担う
- Software Architecture Patterns
    - Client-server
        - クライアントはリクエストをサーバに送信し、サーバーがレスポンスを返す
        - 多くのWebサイトやWebアプリケーションがclient-serverアーキテクチャで構築されている
    - Peer-to-peer
        - ノードと呼ばれるコンピューターが中央サーバーを介さずに、相互に通信できるネットワーク
        - 中央サーバーが存在しないことは、単一障害点が存在しないことを意味する
        - 一部のコンピューター/ノードがダウンした場合でも、ネットワークと通信はアップのまま
        - ブロックチェーンの基礎
    - Model-View-Controller (MVC)
        - アプリケーションロジックを3つのコンポーネントに分割するアーキテクチャ
        - Models
            - どのようにdatabseにデータを保存するかを定義する
        - Views
            - GUIなどのユーザーの目に触れる箇所を担う
        - Controllers
            - ModelとViewのインターフェースとして振舞う
        - デスクトップアプリケーションだけでなく、モバイルおよびWebアプリケーションにも使用される
    - Microservices
        - 機能/タスクが個別のモジュール/コードベースに分割され、それぞれが連携して大規模なサービス全体を形成する
        - モノリシックアーキテクチャと比べて、メンテナンスや開発、テスト、デプロイ等で優れている
    - Event-driven
        - Non-blockingアーキテクチャはReactive、もしくはEvent Drivenアーキテクチャとも呼ばれる
        - Event DrivenアーキテクチャはモダンWebアプリケーション開発では非常にポピュラー
        - 最小限のリソースの消費で、多数の同時コネクションを捌くことができる
        - モダンアプリケーションはスケールのために非同期で動作する必要がある
    - Layered
        - 特定の抽象化レベルを元にレイヤーを構築する
        - 各レイヤーは上位のレイヤーに機能を提供する
        - Presentation layer
        - Application layer
        - Business logic layer
        - Data access layer
    - Hexagona  
        - 3つのコンポねーントで構成される
            - Ports
            - Adapters
            - Domain
        - アプリケーションのコンポーネントを疎結合にして、テストを容易にすることにフォーカスする
        - ビジネスロジックとして、Domainをコアする
        - 外のレイヤーは、PortsとAdpterが存在する
- Horizontal or Vertical Scaling
    - 一貫した最低限のトラフィックを捌く場合(内部ツールなど)は、分散環境でホストする必要はなく単一サーバーで十分
    - その場合は垂直スケーリングを選択する
    - アプリケーションが公開されており、トラフィックが将来爆発的の増加することが予想される場合は、高可用性と水平スケーラビリティの両方が重要
    - クラウドにデプロイし、水平方向のスケーラビリティを念頭に置く
- Monolith or Microservice
    - When to use monolithic architecture
        - シンプルで限られたトラフィックを捌けば良い場合はモノリシックアーキテクチャが最適
        - 長期にわたって、ユーザーベースとトラフィックが指数関数的に増加しないことが決まってる場合など
        - モノリシックアーキテクチャから始めて、後で分散マイクロサービスアーキテクチャにスケールアウトすることを決定する場合もある
        - 必要に応じて段階的にアプリケーションの複雑さに対処できる
    - When to use microservice architecture
        - 複雑なユースケースや将来的なトラフィックの増加が見込まれる場合に適している
        - 典型的なソーシャルネットワーキングアプリケーションの場合は↓のようなコンポーネントを持つ
            - messaging
            - real-time chat
            - live video streaming 
            - image uploads
            - liking
            - sharing features
        - このケースでは、単一責任と関心の分離の原則に従って。各コンポーネントは別々に開発される
- NoSQL or SQL?
    - When to pick a SQL database?
        - Transactions and Data Consistency
            - お金や数字に関係するトランザクションが必要、またはACIDに準拠する必要がある場合、データの一貫性は非常に重要であり、RDBはトランザクションとデータの一貫性に関して優れている
        - Storing Relationships
            - relationshipsを表現しなければいけない場合
                - 友達とかいいねとか
    - When to pick a NoSQL database
        - Handling a large number of read-write operations
            - 素早くスケールする必要がある場合
            - 大量のread-write操作や大量のデータを処理する場合
            - すぐにノードを追加できるため、より多くの同時トラフィックと大量のデータを最小限の遅延で処理できる
        - Running data analytics
            - 大量のデータに対応する必要があるデータ分析のユースケースにも最適
- ソフトウェアアーキテクチャに慣れる最良の方法の1つは、独自のWebアプリケーションを設計すること
- https://www.educative.io/courses/web-application-software-architecture-101

API

Microservices

The Rise of Service Mesh Architecture

- Service Meshとは?
    - マイクロサービスアーキテクチャの内部のサービス通信をハンドルするインフラストラクチャレイヤーとして定義できる
    - マイクロサービスアーキテクチャに関連する複雑さを軽減し、下記のような機能を提供できる
        - Load balancing
        - Service discovery
        - Health checks
        - Authentication
        - Traffic management and routing
        - Circuit breaking and failover policy
- Service Meshが必要な理由?
    - マイクロサービスアーキテクチャではほとんどの場合サードパーティのライブラリまたはコンポーネントに依存して、service discovery, load balancing, circuit breaker, metrics, telemetryなどの機能を提供する
    - Netlifxのような企業は、Hystrix for circuit breakers, Eureka for service discovery, Ribbon for load balancingのようにライブラリを内製している
    - だがこれらのコンポーネントはアプリケーションコード内で実装する必要があり、言語によっても異なる
    - 外部のコンポーネントをアップグレードしたい時は、アプリケーションを検証、更新、デプロイをする必要がある
    - 密な結合はアプリケーションの複雑さを増し、問題が発生した場合にトラブルシューティングできるように、これらのコンポーネントの構成方法を開発者は理解する必要がある
    - Service Meshにより、上記の複雑さをアプリケーションから切り離し、以下のような機能をサービスプロキシーで提供可能になる
    - これによりアプリケーションはビジネスロジックの実装に専念できる
    - マイクロサービスアーキテクチャで、5つのサービスが互いに通信をしている場合
        - 各マイクロサービスで共通する実装であるconfiguration、routing、telemetry, logging, circuit breakingなどの実装を分離されたコンポーネントであるサービスプロキシーに抽象化する方が合理的
    - Service Meshの導入により、責務が明確に分離される
    - 問題発生時も、アプリケーションに関連するのかネットワークに関連するのかに基づいて、根本原因を簡単に特定できる
- Service Meshの実装方法?
    - サービスとともにプロキシをデプロイする
        - サイドカーパターン
        - アプリケーションから複雑さを抽象化する
    - Envoy from Lyft
        - 最もポピュラーな、クラウドネイティブアプリケーションように設計されたオープンソースのプロキシー
        - 他のサービスと並行して実行され、プラットフォームに依存しない形で必要な機能を提供
        - 全てのトラフィックはEnvoy Proxyを通じて、各サービスに到達する
- Istioとは?
    - マイクロサービスを接続、管理、保護するためのオープンプラットフォーム
        - Kubernetes communityでポピュラーで広く使われている
    - 現時点でのServic Meshの最良のものの1つ。基盤となるインフラストラクチャの詳細な知識がなくてもマイクロサービスを展開できる
    - これから多くの組織でモノリシックなアプリケーションをマイクロサービスアーキテクチャーに移行を始める
        - サービスの管理が負担になった際には、Service Meshを用いる
        - アプリケーションの変更は不要で、複雑さを取り除くことができる

The Dark Side of Microservices

- Distributed Systems Are Hard
    - 主に二つの点でマイクロサービスはハードとなる
        - consensus
        - partial failure
- Partial Failure
    - モノリスアプリケーションによって処理されるHTTPリクエストの場合、リクエストを受け取ると、単一のサーバーがトランザクションを最初から最後まで処理する
        - 問題がある場合、例えばソフトウェアのバグやハードウェアの故障の場合は、全体のモノリシックアプリケーションがクラッシュする
    - マイクロサービスでHTTPリクエストを処理する場合は、マイクロサービスは他のマイクロサービスに新たなリクエストを送信する場合がある
    - さらにその先で、別のマイクロサービスにリクエストを行う可能性もある
    - それらのマイクロサービスの一つが失敗する時にどうする?
- More Moving Pieces
    - Development
    - Debugging
        - 複数のサービスにまたがってデバッグをする必要がある
        - 分散トレースツールを使う
            - Jaeger
    - Logging
        - Splunkなどでデータを集約する必要
    - Monitoring
        - Nagiosのようなシンプルなサーバー上の監視ツールは、マイクロサービスを利用しているときはスケールに対応できない
        - Prometheus/Datadog/Sysdig
    - Deployment
        - Chef/Puppetはモノリスアプリケーションのデプロイであれば十分
        - マイクロサービスではKubernetesなどが必要
    - Networking
        - モノリスアプリケーションはシンプルなロードバランサーで処理可能
        - マイクロサービスはより多くのエンドポイントが存在し、それら全てのエンドポイントでload balancing, service discovery, consistent security policyなどが必要
        - service meshでこれらの問題を解決できる
- Microservices Make Sense, Sometimes
    - 技術的な観点からマイクロサービスはモノリシックアプリケーションより難しい
    - しかし人間的な観点から見ると、マイクロサービスは大規模組織における効率に影響を与える
        - 大規模組織の異なるチームが、ソフトウェアを独立してデプロイ可能となる
    - マイクロサービスのトレードオフ
        - 組織の効率化 <=> 技術的な複雑さ

Microservice Integration — SAGA Pattern

- integration patternを設計するの考慮点
    - Partial error handling
        - 1つのマイクロサービスでリクエストが失敗した場合(local transaction)、システム全体もロールバック(compensation transaction)しなくてはならない
    - Manage the situations where we need to collect data from multiple services
        - マイクロサービスでは複数のマイクロサービスからデータを取得する必要がある場合、適切に統合する必要がある
- SAGAパターンとは
    - マイクロサービスアーキテクチャはサービスごとのデータベースの原則により、これらのデータベースを同期する必要が生じる
    - 分散トランザクションの整合性を確保するために適用できるSAGAパターン
- Choreography Based SAGA Pattern
    - 各ローカルトランザクションは、ジョブが完了するとイベントを発行する
    - このイベントを受信する他のローカルトランザクションは、適切な動作を実行する
    - benefits
        - 実装が簡単
        - ローカルトランザクションの数が少ない時
        - 疎結合なエンドポイント
        - アジャイル組織に適している
    - drawbacks
        - ローカルトランザクションの数が多い時に、非常に複雑になる
        - サービス間で循環依存が発生する場合がある
- Orchestration Based SAGA Pattern
    - プロセス全体を調整するインテリジェントエンドポイント(オーケストレーションを実行する別のサービス)が存在
    - ローカルトランザクションの1つが何らかの理由で失敗した場合、オーケストレーターは以前に実行されたトランザクションのロールバックも担当
    - benefits
        - 実装、メンテナンスが簡単
        - ローカルトランザクションの数が劇的に増加する場合、複雑さが問題でにならない
    - drawbacks
        - ビジネスロジックはオーケストレーター内に実装される

DDD

Fizz Buzz と税率とタイムゾーンの話 (ドメインレイヤとアプリケーションレイヤの話、あるいは時間変化する値をモデリングする話

- FizzBuzzのロジックをドメイン(Entities層)とアプリケーションレイヤ(UseCase層)のどちらに書くか
    - FizzBuzz自体のロジックはドメイン層に書く
    - アプリケーション層(UseCase層)にはアプリケーションとしてどう使われるかに応じたロジックを書く
    - FizzBuzzの数値から文字列を生成するロジックは問題の最上位レベルのルールなのでエンティティで、入出力回りなどをユースケースに記述する

Clean Architecture

Design Pattern