Spring Cloud 入門到進階 - 01 Eureka集羣搭建(中)
博主整理的SpringCloud系列:目錄
上篇:Spring Cloud 入門到進階 - 01 Eureka介紹及簡單服務搭建(上)
一、Eureka 集羣搭建
在上篇,運行第一個 Eureka 應用時,服務器實例、服務提供者實例都只啓動了一個,並沒有體現高可用的特性,本篇將對上篇的 Eureka 應用進行改造,使其可以進行集羣部署。
請提前編寫或下載上篇的示例代碼,本篇將基於上篇的示例代碼,進行修改演示。
1、本例集羣結構圖
本例將會運行兩個服務器實例、兩個服務提供者實例,然後服務調用者請求服務。
第一個 Eureka 應用,使用的是瀏覽器訪問 Eureka 的服務調用者,而改造後,爲了能看到負載均衡的效果,會編寫一個 HttpClient 的 REST 客戶端訪問服務調用者發佈的服務。
由於博主的開發環境只有一臺電腦,操作系統爲 Windows ,如果要構建集羣,需要修改 hosts 文件,爲其添加主機名的映射。修改 C:\Windows\System32\drivers\etc
文件,添加以下內容:
127.0.0.1 slave1 slave1
2、改造服務器端
新建項目 first-cloud-server
,使用的 Maven 配置與上篇的 first-ek-server
一樣,可直接複製過來使用。
2.1、配置 application.yml
由於我們需要對同一個應用程序啓動兩次(啓動兩個服務中心),因此需要在配置文件中使用 profiles
如下。
spring:
profiles:
active: slave1 #可通過JVM啓動參數修改
---
server:
port: 8761
spring:
application:
name: first-cloud-server
profiles: slave1
eureka:
instance:
hostname: slave1
client:
serviceUrl:
defaultZone: http://slave2:8762/eureka/
---
server:
port: 8762
spring:
application:
name: first-cloud-server
profiles: slave2
eureka:
instance:
hostname: slave2
client:
serviceUrl:
defaultZone: http://slave1:8761/eureka/
上面配置文件中,配置了兩個 profiles ,名稱分別爲 slave1
和 slave2
。
在 slave1
中,配置了應用端口爲 8761
,主機名爲 slave1
。當使用 slave1
這個 profiles 來啓動服務器時,將會向 http://slave2:8762/eureka/
註冊自己。
在 slave2
中,配置了應用端口爲 8762
,主機名爲 slave2
。當使用 slave2
這個 profiles 來啓動服務器時,將會向 http://slave1:8761/eureka/
註冊自己。
簡單點說,就是兩個服務器啓動後,它們會互相註冊。
2.2、服務啓動方式
啓動多實例加載不同配置,這裏提供兩種方式,任選一種即可(博主這裏使用第二種)。
-
1.使用 SpringApplicationBuilder 設置
修改啓動類,讓類在啓動時讀取控制檯的輸入,決定使用哪個 profiles 來啓動服務器。package com.swotxu.firstcloudserver; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; import java.util.Scanner; /** * Eureka 集羣服務 * * 啓動多實例加載不同配置的兩種方式: * 方式一: * 啓動時,添加JVM參數: -Dspring.profiles.active=slave1 * * 方式二: * 從控制檯輸入環境參數,並通過 SpringApplicationBuilder 進行設置。 * * @Date: 2020/6/27 22:05 * @Author: swotXu */ @SpringBootApplication @EnableEurekaServer // 聲明這是一個 Eureka 服務器 public class FirstCloudServer { public static void main(String[] args) { /*System.out.println("請輸入當前服務的環境 profiles = "); Scanner scanner = new Scanner(System.in); String profiles = scanner.nextLine(); new SpringApplicationBuilder(FirstCloudServer.class).profiles(profiles).run(args);*/ // 這裏採用第二種方式 new SpringApplicationBuilder(FirstCloudServer.class).run(args); } }
在啓動類中,先讀取控制檯的輸入,再調用 profiles 方法設置啓動的 profiles 。
-
2.設置JVM啓動參數
這裏以IDEA爲例,我們可以複製兩個啓動類配置,分別設置爲-Dspring.profiles.active=slave1
和-Dspring.profiles.active=slave2
,最後依次啓動即可。
需要注意的是,第一個啓動的服務器會拋出異常,異常原因我們在上篇中己經講述過,拋出的異常不必理會。
2.3、項目完整結構圖 - first-cloud-server
3、改造服務提供者
服務提供者也需要啓動兩個實例,服務提供者的改造與服務端類似。
我們將上篇的 first-ek-server-provider
複製出來,並改名爲 first-cloud-provider
。
3.1、配置 application.yml
修改配置文件,將服務提供者註冊到兩個服務器中,配置文件如下:
spring:
application:
name: first-cloud-provider
eureka:
instance:
hostname: localhost
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
3.2、服務啓動方式
同上,爲了避免端口衝突,啓動多實例加載不同配置,這裏提供兩種方式,任選一種即可(博主這裏使用第二種)。
-
1.使用 SpringApplicationBuilder 設置
修改啓動類,讓類在啓動時讀取控制檯輸入的端口,來設置並啓動服務器。package com.swotxu.firstekcloudprovider; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /** * 啓動多實例加載不同配置的兩種方式: * 方式一: * 啓動時,添加JVM參數: -Dserver.port=8081 * * 方式二: * 從控制檯輸入環境參數,並通過 SpringApplicationBuilder 進行設置。 */ @EnableEurekaClient @SpringBootApplication public class FirstCloudProviderApplication { public static void main(String[] args) { /*System.out.println("請輸入當前服務的端口 port = "); Scanner scanner = new Scanner(System.in); String port = scanner.nextLine(); new SpringApplicationBuilder(FirstEkServerProviderApplication.class).properties("server.port=" + port).run(args);*/ // 這裏採用第二種方式 new SpringApplicationBuilder(FirstCloudProviderApplication.class).run(args); } }
-
2.設置JVM啓動參數
這裏以IDEA爲例,我們可以複製兩個啓動類配置,分別設置JVM參數爲-Dserver.port=8081
和-Dserver.port=8081
,最後依次啓動即可。
3.3、修改服務提供類
爲了能看到效果,還需要改造控制器,將服務調用者請求的 URL 保存起來並返回,修改後的控制器代碼如下:
package com.swotxu.firstekcloudprovider.web;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* @Date: 2020/6/25 20:50
* @Author: swotXu
*/
@RestController
public class FirstController {
@RequestMapping(value = "/user/{userId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public UserInfo findUser(@PathVariable("userId") Integer userId, HttpServletRequest request){
// 爲了查看結果,獲取請求的 url
String url = request.getRequestURL().toString();
UserInfo userInfo = new UserInfo(userId, "swotxu", 18, url);
return userInfo;
}
}
3.4、項目完整結構圖 - first-cloud-provider
4、改造服務調用者
服務提供者只需要啓動一個實例。我們將上篇的 first-ek-server-invoker
複製出來,並改名爲 first-cloud-invoker
。
4.1、配置 application.yml
修改配置文件,將服務調用者註冊到兩個服務器中,配置文件如下:
server:
port: 9000
spring:
application:
name: first-cloud-invoker
eureka:
instance:
hostname: localhost
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
4.2、修改服務調用者
package com.swotxu.firstcloudinvoker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @Date: 2020/6/27 17:09
* @Author: swotXu
*/
@Slf4j
@Configuration
@RestController
public class lnvokerController {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
@RequestMapping(value = "/router", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public String router(){
RestTemplate restTemplate = getRestTemplate();
// 根據應用名稱調用服務。其中 first-cloud-provider 是服務提供者配置的服務名(spring.application.name)
String json = restTemplate.getForObject("http://first-cloud-provider/user/1", String.class);
log.info("result: {}", json);
return json;
}
}
4.3、項目完整結構圖 - first-cloud-invoder
5、編寫 REST 客戶端進行測試
這裏我們使用的是 HttpClient,HttpClient 是 Apache 提供的一個 HTTP 工具包。通過代碼的方式,模擬用戶瀏覽器請求。
我們新建一個名爲 first-cloud-rest-client
的 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>com.swotxu</groupId>
<artifactId>first-cloud-rest-client</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
</dependencies>
</project>
新建一個類,在 main 方法中編寫調用 REST 服務的代碼。
package com.swotxu.firstcloudrestclient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
/**
* @Date: 2020/6/28 16:20
* @Author: swotXu
*/
public class TestHttpClient {
public static void main(String[] args) throws IOException {
// 創建默認的 HttpClient
CloseableHttpClient client = HttpClients.createDefault();
// 調用 6 次服務並輸出結果
for (int i = 0; i < 6; i++) {
// 調用 GET 方法請求服務
HttpGet httpGet = new HttpGet("http://localhost:9000/router");
// 獲取響應
CloseableHttpResponse response = client.execute(httpGet);
// 根據響應解析出字符串
System.out.println(EntityUtils.toString(response.getEntity()));
}
}
}
項目完整結構圖 - first-cloud-rest-client
二、Eureka 集羣測試
1、啓動 Eureka 集羣
集羣項目搭建完成後,我們按以下順序依次啓動各個組件:
-
啓動兩個 Eureka 服務器。
slave1
服務
slave2
服務
-
啓動兩個 Eureka 服務提供者。
服務提供者發佈的 REST 接口:
-
啓動一個 Eureka 服務調用者。
2、測試訪問集羣
整個集羣啓動成功以後,我們運行 TestHttpClient,查看運行結果。
根據輸出結果可知, 8081 與 8082 端口分別被請求了 3 次,可見己經達到負載均衡的目的,關於負載均衡更詳細的內容,我們後面再說。
三、項目下載
1、項目完整結構圖
2、源碼下載
碼雲Gitee倉庫地址:https://gitee.com/swotxu/Spring-Cloud-Study.git
項目路徑:Spring-Cloud-Study/01/springcloud02
爲了能演示 Eureka 高可用特性,下篇,我們將會以本案例爲基礎,講解服務實例的健康自檢。
下篇:Spring Cloud 入門到進階 - 01 Eureka 服務實例的健康自檢 (下)
別忘了點贊關注收藏~