㈠ 架構高可用高並發系統的設計原則
通過學習《億級流量網站架構核心技術》及《linux就該這么學》學習筆記及自己的感悟:架構設計之高可用高並發系統設計原則,架構設計包括墨菲定律、康威定律和二八定律三大定律,而系統設計包括高並發原則、高可用和業務設計原則等。
架構設計三大定律
墨菲定律 – 任何事沒有表面看起來那麼簡單 – 所有的事都會比預計的時間長 – 可能出錯的事情總會出錯 – 擔心某種事情發生,那麼它就更有可能發生
康威定律 – 系統架構師公司組織架構的反映 – 按照業務閉環進行系統拆分/組織架構劃分,實現閉環、高內聚、低耦合,減少溝通成本 – 如果溝通出現問題,應該考慮進行系統和組織架構的調整 – 適合時機進行系統拆分,不要一開始就吧系統、服務拆分拆的非常細,雖然閉環,但是每個人維護的系統多,維護成本高 – 微服務架構的理論基礎 – 康威定律https://yq.aliyun.com/articles/8611– 每個架構師都應該研究下康威定律http://36kr.com/p/5042735.html
二八定律 – 80%的結果取決於20%的原因
系統設計遵循的原則
1.高並發原則
無狀態
無狀態應用,便於水平擴展
有狀態配置可通過配置中心實現無狀態
實踐: Disconf、Yaconf、Zookpeer、Consul、Confd、Diamond、Xdiamond等
拆分
系統維度:按照系統功能、業務拆分,如購物車,結算,訂單等
功能維度:對系統功能在做細粒度拆分
讀寫維度:根據讀寫比例特徵拆分;讀多,可考慮多級緩存;寫多,可考慮分庫分表
AOP維度: 根據訪問特徵,按照AOP進行拆分,比如商品詳情頁可分為CDN、頁面渲染系統,CDN就是一個AOP系統
模塊維度:對整體代碼結構劃分Web、Service、DAO
服務化
服務化演進: 進程內服務-單機遠程服務-集群手動注冊服務-自動注冊和發現服務-服務的分組、隔離、路由-服務治理
考慮服務分組、隔離、限流、黑白名單、超時、重試機制、路由、故障補償等
實踐:利用Nginx、HaProxy、LVS等實現負載均衡,ZooKeeper、Consul等實現自動注冊和發現服
消息隊列
目的: 服務解耦(一對多消費)、非同步處理、流量削峰緩沖等
大流量緩沖: 犧牲強一致性,保證最終一致性(案例:庫存扣減,現在Redis中做扣減,記錄扣減日誌,通過後台進程將扣減日誌應用到DB)
數據校對: 解決非同步消息機制下消息丟失問題
數據異構
數據異構: 通過消息隊列機制接收數據變更,原子化存儲
數據閉環: 屏蔽多從數據來源,將數據異構存儲,形成閉環
緩存銀彈
用戶層:
DNS緩存
瀏覽器DNS緩存
操作系統DNS緩存
本地DNS服務商緩存
DNS伺服器緩存
客戶端緩存
瀏覽器緩存(Expires、Cache-Control、Last-Modified、Etag)
App客戶緩存(js/css/image…)
代理層:
CDN緩存(一般基於ATS、Varnish、Nginx、Squid等構建,邊緣節點-二級節點-中心節點-源站)
接入層:
Opcache: 緩存PHP的Opcodes
Proxy_cache: 代理緩存,可以存儲到/dev/shm或者SSD
FastCGI Cache
Nginx+Lua+Redis: 業務數據緩存
Nginx為例:
PHP為例:
應用層:
頁面靜態化
業務數據緩存(Redis/Memcached/本地文件等)
消息隊列
數據層:
Nosql: Redis、Memcache、SSDB等
MySQL: Innodb/MyISAM等Query Cache、Key Cache、Innodb Buffer Size等
系統層:
CPU : L1/L2/L3 Cache/NUMA
內存
磁碟:磁碟本身緩存、dirtyratio/dirtybackground_ratio、陣列卡本身緩存
並發化
2.高可用原則
降級
降級開關集中化管理:將開關配置信息推送到各個應用
可降級的多級讀服務:如服務調用降級為只讀本地緩存
開關前置化:如Nginx+lua(OpenResty)配置降級策略,引流流量;可基於此做灰度策略
業務降級:高並發下,保證核心功能,次要功能可由同步改為非同步策略或屏蔽功能
限流
目的: 防止惡意請求攻擊或超出系統峰值
實踐:
惡意請求流量只訪問到Cache
穿透後端應用的流量使用Nginx的limit處理
惡意IP使用Nginx Deny策略或者iptables拒絕
切流量
目的:屏蔽故障機器
實踐:
DNS: 更改域名解析入口,如DNSPOD可以添加備用IP,正常IP故障時,會自主切換到備用地址;生效實踐較慢
HttpDNS: 為了繞過運營商LocalDNS實現的精準流量調度
LVS/HaProxy/Nginx: 摘除故障節點
可回滾
發布版本失敗時可隨時快速回退到上一個穩定版本
3.業務設計原則
防重設計
冪等設計
流程定義
狀態與狀態機
後台系統操作可反饋
後台系統審批化
文檔注釋
備份
4.總結
先行規劃和設計時有必要的,要對現有問題有方案,對未來有預案;欠下的技術債,遲早都是要還的。
本文作者為網易高級運維工程師
㈡ 微服務架構實踐 - 你只懂docker與spring boot就夠了嗎
背景
隨著公司一年多的成長,我們已經開發了數十個項目了,後台有JAVA的有PHP的,為了更好地提升開發與管理效率,各技術大牛小牛們時常進行激烈的PK,碰撞出了許許多多愛的火花,比如其中之一:微服務實踐
設計
只需要有一套BASE微服務,BASE微服務生成業務系統微服務實例,供各個業務系統調用;業務系統不直接調用BASE,只能調用微服務INSTANCE。
這是運維的問題,讓運維去解決,運維使用工具,實際也不算困難,反正執行的都是腳本,不需要手工操作。
單點故障影響全局,我們選擇了穩定更重要;另外saas的話,為了應對不同行業,會存在過度設計的嫌疑;私有化更容易。
調用邏輯
設計理念
非模塊化,談不上微服務,比如我們上面的用戶微服務、產品微服務、地址微服務等,都需要先模塊化,為了更好地落實開發,你可能不得不,邊模塊化邊微服務,模塊化的時候要注意,不能有關聯查詢,包要完全獨立,到時候微服務才能拆開。
松耦合表示我們模塊之間不直接依賴,無狀態,可以單獨地為外界提供服務;
強內聚是指,我們雖然要拆分成一個個小的微服務,但是也要考慮某些功能的強關聯性,比如一個凳子是由四個腳與一個板組成,我們不能把四個腳與板分開售賣,就沒有意義了。
開發
spring-boot :較springmvc更加簡約了,springmvc有一大零的配置文件,比如spring-servlet、spring-mybatis、spring.xml與web.xml,這些在spring-boot都不需要了,只需要強大的註解功能即可,boot更合適微服務。
spring-cloud :裡面有比較多組件,用於支持微服務,比如spring cloud config統一配置中心,用於多環境的配置文件配置,大家再也不用為多個微服務的開發、測試與生產環境的配置文件管理而發愁了;spring cloud eureka用於服務注冊與發現,下面有單獨介紹;其它的組件大家可以去官網看看,這里不一一介紹,總之如果JAVA平台,盡量使用spring體系的內容。
我們採用mysql,因為我們是應用多,但數據量單表並不算大,多則不超過百萬,mongodb也實驗過,開發非常快,也非常靈活,但因為不是關系型資料庫,維護成本較高。
RESTFUL :URL的資源與操作解耦,讓URL更加符合語義,上百個介面也非常好管理,網上有很多文章講得非常透徹,這玩意不是特別好理解,要多領悟,在項目中實踐,就有矛塞盾開的感覺,這里不做詳細介紹。
介面文檔swagger :比起傳統全手工寫介面文檔,swagger有統一的輸出格式,不管是幾個人寫的;swagger採用寫代碼的方式來寫介面文檔,以前修改了代碼,還必須打開wiki手工修改介面文檔,現在只需要修改一下代碼即可,程序員更願意修改了,成本更低了,前端與其它調用者不會天天吼著,你這介面咋又變了,新加的欄位是啥意思呀。
RocketMQ:一直糾結kafka與rocketMQ,最終選擇了RocketMQ
為了性能上面的考慮,盡量使用非同步編程,比如注冊送優惠券,那麼注冊成功就可以給用戶返回注冊成功了,但是送優惠券可以是非同步調用的,不阻塞注冊的線程。
微服務框架下,日誌不可能還分散在各個服務節點上,必須有統一的日誌中心。ELK是一個實時日誌分析平台,就是將各個服務的日誌匯總於日誌中心,然後可以按照系統、節點等進行搜索,除上述搜索條件外,我們還在各個微服務實現了按照業務id(一次請求生成一個業務id)與用戶id搜索日誌,方便跟蹤與定位問題。
當然可能有更加輕量級與好用的disconf或spring cloud config,但是我們有php開發的應用,以上二者都不支持。如果全是JAVA應用,採用disconf還是非常不錯的。
測試
每個程序員都有這樣的經歷,剛上線,客戶又反饋了bug,原來是我們修改某個功能代碼的時候,導致了其它功能的bug,每次上線心裡都沒底;這就體現了介面測試的必須性,尤其是每次版本升級的時候,都需要執行一遍,以防修改某個介面導致其它介面報錯,比手動測試靠譜許多。
部署
docker已經家喻戶曉了,這是繼虛擬機以後,又一重大變革,將所有的單個微服務都放在docker中,這樣你何時何地想部署,直接丟過去就OK了,快到爆。
用幾句簡單的命令就搞定了負載均衡,而且還可以平滑升級,版本升級的時候,大家就不用告訴客戶:系統通知,某日某晚00:00-08:00我行處於系統升級維護中,大家不要去取錢哦,因為你可能取不出來,呵呵。
升級
我們採用工具flyway,可以對資料庫腳本進行版本控制。
傳統的版本升級,
1.開發推代碼並同時記錄自己提交了哪些文件;
2.項目經理根據svn審核文件,並打包成war包;
3.投到測試環境讓測試公司測試;
4.中途修改了文件,可能需要重新打包;
….
我都寫不下去了,項目經理像個超人似的。
現在用持續集成(CI)非常簡單,我們用的工具是Jenkins,推完代碼,點幾下按鈕就完成了上線,不管是測試環境,還是生產環境都非常簡單,不然項目經理核對文件眼睛都綠了。
結尾
本文主要是介紹微服務開發上的選型,對於細則不做深究,大家感興趣可以了解下各個組件。當然,我們的選型未免正確,不同場景應用可能完全不同,本文僅供參考。
㈢ disconf-web 可以不配置redis么
disconf-web 可以不配置redis
語句的功能是,若表達式x=y+5大於0則z=x。
下述語句是非法的:
if((x=y+5;)>0) z=x;
因為x=y+5;是語句,不能出現在表達式中。
4.3 數據輸入輸出的概念及在C語言中的實現
1) 所謂輸入輸出是以計算機為主體而言的。
2) 本章介紹的是向標准輸出設備顯示器輸出數據的語句。
3) 在C語言中,所有的數據輸入/輸出都是由庫函數完成的。 因此都是函數語句。
4) 在使用C語言庫函數時,要用預編譯命令
#include
將有關「頭文件」包括到源文件中。
㈣ disconf相關問題總結-結合issue,官方文檔
對於Web系統:
要實現統一讀取,可以使用ThreadContext+AOP來實現。
ThreadContext的使用方式有以下幾種:
解決方法一 :提供ThreadContext包,在每次請求一開始時都復制系統里的所有配置緩存(復制過程要與配置更新Sync互斥),從而保證每次會話的數據的一致性。
解決方法二 :提供ThreadContext包,每次請求都綁定一個版本號,如果讀取時版本號不一致則報錯,需要重新請求。
解決方法三 :方法二的加強版,添加一個註解定義,標注它是需要強一制性的,每次會話讀取時只復制這些強一制性配置(復制過程要與配置更新Sync互斥)。
解決方法四 :提供ThreadContext包,系統內保存有多個配置緩存層,讀取時統一讀取某個版本的緩存。每當配置更新時,緩存層增加。
第一種方法,代價太大。第二種方法,嚴重增加用戶負擔,第三種還是需要用戶關心這個事情。我們將採用 第四種方法 。
對於非Web項目:
比較難解決非一致性讀取的問題。因為它沒有了會話這樣一個概念。Apache的FileChangedReloadingStrategy Reload配置文件的方案也沒有解決此問題。所以,我們打算放棄這方面的解決。但是,我們還是會提供一個簡單卻Ugly的解決方案: 提供函數來標識用戶讀取配置的邊界 。用戶可以放棄使用這個方案,但是我們不保證不會發生「不一致讀』問題。
服務啟動前,zk連接上了:
注意
ZK一般需要以集群的形式提供出來。假設有N台ZK,
** * disconf-client的ZK異常處理
disconf-client可以完全保證: 如果在啟動程序時保證ZK集群是可用的 ,那麼,就可以保證在任何情況下,與ZK集群的自動連接。
下面按情況進行分析:
程序啟動前,zk連接不上
這時disconf-client無法在ZK上注冊信息。這是必須禁止發生的情況。也是disconf-client無法支持的情況。
一旦發生這種情況,請先恢復ZK集群,再啟動你的程序。
程序啟動前,zk連接上了:
如果在程序啟動過程中,ZK是正常的,那麼,disconf-client可以保證與ZK連接的自動性。
注意
disconf-client必須保證在程序在啟動時,ZK集群的可用性。
㈤ disconf zk部署情況為空怎麼回事
查看disconf日誌,發現zk沒有啟動。
實際情況是:zk已經啟動,可以使用zkServer.sh status命令進行查看。
那麼問題就明確了,disconf沒有關聯上zk。
經過排查,發現在disconf部署目錄之下,有一個zk的jar,且版本號和實際使用的版本號不一致。因此,zk才沒法連接到disconf,導致最終的zk部署情況為空。
解決辦法比較簡單:讓這個zk的jar和實際使用的zk版本保持一致就OK了。
詳細步驟如下:
①在POM.xml中重新改動zk依賴的版本號(改為實際使用的zk版本),重新編譯。
②將disconf-web部署目錄下的zoo.properties中的hosts改為要啟動的zk的client埠號,本機為127.0.0.1:2181。【重要】
經過上述步驟,重新啟動zk,發現disconf日誌中顯示zk已經能夠正確連接。
㈥ Spring Cloud全家桶主要組件及簡要介紹
一、微服務簡介
微服務是最近的一兩年的時間里是很火的一個概念。感覺不學習一下都快跟不上時代的步伐了,下邊做一下簡單的總結和介紹。
何為微服務?簡而言之,微服務架構風格這種開發方法,是以開發一組小型服務的方式來開發一個獨立的應用系統的。其中每個小型服務都運行在自己的進程中,並經常採用HTTP資源API這樣輕量的機制來相互通信。這些服務圍繞業務功能進行構建,並能通過全自動的部署機制來進行獨立部署。這些微服務可以使用不同的語言來編寫,並且可以使用不同的數據存儲技術。對這些微服務我們僅做最低限度的集中管理。
一個微服務一般完成某個特定的功能,比如下單管理、客戶管理等等。每一個微服務都是微型六角形應用,都有自己的業務邏輯和適配器。一些微服務還會發布API給其它微服務和應用客戶端使用。其它微服務完成一個Web UI,運行時,每一個實例可能是一個雲VM或者是Docker容器。
比如,一個前面描述系統可能的分解如下:
總的來說,微服務的主旨是將一個原本獨立的系統拆分成多個小型服務,這些小型服務都在各自獨立的進程中運行,服務之間通過基於HTTP的RESTful API進行通信協作,並且每個服務都維護著自身的數據存儲、業務開發、自動化測試以及獨立部署機制。
二、微服務的特徵
1、每個微服務可獨立運行在自己的進程里;
2、一系列獨立運行的微服務共同構建起了整個系統;
3、每個服務為獨立的業務開發,一個微服務一般完成某個特定的功能,比如:訂單管理、用戶管理等;
4、微服務之間通過一些輕量的通信機制進行通信,例如通過REST API或者RPC的方式進行調用。
三、微服務的優缺點
1、易於開發和維護
2、啟動較快
3、局部修改容易部署
4、技術棧不受限
5、按需伸縮
6、DevOps
四、常見微服務框架
1、服務治理框架
(1)Dubbo、Dubbox(當當網對Dubbo的擴展)
最近的好消息是Dubbo已近重新開始進行運維啦!
(2)Netflix的Eureka、Apache的Consul等。
Spring Cloud Eureka是對Netflix的Eureka的進一步封裝。
2、分布式配置管理
(1)網路的Disconf
(2)360的QConf
(3)Spring Cloud組件中的Config
(3)淘寶的Diamond
3、批量任務框架
(1)Spring Cloud組件中的Task
(2)LTS
4、服務追蹤框架
。。。
五、Spring Cloud全家桶組件
在介紹Spring Cloud 全家桶之前,首先要介紹一下Netflix ,Netflix 是一個很偉大的公司,在Spring Cloud項目中占著重要的作用,Netflix 公司提供了包括Eureka、Hystrix、Zuul、Archaius等在內的很多組件,在微服務架構中至關重要,Spring在Netflix 的基礎上,封裝了一系列的組件,命名為:Spring Cloud Eureka、Spring Cloud Hystrix、Spring Cloud Zuul等,下邊對各個組件進行分別得介紹:
(1)Spring Cloud Eureka
我們使用微服務,微服務的本質還是各種API介面的調用,那麼我們怎麼產生這些介面、產生了這些介面之後如何進行調用那?如何進行管理哪?
答案就是Spring Cloud Eureka,我們可以將自己定義的API 介面注冊到Spring Cloud Eureka上,Eureka負責服務的注冊於發現,如果學習過Zookeeper的話,就可以很好的理解,Eureka的角色和 Zookeeper的角色差不多,都是服務的注冊和發現,構成Eureka體系的包括:服務注冊中心、服務提供者、服務消費者。
1、兩台Eureka服務注冊中心構成的服務注冊中心的主從復制集群;
2、然後服務提供者向注冊中心進行注冊、續約、下線服務等;
3、服務消費者向Eureka注冊中心拉去服務列表並維護在本地(這也是客戶端發現模式的機制體現!);
4、然後服務消費者根據從Eureka服務注冊中心獲取的服務列表選取一個服務提供者進行消費服務。
(2)Spring Cloud Ribbon
在上Spring Cloud Eureka描述了服務如何進行注冊,注冊到哪裡,服務消費者如何獲取服務生產者的服務信息,但是Eureka只是維護了服務生產者、注冊中心、服務消費者三者之間的關系,真正的服務消費者調用服務生產者提供的數據是通過Spring Cloud Ribbon來實現的。
在(1)中提到了服務消費者是將服務從注冊中心獲取服務生產者的服務列表並維護在本地的,這種客戶端發現模式的方式是服務消費者選擇合適的節點進行訪問服務生產者提供的數據,這種選擇合適節點的過程就是Spring Cloud Ribbon完成的。
Spring Cloud Ribbon客戶端負載均衡器由此而來。
(3)Spring Cloud Feign
上述(1)、(2)中我們已經使用最簡單的方式實現了服務的注冊發現和服務的調用操作,如果具體的使用Ribbon調用服務的話,你就可以感受到使用Ribbon的方式還是有一些復雜,因此Spring Cloud Feign應運而生。
簡單的可以理解為:Spring Cloud Feign 的出現使得Eureka和Ribbon的使用更為簡單。
(4)Spring Cloud Hystrix
我們在(1)、(2)、(3)中知道了使用Eureka進行服務的注冊和發現,使用Ribbon實現服務的負載均衡調用,還知道了使用Feign可以簡化我們的編碼。但是,這些還不足以實現一個高可用的微服務架構。
例如:當有一個服務出現了故障,而服務的調用方不知道服務出現故障,若此時調用放的請求不斷的增加,最後就會等待出現故障的依賴方 相應形成任務的積壓,最終導致自身服務的癱瘓。
Spring Cloud Hystrix正是為了解決這種情況的,防止對某一故障服務持續進行訪問。Hystrix的含義是:斷路器,斷路器本身是一種開關裝置,用於我們家庭的電路保護,防止電流的過載,當線路中有電器發生短路的時候,斷路器能夠及時切換故障的電器,防止發生過載、發熱甚至起火等嚴重後果。
(5)Spring Cloud Config
對於微服務還不是很多的時候,各種服務的配置管理起來還相對簡單,但是當成百上千的微服務節點起來的時候,服務配置的管理變得會復雜起來。
分布式系統中,由於服務數量巨多,為了方便服務配置文件統一管理,實時更新,所以需要分布式配置中心組件。在Spring Cloud中,有分布式配置中心組件Spring Cloud Config ,它支持配置服務放在配置服務的內存中(即本地),也支持放在遠程Git倉庫中。在Cpring Cloud Config 組件中,分兩個角色,一是Config Server,二是Config Client。
Config Server用於配置屬性的存儲,存儲的位置可以為Git倉庫、SVN倉庫、本地文件等,Config Client用於服務屬性的讀取。
(6)Spring Cloud Zuul
我們使用Spring Cloud Netflix中的Eureka實現了服務注冊中心以及服務注冊與發現;而服務間通過Ribbon或Feign實現服務的消費以及均衡負載;通過Spring Cloud Config實現了應用多環境的外部化配置以及版本管理。為了使得服務集群更為健壯,使用Hystrix的融斷機制來避免在微服務架構中個別服務出現異常時引起的故障蔓延。
先來說說這樣架構需要做的一些事兒以及存在的不足:
1、首先,破壞了服務無狀態特點。為了保證對外服務的安全性,我們需要實現對服務訪問的許可權控制,而開放服務的許可權控制機制將會貫穿並污染整個開放服務的業務邏輯,這會帶來的最直接問題是,破壞了服務集群中REST API無狀態的特點。從具體開發和測試的角度來說,在工作中除了要考慮實際的業務邏輯之外,還需要額外可續對介面訪問的控制處理。
2、其次,無法直接復用既有介面。當我們需要對一個即有的集群內訪問介面,實現外部服務訪問時,我們不得不通過在原有介面上增加校驗邏輯,或增加一個代理調用來實現許可權控制,無法直接復用原有的介面。
面對類似上面的問題,我們要如何解決呢?下面進入本文的正題:服務網關!
為了解決上面這些問題,我們需要將許可權控制這樣的東西從我們的服務單元中抽離出去,而最適合這些邏輯的地方就是處於對外訪問最前端的地方,我們需要一個更強大一些的均衡負載器,它就是本文將來介紹的:服務網關。
服務網關是微服務架構中一個不可或缺的部分。通過服務網關統一向外系統提供REST API的過程中,除了具備服務路由、均衡負載功能之外,它還具備了許可權控制等功能。Spring Cloud Netflix中的Zuul就擔任了這樣的一個角色,為微服務架構提供了前門保護的作用,同時將許可權控制這些較重的非業務邏輯內容遷移到服務路由層面,使得服務集群主體能夠具備更高的可復用性和可測試性。
(7)Spring Cloud Bus
在(5)Spring Cloud Config中,我們知道的配置文件可以通過Config Server存儲到Git等地方,通過Config Client進行讀取,但是我們的配置文件不可能是一直不變的,當我們的配置文件放生變化的時候如何進行更新哪?
一種最簡單的方式重新一下Config Client進行重新獲取,但Spring Cloud絕對不會讓你這樣做的,Spring Cloud Bus正是提供一種操作使得我們在不關閉服務的情況下更新我們的配置。
Spring Cloud Bus官方意義:消息匯流排。
當然動態更新服務配置只是消息匯流排的一個用處,還有很多其他用處。
六、總結
Spring Cloud 的組件還不止這些,通過上邊的口水話的介紹,應該可以大致有一定的了解,但是每一個組件的功能遠不止上述介紹的那些,每一個組件還有很多其他的功能點,這里的介紹希望能夠帶大家入個門,不要對微服務這個這么大的概念有所畏懼。