Showing posts with label microservices. Show all posts
Showing posts with label microservices. Show all posts

Saturday, December 29, 2018

The Unintentional Side Effect of a Bad Concurrency Model

這篇 The Unintentional Side Effect of a Bad Concurrency Model 出自 Joe Armstrong 的 blog 。文章裡提到的 Erlang 世界觀,跟 Robert C. Martin 主張的 Clean Architecture 相左。 Robert C. Martin 認為:「 micro-services 只是一種 deploy 的選項 ,並不是 Architecture 。」然而在 Erlang 的世界觀卻不這麼認為,在 Erlang programmer 的世界觀認為:
(1) micro-services 的設計,才應該是 default 的選項。我們應該要透過不停地在系統中加入新的小型獨立的 communicating objects 來讓系統成長 (micro-services),而不是把「不需要溝通」的程式愈寫愈大 (monolithic)。
(2) 模組與模組之間,應該要透過 communication protocol/message 來溝通,而不是依賴於 API 。

而作者的結論是:『為什麼世界上大部分的程式都不是用 erlang 的世界觀在開發,主要就是因為大部分的其它語言都沒有一個好的 concurrency model ,於是就造成了一種未意料到的副作用。』

Sequential languages are designed to write sequential programs, and the only way for a sequential program to grow in functionality is for it to get larger. It's technically difficult to split it into cooperating processes so this is not usually done. The concurrency in the application cannot be used to structure the application.

We should grow things by adding more small communicating objects, rather than making larger and larger non-communicating objects.

Concentrating on the communication provides a higher level of abstraction than concentrating on the function APIs used within the system. Black-box equivalence says that two systems are equivalent if they cannot be distinguished by observing their communication patterns. Two black-boxes are equivalent if they have identical input/output behavior.

Friday, December 28, 2018

How to build stable systems

 How to build stable systems 算是一篇集大成的文章,內容同時涵蓋了軟體開發的各種層面,並且提出作者認為合理、有效的作法。

在「前置準備」方面,他主張,『如果要試用新的技術,只能做單一賭博』不要一口氣嘗試太多技術,過度增加專案的危險性。
A project usually have a single gamble only. Doing something you’ve never done before or has high risk/reward is a gamble. Picking a new programming language is a gamble. Using a new framework is a gamble. Using some new way to deploy the application is a gamble. Control for risk by knowing where you have gambled and what is the stable part of the software. Be prepared to re-roll (mulligan) should the gamble come out unfavorably.

在「系統規畫」方面:
由於作者來自 erlang 的背景,他的思維是以 micro-services 做為預設值,所以他主張,模組與模組之間要透過 protocol 來溝通。( 注意:傳統的系統規畫通常是建議,系統先做成 monolithic,模組與模組之間先透過 API 來溝通,之後再逐步視需要,將模組變成獨立運作的 service。)
Your system is a flat set of modules with loose coupling. Each module have one responsibility and manages that for the rest of the software. Modules communicate loosely via a protocol, which means any party in a communication can be changed, as long as they still speak the protocol in the same way. Design protocols for future extension. Design each module for independence. Design each module so it could be ripped out and placed in another system and still work.

他主張 end-to-end principle 。只有端點需要有複雜的邏輯。
In a communication chain, the end points have intelligence and the intermediaries just pass data on. That is, exploit parametricity on mulitple levels: build systems in which any opaque blob of data is accepted and passed on. Avoid intermediaries parsing and interpreting on data. Code and data changes over time, so by being parametric over the data simplifies change.

在「設置檔」方面,他主張「除非系統真的超大,不然,並不需要全然動態的『設置檔』」所以不需要太早使用 etcd/Consul 之類的,把設置檔放在 S3 即可。
Avoid the temptation of too early etcd/Consul/chubby setups. Unless you are large, you don’t need fully dynamic configuration systems. A file on S3 downloaded at boot will suffice in many cases.

Thursday, August 2, 2018

Clean Micro-service Architecture

Clean Micro-service Architecture 又是 Robert C. Martin 的文章。

大意如下:

Clean Architecture 與 microservices 是兩個正交的概念

  • Clean Architecture 是指軟體系統的設計要可以清楚地區分成 entity, use cases, controller & gateway & presenter 這三個圈圈。之後才可以不斷地配合需求而修改。
  • microservices 是一種 deployment option (布署選項) ,而且這個布署的選項有它的 trade-off 。此外,還有其它的布署選項。使用不同的布署選項,是為了達成不同的 scalability  。

其它相關的布署選項還有:

  • 在同一個 thread 裡的 jar ,彼此透過函數來溝通。 
  • 在同一個 process 裡的 thread ,彼此透過 mailbox 或是 queue 溝通
  • 在同一台 machine 裡的不同 process ,彼此透過 socket 溝通
  • 在 Internet 上不同的 services ,彼此透過 asynchronous API 溝通
引述文章裡的一小段話 --- The deployment model is a detail. Micro-services are deployment option, not an architecture. 作者主張:「開發軟體系統,要視實際的需求,再來決定要用哪一種合適的布署選項。」

注意: jar 也可以達成 independent deployability (可獨立布署性) 和 hot swapping (程式碼熱抽換。) 所以也是相關的 deployment option


Saturday, December 30, 2017

microservices prerequisites

這兩天看了一篇文章, Enough with the microservices ,文章的大意是講,作者反對成長中的公司,盲目地將公司的軟體架構改成「微服務」,因為帶來的損害大過優點。

文章的最後,介紹了 Martin Fowler 的「微服務的先決條件 (microservices prerequisites) 」。即,要把公司的軟體架構改成微服務,要先做哪些事? 並且提到,對於許多公司,光是完成前兩項,大概就可以解決 90% 以上的問題,並不需要真的做到五項都完成,完整地把軟體架構改成微服務。

先決條件清單如下:

  1. 清理應用程序。確保應用程序具有良好的自動化測試套件,並使用了最新版本的軟件包、框架和編程語言。
  2. 重構應用程序,把它拆分成多個模塊,為模塊定義清晰的API。不要讓外部代碼直接觸及模塊內部,所有的交互都應該通過模塊提供的API來進行。
  3. 從應用程序中選擇一個模塊,並把它拆分成獨立的應用程序,部署在相同的主機上。你可以從中獲得一些好處,而不會帶來太多的運維麻煩。不過,你仍然需要解決這兩個應用之間的交互問題,雖然它們都部署在同一個主機上。不過你可以無視微服務架構裡固有的網絡分區問題和分佈式系統的可用性問題。
  4. 把獨立出來的模塊移動到不同的主機上。現在,你需要處理跨網絡交互問題,不過這樣可以讓這兩個系統之間的耦合降得更低。
  5. 如果有可能,可以重構數據存儲系統,讓另一個主機上的模塊負責自己的數據存儲。



Tuesday, October 31, 2017

讀網路上的技術文章有感

身為中文的使用者,偷懶的時候,還是會傾向先讀一下中文的資料。此外,國外的一些進階者寫的東西有時候相對比較難、多用了專有詞彙,我又會偷懶看一般人寫的心得。

然後就出現了一些問題:以訛傳訛

比方說像 microservices 。我看了很多文章都把 microservices  的重點放在 docker 、放在 container ,而不是 database 的獨立性:『每個微服務應該有自己獨立的持久性資料儲存,而且這些資料只能透過微服務本身的 API 來存取。』這些搞錯重點的文章居然還一大堆,無形中也助長了人的無知、誤了好多人。

此外, concurrency model 也是一個例子。Golang 很紅。然後就會有一些介紹 Golang 的文章錯誤地把 Erlang 的 Actor model 講成說這跟 Golang 的 CSP model 是一樣的、差不多的。這也是差很多啊…。

Friday, October 14, 2016

[open-falcon] micro services 與 message queue

公司做的監控系統是基於 open-falcon 去開發的。open-falcon 裡用來讓 agent 這個 micro services 可以同時對數個資料庫送出「訊息」的模組叫 transfer 。而由於一些討論 micro services 的文章建議,如果 micro service 之間是做一對一的溝通適合用 RPC(remote procedure call) ,如果是 micro services 之間做一對多的溝通,則建議使用 message queue 。

於是,當我上回安裝過 rabbitMQ 之後,我就不自覺地去想,能不能用 rabbitMQ 來取代 transfer ? 如果用 rabbitMQ 來取代 transfer 之後,可以有什麼好處? 我在除錯 agent 的時候,常常需要做的一件事是,用 tcpdump 去看 RPC 裡傳輸的資料,透過這個動作才容易把錯誤的點加以定位。如果用了 rabbitMQ 的話,就可以有一個 web UI 介面,可以輕易地看到正在傳遞的「訊息」,而不需要 tcpdump 了。

常常嗆主管是資淺工程師的M大大聽完我的想法之後,終於按捺不住地來指導我了。他的指導主要有兩件事:
(1) 上述的需求是除錯(diagnostics)的問題。

既然如此,應該考慮從 log 的改進、或是自行設計更合用的 run time debug tool。引入一個有複雜功能 rabbitMQ 並不是用來解決「除錯」問題的好解法,更不是一種透過「改進系統的架構」來解決問題的解法。好的系統設計,確實可以減少錯誤。但是那個原因是在於「概念完整性conceptual integrity

註:Conceptual integrity is the quality of a system where all the concepts and their relationships with each other are applied in a consistent way throughout the system.

(2) 抽象化可以解決問題,例如修改的彈性、或是程式的簡潔,但是抽象化也要付出代價。

M大大說著就提到了他找工作時,被考官質問的許多問題。「我在找求職時,有時候會被一些考官問一些莫名其妙的問題。例如,『你的前公司為什麼不用XX技術?XX技術不是OO大公司在用嗎?』這是什麼鳥問題?問這類問題的面試官一整個很像外行人。」

流行的技術或是工具背後,總是有力推的廠商或是社群,這些推廣技術的人,永遠只會講技術有多好,功能有多強。然而,從系統設計者的角度,要考慮的問題則是 trade off 。工具的功能再強不是重點,重點是適不適合解決手上的問題,還有解決問題需要付出什麼代價。