欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用Gateway自定義負載均衡過濾器

 更新時間:2020年07月06日 10:13:16   作者:愛唱歌的Coder  
這篇文章主要介紹了Java使用Gateway自定義負載均衡過濾器,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

背景

最近項目中需要上傳視頻文件,由于視頻文件可能會比較大,但是我們應用服務器tomcat設置單次只支持的100M,因此決定開發(fā)一個分片上傳接口。
把大文件分成若干個小文件上傳。所有文件上傳完成后通過唯一標示進行合并文件。
我們的開發(fā)人員很快完成了開發(fā),并在單元測試中表現(xiàn)無誤。上傳代碼到測試環(huán)境,喔嚯?。?!出錯了。
經(jīng)過一段時間的辛苦排查終于發(fā)現(xiàn)問題,測試環(huán)境多實例,分片上傳的接口會被路由到不同的實例,導致上傳后的分片文件在不同的機器,那么也就無法被合并。
知道了原因就好解決,經(jīng)過一系列的過程最終決定修改網(wǎng)關把uuid相同的請求路由到相同的實例上,這樣就不會出錯了!

準備

由于是公司代碼不方便透露,現(xiàn)使用本地測試代碼。
準備:Eureka注冊中心,Gateway網(wǎng)關,測試微服務

啟動后服務如下兩個測試的微服務,一個網(wǎng)關服務

gateway版本

<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>

此處就說下我網(wǎng)關的配置。

#網(wǎng)關名
spring.cloud.gateway.routes[0].id=route-my-service-id
#網(wǎng)關uri,lb代表負載均衡,后面是服務名,必須要和微服務名一致,不能錯,錯了肯定不能路由
spring.cloud.gateway.routes[0].uri=lb://my-service-id
#斷言,配置的路徑
spring.cloud.gateway.routes[0].predicates[0]=Path=/my-service-id/v3/**
#截取uri前面兩個位置的
spring.cloud.gateway.routes[0].filters[0]=StripPrefix=2

分析

想要修改路由就要知道gateway是如何把我們的請求路由到各個微服務的實例上的。

gateway其實無非就是不同的過濾器,然后對請求進行處理,和zuul類似。gateway自帶了很多過濾器。過濾器分為兩種:

1、GlobalFilter 。顧名思義,全局過濾器,所有請求都會走的過濾器。常見的自帶過濾器LoadBalancerClientFilter(負載均衡過濾器,后面我們就是修改這個地方)。

2、GatewayFilter。網(wǎng)關過濾器,該過濾器可以指定過濾的條件,只有達到了條件的才進入該過濾器。

如果想知道自帶有哪些配置,我們可以查看gateway的自動注入類GatewayAutoConfiguration。

/**
 * @author Spencer Gibb
 */
@Configuration
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,
		WebFluxAutoConfiguration.class })
@AutoConfigureAfter({ GatewayLoadBalancerClientAutoConfiguration.class,
		GatewayClassPathWarningAutoConfiguration.class })
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {

	@Bean
	public StringToZonedDateTimeConverter stringToZonedDateTimeConverter() {
		return new StringToZonedDateTimeConverter();
	}

	@Bean
	public RouteLocatorBuilder routeLocatorBuilder(
			ConfigurableApplicationContext context) {
		return new RouteLocatorBuilder(context);
	}

	@Bean
	@ConditionalOnMissingBean
	public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(
			GatewayProperties properties) {
		return new PropertiesRouteDefinitionLocator(properties);
	}
省略.......

然后查看負載均衡配置。
GatewayLoadBalancerClientAutoConfiguration

/**
 * @author Spencer Gibb
 */
@Configuration
@ConditionalOnClass({ LoadBalancerClient.class, RibbonAutoConfiguration.class,
		DispatcherHandler.class })
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@EnableConfigurationProperties(LoadBalancerProperties.class)
public class GatewayLoadBalancerClientAutoConfiguration {

	// GlobalFilter beans

	//負載均衡
	@Bean
	@ConditionalOnBean(LoadBalancerClient.class)
	@ConditionalOnMissingBean(LoadBalancerClientFilter.class)
	public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client,
			LoadBalancerProperties properties) {
		return new LoadBalancerClientFilter(client, properties);
	}

}

進入LoadBalancerClientFilter,其實就是一個GlobalFilter。
調(diào)試代碼試一試呢?發(fā)現(xiàn)果然要走。(此處圖片中應該是my-service-id)。


最終被路由到這個地方,負載均衡使用的是ribbon,關于ribbon暫時不討論。


重點在這兒,通過現(xiàn)在的uri選擇到具體的uri。而這個方法恰恰是一個protected方法,我們可以重寫該方法加上我們自己的業(yè)務邏輯。

protected ServiceInstance choose(ServerWebExchange exchange) {
		return loadBalancer.choose(
				((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost());
	}

實現(xiàn)

重寫LoadBalancerClientFilter中的choose方法,實現(xiàn)自定義邏輯

/**
 * @Description 自定義負載均衡
 * @Author Singh
 * @Date 2020-07-02 10:36
 * @Version
 **/
public class CustomLoadBalancerClientFilter extends LoadBalancerClientFilter implements BeanPostProcessor {

  private final DiscoveryClient discoveryClient;

  private final List<IChooseRule> chooseRules;

  public CustomLoadBalancerClientFilter(LoadBalancerClient loadBalancer,
                     LoadBalancerProperties properties,
                     DiscoveryClient discoveryClient) {
    super(loadBalancer, properties);
    this.discoveryClient = discoveryClient;
    this.chooseRules = new ArrayList<>();
    chooseRules.add(new EngineeringChooseRule());
  }

  protected ServiceInstance choose(ServerWebExchange exchange) {
    if(!CollectionUtils.isEmpty(chooseRules)){
      Iterator<IChooseRule> iChooseRuleIterator = chooseRules.iterator();
      while (iChooseRuleIterator.hasNext()){
        IChooseRule chooseRule = iChooseRuleIterator.next();
        ServiceInstance choose = chooseRule.choose(exchange,discoveryClient);
        if(choose != null){
          return choose;
        }
      }
    }
    return loadBalancer.choose(
        ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost());
  }
}

定義通用選擇實例規(guī)則

/**
 * @Description 自定義選擇實例規(guī)則
 * @Author Singh
 * @Date 2020-07-02 11:03
 * @Version
 **/
public interface IChooseRule {

  /**
   * 返回null那么使用gateway默認的負載均衡策略
   * @param exchange
   * @param discoveryClient
   * @return
   */
  ServiceInstance choose(ServerWebExchange exchange, DiscoveryClient discoveryClient);

}

實現(xiàn)自定義路由策略

/**
 * @Description 微服務負載均衡策略
 * @Author Singh
 * @Date 2020-07-02 11:10
 * @Version
 **/
public class EngineeringChooseRule implements IChooseRule {

  @Override
  public ServiceInstance choose(ServerWebExchange exchange, DiscoveryClient discoveryClient) {
    URI originalUrl = (URI) exchange.getAttributes().get(GATEWAY_REQUEST_URL_ATTR);
    String instancesId = originalUrl.getHost();
    if(instancesId.equals("my-service-id")){
      if(originalUrl.getPath().contains("/files/upload")){
        try{
          List<ServiceInstance> instances = discoveryClient.getInstances(instancesId);
          MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
          String uuid = queryParams.get("uuid").get(0);
          int hash = uuid.hashCode() >>> 16 ;
          int index = hash % instances.size();
          return instances.get(index);
        }catch (Exception e){
          //do nothing
        }
      }
    }

    return null;
  }
}

最后注入自定義負載均衡過濾器。

/**
 * @Description
 * @Author Singh
 * @Date 2020-07-01 17:57
 * @Version
 **/
@Configuration
public class GetawayConfig {

//  @Bean
//  public RouteLocator routeLocator(RouteLocatorBuilder builder) {
//    //lb://hjhn-engineering/files/upload
//    return builder.routes()
//        .route(r ->r.path("/**").filters(
//                    f -> f.stripPrefix(2).filters(new EngineeringGatewayFilter())
//                ).uri("lb://hjhn-engineering")
//        ) .build();
//  }

  @Bean
  public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client,
                               LoadBalancerProperties properties,
                              DiscoveryClient discoveryClient) {
      return new CustomLoadBalancerClientFilter(client, properties,discoveryClient);
  }

}

如此,相同uuid的請求就可以通過hash取模路由到相同的機器上了,當然這樣還是存在問題,比如多添加一個實例,或者掛了一個實例,掛之前有一個請求到A,掛之后可能到B,因為此時取模就不同了,還是會到不同請求。但是這種情況很少發(fā)生,所以暫時不考慮。

或許有hash槽的方式可以解決一點問題,后續(xù)研究?。。。?!

到此這篇關于Java使用Gateway自定義負載均衡過濾器的文章就介紹到這了,更多相關Java 自定義負載均衡過濾器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 詳解java設計模式之六大原則

    詳解java設計模式之六大原則

    這篇文章主要介紹了java設計模式之六大原則,對設計模式感興趣的同學,可以參考下
    2021-05-05
  • Eclipse查看開發(fā)包jar里源代碼的方法

    Eclipse查看開發(fā)包jar里源代碼的方法

    這篇文章主要介紹了Eclipse查看開發(fā)包jar里源代碼的方法的相關資料,需要的朋友可以參考下
    2017-07-07
  • 使用java寫的矩陣乘法實例(Strassen算法)

    使用java寫的矩陣乘法實例(Strassen算法)

    這篇文章主要給大家介紹了關于如何使用java寫的矩陣乘法(Strassen算法)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • MyBatis中多對一和一對多數(shù)據(jù)的處理方法

    MyBatis中多對一和一對多數(shù)據(jù)的處理方法

    這篇文章主要介紹了MyBatis中多對一和一對多數(shù)據(jù)的處理,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • Mac系統(tǒng)搭建JDK及JMETER過程解析

    Mac系統(tǒng)搭建JDK及JMETER過程解析

    這篇文章主要介紹了Mac系統(tǒng)搭建JDK及JMETER過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • Java Arrays.AsList原理及用法實例

    Java Arrays.AsList原理及用法實例

    這篇文章主要介紹了Java Arrays.AsList原理及用法實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • SpringSecurity概念及整合ssm框架的示例詳解

    SpringSecurity概念及整合ssm框架的示例詳解

    用戶登錄系統(tǒng)時我們協(xié)助?SpringSecurity?把用戶對應的角色、權限組裝好,同時把各個資源所要求的權限信息設定好,剩下的“登錄驗證”、“權限驗證”等等工作都交給SpringSecurity,對SpringSecurity整合ssm框架相關知識感興趣的朋友跟隨小編一起看看吧
    2022-12-12
  • Spring?Boot?中的?Native?SQL基本概念及使用方法

    Spring?Boot?中的?Native?SQL基本概念及使用方法

    在本文中,我們介紹了 Spring Boot 中的 Native SQL,以及如何使用 JdbcTemplate 和 NamedParameterJdbcTemplate 來執(zhí)行自定義的 SQL 查詢或更新語句,需要的朋友跟隨小編一起看看吧
    2023-07-07
  • SpringBoot中Shiro緩存使用Redis、Ehcache的方法

    SpringBoot中Shiro緩存使用Redis、Ehcache的方法

    這篇文章主要介紹了SpringBoot中Shiro緩存使用Redis、Ehcache的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • 為什么說HashMap線程不安全

    為什么說HashMap線程不安全

    本文主要介紹了為什么說HashMap線程不安全,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04

最新評論