Spring Cloud實戰系列(二) - 客戶端呼叫Rest + Ribbon

零壹技術棧發表於2019-01-27

相關

  1. Spring Cloud實戰系列(一) - 服務註冊與發現Eureka

  2. Spring Cloud實戰系列(二) - 客戶端呼叫Rest + Ribbon

  3. Spring Cloud實戰系列(三) - 宣告式客戶端Feign

  4. Spring Cloud實戰系列(四) - 熔斷器Hystrix

  5. Spring Cloud實戰系列(五) - 服務閘道器Zuul

  6. Spring Cloud實戰系列(六) - 分散式配置中心Spring Cloud Config

  7. Spring Cloud實戰系列(七) - 服務鏈路追蹤Spring Cloud Sleuth

  8. Spring Cloud實戰系列(八) - 微服務監控Spring Boot Admin

  9. Spring Cloud實戰系列(九) - 服務認證授權Spring Cloud OAuth 2.0

  10. Spring Cloud實戰系列(十) - 單點登入JWT與Spring Security OAuth

前言

上一篇文章我們介紹了 Eureka 服務註冊中心 的搭建,這篇文章介紹一下如何使用 Eureka 服務註冊中心,搭建一個簡單的 服務端註冊服務,由 客戶端 通過 Ribbon 負載均衡 地去呼叫服務案例。

正文

1. 建立服務提供者

建立一個 service-hiModule,建立完成後的 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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>io.ostenant.github.springcloud</groupId>
    <artifactId>service-hi</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>service-hi</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-cloud-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
複製程式碼

通過 註解 @EnableEurekaClient 表明自己是一個 Eureka Client

@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHiApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceHiApplication.class, args);
    }
}
複製程式碼

建立一個控制器 HelloController,對外提供一個 /hiHTTP 的服務。在響應資料中返回當前 服務例項埠號

@RestController
public class HelloController {

    @Value("${server.port}")
    private String port;

    @RequestMapping("/hi")
    public String hi(@RequestParam String name) {
        return "Hi " + name + ", I am from port: "  + port;
    }
}
複製程式碼

配置檔案 中註明的 服務註冊中心 的地址,application.yml 配置檔案如下:

spring:
  active:
    profiles: service-hi1 # service-hi2

---

spring:
  profiles: service-hi1
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8763
spring:
  application:
    name: service-hi

---

spring:
  profiles: service-hi2
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8764
spring:
  application:
    name: service-hi
複製程式碼

分別以 spring.profiles.active=hi1spring.profiles.active=hi2 作為 Spring Boot啟動命令引數,在 埠號 87638764 啟動 2服務提供者 例項。

2. 建立服務消費者

重新新建 service-ribbonModule,在它的 pom.xml 檔案分別引入 起步依賴 spring-cloud-starter-eurekaspring-cloud-starter-ribbonspring-boot-starter-web,程式碼如下:

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>io.ostenant.github.springcloud</groupId>
    <artifactId>service-ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>service-ribbon</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <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>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
複製程式碼

在專案的 配置檔案 指定服務的 服務註冊中心 的地址,應用名稱service-ribbon埠號8762。完整配置檔案 application.yml 如下:

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8762
spring:
  application:
    name: service-ribbon
複製程式碼

在應用 啟動類 上,通過 @EnableDiscoveryClient服務中心 註冊自身資訊,向 Spring Boot 容器註冊一個 RestTemplate 物件,並通過 @LoadBalanced 註解表明這個 RestRemplate 開啟 客戶端負載均衡 的功能。

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceRibbonApplication.class, args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
複製程式碼

寫一個 測試介面,注入上面的 RestTemplate 物件來消費 service-hi 服務的 /hi 介面。在 RestTemplateURL 中,我們將具體 服務生產者主機名稱埠號 替換為它的 服務名稱

@RestController
public class HelloController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/hi")
    public String requestForHi(@RequestParam String name){
        return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
    }
}
複製程式碼

在瀏覽器上多次訪問 http://localhost:8762/hi?name=ribbon,瀏覽器交替顯示:

Hi ribbon, I am from port: 8763

Hi ribbon, I am from port: 8764

在具體的呼叫過程中,Ribbon 提供的 @LoadBalanced 註解會從 Eureka Server 上查詢 服務列表,根據 服務名稱 找到 SERVICE-HI服務例項。如果有多個 SERVICE-HI 例項,Ribbon 會根據 客戶端負載均衡 演算法篩選其中一臺,並把 URL 中的 SERVICE-HI 替換為具體例項的 主機名稱埠號

參考

  • 方誌朋《深入理解Spring Cloud與微服務構建》

歡迎關注技術公眾號: 零壹技術棧

零壹技術棧

本帳號將持續分享後端技術乾貨,包括虛擬機器基礎,多執行緒程式設計,高效能框架,非同步、快取和訊息中介軟體,分散式和微服務,架構學習和進階等學習資料和文章。

相關文章