樂優、青橙商城相關技術總結
文章目錄
SSM
SSM(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis兩個開源框架整合而成(SpringMVC是Spring中的部分內容)。常作爲數據源較簡單的web項目的框架。
Spring
Spring就像是整個項目中裝配 bean
的大工廠,在配置文件中可以指定使用特定的參數去調用實體類的構造方法來實例化對象。也可以稱之爲項目中的粘合劑。
Spring的核心思想是IoC(控制反轉),即不再需要程序員去顯式地 new
一個對象,而是讓Spring框架幫你來完成這一切。
SpringMVC
SpringMVC在項目中攔截用戶請求,它的核心Servlet即DispatcherServlet承擔中介或是前臺這樣的職責,將用戶請求通過HandlerMapping去匹配Controller,Controller就是具體對應請求所執行的操作。SpringMVC相當於SSH框架中struts。
mybatis
mybatis是對jdbc的封裝,它讓數據庫底層操作變的透明。mybatis的操作都是圍繞一個sqlSessionFactory實例展開的。mybatis通過配置文件關聯到各實體類的Mapper文件,Mapper文件中配置了每個類對數據庫所需進行的sql語句映射。在每次與數據庫交互時,通過sqlSessionFactory拿到一個sqlSession,再執行sql命令。
頁面發送請求給控制器,控制器調用業務層處理邏輯,業務層向持久層發送請求,持久層與數據庫交互,後將結果返回給業務層,業務層將處理邏輯發送給控制器,控制器再調用視圖展現數據。
通用Mapper
通用 Mapper 是一個可以實現任意 MyBatis 通用方法的框架,項目提供了常規的增 刪改查操作以及Example相關的單表操作。爲什麼要用通用mapper?我們這裏列舉一下 原生Mybatis的痛點:
- mapper.xml文件裏有大量的sql,當數據庫表字段變動,配置文件就要修改
- 需要自己實現sql分頁,select * from table where . . . limit 1,3 自己手寫分頁,除了傳參page、pageSize,還需要返回條目總數count。
- 數據庫可移植性差:如果項目更換數據庫,比如oracle–>mysql,mapper.xml中的 sql要重新寫,因爲Oracle的PLSQL 和mysql 支持的函數是不同的。
- 生成的代碼量過大。
- 批量操作,批量插入,批量更新,需要自寫。
而這些,通過通用mapper就可以很輕鬆的解決了。
在線官方文檔:https://gitee.com/free/Mapper/wikis/Home
官方的文檔中介紹了通用mapper的三種使用方式 :純java使用方式、與Spring集成式、與SpringBoot集成方式。
zookeeper
ZooKeeper是一個分佈式的,開放源碼的分佈式應用程序協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件。它是一個爲分佈式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分佈式同步、組服務等。
ZooKeeper的基本運轉流程:
- 選舉Leader。
- 同步數據。
- 選舉Leader過程中算法有很多,但要達到的選舉標準是一致的。
- Leader要具有最高的執行ID,類似root權限。
- 集羣中大多數的機器得到響應並接受選出的Leader。
相關詳細介紹:
ElementUI
Element,一套爲開發者、設計師和產品經理準備的基於 Vue 2.0 的組件庫,提供了配套設計資源,幫助你的網站快速成型。由餓了麼公司前端團隊開源。
特性:
-
一致性 Consistency
- 與現實生活一致:與現實生活的流程、邏輯保持一致,遵循用戶習慣的語言和概念;
- 在界面中一致:所有的元素和結構需保持一致,比如:設計樣式、圖標和文本、元素的位置等。
-
反饋 Feedback
- 控制反饋:通過界面樣式和交互動效讓用戶可以清晰的感知自己的操作;
- 頁面反饋:操作後,通過頁面元素的變化清晰地展現當前狀態。
-
效率 Efficiency
- 簡化流程:設計簡潔直觀的操作流程;
- 清晰明確:語言表達清晰且表意明確,讓用戶快速理解進而作出決策;
- 幫助用戶識別:界面簡單直白,讓用戶快速識別而非回憶,減少用戶記憶負擔。
-
可控 Controllability
- 用戶決策:根據場景可給予用戶操作建議或安全提示,但不能代替用戶進行決策;
- 結果可控:用戶可以自由的進行操作,包括撤銷、回退和終止當前操作等。
安裝指南、使用組件請訪問官方網站:https://element.eleme.cn/#/zh-CN
ES6
ECMAScript 6(簡稱ES6)是於2015年6月正式發佈的JavaScript語言的標準,正式名爲ECMAScript 2015(ES2015)。它的目標是使得JavaScript語言可以用來編寫複雜的大型應用程序,成爲企業級開發語言 。
另外,一些情況下ES6也泛指ES2015及之後的新增特性,雖然之後的版本應當稱爲ES7、ES8等。
編程語言JavaScript是ECMAScript的實現和擴展 。ECMAScript是由ECMA(一個類似W3C的標準組織)參與進行標準化的語法規範。ECMAScript定義了:
- 語言語法 – 語法解析規則、關鍵字、語句、聲明、運算符等。
- 類型 – 布爾型、數字、字符串、對象等。
- 原型和繼承。
- 內建對象和函數的標準庫 – JSON、Math、數組方法、對象自省方法等。
ECMAScript標準不定義HTML或CSS的相關功能,也不定義類似DOM(文檔對象模型)的Web API,這些都在獨立的標準中進行定義。ECMAScript涵蓋了各種環境中JS的使用場景,無論是瀏覽器環境還是類似node.js的非瀏覽器環境。
ECMAScript標準的歷史版本分別是1、2、3、5。
那麼爲什麼沒有第4版?其實,在過去確實曾計劃發佈提出巨量新特性的第4版,但最終卻因想法太過激進而慘遭廢除(這一版標準中曾經有一個極其複雜的支持泛型和類型推斷的內建靜態類型系統)。
ES4飽受爭議,當標準委員會最終停止開發ES4時,其成員同意發佈一個相對謙和的ES5版本,隨後繼續制定一些更具實質性的新特性。這一明確的協商協議最終命名爲“Harmony”,因此,ES5規範中包含這樣兩句話:
ECMAScript是一門充滿活力的語言,並在不斷進化中。
未來版本的規範中將持續進行重要的技術改進。
另外,一些情況下ES6也泛指ES2015及之後的新增特性,雖然之後的版本應當稱爲ES7、ES8等。
編程語言JavaScript是ECMAScript的實現和擴展 。ECMAScript是由ECMA(一個類似W3C的標準組織)參與進行標準化的語法規範。ECMAScript定義了:
語言語法 – 語法解析規則、關鍵字、語句、聲明、運算符等。
2009年發佈的改進版本ES5,引入了Object.create()、Object.defineProperty()、getters和setters、嚴格模式以及JSON對象。
ECMAScript 6.0(以下簡稱ES6)是JavaScript語言的下一代標準,2015年6月正式發佈。它的目標,是使得JavaScript語言可以用來編寫複雜的大型應用程序,成爲企業級開發語言。
OSS
阿里雲對象存儲服務(Object Storage Service,簡稱OSS)爲您提供基於網絡的數據存取服務。使用OSS,您可以通過網絡隨時存儲和調用包括文本、圖片、音頻和視頻等在內的各種非結構化數據文件。
阿里雲OSS將數據文件以對象(object)的形式上傳到存儲空間(bucket)中。
您可以進行以下操作:
- 創建一個或者多個存儲空間,向每個存儲空間中添加一個或多個文件。
- 通過獲取已上傳文件的地址進行文件的分享和下載。
- 通過修改存儲空間或文件的屬性或元信息來設置相應的訪問權限。
- 在阿里雲管理控制檯執行基本和高級OSS任務。
- 使用阿里雲開發工具包或直接在應用程序中進行RESTful API調用執行基本和高級OSS任務。
阿里雲OSS:https://www.aliyun.com/product/oss/
OSS API文檔:http://doc.oss.aliyuncs.com/
Vue
認識Vue之前,先聊一下前端開發模式的發展。
靜態頁面
最初的網頁以HTML爲主,是純靜態的網頁。網頁是隻讀的,信息流只能從服務端到客戶端單向流通。開發人員也只關心頁面的樣式和內容即可。
異步刷新,操作DOM
1995年,網景工程師Brendan Eich 花了10天時間設計了JavaScript語言.
隨着JavaScript的誕生,我們可以操作頁面的DOM元素及樣式,頁面有了一些動態的效果,但是依然是以靜態爲主。
ajax盛行:
- 2005年開始,ajax逐漸被前端開發人員所重視,因爲不用刷新頁面就可以更新頁面的數據和渲染效果。
- 此時的開發人員不僅僅要編寫HTML樣式,還要懂ajax與後端交互,然後通過JS操作Dom元素來實現頁面動態效果。比較流行的框架如Jquery就是典型代表。
MVVM,關注模型和視圖
2008年,google的Chrome發佈,隨後就以極快的速度佔領市場,超過IE成爲瀏覽器市場的主導者。
2009年,Ryan Dahl在谷歌的Chrome V8引擎基礎上,打造了基於事件循環的異步IO框架:Node.js。
- 基於事件循環的異步IO
- 單線程運行,避免多線程的變量同步問題
- JS可以編寫後臺代碼,前後臺統一編程語言
node.js的偉大之處不在於讓JS邁向了後端開發,而是構建了一個龐大的生態系統。
2010年,NPM作爲node.js的包管理系統首次發佈,開發人員可以遵循Common.js規範來編寫Node.js模塊,然後發佈到NPM上供其他開發人員使用。目前已經是世界最大的包模塊管理系統。
隨後,在node的基礎上,湧現出了一大批的前端框架:
MVVM模式
- M:即Model,模型,包括數據和一些基本操作
- V:即View,視圖,頁面渲染結果
- VM:即View-Model,模型與視圖間的雙向操作(無需開發人員干涉)
在MVVM之前,開發人員從後端獲取需要的數據模型,然後要通過DOM操作Model渲染到View中。而後當用戶操作視圖,我們還需要通過DOM獲取View中的數據,然後同步到Model中。
而MVVM中的VM要做的事情就是把DOM操作完全封裝起來,開發人員不用再關心Model和View之間是如何互相影響的:
- 只要我們Model發生了改變,View上自然就會表現出來。
- 當用戶修改了View,Model中的數據也會跟着改變。
把開發人員從繁瑣的DOM操作中解放出來,把關注點放在如何操作Model上。
Vue就是一款MVVM模式的框架。
Vue 是一套用於構建用戶界面的漸進式JavaScript框架。與其它大型框架不同的是,Vue 被設計爲可以自底向上逐層應用。Vue 的核心庫只關注視圖層,方便與第三方庫或既有項目整合。
Vue.js是一套構建用戶界面的漸進式框架。與其他重量級框架不同的是,Vue 採用自底向上增量開發的設計。Vue 的核心庫只關注視圖層,並且非常容易學習,非常容易與其它庫或已有項目整合。另一方面,Vue 完全有能力驅動採用單文件組件和Vue生態系統支持的庫開發的複雜單頁應用。
Vue.js 的目標是通過儘可能簡單的 API 實現響應的數據綁定和組合的視圖組件 。
Vue.js 自身不是一個全能框架——它只聚焦於視圖層。因此它非常容易學習,非常容易與其它庫或已有項目整合。另一方面,在與相關工具和支持庫一起使用時 ,Vue.js 也能完美地驅動複雜的單頁應用。
特點:
-
易用
在有HTML CSS JavaScript的基礎上,快速上手。
-
靈活
簡單小巧的核心,漸進式技術棧,足以應付任何規模的應用。
-
性能
20kb min+gzip 運行大小、超快虛擬 DOM 、最省心的優化。
官方網站:https://cn.vuejs.org/
Git地址:https://github.com/vuejs
教程:https://www.runoob.com/vue2/vue-tutorial.html
參考:https://cn.vuejs.org/v2/guide/
黑馬架構師
《黑馬架構師》一款由傳智播客教育集團研究院開發的基於自主研發的模板引擎的“代碼生成神器”。即便是一個工程幾百個表,也可以瞬間完成基礎代碼的構建!用戶只需建立數據庫表結構,簡單的幾步操作就可以快速生成可以運行的一整套代碼,可以極大地縮短開發週期,降低人力成本。《黑馬架構師》內置了當前java和前端主流的架構模板,如SSM+dubbo 、springBoot+springCloud+springData 、前後端分離的vue+elementUI 模板、swagger API模板、數據庫文檔模板等。 用戶通過自己開發模板也可以實現生成php、python、C# 、c++、數據庫存儲過程等其它編程語言的代碼。
下載地址:https://gitee.com/chuanzhiliubei/codeutil
Dubbo
Dubbo是阿里巴巴公司開源的一個高性能優秀的服務框架,使得應用可通過高性能的 RPC 實現服務的輸出和輸入功能,可以和spring框架無縫集成。
Dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。
- 主要核心部件:
- 工作原理
節點 | 角色說明 |
---|---|
Provider | 暴露服務的服務提供方–“服務提供者” |
Consumer | 調用遠程服務的服務消費方-- “服務消費者” |
Registry | 服務註冊與發現的註冊中心-- “服務註冊中心” |
Monitor | 統計服務的調用次數和調用時間的監控中心-- “服務監控中心” |
Container | 服務運行容器 |
官方網站:http://dubbo.apache.org/en-us/
相關介紹:GitHub 超 32,000 Star!火了近十年的阿里開源項目 Apache Dubbo 雲原生實踐(強烈推薦)
SpringBoot
SpringBoot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。通過這種方式,Spring Boot致力於在蓬勃發展的快速應用開發領域(rapid application development)成爲領導者。
SpringBoot是Spring項目中的一個子工程,與我們所熟知的Spring-framework 同屬於spring的產品:
我們可以看到下面的一段介紹:
Spring Boot你只需要“run”就可以非常輕易的構建獨立的、生產級別的spring應用。
我們爲spring平臺和第三方依賴庫提供了一種固定化的使用方式,使你能非常輕鬆的開始開發你的應用程序。大部分Spring Boot應用只需要很少的配置。
其實人們把Spring Boot稱爲搭建程序的腳手架
。其最主要作用就是幫我們快速的構建龐大的spring項目,並且儘可能的減少一切xml配置,做到開箱即用,迅速上手,讓我們關注於業務而非配置。
我們可以使用SpringBoot創建java應用,並使用java –jar 啓動它,就能得到一個生產級別的web工程。
java一直被人詬病的一點就是臃腫、麻煩。當我們還在辛苦的搭建項目時,可能Python程序員已經把功能寫好了,究其原因主要是兩點:
-
複雜的配置
項目各種配置其實是開發時的損耗, 因爲在思考 Spring 特性配置和解決業務問題之間需要進行思維切換,所以寫配置擠佔了寫應用程序邏輯的時間。
-
混亂的依賴管理
項目的依賴管理也是件喫力不討好的事情。決定項目裏要用哪些庫就已經夠讓人頭痛的了,你還要知道這些庫的哪個版本和其他庫不會有衝突,這也是件棘手的問題。並且,依賴管理也是一種損耗,添加依賴不是寫應用程序代碼。一旦選錯了依賴的版本,隨之而來的不兼容問題毫無疑問會是生產力殺手。
而SpringBoot讓這一切成爲過去!
SpringBoot 主要特徵是:
- 創建獨立的spring應用程序
- 直接內嵌tomcat、jetty和undertow(不需要打包成war包部署)
- 提供了固定化的“starter”配置,以簡化構建配置
- 儘可能的自動配置spring和第三方庫
- 提供產品級的功能,如:安全指標、運行狀況監測和外部化配置等
- 絕對不會生成代碼,並且不需要XML配置
總之,Spring Boot爲所有 Spring 的開發者提供一個開箱即用的、非常快速的、廣泛接受的入門體驗
更多細節,大家可以到官網查看。
相關介紹:目錄:SpringBoot 1.x | 2.x 基礎篇、核心篇、實戰篇
SpringCloud
微服務是一種架構方式,最終肯定需要技術架構去實施。
微服務的實現方式很多,但是最火的莫過於Spring Cloud了。爲什麼?
- 後臺硬:作爲Spring家族的一員,有整個Spring全家桶靠山,背景十分強大。
- 技術強:Spring作爲Java領域的前輩,可以說是功力深厚。有強力的技術團隊支撐,一般人還真比不了
- 羣衆基礎好:可以說大多數程序員的成長都伴隨着Spring框架,試問:現在有幾家公司開發不用Spring?SpringCloud與Spring的各個框架無縫整合,對大家來說一切都是熟悉的配方,熟悉的味道。
- 使用方便:相信大家都體會到了SpringBoot給我們開發帶來的便利,而SpringCloud完全支持SpringBoot的開發,用很少的配置就能完成微服務框架的搭建
SpringCloud是Spring旗下的項目之一,官網地址:http://projects.spring.io/spring-cloud/
Spring最擅長的就是集成,把世界上最好的框架拿過來,集成到自己的項目中。
SpringCloud也是一樣,它將現在非常流行的一些技術整合到一起,實現了諸如:配置管理,服務發現,智能路由,負載均衡,熔斷器,控制總線,集羣狀態等等功能。其主要涉及的組件包括:
- Eureka:服務治理組件,包含服務註冊中心,服務註冊與發現機制的實現。(服務治理,服務註冊/發現)
- Zuul:網關組件,提供智能路由,訪問過濾功能
- Ribbon:客戶端負載均衡的服務調用組件(客戶端負載)
- Feign:服務調用,給予Ribbon和Hystrix的聲明式服務調用組件 (聲明式服務調用)
- Hystrix:容錯管理組件,實現斷路器模式,幫助服務依賴中出現的延遲和爲故障提供強大的容錯能力。(熔斷、斷路器,容錯)
架構圖:
以上只是其中一部分。
因爲Spring Cloud不同其他獨立項目,它擁有很多子項目的大項目。所以它的版本是版本名+版本號 (如Angel.SR6)。
版本名:是倫敦的地鐵名
版本號:SR(Service Releases)是固定的 ,大概意思是穩定版本。後面會有一個遞增的數字。
所以 Edgware.SR3就是Edgware的第3個Release版本。
我們在項目中,會是以Finchley的版本。
其中包含的組件,也都有各自的版本,如下表:
Component | Edgware.SR3 | Finchley.RC1 | Finchley.BUILD-SNAPSHOT |
---|---|---|---|
spring-cloud-aws | 1.2.2.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-bus | 1.3.2.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-cli | 1.4.1.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-commons | 1.3.3.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-contract | 1.2.4.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-config | 1.4.3.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-netflix | 1.4.4.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-security | 1.2.2.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-cloudfoundry | 1.1.1.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-consul | 1.3.3.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-sleuth | 1.3.3.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-stream | Ditmars.SR3 | Elmhurst.RELEASE | Elmhurst.BUILD-SNAPSHOT |
spring-cloud-zookeeper | 1.2.1.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-boot | 1.5.10.RELEASE | 2.0.1.RELEASE | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-task | 1.2.2.RELEASE | 2.0.0.RC1 | 2.0.0.RELEASE |
spring-cloud-vault | 1.1.0.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-gateway | 1.0.1.RELEASE | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
spring-cloud-openfeign | 2.0.0.RC1 | 2.0.0.BUILD-SNAPSHOT |
Spring Cloud中文網-官方文檔中文版:https://www.springcloud.cc
SpringCloud教程:https://blog.csdn.net/hellozpc/article/details/83692496
SpringData
官網:http://projects.spring.io/spring-data/
Spring Data是一個用於簡化數據庫訪問,並支持雲服務的開源框架。其主要目標是使得對數據的訪問變得方便快捷。
可以極大的簡化JPA的寫法,可以在幾乎不用寫實現的情況下,實現對數據的訪問和操作。除了CRUD外,還包括如分頁、排序等一些常用的功能。
Spring Data的使命是爲數據訪問提供熟悉且一致的基於Spring的編程模型,同時仍保留底層數據存儲的特殊特性。
它使數據訪問技術,關係數據庫和非關係數據庫,map-reduce框架和基於雲的數據服務變得簡單易用。這是一個傘形項目,其中包含許多特定於給定數據庫的子項目。這些項目是通過與這些激動人心的技術背後的許多公司和開發人員合作開發的。
Spring Data 的使命是給各種數據訪問提供統一的編程接口,不管是關係型數據庫(如MySQL),還是非關係數據庫(如Redis),或者類似Elasticsearch這樣的索引數據庫。從而簡化開發人員的代碼,提高開發效率。
包含很多不同數據操作的模塊:
相關介紹:什麼是Spring Data
Spring Security
官網:https://spring.io/projects/spring-security
什麼是安全框架? 解決系統安全問題的框架。如果沒有安全框架,我們需要手動處理每個資源的訪問控制,非常麻煩。使用安全框架,我們可以通過配置的方式實現對資源的訪問限制。
Spring Security:spring家族一員。是一個能夠爲基於Spring的企業應用系統提供聲明式的安全訪問控制解決方案的安全框架。它提供了一組可以在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面編程)功能,爲應用系統提供聲明式的安全訪問控制功能,減少了爲企業系統安全控制編寫大量重複代碼的工作。
Apache Shiro 是一個功能強大且易於使用的Java安全框架,提供了認證,授權,加密,和會話管理。
相關介紹:Spring Security 參考手冊
Eureka
日益複雜的互聯網環境,一個項目肯定會拆分出十幾,甚至數十個微服務。此時如果還人爲管理地址,不僅開發困難,將來測試、發佈上線都會非常麻煩,這與DevOps的思想是背道而馳的。
這就好比是 網約車
出現以前,人們出門叫車只能叫出租車。一些私家車想做出租卻沒有資格,被稱爲黑車。而很多人想要約車,但是無奈出租車太少,不方便。私家車很多卻不敢攔,而且滿大街的車,誰知道哪個纔是願意載人的。一個想要,一個願意給,就是缺少引子,缺乏管理啊。
此時滴滴這樣的網約車平臺出現了,所有想載客的私家車全部到滴滴注冊,記錄你的車型(服務類型),身份信息(聯繫方式)。這樣提供服務的私家車,在滴滴那裏都能找到,一目瞭然。
此時要叫車的人,只需要打開APP,輸入你的目的地,選擇車型(服務類型),滴滴自動安排一個符合需求的車到你面前,爲你服務,完美!
Eureka就好比是滴滴,負責管理、記錄服務提供者的信息。服務調用者無需自己尋找服務,而是把自己的需求告訴Eureka,然後Eureka會把符合你需求的服務告訴你。
同時,服務提供方與Eureka之間通過“心跳”
機制進行監控,當某個服務提供方出現問題,Eureka自然會把它從服務列表中剔除。
這就實現了服務的自動註冊、發現、狀態監控。
基本架構:
- Eureka:就是服務註冊中心(可以是一個集羣),對外暴露自己的地址
- 提供者:啓動後向Eureka註冊自己信息(地址,提供什麼服務)
- 消費者:向Eureka訂閱服務,Eureka會將對應服務的所有提供者地址列表發送給消費者,並且定期更新
- 心跳(續約):提供者定期通過http方式向Eureka刷新自己的狀態
相關介紹:https://www.jianshu.com/p/e2e3ded1f54a
Ribbon
但是實際環境中,我們往往會開啓很多個服務提供方的集羣。此時我們獲取的服務列表中就會有多個,到底該訪問哪一個呢?
一般這種情況下我們就需要編寫負載均衡算法,在多個實例列表中進行選擇。
不過Eureka中已經幫我們集成了負載均衡組件:Ribbon,簡單修改代碼即可使用。
Ribbon是Netflix 發佈的負載均衡器,它有助於控制HTTP和TCP客戶端的行爲。爲Ribbon配置服務提供者地址列表後,Ribbon就可基於某種負載均衡算法,自動地幫助服務消費者去請求。Ribbon默認爲我們提供了很多的負載均衡算法,例如輪詢、隨機等。當然,我們也可爲Ribbon實現自定義的負載均衡算法。
相關介紹:https://www.jianshu.com/p/1bd66db5dc46
https://www.jianshu.com/p/b04ba8145f56
Hystrix
簡介
Hystrix,英文意思是豪豬,全身是刺,看起來就不好惹,是一種保護機制。
Hystrix也是Netflix公司的一款組件。
主頁:https://github.com/Netflix/Hystrix/
那麼Hystix的作用是什麼呢?具體要保護什麼呢?
Hystix是Netflix開源的一個延遲和容錯庫,用於隔離訪問遠程服務、第三方庫,防止出現級聯失敗。
雪崩問題
微服務中,服務間調用關係錯綜複雜,一個請求,可能需要調用多個微服務接口才能實現,會形成非常複雜的調用鏈路:
如圖,一次業務請求,需要調用A、P、H、I四個服務,這四個服務又可能調用其它服務。
如果此時,某個服務出現異常:
例如微服務I發生異常,請求阻塞,用戶不會得到響應,則tomcat的這個線程不會釋放,於是越來越多的用戶請求到來,越來越多的線程會阻塞:
服務器支持的線程和併發數有限,請求一直阻塞,會導致服務器資源耗盡,從而導致所有其它服務都不可用,形成雪崩效應。
這就好比,一個汽車生產線,生產不同的汽車,需要使用不同的零件,如果某個零件因爲種種原因無法使用,那麼就會造成整臺車無法裝配,陷入等待零件的狀態,直到零件到位,才能繼續組裝。 此時如果有很多個車型都需要這個零件,那麼整個工廠都將陷入等待的狀態,導致所有生產都陷入癱瘓。一個零件的波及範圍不斷擴大。
Hystix解決雪崩問題的手段有兩個:
- 線程隔離
- 服務熔斷
線程隔離,服務降級:
線程隔離示意圖:
解讀:
Hystrix爲每個依賴服務調用分配一個小的線程池,如果線程池已滿調用將被立即拒絕,默認不採用排隊.加速失敗判定時間。
用戶的請求將不再直接訪問服務,而是通過線程池中的空閒線程來訪問服務,如果線程池已滿,或者請求超時,則會進行降級處理,什麼是服務降級?
服務降級:優先保證核心服務,而非核心服務不可用或弱可用。
用戶的請求故障時,不會被阻塞,更不會無休止的等待或者看到系統崩潰,至少可以看到一個執行結果(例如返回友好的提示信息) 。
服務降級雖然會導致請求失敗,但是不會導致阻塞,而且最多會影響這個依賴服務對應的線程池中的資源,對其它服務沒有響應。
觸發Hystix服務降級的情況:
- 線程池已滿
- 請求超時
服務熔斷:
熔斷器,也叫斷路器,其英文單詞爲:Circuit Breaker
熔斷機制的原理很簡單,像家裏的電路熔斷器,如果電路發生短路能立刻熔斷電路,避免發生災難。在分佈式系統中應用這一模式之後, 服務調用方可以自己進行判斷某些服務反應慢或者存在大量超時的情況時,能夠主動熔斷,防止整個系統被拖垮。
不同於電路熔斷只能斷不能自動重連,Hystrix 可以實現彈性容錯,當情況好轉之後,可以自動重連。這就好比魔術師把鴿子變沒了容易,但是真正考驗技術的是如何把消失的鴿子再變回來。通過斷路的方式,可以將後續請求直接拒絕掉,一段時間之後允許部分請求通過,如果調用成功則回到電路閉合狀態,否則繼續斷開。
熔斷狀態機3個狀態:
- Closed:關閉狀態,所有請求都正常訪問。
- Open:打開狀態,所有請求都會被降級。Hystix會對請求情況計數,當一定時間內失敗請求百分比達到閾值,則觸發熔斷,斷路器會完全打開。默認失敗比例的閾值是50%,請求次數最少不低於20次。
- Half Open:半開狀態,open狀態不是永久的,打開後會進入休眠時間(默認是5S)。隨後斷路器會自動進入半開狀態。此時會釋放部分請求通過,若這些請求都是健康的,則會完全關閉斷路器,否則繼續保持打開,再次進行休眠計時。
相關介紹:SpringBoot集成Hystrix
Feign
Feign可以把Rest的請求進行隱藏,僞裝成類似SpringMVC的Controller一樣。你不用再自己拼接url,拼接參數等等操作,一切都交給Feign去做。
項目主頁:https://github.com/OpenFeign/feign
Zuul
我們使用Spring Cloud實現微服務的架構基本成型,大致是這樣的:
我們使用Spring Cloud Netflix中的Eureka實現了服務註冊中心以及服務註冊與發現;而服務間通過Ribbon或Feign實現服務的消費以及均衡負載。爲了使得服務集羣更爲健壯,使用Hystrix的融斷機制來避免在微服務架構中個別服務出現異常時引起的故障蔓延。
在該架構中,我們的服務集羣包含:內部服務Service A和Service B,他們都會註冊與訂閱服務至Eureka Server,而Open Service是一個對外的服務,通過均衡負載公開至服務調用方。我們把焦點聚集在對外服務這塊,直接暴露我們的服務地址,這樣的實現是否合理,或者是否有更好的實現方式呢?
先來說說這樣架構需要做的一些事兒以及存在的不足:
-
破壞了服務無狀態特點。
爲了保證對外服務的安全性,我們需要實現對服務訪問的權限控制,而開放服務的權限控制機制將會貫穿並污染整個開放服務的業務邏輯,這會帶來的最直接問題是,破壞了服務集羣中REST API無狀態的特點。
從具體開發和測試的角度來說,在工作中除了要考慮實際的業務邏輯之外,還需要額外考慮對接口訪問的控制處理。
-
無法直接複用既有接口。
當我們需要對一個即有的集羣內訪問接口,實現外部服務訪問時,我們不得不通過在原有接口上增加校驗邏輯,或增加一個代理調用來實現權限控制,無法直接複用原有的接口。
面對類似上面的問題,我們要如何解決呢?答案是:服務網關!
爲了解決上面這些問題,我們需要將權限控制這樣的東西從我們的服務單元中抽離出去,而最適合這些邏輯的地方就是處於對外訪問最前端的地方,我們需要一個更強大一些的均衡負載器的 服務網關。
服務網關是微服務架構中一個不可或缺的部分。通過服務網關統一向外系統提供REST API的過程中,除了具備服務路由
、均衡負載
功能之外,它還具備了權限控制
等功能。Spring Cloud Netflix中的Zuul就擔任了這樣的一個角色,爲微服務架構提供了前門保護的作用,同時將權限控制這些較重的非業務邏輯內容遷移到服務路由層面,使得服務集羣主體能夠具備更高的可複用性和可測試性。
官網:https://github.com/Netflix/zuul
事實上,在微服務架構中,Zuul就是守門的大Boss!一夫當關,萬夫莫開!
Zuul加入後的架構:
不管是來自於客戶端(PC或移動端)的請求,還是服務內部調用。一切對服務的請求都會經過Zuul這個網關,然後再由網關來實現 鑑權、動態路由等等操作。Zuul就是我們服務的統一入口。
相關介紹:ZUUL-API網關
Vuetify
Vue雖然會幫我們進行視圖的渲染,但樣式還是由我們自己來完成。這顯然不是我們的強項,因此後端開發人員一般都喜歡使用一些現成的UI組件,拿來即用,常見的例如:
- BootStrap
- LayUI
- EasyUI
- ZUI
然而這些UI組件的基因天生與Vue不合,因爲他們更多的是利用DOM操作,藉助於jQuery實現,而不是MVVM的思想。
而目前與Vue吻合的UI框架也非常的多,國內比較知名的如:
- element-ui:餓了麼出品(前文提到)
- i-view:某公司出品
vuetify是一個基於vue2.0,爲移動而生的組件框架,一個漸進式的UI框架。
Vuetify支持SSR(服務端渲染),SPA(單頁應用程序),PWA(漸進式web應用程序)和標準HTML頁面。
官方網站:https://vuetifyjs.com/zh-Hans/
- Vuetify幾乎不需要任何CSS代碼,而element-ui許多佈局樣式需要我們來編寫
- Vuetify從底層構建起來的語義化組件。簡單易學,容易記住。
- Vuetify基於Material Design(谷歌推出的多平臺設計規範),更加美觀,動畫效果酷炫,且風格統一
基於官方網站的文檔進行學習:
我們重點關注UI components
即可,裏面有大量的UI組件,我們要用的時候再查看,不用現在學習,先看下有什麼:
以後用到什麼組件,就來查詢即可。
相關介紹:初次使用VUE-Vuetify框架
Nginx
nginx可以作爲web服務器,但更多的時候,我們把它作爲網關,因爲它具備網關必備的功能:
- 反向代理
- 負載均衡
- 動態路由
- 請求過濾
nginx作爲web服務器
Web服務器分2類:
- web應用服務器,如:
- tomcat
- resin
- jetty
- web服務器,如:
- Apache 服務器
- Nginx
- IIS
區分:web服務器不能解析jsp等頁面,只能處理js、css、html等靜態資源。
併發:web服務器的併發能力遠高於web應用服務器。
nginx作爲反向代理
什麼是反向代理?
- 代理:通過客戶機的配置,實現讓一臺服務器代理客戶機,客戶的所有請求都交給代理服務器處理。
- 反向代理:用一臺服務器,代理真實服務器,用戶訪問時,不再是訪問真實服務器,而是代理服務器。
nginx可以當做反向代理服務器來使用:
- 我們需要提前在nginx中配置好反向代理的規則,不同的請求,交給不同的真實服務器處理
- 當請求到達nginx,nginx會根據已經定義的規則進行請求的轉發,從而實現路由功能
利用反向代理,就可以解決我們前面所說的端口問題,如圖:
相關介紹:Nginx 安裝配置
CORS
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。
它允許瀏覽器向跨源服務器,發出XMLHttpRequest
請求,從而克服了AJAX只能同源使用的限制。
CORS需要瀏覽器和服務器同時支持。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低於IE10。
-
瀏覽器端:
目前,所有瀏覽器都支持該功能(IE10以下不行)。整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。
-
服務端:
CORS通信與AJAX沒有任何差別,因此你不需要改變以前的業務邏輯。只不過,瀏覽器會在請求中攜帶一些頭信息,我們需要以此判斷是否允許其跨域,然後在響應頭中加入一些信息即可。這一般通過過濾器完成即可。
瀏覽器會將ajax請求分爲兩類,其處理方案略有差異:簡單請求、特殊請求。
只要同時滿足以下兩大條件,就屬於簡單請求:
(1) 請求方法是以下三種方法之一:
- HEAD
- GET
- POST
(2)HTTP的頭信息不超出以下幾種字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限於三個值
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
當瀏覽器發現發起的ajax請求是簡單請求時,會在請求頭中攜帶一個字段:Origin
.
Origin中會指出當前請求屬於哪個域(協議+域名+端口)。服務會根據這個值決定是否允許其跨域。
如果服務器允許跨域,需要在返回的響應頭中攜帶下面信息:
Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
- Access-Control-Allow-Origin:可接受的域,是一個具體域名或者*(代表任意域名)
- Access-Control-Allow-Credentials:是否允許攜帶cookie,默認情況下,cors不會攜帶cookie,除非這個值是true
有關cookie:
要想操作cookie,需要滿足3個條件:
- 服務的響應頭中需要攜帶Access-Control-Allow-Credentials並且爲true。
- 瀏覽器發起ajax需要指定withCredentials 爲true
- 響應頭中的Access-Control-Allow-Origin一定不能爲*,必須是指定的域名
不符合簡單請求的條件,會被瀏覽器判定爲特殊請求,,例如請求方式爲PUT。
預檢請求
特殊請求會在正式通信之前,增加一次HTTP查詢請求,稱爲"預檢"請求(preflight)。
瀏覽器先詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答覆,瀏覽器纔會發出正式的XMLHttpRequest
請求,否則就報錯。
一個“預檢”請求的樣板:
OPTIONS /cors HTTP/1.1
Origin: http://manage.leyou.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.leyou.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
與簡單請求相比,除了Origin以外,多了兩個頭:
- Access-Control-Request-Method:接下來會用到的請求方式,比如PUT
- Access-Control-Request-Headers:會額外用到的頭信息
預檢請求的響應
服務的收到預檢請求,如果許可跨域,會發出響應:
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 1728000
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
除了Access-Control-Allow-Origin
和Access-Control-Allow-Credentials
以外,這裏又額外多出3個頭:
- Access-Control-Allow-Methods:允許訪問的方式
- Access-Control-Allow-Headers:允許攜帶的頭
- Access-Control-Max-Age:本次許可的有效時長,單位是秒,過期之前的ajax請求就無需再次進行預檢了
如果瀏覽器得到上述響應,則認定爲可以跨域,後續就跟簡單請求的處理是一樣的了。
相關介紹:使用CORS解決跨域問題
FastDFS
什麼是分佈式文件系統?
分佈式文件系統(Distributed File System)是指文件系統管理的物理存儲資源不一定直接連接在本地節點上,而是通過計算機網絡與節點相連。
通俗來講:
- 傳統文件系統管理的文件就存儲在本機。
- 分佈式文件系統管理的文件存儲在很多機器,這些機器通過網絡連接,要被統一管理。無論是上傳或者訪問文件,都需要通過管理中心來訪問
什麼是FastDFS?
FastDFS是由淘寶的餘慶先生所開發的一個輕量級、高性能的開源分佈式文件系統。用純C語言開發,功能豐富:
- 文件存儲
- 文件同步
- 文件訪問(上傳、下載)
- 存取負載均衡
- 在線擴容
適合有大容量存儲需求的應用或系統。同類的分佈式文件系統有谷歌的GFS、HDFS(Hadoop)、TFS(淘寶)等。
架構圖:
FastDFS兩個主要的角色:Tracker Server 和 Storage Server 。
- Tracker Server:跟蹤服務器,主要負責調度storage節點與client通信,在訪問上起負載均衡的作用,和記錄storage節點的運行狀態,是連接client和storage節點的樞紐。
- Storage Server:存儲服務器,保存文件和文件的meta data(元數據),每個storage server會啓動一個單獨的線程主動向Tracker cluster中每個tracker server報告其狀態信息,包括磁盤使用情況,文件同步情況及文件上傳下載次數統計等信息
- Group:文件組,多臺Storage Server的集羣。上傳一個文件到同組內的一臺機器上後,FastDFS會將該文件即時同步到同組內的其它所有機器上,起到備份的作用。不同組的服務器,保存的數據不同,而且相互獨立,不進行通信。
- Tracker Cluster:跟蹤服務器的集羣,有一組Tracker Server(跟蹤服務器)組成。
- Storage Cluster :存儲集羣,有多個Group組成。
上傳
- Client通過Tracker server查找可用的Storage server。
- Tracker server向Client返回一臺可用的Storage server的IP地址和端口號。
- Client直接通過Tracker server返回的IP地址和端口與其中一臺Storage server建立連接並進行文件上傳。
- 上傳完成,Storage server返回Client一個文件ID,文件上傳結束。
下載
相關介紹:用FastDFS一步步搭建文件管理系統
Elasticsearch
用戶訪問我們的首頁,一般都會直接搜索來尋找自己想要購買的商品。
而商品的數量非常多,而且分類繁雜。如何能正確的顯示出用戶想要的商品,並進行合理的過濾,儘快促成交易,是搜索系統要研究的核心。
面對這樣複雜的搜索業務和數據量,使用傳統數據庫搜索就顯得力不從心,一般我們都會使用全文檢索技術,比如之前大家學習過的Solr。
不過今天,我們要講的是另一個全文檢索技術:Elasticsearch。
Elastic
Elastic官網:https://www.elastic.co/cn/
Elastic有一條完整的產品線及解決方案:Elasticsearch、Kibana、Logstash等,前面說的三個就是大家常說的ELK技術棧。
Elasticsearch
Elasticsearch是一個基於Lucene的搜索服務器。它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java語言開發的,並作爲Apache許可條款下的開放源碼發佈,是一種流行的企業級搜索引擎。Elasticsearch用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。官方客戶端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和許多其他語言中都是可用的。根據DB-Engines的排名顯示,Elasticsearch是最受歡迎的企業搜索引擎,其次是Apache Solr,也是基於Lucene。
Elasticsearch官網:https://www.elastic.co/cn/products/elasticsearch
如上所述,Elasticsearch具備以下特點:
- 分佈式,無需人工搭建集羣(solr就需要人爲配置,使用Zookeeper作爲註冊中心)
- Restful風格,一切API都遵循Rest原則,容易上手
- 近實時搜索,數據更新在Elasticsearch中幾乎是完全同步的。
相關介紹:全文搜索引擎 Elasticsearch 入門教程
Spring Data Elasticsearch
Spring Data Elasticsearch是Spring Data項目下的一個子模塊。
Spring Data Elasticsearch的頁面:https://projects.spring.io/spring-data-elasticsearch/
特徵:
- 支持Spring的基於
@Configuration
的java配置方式,或者XML配置方式 - 提供了用於操作ES的便捷工具類**
ElasticsearchTemplate
**。包括實現文檔到POJO之間的自動智能映射。 - 利用Spring的數據轉換服務實現的功能豐富的對象映射
- 基於註解的元數據映射方式,而且可擴展以支持更多不同的數據格式
- 根據持久層接口自動生成對應實現方法,無需人工編寫基本操作代碼(類似mybatis,根據接口自動得到實現)。當然,也支持人工定製查詢
相關介紹:Spring Data Elasticsearch基本使用
Thymeleaf
官方網站:https://www.thymeleaf.org/index.html
官方文檔:https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#preface
Thymeleaf是用來開發Web和獨立環境項目的現代服務器端Java模板引擎。
Thymeleaf的主要目標是爲您的開發工作流程帶來優雅的自然模板 - HTML。可以在直接瀏覽器中正確顯示,並且可以作爲靜態原型,從而在開發團隊中實現更強大的協作。
藉助Spring Framework的模塊,可以根據自己的喜好進行自由選擇,可插拔功能組件,Thymeleaf是現代HTML5 JVM Web開發的理想選擇 - 儘管它可以做的更多。
Spring官方支持的服務的渲染模板中,並不包含jsp。而是Thymeleaf和Freemarker等,而Thymeleaf與SpringMVC的視圖技術,及SpringBoot的自動化配置集成非常完美,幾乎沒有任何成本,你只用關注Thymeleaf的語法即可。
特點:
- 動靜結合:Thymeleaf 在有網絡和無網絡的環境下皆可運行,即它可以讓美工在瀏覽器查看頁面的靜態效果,也可以讓程序員在服務器查看帶數據的動態頁面效果。這是由於它支持 html 原型,然後在 html 標籤裏增加額外的屬性來達到模板+數據的展示方式。瀏覽器解釋 html 時會忽略未定義的標籤屬性,所以 thymeleaf 的模板可以靜態地運行;當有數據返回到頁面時,Thymeleaf 標籤會動態地替換掉靜態內容,使頁面動態顯示。
- 開箱即用:它提供標準和spring標準兩種方言,可以直接套用模板實現JSTL、 OGNL表達式效果,避免每天套模板、改jstl、改標籤的困擾。同時開發人員也可以擴展和創建自定義的方言。
- 多方言支持:Thymeleaf 提供spring標準方言和一個與 SpringMVC 完美集成的可選模塊,可以快速的實現表單綁定、屬性編輯器、國際化等功能。
- 與SpringBoot完美整合,SpringBoot提供了Thymeleaf的默認配置,並且爲Thymeleaf設置了視圖解析器,我們可以像以前操作jsp一樣來操作Thymeleaf。代碼幾乎沒有任何區別,就是在模板語法上有區別。
Thymeleaf VS Vue
我們在前面已經講解了vue.js這樣的前端框架,爲什麼我們還要在項目中使用thymeleaf ? 首先說這兩種技術本質上屬於不同類型的產品。vue.js屬於前端框架,而thymeleaf 屬於模板引擎。雖然它們可以實現相同的功能(比如一個列表),但是它們的工作過程卻是不同: vue.js通過異步方式請求數據,後端給前端返回json,前端通過vue指令循環渲染列表。thymeleaf 則是在後端實現頁面的渲染,將渲染後的頁面直接給瀏覽器展示。
什麼時候使用vue.js,什麼使用thymeleaf 呢?一般來說,管理後臺我們會使用前端框架,而網站前臺的部分有些頁面會使用thymeleaf。原因有兩點:
(1)因爲使用vue.js由於是異步請求,從頁面打開到信息的展示會出現延遲,而使用thymeleaf,頁面打開會立刻看到頁面的信息。
(2)異步加載的數據不會被搜索引擎抓取。所以當我們希望數據被搜索引擎收錄,就需要使用thymeleaf這樣的模板引擎。
相關介紹:Thymeleaf入門到喫灰
RabbitMQ
爲什麼使用RabbitMQ?
例如:當我們已經完成了商品詳情和搜索系統的開發。
- 商品的原始數據保存在數據庫中,增刪改查都在數據庫中完成。
- 搜索服務數據來源是索引庫,如果數據庫商品發生變化,索引庫數據不能及時更新。
- 商品詳情做了頁面靜態化,靜態頁面數據也不會隨着數據庫商品發生變化。
如果我們在後臺修改了商品的價格,搜索頁面和商品詳情頁顯示的依然是舊的價格,這樣顯然不對。該如何解決?
這裏有兩種解決方案:
- 方案1:每當後臺對商品做增刪改操作,同時要修改索引庫數據及靜態頁面
- 方案2:搜索服務和商品頁面服務對外提供操作接口,後臺在商品增刪改後,調用接口
以上兩種方式都有同一個嚴重問題:就是代碼耦合,後臺服務中需要嵌入搜索和商品頁面服務,違背了微服務的獨立
原則。
所以,我們會通過另外一種方式來解決這個問題:消息隊列。
MQ
消息隊列,即MQ,Message Queue。
消息隊列是典型的:生產者、消費者模型。生產者不斷向消息隊列中生產消息,消費者不斷的從隊列中獲取消息。因爲消息的生產和消費都是異步的,而且只關心消息的發送和接收,沒有業務邏輯的侵入,這樣就實現了生產者和消費者的解耦。
結合前面所說的問題:
- 商品服務對商品增刪改以後,無需去操作索引庫或靜態頁面,只是發送一條消息,也不關心消息被誰接收。
- 搜索服務和靜態頁面服務接收消息,分別去處理索引庫和靜態頁面。
如果以後有其它系統也依賴商品服務的數據,同樣監聽消息即可,商品服務無需任何代碼修改。
MQ是消息通信的模型,並不是具體實現。現在實現MQ的有兩種主流方式:AMQP、JMS。
兩者間的區別和聯繫:
- JMS是定義了統一的接口,來對消息操作進行統一;AMQP是通過規定協議來統一數據交互的格式
- JMS限定了必須使用Java語言;AMQP只是協議,不規定實現方式,因此是跨語言的。
- JMS規定了兩種消息模型;而AMQP的消息模型更加豐富
常見MQ產品:
- ActiveMQ:基於JMS
- RabbitMQ:基於AMQP協議,erlang語言開發,穩定性好
- RocketMQ:基於JMS,阿里巴巴產品,目前交由Apache基金會
- Kafka:分佈式消息系統,高吞吐量
RabbitMQ
RabbitMQ是基於AMQP的一款消息管理系統
官網: http://www.rabbitmq.com/
官方教程:http://www.rabbitmq.com/getstarted.html
相關介紹:centos7安裝rabbitMQ
rabbitmq官方的六種工作模式
Spring AMQP
Spring有很多不同的項目,其中就有對AMQP的支持。
Spring AMQP的頁面:http://spring.io/projects/spring-amqp
注意圖片裏一段描述:
The project consists of two parts; spring-amqp is the base abstraction, and spring-rabbit is the RabbitMQ implementation.
Spring-amqp是對AMQP協議的抽象實現,而spring-rabbit 是對協議的具體實現,也是目前的唯一實現。底層使用的就是RabbitMQ。
相關介紹:Spring AMQP的使用
Hibernate Validator
Hibernate Validator是Hibernate提供的一個開源框架,使用註解方式非常方便的實現服務端的數據校驗。
官網:http://hibernate.org/validator/
hibernate Validator 是 Bean Validation 的參考實現 。
Hibernate Validator 提供了 JSR 303 規範中所有內置 constraint(約束) 的實現,除此之外還有一些附加的 constraint。
在日常開發中,Hibernate Validator經常用來驗證bean的字段,基於註解,方便快捷高效。
常用註解如下:
Constraint | 詳細信息 |
---|---|
@Valid | 被註釋的元素是一個對象,需要檢查此對象的所有字段值 |
@Null | 被註釋的元素必須爲 null |
@NotNull | 被註釋的元素必須不爲 null |
@AssertTrue | 被註釋的元素必須爲 true |
@AssertFalse | 被註釋的元素必須爲 false |
@Min(value) | 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值 |
@Max(value) | 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值 |
@DecimalMin(value) | 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值 |
@DecimalMax(value) | 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值 |
@Size(max, min) | 被註釋的元素的大小必須在指定的範圍內 |
@Digits (integer, fraction) | 被註釋的元素必須是一個數字,其值必須在可接受的範圍內 |
@Past | 被註釋的元素必須是一個過去的日期 |
@Future | 被註釋的元素必須是一個將來的日期 |
@Pattern(value) | 被註釋的元素必須符合指定的正則表達式 |
被註釋的元素必須是電子郵箱地址 | |
@Length | 被註釋的字符串的大小必須在指定的範圍內 |
@NotEmpty | 被註釋的字符串的必須非空 |
@Range | 被註釋的元素必須在合適的範圍內 |
@NotBlank | 被註釋的字符串的必須非空 |
@URL(protocol=,host=, port=,regexp=, flags=) | 被註釋的字符串必須是一個有效的url |
@CreditCardNumber | 被註釋的字符串必須通過Luhn校驗算法,銀行卡,信用卡等號碼一般都用Luhn計算合法性 |
相關介紹:springboot使用hibernate validator校驗
JWT
JWT,全稱是Json Web Token, 是JSON風格輕量級的授權和身份認證規範,可實現無狀態、分佈式的Web應用授權。
官網:https://jwt.io
GitHub上jwt的java客戶端:https://github.com/jwtk/jjwt
JWT包含三部分數據:
-
Header:頭部,通常頭部有兩部分信息:
- 聲明類型,這裏是JWT
我們會對頭部進行base64編碼,得到第一部分數據
-
Payload:載荷,就是有效數據,一般包含下面信息:
- 用戶身份信息(注意,這裏因爲採用base64編碼,可解碼,因此不要存放敏感信息)
- 註冊聲明:如token的簽發時間,過期時間,簽發人等
這部分也會採用base64編碼,得到第二部分數據
-
Signature:簽名,是整個數據的認證信息。一般根據前兩步的數據,再加上服務的的密鑰(secret)(不要泄漏,最好週期性更換),通過加密算法生成。用於驗證整個數據完整和可靠性
生成的數據格式:token==個人證件 jwt=個人身份證
可以看到分爲3段,每段就是上面的一部分數據。
JWT交互流程圖:
步驟翻譯:
- 1、用戶登錄
- 2、服務的認證,通過後根據secret生成token
- 3、將生成的token返回給瀏覽器
- 4、用戶每次請求攜帶token
- 5、服務端利用公鑰解讀jwt簽名,判斷簽名有效後,從Payload中獲取用戶信息
- 6、處理請求,返回響應結果
因爲JWT簽發的token中已經包含了用戶的身份信息,並且每次請求都會攜帶,這樣服務的就無需保存用戶信息,甚至無需去數據庫查詢,完全符合了Rest的無狀態規範。
加密技術是對信息進行編碼和解碼的技術,編碼是把原來可讀信息(又稱明文)譯成代碼形式(又稱密文),其逆過程就是解碼(解密),加密技術的要點是加密算法,加密算法可以分爲三類:
- 對稱加密,如AES
- 基本原理:將明文分成N個組,然後使用密鑰對各個組進行加密,形成各自的密文,最後把所有的分組密文進行合併,形成最終的密文。
- 優勢:算法公開、計算量小、加密速度快、加密效率高
- 缺陷:雙方都使用同樣密鑰,安全性得不到保證
- 非對稱加密,如RSA
- 基本原理:同時生成兩把密鑰:私鑰和公鑰,私鑰隱祕保存,公鑰可以下發給信任客戶端
- 私鑰加密,持有私鑰或公鑰纔可以解密
- 公鑰加密,持有私鑰纔可解密
- 優點:安全,難以破解
- 缺點:算法比較耗時
- 基本原理:同時生成兩把密鑰:私鑰和公鑰,私鑰隱祕保存,公鑰可以下發給信任客戶端
- 不可逆加密,如MD5,SHA
- 基本原理:加密過程中不需要使用密鑰,輸入明文後由系統直接經過加密算法處理成密文,這種加密後的數據是無法被解密的,無法根據密文推算出明文。
RSA算法歷史:
1977年,三位數學家Rivest、Shamir 和 Adleman 設計了一種算法,可以實現非對稱加密。這種算法用他們三個人的名字縮寫:RSA
BCrypt
官網:http://www.mindrot.org/projects/jBCrypt/
BCrypt是一種跨平臺的文件加密工具,是布魯斯·施內爾在1993年發佈的Blowfish 加密算法,其加密的文件可在所有支持的操作系統和處理器上進行轉移,同時Bcrypt的加密時間非常慢,這樣暴力破解需要枚舉遍歷所有可能結果時,就需要花上非常非常長的時間.理論上大大增加了破解的難度.
Bcrypt也是採用隨機鹽的方式,進行密碼混淆。
相關介紹:Bcrypt加密原理
Swagger-UI
什麼是OpenAPI?
隨着互聯網技術的發展,現在的網站架構基本都由原來的後端渲染,變成了:前端渲染、前後端分離的形態,而且前端技術和後端技術在各自的道路上越走越遠。 前端和後端的唯一聯繫,變成了API接口;API文檔變成了前後端開發人員聯繫的紐帶,變得越來越重要。
沒有API文檔工具之前,大家都是手寫API文檔的,在什麼地方書寫的都有,而且API文檔沒有統一規範和格式,每個公司都不一樣。這無疑給開發帶來了災難。
OpenAPI規範(OpenAPI Specification 簡稱OAS)是Linux基金會的一個項目,試圖通過定義一種用來描述API格式或API定義的語言,來規範RESTful服務開發過程。目前V3.0版本的OpenAPI規範已經發布並開源在github上 。
官網:https://github.com/OAI/OpenAPI-Specification
什麼是swagger?
OpenAPI是一個編寫API文檔的規範,然而如果手動去編寫OpenAPI規範的文檔,是非常麻煩的。而Swagger就是一個實現了OpenAPI規範的工具集。
官網:https://swagger.io/
看官方的說明:
Swagger包含的工具集:
- Swagger編輯器: Swagger Editor允許您在瀏覽器中編輯YAML中的OpenAPI規範並實時預覽文檔。
- Swagger UI: Swagger UI是HTML,Javascript和CSS資產的集合,可以從符合OAS標準的API動態生成漂亮的文檔。
- **Swagger Codegen:**允許根據OpenAPI規範自動生成API客戶端庫(SDK生成),服務器存根和文檔。
- **Swagger Parser:**用於解析來自Java的OpenAPI定義的獨立庫
- **Swagger Core:**與Java相關的庫,用於創建,使用和使用OpenAPI定義
- Swagger Inspector(免費): API測試工具,可讓您驗證您的API並從現有API生成OpenAPI定義
- SwaggerHub(免費和商業): API設計和文檔,爲使用OpenAPI的團隊構建。
相關介紹:Swagger UI安裝與使用教程
EChars
ECharts,百度開源的圖表插件。一個使用 JavaScript 實現的開源可視化庫,可以流暢的運行在 PC 和移動設備上,兼容當前絕大部分瀏覽器(IE8/9/10/11,Chrome, Firefox,Safari等),底層依賴輕量級的矢量圖形庫 ZRender,提供直觀,交互豐富,可高度個性化定製的數據可視化圖表。
ECharts 提供了常規的折線圖、柱狀圖、散點圖、餅圖、K線圖,用於統計的盒形圖,用於地理數據可視化的地圖、熱力圖、線圖,用於關係數據可視化的關係圖、treemap、旭日圖,多維數據可視化的平行座標,還有用於 BI 的漏斗圖,儀表盤,並且支持圖與圖之間的混搭。
詳見EChars官網 https://echarts.baidu.com/
IK分詞器
IK分詞是一款國人開發的相對簡單的中文分詞器。雖然開發者自2012年之後就不在維護了,但在工程應用中IK算是比較流行的一款!
下載地址:https://github.com/medcl/elasticsearch-analysis-ik/releases
相關介紹:https://www.jianshu.com/p/4e79845bc72d
Kibana
Kibana 是一個開源的分析和可視化平臺,旨在與 Elasticsearch 合作。Kibana 提供搜索、查看和與存儲在 Elasticsearch 索引中的數據進行交互的功能。開發者或運維人員可以輕鬆地執行高級數據分析,並在各種圖表、表格和地圖中可視化數據。
CAS
什麼是單點登錄?
單點登錄(Single Sign On),簡稱爲 SSO,是目前比較流行的企業業務整合的解決方案之一。SSO的定義是在多個應用系統中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統。
實現單點登錄有多種方案:
(1)使用redis實現session共享
(2)使用開源的單點登錄系統(推薦)
CAS(Central Authentication Service的縮寫,中央認證服務)是耶魯大學Technology and Planning實驗室的Shawn Bayern 在2002年出的一個開源系統。剛開始名字叫Yale CAS。 Yale CAS 1.0的目標只是一個單點登錄的系統,隨着慢慢用開,功能就越來越多了,2.0就提供了多種認證的方式。
2004年12月,CAS轉成JASIG(Java Administration Special Interesting Group)的一個項目,項目也隨着改名爲 JASIG CAS,這就是爲什麼現在有些CAS的鏈接還是有jasig的字樣。
2012年,JASIG跟Sakai基金會合並,改名爲Apereo基金會,所有CAS也隨着改名爲Apereo CAS。
cas官網: https://www.apereo.org/projects/cas
源碼地址: https://github.com/apereo/cas/tree/5.3.x
CAS 具有以下特點:
- 開源的企業級單點登錄解決方案。
- CAS Server 爲需要獨立部署的 Web 應用。
- CAS Client 支持非常多的客戶端(這裏指單點登錄系統中的各個 Web 應用),包括 Java, .Net, PHP, Perl,Apache, uPortal, Ruby 等。
從結構上看,CAS 包含兩個部分: CAS Server 和 CAS Client。
- CAS Server 需要獨立部署,主要負責對用戶的認證工作;
- CAS Client 負責處理對客戶端受保護資源的訪問請求,需要登錄時,重定向到 CAS Server。
下圖是 CAS 最基本的協議過程:
SSO單點登錄訪問流程主要有以下步驟:
- 訪問服務:SSO客戶端發送請求訪問應用系統提供的服務資源。
- 定向認證:SSO客戶端會重定向用戶請求到SSO服務器。
- 用戶認證:用戶身份認證。
- 發放票據:SSO服務器會產生一個隨機的ServiceTicket。
- 驗證票據:SSO服務器驗證票據Service Ticket的合法性,驗證通過後,允許客戶端訪問服務。
- 傳輸用戶信息:SSO服務器驗證票據通過後,傳輸用戶認證結果信息給客戶端。
相關介紹:系統開發單點登錄解決方案-CAS快速入門
Redis
Redis(Remote Dictionary Server ),即遠程字典服務,是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。從2010年3月15日起,Redis的開發工作由VMware主持。從2013年5月開始,Redis的開發由Pivotal贊助。
官網:https://redis.io/
在線測試:http://try.redis.io/
相關介紹:Redis簡明教程
CAP定理
分佈式系統(distributed system)正變得越來越重要,大型網站幾乎都是分佈式的。
分佈式系統的最大難點,就是各個節點的狀態如何同步。CAP 定理是這方面的基本定理,也是理解分佈式系統的起點。
CAP定理是在 1998年加州大學的計算機科學家 Eric Brewer (埃裏克.布魯爾)提出,分佈式系統有三個指標:
- Consistency 一致性
- Availability 可用性
- Partition tolerance 分區容錯
它們的第一個字母分別是 C、A、P。
Eric Brewer 說,這三個指標不可能同時做到。這個結論就叫做 CAP 定理。
Partition tolerance
大多數分佈式系統都分佈在多個子網絡。每個子網絡就叫做一個區(partition)。分區容錯的意思是,區間通信可能失敗。比如,一臺服務器放在中國,另一臺服務器放在美國,這就是兩個區,它們之間可能無法通信。
上圖中,G1 和 G2 是兩臺跨區的服務器。G1 向 G2 發送一條消息,G2 可能無法收到。系統設計的時候,必須考慮到這種情況。
一般來說,分區容錯無法避免,因此可以認爲 CAP 的 P 總是成立。CAP 定理告訴我們,剩下的 C 和 A 無法同時做到。
Consistency
意思是,寫操作之後的讀操作,必須返回該值。舉例來說,某條記錄是 v0,用戶向 G1 發起一個寫操作,將其改爲 v1。
接下來,用戶的讀操作就會得到 v1。這就叫一致性。
問題是,用戶有可能向 G2 發起讀操作,由於 G2 的值沒有發生變化,因此返回的是 v0。G1 和 G2 讀操作的結果不一致,這就不滿足一致性了。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cQWVJHeC-1590478300386)(assets/bg2018071604.png)]
爲了讓 G2 也能變爲 v1,就要在 G1 寫操作的時候,讓 G1 向 G2 發送一條消息,要求 G2 也改成 v1。
這樣的話,用戶向 G2 發起讀操作,也能得到 v1。
Availability
意思是隻要收到用戶的請求,服務器就必須給出迴應。
用戶可以選擇向 G1 或 G2 發起讀操作。不管是哪臺服務器,只要收到請求,就必須告訴用戶,到底是 v0 還是 v1,否則就不滿足可用性。
Consistency 和 Availability 的矛盾
一致性和可用性,爲什麼不可能同時成立?答案很簡單,因爲可能通信失敗(即出現分區容錯)。
如果保證 G2 的一致性,那麼 G1 必須在寫操作時,鎖定 G2 的讀操作和寫操作。只有數據同步後,才能重新開放讀寫。鎖定期間,G2 不能讀寫,沒有可用性不。
如果保證 G2 的可用性,那麼勢必不能鎖定 G2,所以一致性不成立。
綜上所述,G2 無法同時做到一致性和可用性。系統設計時只能選擇一個目標。如果追求一致性,那麼無法保證所有節點的可用性;如果追求所有節點的可用性,那就沒法做到一致性。
參考來源:阮一峯 -CAP 定理的含義
BASE理論
BASE:全稱:Basically Available(基本可用),Soft state(軟狀態),和 Eventually consistent(最終一致性)三個短語的縮寫,來自 ebay 的架構師提出。
Base 理論是對 CAP 中一致性和可用性權衡的結果,其來源於對大型互聯網分佈式實踐的總結,是基於 CAP 定理逐步演化而來的。其核心思想是:
既是無法做到強一致性(Strong consistency),但每個應用都可以根據自身的業務特點,採用適當的方式來使系統達到最終一致性(Eventual consistency)。
Basically Available(基本可用)
什麼是基本可用呢?假設系統,出現了不可預知的故障,但還是能用,相比較正常的系統而言:
- 響應時間上的損失:正常情況下的搜索引擎 0.5 秒即返回給用戶結果,而基本可用的搜索引擎可以在 1 秒作用返回結果。
- 功能上的損失:在一個電商網站上,正常情況下,用戶可以順利完成每一筆訂單,但是到了大促期間,爲了保護購物系統的穩定性,部分消費者可能會被引導到一個降級頁面。
Soft state(軟狀態)
什麼是軟狀態呢?相對於原子性而言,要求多個節點的數據副本都是一致的,這是一種 “硬狀態”。
軟狀態指的是:允許系統中的數據存在中間狀態,並認爲該狀態不影響系統的整體可用性,即允許系統在多個不同節點的數據副本存在數據延時。
Eventually consistent(最終一致性)
這個比較好理解了哈。
上面說軟狀態,然後不可能一直是軟狀態,必須有個時間期限。在期限過後,應當保證所有副本保持數據一致性。從而達到數據的最終一致性。這個時間期限取決於網絡延時,系統負載,數據複製方案設計等等因素。
稍微官方一點的說法就是:
系統能夠保證在沒有其他新的更新操作的情況下,數據最終一定能夠達到一致的狀態,因此所有客戶端對系統的數據訪問最終都能夠獲取到最新的值。
而在實際工程實踐中,最終一致性分爲 5 種:
1. 因果一致性(Causal consistency)
指的是:如果節點 A 在更新完某個數據後通知了節點 B,那麼節點 B 之後對該數據的訪問和修改都是基於 A 更新後的值。於此同時,和節點 A 無因果關係的節點 C 的數據訪問則沒有這樣的限制。
2. 讀己之所寫(Read your writes)
這種就很簡單了,節點 A 更新一個數據後,它自身總是能訪問到自身更新過的最新值,而不會看到舊值。其實也算一種因果一致性。
3. 會話一致性(Session consistency)
會話一致性將對系統數據的訪問過程框定在了一個會話當中:系統能保證在同一個有效的會話中實現 “讀己之所寫” 的一致性,也就是說,執行更新操作之後,客戶端能夠在同一個會話中始終讀取到該數據項的最新值。
4. 單調讀一致性(Monotonic read consistency)
單調讀一致性是指如果一個節點從系統中讀取出一個數據項的某個值後,那麼系統對於該節點後續的任何數據訪問都不應該返回更舊的值。
5. 單調寫一致性(Monotonic write consistency)
指一個系統要能夠保證來自同一個節點的寫操作被順序的執行。
然而,在實際的實踐中,這 5 種系統往往會結合使用,以構建一個具有最終一致性的分佈式系統。實際上,不只是分佈式系統使用最終一致性,關係型數據庫在某個功能上,也是使用最終一致性的,比如備份,數據庫的複製過程是需要時間的,這個複製過程中,業務讀取到的值就是舊的。當然,最終還是達成了數據一致性。這也算是一個最終一致性的經典案例。
參考來源:分佈式理論(二)——Base 理論
Mycat
如今隨着互聯網的發展,數據的量級也是呈指數的增長,從GB到TB到PB。對數據的各種操作也是愈加的困難,如何解決這個問題呢?此時就需要做數據庫集羣,爲了提高查詢性能將一個數據庫的數據分散到不同的數據庫中存儲,這就是我們通常所說的數據庫分片。
如何實現數據庫分片?我們通常會使用mycat數據庫中間件來解決。
MyCat是一個開源的分佈式數據庫系統,是一個實現了MySQL協議的服務器,前端用戶可以把它看作是一個數據庫代理,用MySQL客戶端工具和命令行訪問,而其後端可以用MySQL原生協議與多個MySQL服務器通信,也可以用JDBC協議與大多數主流數據庫服務器通信,其核心功能是分表分庫,即將一個大表水平分割爲N個小表,存儲在後端MySQL服務器裏或者其他數據庫裏。
MyCat發展到目前的版本,已經不是一個單純的MySQL代理了,它的後端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流數據庫,也支持MongoDB這種新型NoSQL方式的存儲,未來還會支持更多類型的存儲。而在最終用戶看來,無論是那種存儲方式,在MyCat裏,都是一個傳統的數據庫表,支持標準的SQL語句進行數據的操作,這樣一來,對前端業務系統來說,可以大幅降低開發難度,提升開發速度。
相關介紹:數據庫中間件——MyCat
Snowflake
snowflake是Twitter開源的分佈式ID生成算法,結果是一個long型的ID。
這種方案大致來說是一種以劃分命名空間(UUID也算,由於比較常見,所以單獨分析)來生成ID的一種算法,這種方案把64-bit分別劃分成多段,分開來標示機器、時間等。
其核心思想是:使用41bit作爲毫秒數,10bit作爲機器的ID(5個bit是數據中心,5個bit的機器ID),12bit作爲毫秒內的流水號,最後還有一個符號位,永遠是0。
比如在snowflake中的64-bit分別表示如下圖(圖片來自網絡)所示:
相關介紹:雪花算法(snowflake) :分佈式環境,生成全局唯一的訂單號
Twitter的分佈式自增ID算法snowflake (Java版)
編者語
僅供學習交流使用,引用或參考不繫編者個人觀點,請諸位學者批評與指正。
lph-China:https://blog.csdn.net/lph188
2020/5/26