1. 程式人生 > 其它 >SpringCloud五大神獸02-Ribbon/Feign負載均衡

SpringCloud五大神獸02-Ribbon/Feign負載均衡

技術標籤:java學習javaspring cloud

1.簡介

  • Ribbon是Netflix釋出的雲中間層服務開源專案,主要功能是提供客戶端負載均衡演算法。使用Ribbon的時候,只要服務提供者的名稱相同,就自動形成了叢集,並且有預設負載均衡策略(輪詢)。
  • Feign是對Ribbon的封裝,簡化了服務的呼叫方式,即呼叫服務的時候,不再需要拼接需要傳遞的引數到訪問地址上,而是採用定義介面(遵循Feign提供的模板)的方式去實現,Feign會完全代理HTTP請求。

2.使用

建立兩個微服務,一個叫Consumer,一個叫Provider,用Consumer去呼叫Provider。當然,Eureka也是必不可少的。這三個微服務作為子模組,它們的父模組的pom.xml還是採用依賴版本管理的方式。

<properties>
      <spring.cloud-version>Finchley.SR4</spring.cloud-version>
      <spring.boot-version>2.0.5.RELEASE</spring.boot-version>
</properties>
<dependencyManagement>
      <dependencies>
          <dependency>
              <groupId>
org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot-version}</version> <type>pom</type> <scope>import</scope> </dependency> <
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>

2.1.Ribbon

2.1.1.匯入依賴

  • 服務消費者Consumer:Eureka客戶端、Ribbon場景啟動器
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

        <!-- Ribbon場景啟動器 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
   </dependency>
</dependencies>
  • 服務提供者Provider:Eureka客戶端(不需要Ribbon依賴)
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

2.1.2.寫啟動類

  • 服務消費者Consumer:配置RestTemplate、配置負載均衡策略
@SpringBootApplication
@EnableEurekaClient //可寫可不寫
public class RibbonConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(RibbonConsumerApp.class,args);
    }
    /**
     * @LoadBalanced: 開啟負載均衡策略,預設是輪詢
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    /**
     * 修改負載均衡策略(IRule是一個介面,只能new它的實現類)
     *      new RandomRule():隨機策略
     *      new WeightedResponseTimeRule():權重策略
     *      new RoundRobinRule():輪詢策略--預設
     * @return
     */
    @Bean
    public IRule iRule(){
        return new RoundRobinRule();
    }
}
  • 服務提供者Provider:正常寫即可
@SpringBootApplication
@EnableEurekaClient //可寫可不寫
public class Provider8082App {
    public static void main(String[] args) {
        SpringApplication.run(Provider8082App.class,args);
    }
}

2.1.3.寫yml配置

  • 服務消費者Consumer:配置埠和服務名稱、註冊服務到Eureka註冊中心
server:
  port: 9090

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    instance-id: ribbon-consumer:9090    #自定義一個服務id名稱,否則就預設使用當前計算機名稱作為服務的id

spring:
  application:
    name:  RIBBON-CONSUMER   #服務名稱標識 如果不配置,則預設是UNKNOWN
  • 服務提供者Provider:配置埠和服務名稱、註冊服務到Eureka註冊中心
server:
  port: 8082

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    instance-id: service-provider-ribbon:8082    #自定義一個服務id名稱,否則就預設使用當前計算機名稱作為服務的id

spring:
  application:
    name:  SERVICE-PROVIDER-RIBBON   #服務名稱標識 如果不配置,則預設是UNKNOWN

2.1.4.寫Controller

僅做一個簡單的測試,在瀏覽器訪問服務消費者,服務消費者呼叫服務提供者的服務,返回一個字串在瀏覽器上展示

  • 服務消費者Consumer:用RestTemplate來發HTTP請求,呼叫Provider
@RestController
public class RibbonConsumerController {
    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/ribbon/consumer")
    public String consumer(){
        System.out.println("consumer...................");
        //傳送get請求,訪問另一個provider服務
        //如果需要傳遞引數,需要拼接到URL上
        String s = restTemplate.getForObject("http://SERVICE-PROVIDER-RIBBON/ribbon/provider", String.class);

        return s;
    }
}
  • 服務提供者Provider:返回一個字串
@RestController
public class ProviderController8082 {
    /**
     * @return
     */
    @GetMapping("/ribbon/provider")
    public String provider(){
        System.out.println("provider..............");
        return "*****8082*****";
    }
}

2.1.5.瀏覽器訪問測試

瀏覽器訪問測試

2.2.Feign

Ribbon和Feign都是配置在服務消費者上,服務提供者的配置是一樣的

2.2.1.匯入依賴

  • 服務消費者Consumer:Eureka客戶端、Feign場景啟動器(注意:依賴的名字叫openfeign
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <!-- feign場景啟動器 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

2.2.2.寫啟動類

  • 服務消費者Consumer:
    注意:一定要加@EnableFeignClients註解
/**
 * @EnableFeignClients 這個註解表示開啟動態代理
 *  會自動遞迴掃描當前啟動類所在的包【掃描所有添加了@FeignClient註解的介面,然後採用動態代理技術生成實現類,
 *  建立物件儲存到Spring容器中】
 */
@SpringBootApplication
@EnableFeignClients
@EnableEurekaClient
public class FeignConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApp.class,args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

2.2.3.寫yml配置

  • 服務消費者Consumer:埠和服務名稱配置、服務註冊到Eureka服務中心
server:
  port: 9091

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    instance-id: feign-consumer:9091    #自定義一個服務id名稱,否則就預設使用當前計算機名稱作為服務的id

spring:
  application:
    name:  FEIGN-CONSUMER   #服務名稱標識 如果不配置,則預設是UNKNOWN

2.2.4.寫Feign客戶端介面

Feign客戶端介面寫在服務消費者方,它是一個介面,介面上需要添加@FeignClient註解
介面中的方法引數、返回值、請求地址必須和對應的服務提供者Controller中的方法定義的一致。
為方便起見,可以直接把服務提供者中對應的方法copy過來,刪除方法體即可。

/**
 * @FeignClient 表明當前介面是Feign的客戶端介面,並在value屬性中指定所呼叫的服務名稱
 */
@FeignClient(value = "SERVICE-PROVIDER")
@Component
public interface ProviderClient {
    @GetMapping("/feign/provider")
    String provider();
}

2.2.5.寫Controller

  • 服務消費者Consumer:依賴注入Client物件,呼叫方法即可(使用方式類似於mapper層介面)
@RestController
public class FeignConsumerController {
    @Autowired
    private ProviderClient providerClient;

    @GetMapping("/feign/consumer")
    public String feignConsumer(){
        System.out.println("feignConsumer.....................");
        String s = providerClient.provider();
        return s;
    }
}

2.2.6.瀏覽器訪問測試

瀏覽器訪問

3.Ribbon和Feign的區別

Feign是通過定義FeignClient介面的方式呼叫(類似於mapper層介面的使用方式),我們只需要定義好介面,在介面上加@FeignClient註解並指定要呼叫的服務名稱或者服務叢集名稱,在啟動類上加@EnableFeignClients註解,Feign底層就會動態代理生成FeignClient介面的實現類,實現類中重寫介面的方法,內部還是採用的Ribbon的方式去呼叫(用RestTemplate傳送HTTP請求)。
由於Feign是對Ribbon進行的封裝,所以Feign也有Ribbon的負載均衡。
另外,Feign內部也集成了Hystrix,所以我們一般會使用Feign。

4.總結

簡單理解,Ribbon是SpringCloud中微服務之間的呼叫方式,有了它,我們可以通過微服務的名稱去呼叫對應的微服務,如果多個微服務有相同的名稱,就自動形成了叢集,並且Ribbon會自動對叢集進行負載均衡,預設的策略是輪詢,也可以自己定義負載均衡策略。
Feign是對Ribbon進行的封裝,擁有Ribbon的所有功能,優化的地方在於採用了定義FeignClient介面的方式去呼叫微服務,傳送HTTP請求的步驟封裝到了底層自動實現,使用更方便。