單體架構:將業務全部功能集中到一個項目中,打成一個war包存儲,部署在一臺服務器中,只有一個數據庫
優點 :架構簡單,部署成本低。適合小型項目
問題:高并發性能問題,開發時代碼耦合問題,部署升級時停服的問題
垂直架構:拆分模塊,每個模塊使用自己的數據庫,如果有模塊需要其他模塊數據時需要自己查對方模塊數據庫
問題:大量代碼冗余,系統難以維護,性能問題,部署問題
分布式架構:根據業務功能對系統做拆分,每個業務功能作為獨立項目開發,稱為一個服務
服務之間相互調用,分布式多節點部署
優點:降低耦合,有利于服務升級和拓展 適合大型互聯網項目
缺點:服務調用關系錯綜復雜
在進行服務拆分的時候要考慮很多問題:服務拆分的粒度如何界定,服務之后如何調用,服務的調用關系如何管理,需要指定一套有效的標準來約束分布架構
微服務
架構特點:1.單一職責,每一個服務對應唯一的業務能力,做到單一職責
2.自治,團隊獨立,技術獨立,數據獨立,獨立部署和交付
3.面向服務,服務提供統一的接口,與語言技術無關
4.隔離性強,服務調用做好隔離,容錯,降級避免出現級聯問題(級聯故障是由于正反饋循環并且隨著時間的增加所產生的故障。典型表現:最初由單個節點或子系統故障觸發的連鎖反應)
微服務的上述特點給分布式架構制定啦一個標準,進一步降低服務之間的耦合,提供服務的獨立性和靈活性。微服務是一種經過良好架構設計的分布式架構方案
微服務技術的對比
SpringCloud微服務框架
官網地址:Spring Cloud
開發springcloud組件的組織:spring社區,alibaba,netflix
springCloud集成了各種微服務功能組件,基于SpringBoot實現組件的自動裝配
常見的組件:服務注冊發現(Eureka,nacos,consul),服務遠程調用(OpenFeign,Dubbo),服務鏈路監控(Zipkin,Sleuth),統一配置管理(SpringCloudConfig,nacos),統一網關路由(SpringCloudGateway,zuul),流控降級保護(Hystix,Sentinel)
SpringCloud底層是依賴于SpringBoot的,并且有版本兼容關系
服務拆分原則:1.不同微服務不用重復開發相同業務
2.微服務數據獨立,有自己的數據庫
3.微服務可以將自己的業務暴露為接口,供其他微服務使用
遠程調用
微服務的調用方式:基于RestTemplate發起的http請求實現遠程調用,http請求做遠程調用只要知道ip,端口,接口路徑,請求參數即可。
步驟:1.注冊RestTemplate的實例到Spring容器
2.修改消費者order-service服務中的OrderService類中的queryOrderById方法,根據Order對象中的userId查詢User
3.將查詢到的User填到Order對象
#在order-service服務中的OrderApplication啟動類中,注冊RestTemplate實例
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}
#修改order-service服務中的OrderService類中的queryOrderById方法
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 1.查詢訂單Order order = orderMapper.findById(orderId);//2查詢用戶String url="http://userservice/user/"+order.getUserId();User user = restTemplate.getForObject(url, User.class);// 3封裝user信息order.setUser(user);// 4.返回return order;}
}
在服務調用關系中,會有兩個不同的角色,這兩個角色是相對的
服務提供者Provider:一次業務中,被其他微服務調用的服務,提供接口給其他服務
服務消費者consumer:一次業務中,調用其他微服務的服務,調用其他微服務提供的接口
注冊中心
解決問題:服務注冊與發現(服務治理問題)
Eureka注冊中心
EurekaServer:服務端,注冊中心
EurekaClient:客戶端
服務注冊:提供者啟動之后將自己的信息注冊到eureka-server(Eureka服務端)
eureka-server保存服務名稱到服務實例地址列表的映射關系
服務拉取:消費者根據服務名稱拉取實例地址列表(注冊表)并緩存到本地
消費者根據負載均衡算法選中一個實例地址,發起遠程調用
健康檢查:提供者每隔一段時間(默認30秒)向eureka-server發起請求,報告自己狀態。稱為心跳
當超過一段時間(90秒)沒有發送心跳,eureka-server認為微服務實例故障,將該實例從列表中剔除,拉取服務時,該故障實例排除
搭建eureka-server
1.引入依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
2.編寫啟動類
@SpringBootApplication
@EnableEurekaServer //開啟eureka的注冊中心功能
public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class, args);}
}
3.編寫配置文件application.yml
server:port: 10086
spring:application:name: eureka-server
eureka:client:service-url: defaultZone: http://127.0.0.1:10086/eureka
啟動成功
服務注冊
引入依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件
spring:application:name: orderservice
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka
可以將user-service多次啟動,模擬多實例部署,注意修改端口設置-Dserver.port=自定義的端口號
如果沒有service選項【IDEA】idea打開新項目,左下角的工作欄中沒有顯示Services解決辦法 - Angel擠一擠 - 博客園
在order-service完成服務拉取,修改OrderService的代碼,修改訪問路徑
在order-service項目的啟動類OrderApplication中RestTemplate添加負載均衡諸界
@Bean@LoadBalanced //負載均衡注解public RestTemplate restTemplate(){return new RestTemplate();}
負載均衡
SpringCloud底層利用Ribbon的組件,實現負載均衡。服務調用者動態調用服務提供者的多個節點
Ribbon內部就是集成了LoadBalancerClient負載均衡,通過@LoadBalance注解開啟負載均衡器。
基本流程:RibbonLoadBalanceClient從請求url中獲取服務名稱,DynamicServerListLoadBalancer根據服務名稱到eureka拉取服務列表eureka返回服務列表,IRule利用內置的負載均衡規則從列表中選擇一個服務,返回給RibbonLoadBalanceClient
Ribbon的負載均衡規則時一個叫IRule的接口來定義的,每一個接口就是一種規則
內置的負載均衡規則:
RoundRobinRule 簡單的輪詢服務列表來選擇服務器,Ribbon默認的負載均衡規則
ZoneAvoidanceRule 以區域可用的服務器為基礎進行服務器的選擇
默認的實現就是ZoneAvoidanceRule,是一種輪詢方案(一般使用默認的負載均衡規則,不修改)
Ribbon采用默認的懶加載,第一次訪問才會去創建LoadBalanceClient,請求時間會很長。
Nacos注冊中心
Nacos是阿里巴巴的產品,現在是SpringCloudAlibaba中的一個組件(SpringCloudAlibaba實現啦對SpringCloud組件進行擴展)
與Eureka的差異:依賴不同,服務地址不同
Nacos服務搭建,下載安裝包,解壓,在bin目錄下運行startup.cmd -mstandalone
引入依賴,在父工程里面,引入
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.6.RELEASE</version><type>pom</type><scope>import</scope>
</dependency>
在服務消費者和提供者的pom文件引入nacos的依賴,注釋掉eureka的依賴
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置nacos地址,在user-service和order-service的application.yml中添加nacos地址,不要忘了注釋掉eureka的地址
spring:cloud:nacos:server-addr: localhost:8848
在啟動類添加注解@EnableDicoveryClient
Nacos服務分級存儲模型
一個服務有多個實例,實例分布在不同的機房中,Nacos將同一機房的實例劃分為一個集群
服務-集群-實例
服務調用盡可能選擇本地集群的服務,跨集群調用延遲較高。(本地集群不可訪問時,在訪問其他集群)
給user-service配置集群,修改user-service的application.yml文件
spring:cloud:nacos:server-addr: localhost:8848discovery:cluster-name: HZ # 集群名稱
復制一個user-service啟動配置,添加屬性
-Dserver.port=8083 -Dspring.cloud.nacos.discovery.cluster-name=SH
默認的zoneAvoidanceRule不能實現同集群有效實現負載均衡,Nacos中提供了一個NacosRule
的實現,可以優先從同集群中挑選實例。
修改負載均衡規則修改order-service的application.yml文件,修改負載均衡規則:
userservice:ribbon:NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 負載均衡規則
根據權重負載均衡:在實際部署中提高權重配置來控制訪問頻率,權重高訪問頻率高
在Nacos控制臺設置實例的權重值0~1之間
環境隔離namespace
Nacos中服務存儲和數據存儲的最外層都是一個namespace的東西,用做最外層隔離,修改order-service的application.yml文件:
spring:cloud:nacos:server-addr: localhost:8848discovery:cluster-name: HZnamespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f9 # 命名空間,填ID
Nacos的服務實例分為兩種類型:
臨時實例:如果實例宕機超過一段時間,會從服務列表中剔除,默認的類型
非臨時實例:如果實例宕機,不會從服務列表中剔除,也叫永久實例
Nacos和Eureka的區別:
相同點:都支持服務注冊和服務拉取,都支持服務提供者心跳方式做健康檢測
區別:1.Nacos支持服務端主動檢測提供者狀態:臨時實例采用心跳檢測,非臨時實例nacos主動詢問
2.臨時實例心跳不正常被剔除,非臨時實例則不會剔除
3.Nacos支持服務禮包變更的消息推送模式,服務列表更新更及時
4.Nacos集群默認采用AP方式,集群中存在非實例時采用CP模式;Eureka采用AP模式
CAP定理:布魯爾定理
指出對于一個分布式計算機來說,不可能同時滿足三點,最多同時滿足兩點:
一致性(Consistency)系統中所有數據備份,在同一時刻同樣的值
可用性(Availability)保證每次請求不管成功失敗都有響應
分區容錯性(Partition tolerance)系統中任意信息的丟失或失敗不會影響系統的繼續運作
配置中心
配置統一管理和配置隔離問題
nacos=SpringCloud eureka注冊中心+SpringCloud config配置中心
項目的核心配置,需要熱更新的配置才有放到nacos管理的必要。基本不會變更的一些配置還是保存在微服務本地比較好。(熱加載:不重啟一個項目,使得部分代碼更新,通過java類加載器實現)
保證項目中有bootstrap.yml
微服務要拉取nacos中管理的配置,并且與本地的application.yml配置合并,才能完成項目啟動
在bootstrap.yml中提那就配置中心相關內容:環境相關spring.profiles.active
配置中心地址,配置文件后綴
配置加載順序:先加載共享配置文件,再加載環境相關配置文件,在加載application.yml
在idea中的使用
導入依賴
<!--nacos配置管理依賴-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
添加bootstrap.yaml
spring:application:name: userservice # 服務名稱profiles:active: dev #開發環境,這里是dev cloud:nacos:server-addr: localhost:8848 # Nacos地址config:file-extension: yaml # 文件后綴名
配置熱更新
最終目的,是修改nacos中的配置后,微服務無需重啟就可以讓配置生效(配置熱更新)
使用兩種方式:
一:@Value注入的變量所在類上添加注解@RefreshScope:
二: 在controller中使用@ConfigurationProperties注解代替@Value注解。