Please enable JavaScript.
Coggle requires JavaScript to display documents.
Microservice Essential & Best Practice Part I (What is MS (Key…
Microservice Essential & Best Practice
Part I
What is MS
small
how small?
small enough and no smaller
service aligns to team structures
the smaller the service, the more you maximize the benefits
Focused on one thing
EX: Monolithic vs Microservice
Autonomous
isolated service
on PaaS, or VM, or Container
via network calls, EX: API
Key Benefits
Technology Heterogeneity
lowest risk to try out new technology
multiple technologies VS. size
Resilience
failure doesn’t cascade
system can carry on working
Scaling
You can target scaling at just those microservices that need it.
EX: FB
Gilt - online fashion retailer
2007 - monolithic Rails AP
2009 - splitting out core parts
today - over 450 microservices
Ease of Deployment
Organizational Alignment (productive)
large teams and large codebases VS smaller teams working on smaller codebases
Composability
拆分成小服務,組合性更高
Optimizing for Replaceability
大型老舊系統改起來風險高
系統越小,改寫成本越低
What About SOA?
reusability of software
easier to maintain or rewrite software
middleware
shared service
Other Decompositional Techniques
Shared Libraries
ability to deploy changes in isolation is reduced 隔離能力降低
point of coupling 增加耦合
Modules
lifecycle management
EX: Erlang
deployed into a running process
No Silver Bullet
complexities of distributed systems
handling deployment, testing, and monitoring to unlock the benefits
distributed transactions or CAP theorem
think differently about how you scale your systems and ensure that they are resilient
How (High-Level)
Good Service?
loose coupling
a
change
to
one service
should
not
require a
change to another
high cohesion
change
behavior
in one place
avoid
changes
in lots of
different places
deploying lots
of services at
once
The Bounded Context
DDD
a specific responsibility enforced by explicit boundaries.
Shared and Hidden Models
Modules and Services
identified
a
boundary
within our domain
thinking clearly about what
models
should
be shared
using
modules
within a
process boundary
to keep related code together and attempt to
reduce the coupling
modular boundaries
then become
excellent candidates
for microservices
microservices
should cleanly
align
to
bounded contexts
Business Capabilities
capabilities those contexts provide the rest of the domain
EX: finance context may well expose the end-of-month accounts
First “What does this context do?”
Then “So what data does it need to do that?”
these capabilities become the key operations
組織架構 & 使用方法
nested approach
full separation approach
什麼方法最好,沒有嚴格規定
nested approach OR full separation approach
based on your organizational structure
nested approach to
simplify
testing
don’t have to stub
each service inside the warehouse context
Communication in Terms of Business Concepts
需求時常變更
更改的範圍有可能被隔離到單一的 microservice boundary
從商業角度反應 service 之間如何溝通
使用共同術語在 Interface 上
就像組織內部使用一些表格作為溝通
The Technical Boundary
Fronted 無狀態 (stateless)
Data Access (RPC)
一層一層穿越技術邊界
洋蔥式架構
一但變更,大多兩個 service 要一起改
RPC 呼叫造成系統脆弱
Interface 過度囉唆,造成效能問題
沒有採用垂直分割、業務導向,採用 in-process API Call,水平分割
總結
組織分割服務是個好方向
Bounded contexts 找到接縫(seams)的重要工具
在 problem space 找到接縫(seams),這些接縫帶來 低耦合 高內聚 的好處
Microservice Essential & Best Practice
Part II
Integration
結論
避免 database integration
REST is a good starting point
choreography
over
orchestration
choreography
orchestration
避免 breaking changes,API 版本必須 遵循 Postel's Law 並 使用
tolerant readers
Postel's Law
Be conservative in what you send, be liberal in what you accept.
對發送的內容保持謹慎,對接收的內容保持自由。
Think of user interfaces as compositional layers
Looking for the Ideal Integration Technology
Avoid Breaking Changes (強調容錯, API add new fields, shouldn't be impacted)
Keep Your APIs (Technology-Agnostic) 與技術無關
避免使用那些支配我們實作 MS 的 tech stacks
Make Your Service Simple for Consumers
讓客戶不會被某種技術綁著,例如使用 client lib,但增加耦合代價
比方用開放的技術,而有自行選擇實作的方法
Hide Internal Implementation Detail
任何迫使我們暴露內部表現細節的技術都應該被避免
SOAP, XML-RPC, REST, Protocol Buffers? 我們想從選擇的技術獲得什麼?
Interfacing with Customers
The Shared Database
database (DB) integration 是業界最常見的作法
1.如果 schema change 讓系統更好維護,其他的整合服務可能會壞掉,DB 實際上是一個非常大的共享 API。需要進行大量的回歸測試。
2.假設今天發現客戶資料更適合存放在非關連式資料庫,改得動嗎?
3.如果今天三個都要編輯客戶資料,就有可能要改三個地方。
Sync VS Async
Orchestration VS Choreography
The
process
for creating a new customer
customer creation via
orchestration
一系列的 request & response
hub in the middle
"god" services
customer creation via
choreography
emit Customer created
subscribe to these events and react accordingly
缺點:process 隱藏反映在系統中
monitor
and
track
that the right things have happened
建議: :star:
build a
monitoring system
that explicitly matches the view of the
business process
RPC
avoid the need for a shared interface definition
不建議使用
like Java RMI, Thrift, or protocol buffers, while SOAP uses XML
Technology Coupling
EX: Java RMI 綁定技術,Thrift and protocol buffers 有多種語言支持
Brittleness
Is RPC Terrible?
Local Calls Are Not Like Remote Calls
Networks aren’t reliable
因為 RPC 封裝成類似本機呼叫,但是隱藏了遠端、資料 marshalling and un-marshalling 等成本問題
REST + HTTP
architectural style
RMM (Richardson Maturity Model)
Varnish cache and mod_proxy
JSON, XML or others?
注意太方便造成的問題,EX: Rails 完整暴露整個資料表
缺點:低延遲、訊息小 不適合 ?????
REST over HTTP is a sensible default choice for service-to-service interactions
Implementing Asynchronous Event-Based Collaboration
Technology Choices
Complexities of Asynchronous Architectures
Services as State Machines
REST over HTTP 仍然是好選擇
Reactive Extensions (Rx)
making more service calls, much simpler
DRY and the Perils風險 of Code Reuse in a Microservice World
avoid
duplicating our system behavior and knowledge
shared library that can be
dangerous
in a microservice architecture.
Client Libraries
分離寫 API 的人
負責 Client Side 升級 (API)
最後,確保客戶端負責何時升級他們的客戶端庫: 我們需要確保我們能夠獨立地發佈我們的服務!
API vs Client libs 需要可以各自獨立升級
Access by Reference
避免舊資料
例如:當收到訂單,透過 Email Service 發送郵件,(要傳送 domain entity 還是 pass 參數?),應該要讓 email service 越簡單越好,只傳 email 或是一些參數,避免太過耦合或是舊資料。
API Versioning
減少 Breaking Changes
Database integration 很難避免
REST 則有所幫助減少,內部更改可避免更改服務介面
Tolerant Reader
able to ignore changes
Postel's Law
known as the robustness principle
使用 Semantic Versioning
MAJOR.MINOR.PATCH
並存 Different Endpoints
Coexisting different endpoint versions allows consumers to migrate gradually
提供擴展能力
RPC 處理版本並存相對就比較難處理
Use Multiple Concurrent Service Versions
更新舊用戶成本高時使用,但少用
需要 middleware or nginx script
????
User Interfaces
不建議使用,因為發布會有相依性
Using a single monolithic gateway to handle calls to/from UIs
建議使用:Using dedicated backends for frontends
Services directly serving up UI components for assembly
Integrating with Third-Party Software
如果是戰略目標就自己刻,如果不是就用現成的
Lack of Control
用什麼工具、程式語言擴展、自訂整合CI?都是依照所選擇的廠商所限制
Customization
如果決定購買一個產品,但是用起來並沒有帶來太大的幫助。
或是受限制,例如:Salesforce 的 force.com 平台上使用的 Apex語言,只存在該系統中。
Integration Spaghetti
整合工具,可能會遇到專有的 Binary Protocol, SOAP, XML-RPC... etc,更糟的是工具允許你直接存取底層資料庫,將導致耦合問題。
On Your Own Terms
大多數情況,從零開始建構是不明智的,依照您的想法訂製,並限制不同工具的數量
EXAMPLE: CMS AS A SERVICE
Hiding a CMS using your own service
EXAMPLE: THE MULTIROLE CRM SYSTEM
Using façade services to mask the underlying CRM
The Strangler Pattern
扼殺者模式 (先建後拆)
Splitting the Monolith
All About Seams
seam 的概念 - 也就是說,一部分代碼可以單獨處理,並在不影響代碼庫其餘部分的情況下進行工作。
我們還要確定接縫。 但是,我們並不是為了清理代碼庫而尋找它們,而是希望識別出可以成為
服務邊界的接縫
。
Breaking Apart MusicCorp
identify the high-level bounded contexts
what bounded contexts the monolith maps to
假設拆解成四個 contexts
Catalog
Finance
Warehouse
Recommendation
重構
把類似的程式碼搬到相同的 package
測試改動的程式是否正常
哪些適合留著,哪些不適合
分析 package 之間的相依性 (尋找不正常的相依,例如:warehouse package 相依於 finance package)
一步一步慢慢來
The Reasons to Split the Monolith
codebase 拆解後,得到什麼好處
改變的步伐
例如:warehouse seam 成一個 service,他就能改變得更快,因為它變成一個獨立單元
Team Structure
拆團隊, take full ownership
Security
分離獨立相關信息敏感服務,例如:Finance,可藉由此服務增加額外的保護&監控、數據傳輸、數據存儲
Technology
開發團隊打算尋找推薦系統的演算法方案,找到一個用 Clojure 寫的框架,如果今天把推薦系統服務拆分出來,這個建構、決定將變得比較容易
Tangled Dependencies
錯綜複雜的依賴關係
需要分離的接縫 Seams,DAG(有向無環圖) 幫你找到很難解的接縫(例如 package 拆解)
範例:打破FK關係
例如:財務報表需要透過 SKU 去撈品項名稱增加報表資訊
Foreign key relationship
透過 API 阻止財務報表進入商品資料表
Post removal of the foreign key relationship
將會拆成兩個資料表,但這是正確的,可能會慢一點,但是架構上完全可以接受
其他限制將浮現,例如如果找不到商品該如何顯示?
Database
複雜的依賴關係之母
DB 也需要找接縫,是一個棘手的問題
Getting to Grips with the Problem
正視問題
將資料庫存儲代碼分離到不同的 bounded context
Splitting out our repository layers
FK 可能是絆腳石,用 SchemaSpy 分離資料表
範例:Shared Static Data
Country codes in the database
方法一:替每個 package 複製一個 table。問題:更新資料表呢?
方法二:property file 放在程式碼裡頭(不錯的做法)
方法三:將這些資料推送到服務中(overkill)
範例:Shared Data
常見問題,共享可變數據
財務跟訂單皆可存取客戶資料
Accessing customer data: are we missing something?
建立 package,最終可能會建立一個獨立個客戶 service
Recognizing the bounded context of the customer
範例:Shared Tables
Tables being shared between different contexts
將目錄與庫存分開
Pulling apart the shared table
Refactoring Databases
Staging the Break
Transactional Boundaries
Updating two tables in a single transaction
Spanning transactional boundaries for a single operation
Try Again Later
如果訂單寫入失敗,放到 queue 在執行一次,我們假設 retry 會正確
這是另一種形式的最終一致性,使用事務邊界來確保狀態一致,我們更接受系統在外來某個時刻一致
Abort the Entire Operation
需要補償交易(compensating transaction)
如果補償交易失敗,可能需要一個簡單的後台管理或一個自動化處理的過程
Distributed Transactions
通常有個 transaction manager 來確保所有事物保持一致狀態,包含跨系統、跨網路的交易
短期交易通常使用 2PC (Two-phase commit)
如果交易管理器得到所有參與者投票,那麼他會告訴所有參與者將繼續他們的提交,否則就 rollback
Distributed Transaction 已經有現成的(EX: Java Transaction API),除非是你的核心路線
So What to Do?
distributed transactions 會抑制擴展,需要更多的補償行為,來修正資料一致性
如果需要 distributed transactions 應避免把它拆分,從純技術性的流程轉移到創建一個具體的概念(狀態),例如:處理中訂單
Reporting
當我們拆分服務,意味著數據儲存也將拆分,這時候問題來了,報表變得很麻煩,但在軟體架構上、流程是有價值的
The Reporting DB
在總帳報表上增加銷售內容描述來豐富數據 或 查看特定高價值客戶的購物行為
在單體式架構上,報表相對容易許多
Standard read replication
缺點:
schema change 風險高,沒人想做
優化數據庫方式選擇有限, change data structure 影響大
資料庫選擇太多
(Report) Data Retrieval via Service Calls
拉更大的數據 API 會掛
microservice's API 通常不是給 report 用的 (例如用 user list id 去查資料)
使用 cache header, 但是 report 通常訪問 long tail data, so cache 容易 miss
解決方案:使用批次 API
一個 API 可以接受 user id list,然後 return 202 accepted, 先接受 request, 後處理,然後系統可以用輪詢的方式 直到收到 201 created
不建議使用這方法,後面有更好可以擴展的方法
Data Pumps
Using a data pump to
periodically
push data to a central reporting
雖然說資料庫集成是個壞主意,但這個方式是個例外,使報表更容易
可以是一個指令或 cron job, 但必須深入理解兩個 DB
Utilizing materialized
views
to form a single monolithic reporting schema
此複雜度更深入 schema, 但是 data pumps 是明智的建議
作者用 data pump 把 JSON file 送到 S3 假裝是個 Data Mart, 之後 populate 到 Excel or Tableau 這樣的 report 工具
Event Data Pump
資料因為綁定的事件驅動,直接將資料推送到 report DB, 而不是依賴一個週期 像是 data pump
stream of events (x happens at timestamp y)
An event data pump using state change events to populate a reporting
缺點:無法直接存取來源資料庫,無法像 data pumps 擴展大量數據
好處:鬆耦合
Backup Data Pump
Netflix 使用 Cassandra 當成資料儲存,這是一個特殊案例的 Data Pump
儲存 SSTable to Cassandra, and backup to S3
使用 Hadoop,它使用 SSTable 備份作為作業的源。
Netflix 實做了一個 project
Aegisthus Project
實現處理大量數據
Toward Real Time
如前面所述,不同方式取得大量數據,dashboard, alerting, financial reports, user analytics 因為不同準確性跟需求,會因此採用不同技術,越來越走向 eventing systems,事件系統可以根據路由把數據發送到不同地方。
Cost of Change
建議 小範圍、漸進式改變
了解每個改變的影響(impact)
減輕錯誤的成本
提供一個技巧 物件導向系統設計方法: class-responsibility-collaboration (CRC) Card
CRC Card Layout
CRC Example
Understanding Root Causes
關鍵在於,在拆分成本太高之前,知道需要拆分
問題二,知道從何開始,從成本拆分服務,找到某個服務、建立新的服務堆棧,都是重要的工作
允許自行佈建 VM,將讓測試跟佈建變得更容易
這本書的其他內容將教你如何降低成本
Summary
沿著服務邊界找到接縫,用漸進的方式改善接縫,降低拆分的成本,持續改進系統,以滿足未來需求。