SpringCloud_04 負載均衡及Ribbon、Feign
- Ribbon是什麼
- Ribbon能幹嘛
- 使用Ribbon實作負載均衡
- 更改預設負載均衡算法
- Feign簡介
- Feign實作
Ribbon是什麼
- SpringCloud Ribbon是基于Netflix Ribbon實作的一套用戶端負載均衡工具。
- Ribbon是Netflix釋出的開源項目,主要功能是提供用戶端的負載均衡算法,将Netflix的中間層服務連接配接在一起。 Ribbon的用戶端元件提供一系列網站的配置項如:連接配接逾時、重試等。簡單的說就是在配置檔案中列出LoadBalancer(簡稱LB:負載均衡)後面所有的基期,Ribbon會自動的幫助你基于某種規則(如簡單輪詢、随機連接配接等)去連接配接這些機器。我們也很容易使用Ribbon實作自定義的負載均衡算法!
Ribbon能幹嘛
- LB,即負載均衡(Load Balancer),在微服務或分布式叢集中經常用到的一種應用。
- 負載均衡簡單的說就是将使用者的請求平攤的配置設定到多個服務上,進而達到系統的HA(高可用)。
- 常見的負載均衡軟體有:Nginx、Lvs等。
- Dubbo、SpringCloud中均給我們提供了負載均衡,SpringCloud的負載均衡算法可以自定義。
- 負載均衡簡單分類:
- 集中式LB:即在服務的消費方和提供方之間使用獨立的LB設施,如Nginx(反向代理伺服器),由該設施負責把通路請求通過某種政策轉發至服務的提供方!
- 程序式LB:将LB邏輯內建到消費方,消費方從服務注冊中心獲知有哪些位址可用,然後自己再從這些位址中選出一個合适的伺服器。Ribbon就屬于程序内LB,它隻是一個類庫,繼承與消費方程序,消費方通過它來擷取到服務提供方的位址!
使用Ribbon實作負載均衡
- 拷貝資料庫
- 建立資料庫springcloud2,springcloud3。
- 插入資料。
- 在消費端spring-cloud-consumer-dept-80導入Eureka相關依賴(Eureka自帶了ribbon,自己導入ribbon會報錯)。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
- 在application.yml配置Eureka
#eureka
eureka:
client:
fetch-registry: true #如果為false表示自己為注冊中心
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
register-with-eureka: false #不向Eureka注冊自己
- 在配置類配置負載均衡實作RestTemplate。
package com.jiu.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class BeanConfig {
//配置負載均衡實作[email protected]
@Bean
@LoadBalanced //ribbon
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
- 在主啟動類開啟Eureka。
package com.jiu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @CLassName : SpringCloudConsumerDep80
* @Description : TODO Ribbon和Eureka整合以後,用戶端可以直接調用,不用關系IP位址和端口号。
* @Author : 九九
* @Date : 2021/7/26,20:26
**/
@SpringBootApplication
@EnableEurekaClient
public class SpringCloudConsumerDep80 {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConsumerDep80.class, args);
}
}
- Controller的變化。
- 之前是通過http://localhost:8001通路的。
- 現在使用Ribbon,那麼位址應該是一個變量,通過服務名來通路。
package com.jiu.controller;
import com.jiu.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
@RequestMapping("/dept")
public class DeptConsumerController {
private RestTemplate template;
// Ribbon,這裡的位址應該是一個變量,通過服務名來通路。
// private static final String REST_URL_PREFIX = "http://localhost:8001";
private static final String REST_URL_PREFIX = "http://SPRING-CLOUD-PROVIDER-DEPT";
@Autowired
public void setTemplate(RestTemplate template) {
this.template = template;
}
@GetMapping("/queryAllDept")
public List queryAllDept(){
return template.getForObject(REST_URL_PREFIX+"/dept/queryAllDept", List.class);
}
}
- 測試
- 先啟動注冊中心spring-cloud-eureka-7001(由于啟動過多程序會占用太多記憶體,是以測試僅啟動一個注冊中心即可)。
- 分别啟動服務提供者spring-cloud-provider-dept-8001、spring-cloud-provider-dept-8002和spring-cloud-provider-dept-8003。
- 可以看到三個服務已經注冊進去了:
- 接着啟動服務消費者spring-cloud-comsumer-dept-80。
- 使用浏覽器通路http://localhost/dept/queryAllDept,結果如下,查詢的是資料庫springcloud2:
- 再次通路,結果查詢的是資料庫springcloud3:
- 再次通路,結果是springcloud1:
- 說明Ribbon的預設負載均衡算法是輪詢算法。
更改預設負載均衡算法
- Ribbon預設實作了多種負載均衡算法。
- AvailabilityFilteringRule : 會過先過濾掉跳閘的服務,對剩下的進行輪詢。
- RoundRobinRule : 輪詢。
- RandomRule : 随機。
- RetryRule : 按照輪詢擷取服務~,如果擷取失敗,會在指定時間内進行重試。
- 更改預設的負載均衡算法隻需将元件注冊到容器中即可。
@Bean
public IRule myRule(){
return new RandomRule();
}
Feign簡介
- Feign是聲明式的web service用戶端,它讓微服務之間的調用變得更簡單了,類似controller調用service。
- SpringCloud內建了Ribbon和Eureka,可以在使用Feign時提供負載均衡的http用戶端。
- 隻需要建立一個接口,然後添加注解即可!
- Feign,主要是社群,大家都習慣面向接口程式設計,這個是很多開發人員的規範。調用微服務的兩種方法:微服務名字(Ribbon)和接口和注解(Feign)。
- Feign能幹什麼?
- Feign旨在使編寫Java Http用戶端變得更容易。
- 前面在使用Ribbon+RestTemplate時,利用RestTemplate對Http請求的封裝處理,形成了一套模闆化的調用方法。但是在實際開發過程中,由于對服務依賴的調用可能不止一處,往往一個接口會被多處調用,是以通常都會針對每個微服務自行封裝一些用戶端類來包裝這些依賴服務的調用。是以,Feign在此基礎上做了進一步封裝,由他來幫助我們定義和實作依賴服務接口。在Feign的實作下,我們隻需要建立一個接口并使用注解的方式來配置它(類似于Dao接口加上Mapper注解,現在是一個微服務接口上面标注一個Feign注解即可),即可完成對服務提供方的接口綁定,簡化了使用SpringCloud Ribbon時,自動封裝服務調用用戶端的開發量。
Feign實作
- 建立一個新的子產品spring-cloud-comsumer-dept-feign-80,導入相關的依賴。
<dependencies>
<dependency>
<groupId>com.jiu</groupId>
<artifactId>spring-cloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- eureka-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
</dependencies>
- 編寫application.yml檔案
server:
port: 80
#eureka
eureka:
client:
fetch-registry: true #如果為false表示自己為注冊中心
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
register-with-eureka: false #不向Eureka注冊自己
- 編寫主啟動類。
- 在spring-cloud-api子產品添加feign依賴。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
- 修改spring-cloud-api子產品,添加service層。
- 編寫DeptService接口。
package com.jiu.service;
import com.jiu.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@FeignClient(value = "SPRING-CLOUD-PROVIDER-DEPT")
public interface DeptService {
@GetMapping("/dept/queryAllDept")
public List<Dept> queryAllDept();
}
- 在spring-cloud-comsumer-dept-feign-80子產品下編寫DeptController
package com.jiu.controller;
import com.jiu.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/dept")
public class DeptConsumerController {
private DeptService deptService;
@Autowired
public void setDeptService(DeptService deptService) {
this.deptService = deptService;
}
@GetMapping("/queryAllDept")
public List queryAllDept(){
return deptService.queryAllDept();
}
}
- 在主啟動類開啟Feign。
package com.jiu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.jiu"}) //開啟Feign,并配置掃描的包。
public class SpringCloudConsumerDepFeign80 {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConsumerDepFeign80.class, args);
}
}
- 測試,啟動spring-cloud-eureka-7001、spring-cloud-provider-dept-8001、spring-cloud-provider-dept-8002、spring-cloud-provider-dept-8001、spring-cloud-comsumer-dept-feign-80,使用浏覽器通路localhost/dept/queryAllDept。
- 結果如下: