軟件架構

何謂架構

 

前言:在這個知識分享的爆炸時代,鑑於java生態的完整和繁榮,各類框架、中間件和工具包供咱們使用。連新培訓出來的人都知道ssm,微服務、集羣、多線程、隊列、高併發等技術,技術的間隔性正變得愈來愈小,彷彿咱們只須要循序漸進的去使用別人說的框架等技術就能夠解決問題.若是刨除redis、rabbitmq、kafka、dubbo、springcloud這些具體的技術框架,你有沒有靜下心來真正思考過架構是什麼呢?這些框架是到底是扮演怎麼樣的角色?若是讓你給架構下一個定義,你會選擇如何去描述架構呢?html

背景: 從業快4年.我記得在我剛從業的時候,當時流行的框架是spring、struts二、hibernate,前端使用的是jsp,業務也不是那麼複雜,整個項目併發量並不大,QPS都不會超過5,當時的作法全部的前端和後端放在一塊兒部署,打成war包直接部署到centos上的tomcat上就能夠運行了,這樣徹底能夠承載實際生產環境的請求量,問題也不大。後來當我換了一家公司,公司採用dubbo微服務化,全部的業務均被劃分紅了一個個服務來提供給接口調用,當時的業務場景也比之前的複雜,採用23臺服務器分開部署,容納的線上負載大概在幾百萬左右.服務進行修改邏輯不再用像之前那麼麻煩須要把整個項目從新打包再部署了.以後就在微服務的路上走的更遠了,全部的服務獨立部署,打包成鏡像文件成爲docker實例,獨立部署在docker的服務器上,結合git,部署、運維、開發的效率獲得了迅速提高前端

目錄 java

一:架構究竟是什麼nginx

二:經常使用的架構技術git

三:安全性問題web

四:  架構設計的誤區redis

五:總結算法

 

一:架構究竟是什麼spring

架構究竟是什麼?首先來看一下維基百科對架構的解釋:sql

軟件架構:是一個系統的草圖。軟件架構描述的對象是直接構成系統的抽象組件。各個組件之間的鏈接則明確和相對細緻地描述組件之間的通信。在實現階段,這些抽象組件被細化爲實際的組件,好比具體某個類或者對像。

軟件架構師:軟件架構師定義和設計軟件的模塊化,模塊之間的交互,用戶界面風格,對外接口方法,創新的設計特性,以及高層事物的對象操做、邏輯和流程

 按照維基百科的解釋:軟件架構實則是各個組件的互相搭配和組件之間的相互配合,是抽象的高層事務的的邏輯流程。簡單來講架構就是各個系統組件如何通信、協調、以及控制操做的邏輯。能夠類比人體的結構來舉個簡單的例子來理解就是:人體是由心肝脾肺胃、耳鼻嘴等多個重要器官組成,各個器官各司其職,它們之間相互配合共同維持人的正常生活。這裏的心、胃等就是整我的體架構的組件,血液就是數據,血管就是傳輸數據的媒介,人的皮膚和長相就是用戶的界面風格,邏輯組織就是食物要首先進入胃去消化而後纔會進入大腸,而不是進入腎臟。按照這個解釋,咱們使用的kafka、redis、ssm、rabbitmq、xxljob等都是組件,這些組件各有各的做用,各自承擔本身的責任去共同完成整個系統的高效流轉.

二:經常使用的架構技術

2.1:分佈式

   分佈式:將同一套業務代碼按照業務功能或者自定義的維度拆分不一樣的子系統,各個系統分開部署,每一個子系統叫作服務,每一個服務之間通常經過rpc或者webservice來調用

2.1.1: 分佈式的優勢

分佈式的好處就是解耦了原系統,從而便於運維部署和水平擴展,提供軟件的伸縮性,甚至服務能夠經過不一樣的語言來實現.各個模塊交給不一樣的人員去開發,每一個人各司其職,出現問題也能夠快速定位

2.1.1:分佈式的缺點

分佈式也並非毫完好點的,存在如下的問題:

:服務調用經過網絡來調用,通常微服務之間使用rpc來調用的,而rpc的底層就是TCP協議,若是網絡故障或者延遲高一點,那麼服務調用就有出現超時的可能性,好比dubbo的話會出現RpcException

:分佈式在業務體量比較小或者粒度劃分的狀況下就是一種災難式開發,開發和運維的成本都會直線上升

:分佈式的數據一致性和事務比較難以保障,業務目前使用最多的是兩階段提交2pc,須要本地事務和遠程事務綜合提交,性能比較差

:分佈式session的維護在單體工程中是不須要考慮session的安全性的,而在分佈式環境中就必須考慮如何去維護session的一致

⑤:分佈式事務問題:分佈式下如何保證各個服務的數據一致性也是一種挑戰,當程序出現異常崩潰的時候可以保證各個服務可以正常回滾是很重要的。

分佈式最多見的技術:分佈式緩存、分佈式存儲、分佈式計算、分佈式靜態資源

2.2:集羣

  集羣:同一套代碼部署在多個服務器上,而多個服務器能夠提供更多的cpu、內存、硬盤等資源,從而提高整理的處理請求能力。集羣的每一個服務器叫作節點,每一個節點提供的是相同的服務,節點的關係只是一種簡單的複製,具體是哪一個節點處理,則是根據負載均衡策略來決定;在網站的處理能力出現下滑的時候,簡單的在集羣中增長服務器臺數就能夠顯著增長總體的數據量處理能力(不過存在上限);

 原理很簡單:所謂衆人拾柴火焰高,多臺服務器一塊兒聚合處理數據量和併發訪問的能力確定比單臺服務器要高不少;在遇到請求處理的瓶頸時候,能夠經過簡單的增長服務器臺數來提升並行處理的能力,不過須要注意的是增長服務器臺數在出現大於某個數量以後性能會停滯不前。

 

 

2.3:緩存

  緩存是提升軟件的性能第一手段,最有效和最具表明性的方法,緩存分爲單機緩存和分佈式緩存。最多見的分佈式緩存技術爲redis、memorycache等,單機緩存好比hashmap、concurrentHashmap、guava等單機緩存的承載容量有限,而分佈式緩存的伸縮性和的存儲容量會比較可觀,就算緩存的空間不足了,也能夠經過增長服務器來擴展。

緩存最顯著的做用有兩個:①加快數據的訪問速度②分擔後端的數據訪問和存儲的負載能力,保護數據庫

使用緩存須要注意如下幾點:

①:緩存雪崩

緩存雪崩指的是全部的緩存在統一時間所有失效,致使大量的請求直接涌入數據庫,數據庫被擊垮。

解決緩存雪崩的方法:緩存過時值在必定的基礎上設置隨機值

②:緩存擊穿

  緩存擊穿是指某些熱點key在某一時間所有失效了,致使大量的請求涌入後臺DB數據庫

解決緩存擊穿的方法:熱點數據設置永不過時

③:緩存穿透

  一直請求不存在的數據,最終走的仍是數據庫就是緩存穿透

解決緩存穿透的方法:採用布隆過濾器(bloomFilter),布隆過濾會有必定的偏差,可是能夠曬選出必定不存在的數據,缺點是沒法斷定某個key是否肯定存在。

 2.4:隊列

   試想這樣一個的高請求量場景:各大電商的雙11,在雙11的那一刻,有大量訂單涌入,後端會接受請求,而後寫入數據庫,等待數據庫的返回.若是請求量很是大的話,數據庫讀寫IO就會阻塞,那麼程序就會出現卡死,數據庫崩潰等問題

若是採用隊列的話,將下單請求發送到隊列中,而後馬上返回(能夠按照業務決定,好比返回處理中,等到真正成功再通知用戶),這樣就不須要等待後端必須返回成功。消費端能夠按照請求的順序平滑的去消費,緩解了高峯的請求,而且實現了請求下單和實現下單的解耦從如下圖能夠看出使用隊列之後處理起來比較平滑~

 2.5:多線程 

    多線程真正的意義有兩個①提升cpu的利用率  ②:加快程序執行效率,目前已是多核的時代,服務器六核、八核家常便飯,在多核的cpu中若是使用單線程那麼無疑是對多核cpu的浪費,多線程可以有效提升cpu利用的效率,多個任務分給多個cpu去處理,能夠實現真正的並行處理。若是在單核cpu中,只是cpu在不停的切換cpu時間。假設咱們有十個表格的數據須要分析處理(計算密集型),採用單線程須要一個個的輪詢表格,而多線程在合理分配線程數的狀況下就能夠同時處理,提升開發的效率

  2.6:限流

    限流是面對高併發的利器之一,例如秒殺場景:在大量的請求涌入後臺,QPS高達幾十萬,若是不能作到有效控制就可能致使請求擊垮數據庫,DB基本上是一個網站的命脈。緩存、隊列、限流等方式的本質其實都是爲了保護DB。限流的簡單理解其實就是過濾掉無效的請求,將請求限制在一個能夠控制的範圍內,最多見的限流有如下方式: 

 ①: Redis限流

  Redis限流的基本思路是採用redis的key過時策略,將業務id和業務值放入到redis中設置必定的過時時間,等請求再次進入的時候,若是能從redis獲取到值,那麼我就由於是重複性請求。Redis過濾限流是最基礎的限流手段,適用於過濾同一個用戶請求的場景

②:令牌桶算法

令牌桶算法的思路是在必定的時間內生成以固定的速度生成有限個令牌數量放入桶中,全部的請求首先從令牌桶中去嘗試獲取令牌,若是能獲取到就能夠繼續執行,不然請求就會被拋棄。Google開源的guava中有RateLimter能夠實現單機限流,令牌桶算法是限流很是有效的手段,

③:  漏桶算法

漏桶算法的基本原理是將請求直接存放在一個漏斗中,請求過多的話,那麼就會漏斗就會溢出,溢出的請求則會被拒絕服務。漏桶算法能夠控制端口的流量輸出速率,平滑請求的突發流量,實現流量整形.

由於漏桶算法的漏出速率是有效的,所以漏桶算法相比於令牌桶算法有一個顯著的缺點是沒法應對突發性的流量.可令牌桶算法是能夠的

④:  滑動窗口

http爲了控制流量的速率採用的方法就是滑動窗口機制。若是要分佈式限流,可採用阿里的Sentinel框架,其基本原理是滑動窗口機制,利用Entry映射資源來平滑的限流

   此外還有nginx限流,好比使用參數來限制某一個ip的在時間範圍內的訪問頻率。客戶端限流:發起請求按鈕點擊後,在後面的幾秒內(由業務決定)設置爲disabled,這一操做步驟雖然很小,可是帶來的限流做用很可觀

2.7:服務降級和熔斷

    不少人會忽視這個問題,對本身設計出來的架構盲目自信,認爲不可能出問題。而事實上,一旦隨着微服務和分佈式架構的持續推動,服務器會愈來愈多,宕機的機率和可能性會逐步提高,雖然出現宕機的可能性基本上很渺茫,不過也應該作好服務降級和熔斷的準備,以防止那萬分之一的機率宕機。假設有1000臺服務器發生宕機的機率是0.001%,就由於存在0.001%的機率會致使咱們的服務並不是100%高可用。

服務的降級和熔斷通常採用的是netfly(沒錯,就是那個美劇巨頭公司)出的hystrix,能夠實現服務熔斷和降級

三:安全性問題

   安全性的問題老是不被重視,其實安全的問題要比咱們想像的要嚴重的多.大公司每時每刻都會有不一樣程度被攻擊者發起攻擊,一旦被黑客獲取到數據庫信息,那麼將會有丟失用戶信息、服務器被植入木馬病毒、服務癱瘓等不容小覷的危險

3.1  sql注入

sql注入是目前全部方式中最頻繁也是最嚴重的攻擊手段,sql注入若是被居心叵測的黑客攻擊極可能整個數據庫都會被刪除掉,其情節和結果十分惡劣。防止sql注入的有效方式就是
採用jdbc提供的preparementStatement進行預編譯,它能有效保證sql的總體結構不會被破壞,萬一被sql攻擊也能夠在預編譯階段失敗,而不會執行成功

3.2 跨域攻擊 

 與主站的域名、端口、協議不一致性的請求均可以理解爲跨域訪問,瀏覽器有同源策略:瀏覽器會限制來自於不一樣源的documet和腳本對當前的document讀取或設置部分屬性,可是好比src\form表單提交\< img >\< iframe >\< link >是沒有跨域限制的。

csrf攻擊:登錄網站A,獲取到了網站A的cookie用戶信息,而後點擊了一個惡意網站外鏈B,網站B能夠利用csrf漏洞模擬A網站的用戶信息去請求A的某些敏感接口,好比轉帳、發送消息、郵件、獲取部分信息、發起惡意代碼等。

如何防止csrf攻擊:①接口請求加上隨機的token值或者token約束的規則,或者是有時效性的token碼。這樣的話,外鏈去訪問接口在攔截器中驗證token是否有效,②在http的頭部加入自定義參數:放到 HTTP 頭中自定義的屬性裏。經過 Ajax,能夠一次性給全部該類請求加上 csrftoken 這個 HTTP 頭屬性,並把 token 值放入其中

③減小使用get提交,get提交會下降門檻

3.3:XSS攻擊

   xss攻擊指的是攻擊者對包含有漏洞的服務器注入js代碼,會誘使受害者打開攻擊的服務器URL,其中裏面的URL會包含一些惡意代碼,好比植入病毒、添加廣告片斷代碼、篡改接口信息等。

預防xss攻擊的方法:對於用戶提交的內容,須要過濾任何有執行能力的腳本或者影響頁面的CSS,

 四:  架構設計的誤區

 4.1:爲了高大上而設計出複雜的架構

試想若是在業務體量不是特色大的狀況下,若是一味的追求時髦,追求新穎,採用分佈式微服務架構,那麼將會增長業務開發的難度,爲了維護大量的微服務而多出不少成本。好的架構必定是適應於自身的業務發展的,而高於業務的,它具備順應業務發展的前瞻性。

4.3:用技術能夠解決一切問題

   企圖用技術解決一切問題,認爲技術是一切的解決之道,是萬能的,其實有的時候技術解決不了的問題能夠用從業務角度來考慮解決。好比以前樓主作個售票系統,主要是賣某個知名景點的票的業務。後期上線後發現不少人買了不少特價免費票,特價票是針對導遊帶領的團員的,每一個導遊天天只能買一張特價免費票和一張半價票,以後看數據發現了不少導遊配了兩張票,而後那張半價票被退掉,只剩下一張免費票被刷了。技術總監就決定查這部分數據是怎麼回事?結果發現部分人利用導遊證這個特惠故意購買無價票,這個問題如何從技術上解決呢?若是不容許導遊買特惠票不合理,不容許退票也不合理。技術上貌似沒有好的手段去杜絕這個問題,只能從線下去處理。

五:總結

    本篇文章的主要概略圖我總結了一下,大概以下,其中包括分佈式、集羣、緩存、微服務、隊列等。架構的話題彌足長遠和複雜,不是一篇簡單的文章能描述清楚的。若是要講明白,估計得寫個連載了。本篇文章只是提綱挈領如下,說實話也是走馬觀花,但願能起到拋磚引玉的效果,不過在工做中思考、在實踐中總結學習,是有助於提升咱們的內功心法的。

相關文章
相關標籤/搜索