上篇文章《SpringCloud之Eureka:服務發佈與調用例子》實現了一個簡單例子,此次對其進行改造,運行兩個服務器實例、兩個服務提供者實例,服務調用者請求服務,使其能夠進行集羣部署。html
集羣結構以下圖所示。java
因爲開發環境只有一臺電腦,要構建集羣,須要修改hosts文件,在裏面添加主機名映射。web
127.0.0.1 slave1 slave2
1、服務器端spring
一、建立項目apache
開發工具:IntelliJ IDEA 2019.2.2
IDEA中建立一個新的SpringBoot項目,名稱爲「first-cloud-server」,SpringBoot版本選擇2.1.9,在選擇Dependencies(依賴)的界面勾選Spring Cloud Discovert ->
Eureka Server,建立完成後的pom.xml配置文件自動添加SpringCloud最新穩定版本依賴,當前爲Greenwich.SR3。
pom.xml完整內容可參考上篇文章《SpringCloud之Eureka:服務發佈與調用例子》。json
二、修改配置application.yml瀏覽器
因爲須要對同一個應用程序啓動兩次,所以須要使用profiles配置。
下面配置了兩個profiles,名稱分別爲slave1和slave2,當使用slave1啓動服務器後,會向http://slave2:8762/eureka/註冊本身,當使用slave2啓動服務器後,會向
http://slave1:8761/eureka/註冊本身,即兩個服務器啓動後,互相註冊。 服務器
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/
三、修改啓動類代碼FirstEkServerApplication.javaapp
除了增長註解@EnableEurekaServer,還讓類在啓動時讀取控制檯輸入,決定使用哪一個profiles來啓動服務器。 負載均衡
package com.example.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; @SpringBootApplication @EnableEurekaServer public class FirstCloudServerApplication { public static void main(String[] args) { //SpringApplication.run(FirstCloudServerApplication.class, args); Scanner scan = new Scanner(System.in); String profiles = scan.nextLine(); new SpringApplicationBuilder(FirstCloudServerApplication.class) .profiles(profiles).run(args); } }
2、編寫服務提供者
一、建立項目
IDEA中建立一個新的SpringBoot項目,除了名稱爲「first-cloud-provider」,其它步驟和上面建立服務器端同樣。
二、修改配置application.yml
spring: application: name: first-cloud-provider eureka: instance: hostname: localhost client: serviceUrl: defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
三、添加類 User.java
package com.example.firstcloudprovider; public class User { private Integer id; private String name; private String message; public User(Integer id, String name){ this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
四、添加控制器 UserController.java
package com.example.firstcloudprovider; 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; @RestController public class UserController { @RequestMapping(value = "/user/{userId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public User findUser(@PathVariable("userId") Integer userId, HttpServletRequest request){ User user = new User(userId, "gdjlc"); user.setMessage(request.getRequestURL().toString()); return user; } }
五、修改啓動類代碼FirstCloudProviderApplication.java
除了增長註解@EnableEurekaClient,還讓類在啓動時讀取控制檯輸入,決定使用哪一個端口啓動服務器。
package com.example.firstcloudprovider; //import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import java.util.Scanner; @SpringBootApplication @EnableEurekaClient public class FirstCloudProviderApplication { public static void main(String[] args) { //SpringApplication.run(FirstCloudProviderApplication.class, args); Scanner scan = new Scanner(System.in); String port = scan.nextLine(); new SpringApplicationBuilder(FirstCloudProviderApplication.class).properties("server.port=" + port).run(args); } }
3、編寫服務調用者
一、建立項目
IDEA中建立一個新的SpringBoot項目,除了名稱爲「first-cloud-invoker」,其它步驟和上面建立服務器端同樣。
二、修改配置application.yml
server: port: 9000 spring: application: name: first-cloud-invoker eureka: instance: hostname: localhost client: serviceUrl: defaultZone: http://slave1:8761/eureka/,http://slave2:8762/eureka/
三、添加控制器 InvokerController.java
package com.example.firstcloudinvoker; 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; @RestController @Configuration public class InvokerController { @Bean @LoadBalanced public RestTemplate getRestTemplate(){ return new RestTemplate(); } @RequestMapping(value = "/router", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public String router(){ RestTemplate restTpl = getRestTemplate(); //根據應用名稱調用服務 String json = restTpl.getForObject("http://first-cloud-provider/user/1", String.class); return json; } }
四、修改啓動類代碼FirstCloudInvokerApplication.java
添加註解@EnableDiscoveryClient,使得服務調用者能夠去Eureka中發現服務。
package com.example.firstcloudinvoker; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class FirstCloudInvokerApplication { public static void main(String[] args) { SpringApplication.run(FirstCloudInvokerApplication.class, args); } }
4、編寫REST客戶端進行測試
一、建立項目
IDEA中建立一個新的SpringBoot項目,名稱爲「first-cloud-rest-client」,SpringBoot版本選擇2.1.9,在選擇Dependencies(依賴)的界面勾選Web->Spring Web。
在pom.xml中增長httpclient依賴。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>first-cloud-rest-client</artifactId> <version>0.0.1-SNAPSHOT</version> <name>first-cloud-rest-client</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <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> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
二、修改配置application.yml
server: port: 9001
三、修改啓動類代碼FirstCloudRestClientApplication.java
編寫調用REST服務的代碼
package com.example.firstcloudrestclient; import org.apache.http.HttpResponse; 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 org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class FirstCloudRestClientApplication { public static void main(String[] args) { SpringApplication.run(FirstCloudRestClientApplication.class, args); } @RequestMapping("/") public String testHttpClient(){ StringBuilder sb = new StringBuilder(); try{ CloseableHttpClient httpClient = HttpClients.createDefault(); for(int i=0;i<10;i++){ HttpGet httpGet = new HttpGet("http://localhost:9000/router"); HttpResponse response = httpClient.execute(httpGet); sb.append(EntityUtils.toString(response.getEntity()) + "<br />"); } }catch(Exception ex){ return ex.getMessage(); } return sb.toString(); } }
四、測試
(1)啓動兩個服務器端,在控制檯中分別輸入slave1和slave2啓動。
(2)啓動兩個服務提供者,在控制檯中分別輸入8763和8764啓動。
(3)啓動服務調用者。
(4)啓動REST客戶端。
瀏覽器訪問 http://slave1:8761/,頁面以下
瀏覽器訪問 http://slave2:8762/,頁面以下
瀏覽器訪問 http://localhost:8763/user/1,頁面輸出:
{"id":1,"name":"gdjlc","message":"http://localhost:8763/user/1"}
瀏覽器訪問 http://localhost:8764/user/1,頁面輸出:
{"id":1,"name":"gdjlc","message":"http://localhost:8764/user/1"}
瀏覽器訪問 http://localhost:9000/router,屢次刷新頁面,頁面輸出在8763和8764切換:
{"id":1,"name":"gdjlc","message":"http://localhost:8763/user/1"}
{"id":1,"name":"gdjlc","message":"http://localhost:8764/user/1"}
瀏覽器訪問 http://localhost:9001/,頁面輸出
{"id":1,"name":"gdjlc","message":"http://localhost:8764/user/1"} {"id":1,"name":"gdjlc","message":"http://localhost:8763/user/1"} {"id":1,"name":"gdjlc","message":"http://localhost:8764/user/1"} {"id":1,"name":"gdjlc","message":"http://localhost:8763/user/1"} {"id":1,"name":"gdjlc","message":"http://localhost:8764/user/1"} {"id":1,"name":"gdjlc","message":"http://localhost:8763/user/1"} {"id":1,"name":"gdjlc","message":"http://localhost:8764/user/1"} {"id":1,"name":"gdjlc","message":"http://localhost:8763/user/1"} {"id":1,"name":"gdjlc","message":"http://localhost:8764/user/1"} {"id":1,"name":"gdjlc","message":"http://localhost:8763/user/1"}
請求了10次,8763和8764分別被請求5次,可見已經達到負載均衡。