springcloud gateway如何实现路由和负载均衡

2025-05-29 0 108

简介:

gateway主要是做路由 负载,过滤 主要是替代zuul 1.x 性能比zuul好 zuul是基于

Servlet ,gateway是基于spring-webflux 用的netty+reactor

yml文件

实现路由 负载 的配置 亲自测试

  1. spring:
  2. application:
  3. name: xgyx_gateway
  4. cloud:
  5. discovery:
  6. locator:
  7. enabled: true
  8. gateway:
  9. routes:
  10. id: a #随便定义不重复就好
  11. uri: lb://xgyx-welfareservice-x #服务名称
  12. predicates:
  13. Path=/m/** #前端访问需加入例如 http:ip:port/m
  14. filters:
  15. StripPrefix=1 #访问后端服务过滤掉m 必填否则找不到后端服务也可以在服务加上统一路径
  16. name: Hystrix #熔断
  17. args:
  18. name: default
  19. fallbackUri: forward:/defaultfallback #熔断后访问路径
  20. id: b
  21. uri: lb://xgyx-welfareservice
  22. predicates:
  23. Path=/welfare/**
  24. filters:
  25. StripPrefix=1
  26. name: Hystrix
  27. args:
  28. name: default
  29. fallbackUri: forward:/fallback
  30. #熔断时间
  31. hystrix:
  32. command:
  33. default:
  34. execution:
  35. isolation:
  36. strategy: SEMAPHORE
  37. thread:
  38. timeoutInMilliseconds: 300000 #熔断时间

上面是用了两天时间根据官网上的demo和说明自己测的可以使用 上面 stripPrefix 用的是 PrefixPath 过滤器 其他过滤器使用可以看官网

springcloud gateway 自定义负载均衡

相关类及接口

LoadbalancerClientFilter:使用ribbon负载均衡,默认使用该类(已不推荐使用)

  1. /** @deprecated */
  2. @Deprecated
  3. public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
  4. public static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10100;
  5. private static final Log log = LogFactory.getLog(LoadBalancerClientFilter.class);
  6. protected final LoadBalancerClient loadBalancer;
  7. private LoadBalancerProperties properties;
  8. public LoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties) {
  9. this.loadBalancer = loadBalancer;
  10. this.properties = properties;
  11. }
  12. public int getOrder() {
  13. return 10100;
  14. }
  15. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  16. URI url = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
  17. String schemePrefix = (String)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
  18. if (url != null && ("lb".equals(url.getScheme()) || "lb".equals(schemePrefix))) {
  19. ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
  20. if (log.isTraceEnabled()) {
  21. log.trace("LoadBalancerClientFilter url before: " + url);
  22. }
  23. ServiceInstance instance = this.choose(exchange);
  24. if (instance == null) {
  25. throw NotFoundException.create(this.properties.isUse404(), "Unable to find instance for " + url.getHost());
  26. } else {
  27. URI uri = exchange.getRequest().getURI();
  28. String overrideScheme = instance.isSecure() ? "https" : "http";
  29. if (schemePrefix != null) {
  30. overrideScheme = url.getScheme();
  31. }
  32. URI requestUrl = this.loadBalancer.reconstructURI(new DelegatingServiceInstance(instance, overrideScheme), uri);
  33. if (log.isTraceEnabled()) {
  34. log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
  35. }
  36. exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
  37. return chain.filter(exchange);
  38. }
  39. } else {
  40. return chain.filter(exchange);
  41. }
  42. }
  43. protected ServiceInstance choose(ServerWebExchange exchange) {
  44. return this.loadBalancer.choose(((URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR)).getHost());
  45. }
  46. }

说明:默认使用该类,可通过下述方法使用ReactiveLoadbalancerClientFilter

​"You already have RibbonLoadBalancerClient on your classpath. It will be used by default.
As Spring Cloud Ribbon is in maintenance mode. We recommend switching to " + BlockingLoadBalancerClient.class.getSimpleName() + " instead.
In order to use it, set the value of `spring.cloud.loadbalancer.ribbon.enabled` to `false`
or remove spring-cloud-starter-netflix-ribbon from your project."

ReactiveLoadBalancerClientFilter负载均衡拦截器

  1. public class ReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {
  2. private static final Log log = LogFactory.getLog(ReactiveLoadBalancerClientFilter.class);
  3. private static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150;
  4. private final LoadBalancerClientFactory clientFactory;
  5. private LoadBalancerProperties properties;
  6. public ReactiveLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory, LoadBalancerProperties properties) {
  7. this.clientFactory = clientFactory;
  8. this.properties = properties;
  9. }
  10. public int getOrder() {
  11. return 10150;
  12. }
  13. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  14. URI url = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
  15. String schemePrefix = (String)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
  16. if (url != null && ("lb".equals(url.getScheme()) || "lb".equals(schemePrefix))) {
  17. //url不为null且协议为lb,或者url以lb开头
  18. ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
  19. if (log.isTraceEnabled()) {
  20. log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);
  21. }
  22. return this.choose(exchange).doOnNext((response) -> {
  23. //获取ServiceInstance实例,进行一些处理
  24. if (!response.hasServer()) {
  25. //如果没有serviceInstance,直接抛出异常
  26. throw NotFoundException.create(this.properties.isUse404(), "Unable to find instance for " + url.getHost());
  27. } else { //如果有serviceInstance,进行相关处理
  28. URI uri = exchange.getRequest().getURI();
  29. String overrideScheme = null;
  30. if (schemePrefix != null) {
  31. overrideScheme = url.getScheme();
  32. }
  33. DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance((ServiceInstance)response.getServer(), overrideScheme);
  34. URI requestUrl = LoadBalancerUriTools.reconstructURI(serviceInstance, uri);
  35. if (log.isTraceEnabled()) {
  36. log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
  37. }
  38. exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
  39. }
  40. }).then(chain.filter(exchange));
  41. } else {
  42. return chain.filter(exchange); //如果获取不到serviceInstance,直接进行后续过滤
  43. }
  44. }
  45. private Mono<Response<ServiceInstance>> choose(ServerWebExchange exchange) {
  46. URI uri = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
  47. ReactorLoadBalancer<ServiceInstance> loadBalancer = (ReactorLoadBalancer)this.clientFactory.getInstance(uri.getHost(), ReactorLoadBalancer.class, new Class[]{ServiceInstance.class});
  48. if (loadBalancer == null) {
  49. throw new NotFoundException("No loadbalancer available for " + uri.getHost());
  50. } else {
  51. return loadBalancer.choose(this.createRequest());
  52. }
  53. }//选择服务实例
  54. private Request createRequest() {
  55. return ReactiveLoadBalancer.REQUEST;
  56. }
  57. }

ReactorLoadBalancer负载均衡接口

  1. public interface ReactorLoadBalancer<T> extends ReactiveLoadBalancer<T> {
  2. Mono<Response<T>> choose(Request request);
  3. default Mono<Response<T>> choose() {
  4. return this.choose(REQUEST);
  5. }
  6. }
  7. ***********************
  8. public interface ReactorServiceInstanceLoadBalancer extends ReactorLoadBalancer<ServiceInstance> {
  9. }

RoundRobinLoadbalancer负载均衡使用轮询

  1. public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
  2. private static final Log log = LogFactory.getLog(RoundRobinLoadBalancer.class);
  3. private final AtomicInteger position;
  4. private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
  5. private final String serviceId;
  6. ************
  7. 构造方法
  8. public RoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
  9. public RoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, int seedPosition) {
  10. ************
  11. 普通方法
  12. public Mono<Response<ServiceInstance>> choose(Request request) {
  13. if (this.serviceInstanceListSupplierProvider != null) {
  14. ServiceInstanceListSupplier supplier = (ServiceInstanceListSupplier)this.serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
  15. return ((Flux)supplier.get()).next().map(this::getInstanceResponse);
  16. } else {
  17. ServiceInstanceSupplier supplier = (ServiceInstanceSupplier)this.serviceInstanceSupplier.getIfAvailable(NoopServiceInstanceSupplier::new);
  18. return ((Flux)supplier.get()).collectList().map(this::getInstanceResponse);
  19. }
  20. }
  21. private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
  22. if (instances.isEmpty()) {
  23. log.warn("No servers available for service: " + this.serviceId);
  24. return new EmptyResponse();
  25. } else {
  26. int pos = Math.abs(this.position.incrementAndGet());
  27. ServiceInstance instance = (ServiceInstance)instances.get(pos % instances.size());
  28. return new DefaultResponse(instance);
  29. }
  30. }//使用轮询获取实例
  31. }

示例:

参数id为偶数时,输出hello new version

网关

配置文件

  1. spring:
  2. application:
  3. name: hellogateway
  4. cloud:
  5. consul:
  6. host: 172.18.0.20
  7. port: 8500
  8. loadbalancer:
  9. ribbon:
  10. enabled: false
  11. gateway:
  12. routes:
  13. id: myRoute
  14. uri: lb://hello-service
  15. predicates:
  16. Path=/hello

自定义过滤器

  1. @Component
  2. public class CustomLoadBalancerClientFilter implements GlobalFilter, Ordered {
  3. private static final Log log = LogFactory.getLog(org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter.class);
  4. @Resource
  5. private final LoadBalancerClientFactory clientFactory;
  6. @Resource
  7. private LoadBalancerProperties properties;
  8. public CustomLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory, LoadBalancerProperties properties) {
  9. this.clientFactory = clientFactory;
  10. this.properties = properties;
  11. }
  12. public int getOrder() {
  13. return 10149;
  14. }
  15. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  16. URI url = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
  17. String schemePrefix = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
  18. if (url != null && ("lb".equals(url.getScheme()) || "lb".equals(schemePrefix))) {
  19. ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
  20. if (log.isTraceEnabled()) {
  21. log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);
  22. }
  23. return this.choose(exchange).doOnNext((response) -> {
  24. if (!response.hasServer()) {
  25. throw NotFoundException.create(this.properties.isUse404(), "Unable to find instance for " + url.getHost());
  26. } else {
  27. URI uri = exchange.getRequest().getURI();
  28. String overrideScheme = null;
  29. if (schemePrefix != null) {
  30. overrideScheme = url.getScheme();
  31. }
  32. int id=Integer.parseInt(Objects.requireNonNull(exchange.getRequest().getQueryParams().getFirst("id")));
  33. if (id%2==0){
  34. while (!"new".equals(response.getServer().getMetadata().get("version"))){
  35. try {
  36. response=this.choose(exchange).toFuture().get();
  37. }catch (Exception e){
  38. System.out.println(e.getMessage());
  39. }
  40. }
  41. }
  42. DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(response.getServer(), overrideScheme);
  43. System.out.println(exchange.getRequest().getQueryParams().getFirst("id")+"对应server的version为:"+serviceInstance.getMetadata().get("version"));
  44. URI requestUrl = LoadBalancerUriTools.reconstructURI(serviceInstance, uri);
  45. if (log.isTraceEnabled()) {
  46. log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
  47. }
  48. exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
  49. }
  50. }).then(chain.filter(exchange));
  51. } else {
  52. return chain.filter(exchange);
  53. }
  54. }
  55. private Mono<Response<ServiceInstance>> choose(ServerWebExchange exchange) {
  56. URI uri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
  57. assert uri != null;
  58. ReactorLoadBalancer<ServiceInstance> loadBalancer = this.clientFactory.getInstance(uri.getHost(), ReactorLoadBalancer.class, new Class[]{ServiceInstance.class});
  59. if (loadBalancer == null) {
  60. throw new NotFoundException("No loadbalancer available for " + uri.getHost());
  61. } else {
  62. return loadBalancer.choose(this.createRequest());
  63. }
  64. }
  65. private Request createRequest() {
  66. return ReactiveLoadBalancer.REQUEST;
  67. }
  68. }

同名应用hello-service1

配置文件

  1. spring:
  2. application:
  3. name: helloservice
  4. cloud:
  5. consul:
  6. host: 172.18.0.20
  7. port: 8500
  8. discovery:
  9. instanceid: ${spring.application.name}-${random.int}
  10. tags: version=old

controller 层

  1. @RestController
  2. public class HelloController {
  3. @RequestMapping("/hello")
  4. public String hello(){
  5. return "hello old version";
  6. }
  7. }

同名应用hello-service2

配置文件

  1. spring:
  2. application:
  3. name: helloservice
  4. cloud:
  5. consul:
  6. host: 172.18.0.20
  7. port: 8500
  8. discovery:
  9. instanceid: ${spring.application.name}-${random.int}
  10. tags: version=new

controller 层

  1. @RestController
  2. public class HelloController {
  3. @RequestMapping("/hello")
  4. public String hello(){
  5. return "hello new version";
  6. }
  7. }

测试输出

consul注册的应用

springcloud gateway如何实现路由和负载均衡

参数测试

springcloud gateway如何实现路由和负载均衡

当id为偶数时,输出为hello new version

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

原文链接:https://blog.csdn.net/cuixinzhou/article/details/93379130

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 springcloud gateway如何实现路由和负载均衡 https://www.kuaiidc.com/106732.html

相关文章

发表评论
暂无评论