寫在前面:
- 你好,歡迎你的閱讀!
- 我熱愛技術,熱愛分享,熱愛生活, 我始終相信:技術是開源的,知識是共享的!
- 博客裏面的內容大部分均爲原創,是自己日常的學習記錄和總結,便於自己在後面的時間裏回顧,當然也是希望可以分享自己的知識。目前的內容幾乎是基礎知識和技術入門,如果你覺得還可以的話不妨關注一下,我們共同進步!
- 除了分享博客之外,也喜歡看書,寫一點日常雜文和心情分享,如果你感興趣,也可以關注關注!
- 微信公衆號:傲驕鹿先生
說明:1、專欄涉及到的源碼已經同步至 https://github.com/SetAlone/springcloud2020(持續更新)
2、springcloud系列博文內容爲學習《尚硅谷2020最新版SpringCloud(H版&alibaba)框架開發教程》的記錄,此係列課程是目前看來個人覺得非常不錯的資源,在此可以與大家進行分享。
3、個人收集到了課程源碼和所需的腦圖、筆記等資源,如需要私信我即可。查找資源不易,希望可以給個點贊和關注。
一、基礎知識
1、什麼是服務治理
Spring Cloud封裝了Netflix公司開發的Eureka模塊來實現服務治理。
在傳統的RPC遠程調用框架中,管理每個服務與服務之間依賴關係比較複雜,所以需要使用 服務治理,管理服務與服務之間的依賴關係,可以實現服務調用、負載均衡、容錯等,實現服務發現與註冊。
2、什麼是服務註冊
Eureka採用了CS的設計架構,Eureka Server作爲服務註冊功能的服務器,它是服務註冊中心。而系統中的其他服務,使用Eureka的額客戶端連接到Eureka Server並維持心跳連接。這樣系統的維護人員就可以通過Eureka Server來監控系統中各個微服務是否正常運行。
在服務註冊和發現中,有一個註冊中心。當服務器啓動的時候,會把當前自己服務器的信息以別名方式註冊到註冊中心上。另一方(消費服務提供者)以該別名的方式去註冊中心上獲取到實際的服務通訊地址,然後在實現本地RPC遠程調用框架核心設計思想:在於註冊中心,因爲使用註冊中心管理每個服務與服務之間的一個依賴關係(服務治理理念)。在任何的RPC遠程框架中,都會有一個註冊中心(存放服務地址相關信息(接口地址))。
3、Eureka的兩個組件
二、單機Eureka構建
1、IDEA生成EurekaServer端服務註冊中心
1)建moudle
在父工程上右鍵,new——>moudle,新建一個新的maven項目,不需要選擇嚮導。命令爲cloud-eureka-server7001。
2)改pom
<?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>springcloud2020</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-eureka-server7001</artifactId>
<dependencies>
<!--eureka-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- 引入自己定義的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--boot web actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--一般通用配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
3)寫yml
在resources文件夾下創建application.yml文件
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服務端的實例名稱
client:
register-with-eureka: false #false表示不向註冊中心註冊自己。
fetch-registry: false #false表示自己端就是註冊中心,我的職責就是維護服務實例,並不需要去檢索服務
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
4)主啓動類
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001
{
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class, args);
}
}
5)測試
因爲是服務註冊中心,所以不需要編寫業務類。進行測試:
在瀏覽器中輸入http://localhost:7001/進行測試,如下爲測試結果圖:
2、EurekaClient端cloud-provider-payment8001 將註冊進EurekaServer成爲服務提供者provider
1)選定8001模塊
2)改pom,在8001模塊的pom文件中添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3)寫yml
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 當前數據源操作類型
driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包
url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
eureka:
client:
#表示是否將自己註冊進EurekaServer默認爲true。
register-with-eureka: true
#是否從EurekaServer抓取已有的註冊信息,默認爲true。單節點無所謂,集羣必須設置爲true才能配合ribbon使用負載均衡
fetchRegistry: true
service-url:
#單機版
defaultZone: http://localhost:7001/eureka
mybatis:
mapperLocations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.springcloud.entities # 所有Entity別名類所在包
4)主啓動
在主啓動類PaymentMain8001中添加@EnableEurekaClient註解
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001
{
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class, args);
}
}
5)測試
啓動Eureka Server,然後進行測試。http:localhost:7001
3、EurekaClient端cloud-consumer-order80 將註冊進EurekaServer成爲服務消費者consumer
1)選定cloud-consumer-order80模塊
2)改pom,在80模塊的pom文件中添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3)寫yml
server:
port: 80
spring:
application:
name: cloud-payment-service
eureka:
client:
#表示是否將自己註冊進EurekaServer默認爲true。
register-with-eureka: true
#是否從EurekaServer抓取已有的註冊信息,默認爲true。單節點無所謂,集羣必須設置爲true才能配合ribbon使用負載均衡
fetchRegistry: true
service-url:
#單機版
defaultZone: http://localhost:7001/eureka
4)主啓動
在主啓動類OderMain8001中添加@EnableEurekaClient註解
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80
{
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class, args);
}
}
5)測試
三、集羣Eureka構建
1、Eureka集羣原理說明
服務註冊:將服務信息註冊到註冊中心
服務發現:從註冊中心上獲取到服務信息
其實質就是:key-value形式的。Key:服務的名字 value:服務調用地址
執行步驟:
1、先啓動eureka註冊中心
2、啓動服務提供者(我們這裏的服務提供者就是payment支付服務)
3、服務提供者在啓動後會把自身的信息(如服務地址,以別名方式註冊到)註冊到eureka中
4、消費者(我們這裏是order服務)在需要調用接口的時候,使用服務別名去註冊中心獲取到實際的RPC遠程調用地址
5、消費者獲取到調用地址後,底層實際是利用HttpClient技術實現遠程調用的
6、消費者獲得服務地址後會緩存在本地的JVM內存中,默認每隔30秒更新移除服務調用地址
如果我們的註冊中心只有一個,在發生故障的情況下,就會導致整個的服務不可用,我們可以通過搭建Eureka註冊中心集羣的方式,實現負載均衡和故障容錯。
原理說明:
前面我們實現了單機Eureka搭建,既然是集羣搭建,就意味着有多個。比如我們現在單臺的eureka端口是7001,假設還有一臺服務是7002.那麼7001的註冊地址應該是7002,7002的註冊地址是7001.這樣就相互註冊了。7001會每30s給7002同步一次心跳,同理7002也會的。所以就相互守望了。因此我們可以用一句話進行概括:互相註冊,互相守望。
2、集羣Eureka構建步驟
1)建moudle
按照上面構建cloud-eureka-server7001的構建步驟,進行cloud-eureka-server7002的構建
2)改pom
複製7001moudle的pom文件即可
3)修改映射配置文件
當我們有兩個應用進行相互註冊相互守望時,eureka服務端的實例名稱不能重複,因此需要修改映射配置文件,找到C:\Windows\System32\drivers\etc路徑下的hosts文件,對其進行修改,增加兩個虛擬的域名:
修改完成後刷新host文件,打開cmd命令窗口,進行如下的操作:
出現上面的界面則說明我們的映射配置文件已修改成功了。
4)寫yml(依次修改7001和7002的yml文件)
7001:
server:
port: 7001
spring:
application:
name: cloud-eureka-service
eureka:
instance:
# eureka服務端的實例名稱
hostname: eureka7001.com
client:
# false表示不向註冊中心註冊自己
register-with-eureka: false
# false表示自己端就是註冊中心,我的職責就是維護服務實例,並不需要檢索服務
fetch-registry: false
service-url:
# 設置與Eureka Server交互的地址查詢服務和註冊服務都需要依賴這個地址
defaultZone: http://eureka7002.com:7002/eureka/
7002:
server:
port: 7002
spring:
application:
name: cloud-eureka-service2
eureka:
instance:
hostname: eureka7002.com
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
3、將支付服務8001微服務發佈到上面2臺Eureka集羣配置中
修改8001的yml文件,將原來的單機版修改爲集羣版即可。
#單機版
# defaultZone: http://localhost:7001/eureka
# 集羣版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
4、將訂單服務80微服務發佈到上面2臺Eureka集羣配置中
修改80的yml文件,將原來的單機版修改爲集羣版即可。
#單機版
# defaultZone: http://localhost:7001/eureka
# 集羣版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
5、支付服務提供者8001集羣環境搭建
1)參考cloud-provider-payment8001,新建cloud-provider-payment8002
2)複製pom文件
3)複製yml文件,修改裏面的端口號
4)複製主啓動類
5)複製業務類
分別修改8001和8002的controller文件,
6)測試
我們可以看到CLOUD-PAYMENT-SERVICE是有兩臺機器。分別是8001和8002
再來分別訪問8001和8002的服務:
我們可以看到把對應服務的端口號返回到頁面上了。
再使用消費者order80測試:
我們發現無論我們怎麼刷新訪問的端口都是8001。但是,我們payment確實啓動了兩個項目8001和8002啊。那麼爲什麼呢?
查看OderController,我們可以看到訪問服務的連接是寫死的,既然後面啓動了兩個服務,我想要既可以訪問8001的端口也要訪問8002的端口,那麼怎麼做呢?
6、負載均衡
如果我們修改成服務名稱呢?那麼服務名稱是什麼?服務名稱就是我們在eureka集羣註冊的application列表下的名稱。
那麼我們直接把CLOUD-PAYMENT-SERVICE這個服務名字複製到PAYMENT_URL中可以嗎?
重啓完成之後,我們重新訪問:
重新訪問的時候,我們看到提示信息是說:java.net.UnknownHostException: CLOUD-PAYMENT-SERVICE。沒有找到這個host異常。
爲什麼呢?我們知道,這個服務是註冊到eureka的服務的別名,而不是真實存在的。如果要想訪問到,這裏就需要使用到負載均衡了。
怎麼修改呢?需要修改RestTemplate的配置類中添加@LoadBalanced註解賦予RestTemplate負載均衡的能力。
修改如下:
在order80項目中,ApplicationContextConfig類裏面getRestTemplate方法上面添加@LoadBalance註解即可。如下圖:
修改完成之後,再次訪問頁面,然後刷新頁面,我們可以看到端口是8001和8002來回切換的。
7、測試
四、actuator微服務信息完善
1、主機名稱:服務名稱修改
主機名稱:服務名稱修改
當前問題:服務註冊含有主機名稱,要想按照規範的要求,只暴露服務名,不要出現主機名。
分別找到8001和8002的yml文件,添加配置即可:
2、訪問信息有ip信息提示
我們可以通過如下的配置,將我們微服務的ip地址進行顯示,方便我們進行調試和排錯。分別在8001和8002的yml文件中進行添加:
修改完成後效果如下:
五、服務發現Discovery
對於註冊eureka裏面的微服務,可以通過服務發現來獲得該服務的信息,具體的步驟如下:
修改cloud-provider-payment8001的Controller
在8001的主啓動上添加註解@EnableDiscoveryClient
六、eureka自我保護
我們暫時將7001和8001模塊還原到eureka的單機模式用以eureka自我保護的測試:
在7001的yml文件中進行配置:
在8001的yml文件中進行配置:
在啓動7001和8001後,停止8001來模仿故障,就會出現如下的結果:其服務
其服務馬上就會被刪除了。