2、SpringCloud快速搭建
SpringCloud構建微服務是基於SpringBoot開發的。
建立服務提供者的訪問方法,消費者如何訪問提供者,SpringCloud是基於rest的訪問,他們之間是通過json進行互動
建立服務提供者
依賴
<!--springboot開發web專案的依賴--> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
controller
@RestController
public class HelloController {
@RequestMapping("/service/hello")
public String hello(){
// 業務處理(省略)
return "hello spring clound";
}
}
建立服務消費者
建立一個新的springboot專案
開發消費者方法,去消費服務提供者提供的服務,這個消費者方法也是一個Controller
@RestController public class WebController { @Autowired private RestTemplate restTemplate; @RequestMapping("/web/hello") public String hello(){ // 邏輯判斷(省略) // 呼叫SpringCloud服務提供者提供的服務(通過RestTemplate這個類遠端呼叫服務) return restTemplate.getForEntity("http://localhost:8080/service/hello", String.class).getBody(); }
配置RestTemplate類
//配置檔案
@Configuration
public class BeanConfig {
/**
* @Bean 等價於 <bean id="restTemplate" class="xxx.xxx.RestTemplate"/>
*
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
埠配置避免兩個專案的埠號衝突
server.port=8081
訪問
通過http://localhost:8081/web/hello
訪問消費者方法,消費者方法會呼叫服務提供者提供的方法
Spring Cloud結構的遠端呼叫模式
服務提供者的服務需要註冊到服務中心上,消費者通過註冊中心獲取提供者註冊的服務,然後進行呼叫
走進服務註冊中心Eureka
微服務架構中,服務註冊與發現是核心元件之一,手動指定每個服務是很低效的,SpringCloud提供多種服務註冊與發現的實現方式,如:Eureka、Consul、Zookeeper。
SpringCloud支援最後的是Eureka,然後Consul、Zookeeper
服務註冊
將服務所在主機、埠、版本號、通訊協議等資訊登記到註冊中心上。
什麼是服務發現?
服務消費者向註冊中心請求已經登記的服務列表,然後得到某個服務的主機、埠、版本號、通訊協議等資訊、從而實現對具體服務的呼叫。
Eureka
- 一個服務治理元件,主要包括服務註冊與發現,用來搭建服務註冊中心
- Eureka 是一個基於 REST 的服務,用來定位服務,進行中間層伺服器的負載均衡和故障轉移
- Eureka 由 Netflix 提供,SpringCloud進行二次封裝
- C/S 設計架構:
- Eureka Server(服務端)是服務中心;維護人員可以通過Eureka Server 來監控系統中的各個微服務是否正常執行
- Eureka Client(客戶端)是一個java客戶端,用於簡化與伺服器的互動,負載均衡,服務的故障切換等;
- 通過客戶連線到服務端,並維持心跳連線;
Eureka 與 Zookeeper 的比較
CAP理論 一個分散式系統不可能同時滿足cap (C:資料一致性,A:服務可用性,P:分割槽容錯性)
- 微服務本身就分為多個節點,當一個節點出現故障時,其他節點不會隨之癱瘓,這就是容錯性是分散式系統必須保證的;
- 服務可用性 和 資料一致性 兩者無法並存只能進行取捨,Zookeeper保證的是CP,而Eureka則是AP
Zookeeper
例如:一個Zookeeper叢集,有三個節點,其中master因網路故障或與其他節點失去聯絡,那麼Zookeeper就會在剩下的節點中選舉出一個節點作為master,但是選舉的過程需要時間,而這段時間整個Zookeeper叢集是不可用的,也就是註冊服務癱瘓,Provider無法向註冊中心註冊服務,這時就失去了C(服務可用性)。Zoo因網路問題導致Zookeeper失去master節點是大概率時間,雖然能回覆,但是選舉時間內導致服務註冊長期不可用是難以容忍的。
Eureka
Eureka叢集與Zookeeper不同,節點之間沒有主從關係,如果某個節點掛了,剩餘節點依然能提供註冊和查詢服務。如果Eureka Client 向 Eureka Server 註冊時發現連線失敗,會自動切換到其他正常的節點。但是無法保證查到的資訊是最新的(不保證強一致性)
例如:
Eureka Client 向 Eureka Server 註冊服務,註冊完後,由於某些原因客戶端停掉了該服務,這是的服務端有可能沒有進行更新,導致消費者(consumer)去註冊中心(Eureka Server)中獲取該服務的註冊資訊是有的,但是呼叫服務的時候卻無法呼叫的問題。
搭建並配置Eureka服務註冊中心
Spring Cloud 中的Eureka 服務註冊中心實際上也是一個Spring Boot工程,通過引入相關依賴和註解配置,讓Spring Boot構建的微服務應用與Eureka進行整合整合。
步驟:
1.建立一個SpringBoot專案,並且新增SpringBoot的相關依賴;
(省略)
2.新增Eureka的依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 新增Eureka依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<!--新增依賴管理-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!--還可以配置Repository-->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestone</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
3.在Spring Boot 的入口類上新增一個@EnableEurekaServer註解,用於開啟Eureka註冊中心服務端
@SpringBootApplication
@EnableEurekaServer //開啟Eureka註冊中心服務端
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4.在application.properties或yaml檔案中配置Eureka服務註冊中心資訊
server.port=8761
#配置該服務註冊中心的hostname(填ip)
eureka.instance.hostname=localhost
#由於我們目前建立的應用是一個服務註冊中心,而不是普通的應用。
# 預設情況下,這個應用會向註冊中心(也是它自己)註冊它自己,設定為false表示禁止這種自己向自己註冊的預設行為
eureka.client.register-with-eureka=false
#表示不去檢索其他的服務,因為服務註冊中心本身的職責就是維護服務例項,它不需要檢索其他服務
eureka.client.fetch-registry=false
#指定服務註冊中心的位置
eureka.client.service-url.defaultZone=http;//${eureka.instance.hostname}:${server.port}/eureka/
啟動與測試Eureka服務註冊中心
1.完成上面的專案搭建後,啟動springboot程式,執行main方法;
2.啟動成功之後,通過在瀏覽器位址列訪問我們的註冊中心
訪問介面如下:
注意
啟動失敗的話,肯能是SpringBoot與SpringCloud之間的相容問題
可以通過SpringCloud官網進行訪問點選跳轉SpringCloud,點檢Deference Doc,檢視相容版本
向Eureka服務註冊中心註冊服務
將服務提供者註冊到Eureka註冊中心
步驟
1.該服務提供者Provider新增Eureka的依賴
服務提供者想註冊中心註冊服務,需要連線eureka,所以需要eureka客戶端的支援
<!-- 新增Eureka客戶端依賴>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- 新增SpringCloud依賴管理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.啟用Eureka中的EnableEurekaClient功能:
在SpringBoot的啟動類上新增@EnableEurekaClient註解來表示自己是一個Eureka Client,使得服務可用連線Eureka註冊中心;
3.配置服務名稱和註冊中心地址
#配置服務的名稱,通常與專案名一致(通過名稱訪問微服務)
server.servlet.context-path: /01springcloud-service-provider
#eureka的訪問地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
4.啟動服務提供者SpringBoot程式的main方法執行
5.訪問Eureka服務中心
這是就有一個服務註冊上了
從Eureka服務註冊中心發現和消費服務
- 服務的發現由Eureka客戶端實現
- 服務的消費由Ribbon實現
- 服務的呼叫需要Eureka Client 和 Ribbon共同完成
Eureka Client
Eureka 客戶端時一個java客戶端,用來連線Eureka服務端,與服務端進行互動,負載均衡,服務的故障切換等
Ribbon
- Ribbon是基於Http 和 TCP 的客戶端負載均衡器。
- 使用Ribbon對服務進行訪問時,它會擴充套件Eureka客戶端的服務發現功能,實現從Eureka註冊中心中獲取服務端列表,並通過Eureka客戶端來確定服務端是否已經啟動。
- Ribbon在Eureka客戶端服務發現的基礎上,實現了對服務例項的選擇策略,從而實現對服務的負載均衡消費。
服務消費者呼叫服務提供者
1.消費者專案新增Eureka Client的依賴
consumer從註冊中心獲取服務,需要連線Eureka,所以需要Eureka支援
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.啟用Eureka中的EnableEurekaClient功能
在啟動類上新增@EnableEurekaClient註解
3.配置服務的名稱和註冊中心的地址
#配置服務的名稱,通常與專案名一致(通過名稱訪問微服務)
server.servlet.context-path: /02springcloud-service-consumer
#eureka的訪問地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
4.呼叫服務提供者時使用ribbon來呼叫
//配置檔案
@Configuration
public class BeanConfig {
/**
* @Bean 等價於 <bean id="restTemplate" class="xxx.xxx.RestTemplate"/>
*
* @return
*/
@LoadBalanced //ribbon支援
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
加入ribbon的支援,那麼呼叫的時候,使用服務名稱來訪問即可
@RestController
public class WebController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/web/hello")
public String hello(){
// Eureka + Ribbon的呼叫服務的方式(這種方式不再需要ip地址和埠號了)
return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/hello", String.class).getBody();
}
}
5.啟動消費者程式
6.訪問消費者
檢驗是否能正常呼叫