第一章 微服務概念
1.0 科普一些術語
科普一下項目開發過程中常出現的術語,方便后續內容的理解。
**服務器:**分軟件與硬件,軟件:類型tomcat這種跑項目的程序, 硬件:用來部署項目的電腦(一般性能比個人電腦好)
**服務:**操作系統上術語:一個程序,開發中術語:一個能對外提供功能的程序
**微服務:**小的服務,一個完整項目可以拆n個子項目,這些子項目能獨立運行,獨立對為提供功能。
**節點:**微觀上:一個服務,宏觀上:一臺服務器
**垂直擴展:**垂直擴展是指增強單機硬件性能
**水平擴展:**通過增加更多的服務器或者程序實例來分散負載,從而提升存儲能力和計算能力。
**容錯率:**允許服務器集群(一堆服務器)錯誤(異常/故障)出現的范圍和概率,
**高內聚低耦合:**內聚–>講究程序功能獨立 耦合—>講究程序間交互,
? 以java為例子:高內聚低耦合:講究類設計時盡量簡單(邊界清晰/功能簡單),類與類間交互盡可能少(減少類間的相互調用)
**流量:**有很多種說,開發中說的是訪問量(請求次數)
**服務間依賴:**項目與項目間的調用,程序與程序間的調用
**資源調度:**各種資源進行合理有效的調節和測量及分析和使用,開發中資源:服務器,內存,CPU,IO等項目運行需要各種軟硬件。
**單點:**唯一,開發中的單點:唯一一個mysql數據庫,唯一個服務器
**單點故障:**如果項目/程序部署唯一一個服務器,它掛了,那就玩完了
**宕機:**服務器掛了
1.1 單體、分布式、集群
我們學習微服務之前,需要先理解單體、集群、分布式這些概念,這樣會幫助我們在學習后面課程會更加容易些.
單體
一個系統業務量很小的時候所有的代碼都放在一個項目中就好了,然后這個項目部署在一臺服務器上就好了。整個項目所有的服務都由這臺服務器提供。這就是單機結構。
單體應用開發簡單,部署測試簡單.但是存在一些問題,比如:單點問題,單機處理能力有限,當你的業務增長到一定程度的時候,單機的硬件資源將無法滿足你的業務需求。
分布式
由于整個系統運行需要使用到Tomcat和MySQL,單臺服務器處理的能力有限,2G的內存需要分配給Tomcat和MySQL使用,,隨著業務越來越復雜,請求越來越多. 內存越來越不夠用了,所以這時候我們就需要進行分布式的部署.
我們進行一個評論的請求,這個請求是需要依賴分布在兩臺不同的服務器的組件[Tomat和MySQL],才能完成的. 所以叫做分布式的系統.
集群
在上面的圖解中其實是存在問題的,比如Tomcat存在單點故障問題,一旦Tomcat所在的服務器宕機不可用了,我們就無法提供服務了,所以針對單點故障問題,我們會使用集群來解決.那什么是集群模式呢?
單機處理到達瓶頸的時候,你就把單機復制幾份,這樣就構成了一個“集群”。集群中每臺服務器就叫做這個集群的一個“節點”,所有節點構成了一個集群。每個節點都提供相同的服務,那么這樣系統的處理能力就相當于提升了好幾倍(有幾個節點就相當于提升了這么多倍)。
但問題是用戶的請求究竟由哪個節點來處理呢?最好能夠讓此時此刻負載較小的節點來處理,這樣使得每個節點的壓力都比較平均。要實現這個功能,就需要在所有節點之前增加一個“調度者”的角色,用戶的所有請求都先交給它,然后它根據當前所有節點的負載情況,決定將這個請求交給哪個節點處理。這個“調度者”有個牛逼了名字——負載均衡服務器。
我們在上面的圖中僅展示了Tomcat的集群,如果MySQL壓力比較大的情況下,我們也是可以對MySQL進行集群的.
1.2 系統架構演變
? 隨著互聯網的發展,網站應用的規模也不斷的擴大,進而導致系統架構也在不斷的變化。
從互聯網早起到現在,系統架構大體經歷了下面幾個過程:
? 單體應用架構—>垂直應用架構—>分布式架構—>SOA架構—>微服務架構。
接下來我們就來了解一下每種系統架構是什么樣子的, 以及各有什么優缺點。
1.2.1 單體應用架構
? 互聯網早期,一般的網站應用流量較小,只需一個應用,將所有功能代碼都部署在一起就可以,這
樣可以減少開發、部署和維護的成本。
? 比如說一個電商系統,里面會包含很多用戶管理,商品管理,訂單管理,物流管理等等很多模塊,
我們會把它們做成一個web項目,然后部署到一臺tomcat服務器上。
優點:
-
項目架構簡單,小型項目的話, 開發成本低
-
項目部署在一個節點上, 維護方便
缺點:
-
全部功能集成在一個工程中,對于大型項目來講不易開發和維護
-
項目模塊之間緊密耦合,單點容錯率低
-
無法針對不同模塊進行針對性優化和水平擴展
1.2.2 垂直應用架構
? 隨著訪問量的逐漸增大,單一應用只能依靠增加節點來應對,但是這時候會發現并不是所有的模塊
都會有比較大的訪問量.
? 還是以上面的電商為例子, 用戶訪問量的增加可能影響的只是用戶和訂單模塊, 但是對消息模塊
的影響就比較小. 那么此時我們希望只多增加幾個訂單模塊, 而不增加消息模塊. 此時單體應用就做不
到了, 垂直應用就應運而生了.
? 所謂的垂直應用架構,就是將原來的一個應用拆成互不相干的幾個應用,以提升效率。比如我們可
以將上面電商的單體應用拆分成:
-
電商系統(用戶管理 商品管理 訂單管理)
-
后臺系統(用戶管理 訂單管理 客戶管理)
-
CMS系統(廣告管理 營銷管理)
這樣拆分完畢之后,一旦用戶訪問量變大,只需要增加電商系統的節點就可以了,而無需增加后臺
和CMS的節點。
優點:
-
系統拆分實現了流量分擔,解決了并發問題,而且可以針對不同模塊進行優化和水平擴展
-
一個系統的問題不會影響到其他系統,提高容錯率
缺點:
-
系統之間相互獨立, 無法進行相互調用
-
系統之間相互獨立, 會有重復的開發任務
1.2.3 分布式架構
? 當垂直應用越來越多,重復的業務代碼就會越來越多。這時候,我們就思考可不可以將重復的代碼
抽取出來,做成統一的業務層作為獨立的服務,然后由前端控制層調用不同的業務層服務呢?
? 這就產生了新的分布式系統架構。它將把工程拆分成表現層和服務層兩個部分,服務層中包含業務
邏輯。表現層只需要處理和頁面的交互,業務邏輯都是調用服務層的服務來實現。
優點:
- 抽取公共的功能為服務層,提高代碼復用性
缺點:
- 系統間耦合度變高,調用關系錯綜復雜,難以維護
1.2.4 SOA架構
? 在分布式架構下,當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增加
一個調度中心對集群進行實時管理。此時,用于資源調度和治理中心(SOA Service Oriented
Architecture,面向服務的架構)是關鍵。
優點:
- 使用注冊中心解決了服務間調用關系的自動調節
缺點:
-
服務間會有依賴關系,一旦某個環節出錯會影響較大( 服務雪崩 )
-
服務關系復雜,運維、測試部署困難
1.2.5 微服務架構
微服務架構在某種程度上是面向服務的架構SOA繼續發展的下一步,它更加強調服務的"徹底拆分"。
優點:
-
服務原子化拆分,獨立打包、部署和升級,保證每個微服務清晰的任務劃分,利于擴展
-
微服務之間采用RESTful等輕量級Http協議相互調用
缺點:
- 分布式系統開發的技術成本高(容錯、分布式事務等)
1.3 微服務架構介紹
? 微服務架構, 簡單的說就是將單體應用進一步拆分,拆分成更小的服務,每個服務都是一個可以獨立運行的項目。
微服務架構的常見問題
一旦采用微服務系統架構,就勢必會遇到這樣幾個問題:
-
這么多小服務,如何管理他們?
-
這么多小服務,他們之間如何通訊?
-
這么多小服務,客戶端怎么訪問他們?
-
這么多小服務,一旦出現問題了,應該如何自處理?
-
這么多小服務,一旦出現問題了,應該如何排錯?
對于上面的問題,是任何一個微服務設計者都不能繞過去的,因此大部分的微服務產品都針對每一個問題提供了相應的組件來解決它們。
1.4 SpringCloud介紹
Spring Cloud是一系列框架的集合。它利用Spring Boot的開發便利性巧妙地簡化了分布式系統基礎設施的開發,如服務發現注冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,都可以用Spring Boot的開發風格做到一鍵啟動和部署。
Spring Cloud并沒有重復制造輪子,它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通過Spring Boot風格進行再封裝屏蔽掉了復雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分布式系統開發工具包。
1.4.1 SpringBoot和SpringCloud有啥關系?
-
SpringBoot專注于快速方便的開發單個個體微服務。
-
SpringCloud是關注全局的微服務協調整理治理框架,它將SpringBoot開發的一個個單體微服務整合并管理起來,為各個微服務之間提供,配置管理、服務發現、斷路器、路由、事件總線、分布式事務、等等集成服務。
總結: SpringBoot專注于快速、方便的開發單個微服務個體,SpringCloud關注全局的服務治理組件的集合。
1.4.2 SpringCloud版本名稱?
因為Spring Cloud不同其他獨立項目,它是擁有很多子項目的大項目。所以它是的版本是 版本名+版本號 (如Greenwich.SR6)。
版本名:是倫敦的地鐵名
版本號:SR(Service Releases)是固定的 ,大概意思是穩定版本。后面會有一個遞增的數字。
所以 Greenwich.SR6就是Greenwich的第6個Release版本。
1.4.3 為什么是SpringCloud ?
目前,業界比較成熟的服務框架有很多,比如:Hessian、CXF、Dubbo、Dubbox、Spring Cloud、gRPC、thrift等技術實現
這里我們為什么選擇SpringCloud Alibaba呢,主要因為SpringCloud Netflix的組件:服務注冊與發現的 Eureka、服務限流降級的 Hystrix、網關 Zuul都已經停止更新了,當然繼續使用是沒問題的,只是出現問題,官方不維護,需要自行解決.
第二章 微服務環境搭建
2.1 一些說明
為了方便講解SpringCloud課程,我們以電商項目2個核心模塊:商品模塊、訂單模塊為例子,一一講解SpringCloud組件的使用。
學習SpringCloud組件要訣:不求甚解
1>能解決啥問題
2>怎么解決(理解原理)
3>API調用(代碼怎么寫)–建議寫3遍–【1遍抄全,2遍思考,3遍掌握】
4>總結,開口表述
5>類比以前代碼結構
微服務-----完整項目按功能分類拆分成n個子項目/子模塊,這些子模塊能對外提供對應的功能。我們稱這些服務為微服務
落地到代碼:單看子項目,每個子項目就是一個完整項目(springmvc項目)----記住沒啥高大上的
商品微服務
- 對外提供查詢商品列表接口
- 對外提供查詢某個商品信息接口
訂單微服務
- 對外提供創建訂單接口
服務調用
在微服務架構中,最常見的場景就是微服務之間的相互調用。以下單為例子:客戶向訂單微服務發起一個下單的請求,在進行保存訂單之前需要調用商品微服務查詢商品的信息。
一般把調用方稱為服務消費者,把被調用方稱為服務提供者。
上例中,訂單微服務就是服務消費者, 而商品微服務是服務提供者。
2.2 技術選型
持久層: MyBatis-Plus
數據庫: MySQL5.7
其他: SpringCloud Alibaba 技術棧
2.3 模塊設計
— shop-parent 父工程
? — shop-product-api 商品微服務api 【存放商品實體】
? — shop-product-server 商品微服務 【端口:808x】
? — shop-order-api 訂單微服務api 【存放訂單實體】
? — shop-order-server 訂單微服務 【端口:809x】
shop-product-server:子項目-商品微服務,對外提供查詢商品信息的接口
shop-order-server:子項目-訂單微服務,對外提供創建訂單的接口
shop-product-api / shop-order-api : 各自微服務依賴的實體類,為啥要拆開?答案是:解耦
此處暫時先記住
2.4 版本說明
? https://github.com/alibaba/spring-cloud-alibaba/wiki/版本說明
2.5 創建父工程
創建 shop-parent 一個maven工程,然后在pom.xml文件中添加下面內容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.xxx</groupId><artifactId>shop-parent</artifactId><version>1.0.0</version><packaging>pom</packaging><!--父工程--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.2.RELEASE</version></parent><!--依賴版本的鎖定--><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-cloud.version>Hoxton.SR8</spring-cloud.version><spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
</project>
2.6 創建商品微服務
1.創建shop-product-api項目,然后在pom.xml文件中添加下面內容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>shop-parent</artifactId><groupId>cn.xxx</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>shop-product-api</artifactId><!--依賴--><dependencies><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>
2 創建實體類
//商品
@Getter
@Setter
@ToString
@TableName("t_product")
public class Product implements Serializable {@TableId(type= IdType.AUTO)private Long id;//主鍵private String name;//商品名稱private Double price;//商品價格private Integer stock;//庫存
}
3.創建shop-product-server項目,然后在pom.xml文件中添加下面內容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>shop-parent</artifactId><groupId>cn.xxx</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>shop-product-server</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.56</version></dependency><dependency><groupId>cn.xxx</groupId><artifactId>shop-product-api</artifactId><version>1.0.0</version></dependency></dependencies>
</project>
4.編寫配置文件application.yml
server:port: 8081
spring:application:name: product-servicedatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql:///shop-product?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=trueusername: rootpassword: admin
5.在數據庫中創建shop-product的數據庫
CREATE TABLE `t_product` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主鍵',`name` varchar(255) DEFAULT NULL COMMENT '商品名稱',`price` double(10,2) DEFAULT NULL COMMENT '商品價格',`stock` int DEFAULT NULL COMMENT '庫存',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
INSERT INTO t_product VALUE(NULL,'小米','1000','5000');
INSERT INTO t_product VALUE(NULL,'華為','2000','5000');
INSERT INTO t_product VALUE(NULL,'蘋果','3000','5000');
INSERT INTO t_product VALUE(NULL,'OPPO','4000','5000');
6.創建ProductMapper
package cn.xxx.mapper;import cn.xxx.domain.Product;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface ProductMapper extends BaseMapper<Product> {
}
7.創建ProductService接口和實現類
public interface IProductService extends IService<Product> {
}
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {
}
8.創建Controller
package cn.xxx.controller;
@RestController
@Slf4j
public class ProductController {@Autowiredprivate ProductService productService;//商品信息查詢@RequestMapping("/products/{pid}")public Product findByPid(@PathVariable("pid") Long pid) {log.info("接下來要進行{}號商品信息的查詢", pid);Product product = productService.findByPid(pid);log.info("商品信息查詢成功,內容為{}", JSON.toJSONString(product));return product;}
}
9.編寫啟動類ProductServer.java
package cn.xxx;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("cn.xxx.mapper")
public class ProductServer {public static void main(String[] args) {SpringApplication.run(ProductServer.class,args);}
}
10.通過瀏覽器訪問服務
2.7 創建訂單微服務
1.創建shop-order-api項目,然后在pom.xml文件中添加下面內容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>shop-parent</artifactId><groupId>cn.xxx</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>shop-order-api</artifactId><!--依賴--><dependencies><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>
2 創建實體類
package cn.xxx.domain;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Getter;
import lombok.Setter;import java.io.Serializable;//訂單
@Getter
@Setter
@ToString
@TableName("t_order")
public class Order implements Serializable {<