目錄
一、認識微服務
1.單體架構
2.微服務
3.SpringCloud?
二、微服務拆分
1.服務拆分原則
2.服務調用
3. RestTemplate
三、服務注冊和發現
1. 注冊中心原理
2. 服務發現
2.1 服務注冊
2.2 服務發現
四、OpenFeign
一、認識微服務
1.單體架構
單體架構就是整個項目中所有功能模塊都在一個工程中開發;項目部署時需要對所有模塊一起編譯、打包;項目的架構設計、開發模式都非常簡單。
當項目規模較小時,單體架構上手簡單、部署、運維都很方便。但是一旦項目規模變大,例如淘寶那樣的,單體架構就遠遠不夠了。
2.微服務
微服務架構就是將單體架構中的功能模塊從單體架構中拆分出來,獨立部署為多個服務。同時滿足以下要求:
-
單一職責:一個微服務負責一部分業務功能,并且其核心數據不依賴于其它模塊。
-
團隊自治:每個微服務都有自己獨立的開發、測試、發布、運維人員,團隊人員規模不超過10人
-
服務自治:每個微服務都獨立打包部署,訪問自己獨立的數據庫。并且要做好服務隔離,避免對其它服務產生影響
例如上面的商城項目就可以拆分為多個模塊,然后獨立部署。
3.SpringCloud?
微服務拆分以后碰到的各種問題都有對應的解決方案和微服務組件,而SpringCloud框架可以說是目前Java領域最全面的微服務組件的集合了。
SpringCloud依托于SpringBoot的自動裝配能力,大大降低了其項目搭建、組件使用的成本。
在選擇SpringCloud版本的時候,一定要選擇與SpringBoot相對應的版本。
二、微服務拆分
1.服務拆分原則
拆分微服務時,要保證高內聚、低耦合的原則。即對一個微服務進行修改,不會對另一個微服務產生影響。
服務拆分方式有兩種:縱向拆分和橫向拆分。
所謂縱向拆分,就是按照項目的功能模塊來拆分。例如商城項目中,就有用戶管理功能、訂單管理功能、購物車功能、商品管理功能、支付功能等。那么按照功能模塊將他們拆分為一個個服務,就屬于縱向拆分。這種拆分模式可以盡可能提高服務的內聚性。
而橫向拆分,是看各個功能模塊之間有沒有公共的業務部分,如果有將其抽取出來作為通用服務。例如用戶登錄是需要發送消息通知,記錄風控數據,下單時也要發送短信,記錄風控數據。因此消息發送、風控數據記錄就是通用的業務功能,因此可以將他們分別抽取為公共服務:消息中心服務、風控管理服務。這樣可以提高業務的復用性,避免重復開發。同時通用業務一般接口穩定性較強,也不會使服務之間過分耦合。
2.服務調用
因為上述的商城項目使用的是單體架構,一個功能可以隨意調用另一個功能的方法。但是再拆分之后,兩個模塊之間沒有任何聯系。如果購物車業務中需要查詢商品信息,此時就需要去訪問商品模塊,流程如下:
代碼中需要變化的是這一步:
3. RestTemplate
Spring給我們提供了一個RestTemplate的API,可以方便的實現Http請求的發送。常見的Get、Post、Put、Delete請求都支持,如果請求參數比較復雜,還可以使用exchange方法來構造請求。
首先,需要在請求服務的微服務模塊中定義一個配置類,將RestTemplate注冊為一個Bean:
@Configuration
public class RemoteCallConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}
之后,在調用服務的Service類中進行遠程調用:
此時,購物車模塊就可以查詢到商品的相關信息了。
在調用之前,要將RestTemplate這個Bean對象進行注入。
三、服務注冊和發現
如果上述商品的微服務模塊被調用的較多,為了應對更高的并發,進行了多實例部署,如圖:
我們會發現,每一個實例的端口都是不一樣的(實際上可能ip地址也不相同)。但是在上述代碼中我們將ip地址寫死了,導致不管部署多少個實例,都只會調用同一個實例。為了解決該問題,就需要引入注冊中心的概念。
1. 注冊中心原理
在微服務的遠程調用過程中,包括兩個角色:
-
服務提供者:提供接口供其它微服務訪問,比如
item-service
-
服務消費者:調用其它微服務提供的接口,比如
cart-service
在大型微服務項目中,服務提供者的數量會非常多,為了管理這些服務就引入了注冊中心的概念。注冊中心、服務提供者、服務消費者三者間關系如下:
注冊中心會知道服務提供者有多少個實例,然后告知服務調用者,服務調用者會采取某一個負載均衡算法來選擇一個實例進行訪問。如果服務提供者中有某一個實例宕機了,注冊中心就會實時更新,告知服務調用者這個示例不可使用,防止白白訪問,浪費資源。
2. 服務發現
2.1 服務注冊
目前開源的注冊中心框架有很多,這里使用阿里巴巴公司出品的Nacos。首先把item-service
注冊到Nacos(其實可能每一個微服務項目都需要注冊,因為可能將來會被調用)。
注冊步驟分為兩步,添加依賴,進行配置
在item-service
的pom.xml
中添加依賴:
<!--nacos 服務注冊發現-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
在item-service
的application.yml
中添加nacos地址配置,nocos地址改為自己的ip地址。
spring:application:name: item-service # 服務名稱cloud:nacos:server-addr: 192.168.150.101:8848 # nacos地址
完成上述兩步之后,就相當于已經注冊好了。?
2.2 服務發現
在服務調用者的模塊中也要進行上述兩步配置。
然后,服務調用者cart-service
就可以去訂閱item-service
服務了。
服務發現需要用到一個工具,DiscoveryClient,SpringCloud已經幫我們自動裝配,我們可以直接注入使用:
然后對原來的遠程調用進行修改,將寫死的ip和端口改為方法調用來獲取:
四、OpenFeign
我們發現修改之后的代碼,從一行變成了九行,使用RestTemplate實現服務的遠程調用增加了代碼的復雜度。為了簡化代碼,就需要用到OpenFeign組件了。
1.1 首先在購物車微服務模塊中引入OpenFeign
的依賴和loadBalancer
依賴:
<!--openFeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--負載均衡器--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
1.2 在購物車啟動類中上添加注解,啟動OpenFeign功能:
1.3 編寫OpenFeign客戶端:
在模塊中,定義一個新的接口,編寫Feign客戶端,這里是定義了一個商品模塊的客戶端。
package com.hmall.cart.client;import com.hmall.cart.domain.dto.ItemDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.util.List;@FeignClient("item-service")
public interface ItemClient {@GetMapping("/items")List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
}
1.4?使用FeignClient:
首先在代碼中注入ItemClient,然后直接調用ItemClient中的方法。這里我理解的是購物車模塊通過客戶端調用該方法,就相當于在瀏覽器中直接訪問ip(這里不是通過瀏覽器,而是通過Nacos),然后商品模塊中的相應方法就會執行,查詢數據庫之后將結果進行返回。