Spring Cloud GateWay基于nacos如何去做灰度发布

种地  论坛元老 | 2022-12-3 23:37:30 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1093|帖子 1093|积分 3279

如果想直接查看修改部分请跳转 动手-点击跳转

本文基于 ReactiveLoadBalancerClientFilter使用RoundRobinLoadBalancer

灰度发布

灰度发布,又称为金丝雀发布,是一种新旧版本平滑发布的方式。在上面可以对同一个API进行两个版本 的内容,由一部分用户先行体验,如无问题,逐步扩大发布范围

本文将讲述如何基于基于nacos的matedata与Ribbon如何去做灰度发布
重点知识

Spring Cloud Gateway两种负载均衡器

官网说明两种负载均衡器
Gateway有两种客户端负载均衡器,LoadBalancerClientFilter和ReactiveLoadBalancerClientFilter。
LoadBalancerClientFilter使用一个Ribbon的阻塞式LoadBalancerClient,Gateway建议使用ReactiveLoadBalancerClientFilter。
可以通过设置spring.cloud.loadbalancer.ribbon.enabled=false,切换到ReactiveLoadBalancerClientFilter。无论使用Ribbon还是LoadBalancer,在Route中配置的lb是一样的
本节采用 ReactiveLoadBalancerClientFilter 进行设置
采用ReactiveLoadBalancerClientFilter使用RoundRobinLoadBalancer
灰度发布服务器选择 简单示意图

Client —-> gateway —-> GlobalFilter 拦截 选择一个灰度发布服务器 如果没有灰度服务则选取正常服务器 —->转发到服务
nacos的matedata

我们在向 Nacos Server 进行服务注册的时候往往会附加一些 metadata ,可以参考官方文档中 Dubbo 融合 Nacos 成为注册中心 章节。
充分利用好服务实例的 metadata ,可以衍生出许多有意思的实践。
完全可以把相关内容放进 metadata 中,好比说版本号,特性名等等
然后再根据负载均衡路由到不同的服务
  1. 1<br>2<br>
复制代码
  1. spring.cloud.nacos.discovery.metadata.version=1.15<br>spring.cloud.nacos.discovery.metadata.advance=true<br>
复制代码


准备工作

nacos 部署
gateway 部署 -可以参考
部署两台服务A
开始

跟踪代码

  1. 1<br>2<br>3
  2. 4
  3. 5
  4. 6
  5. 7
  6. 8
  7. 9
  8. 10
  9. 11
  10. 12
  11. 13
  12. 14
  13. 15
  14. 16
  15. 17
  16. 18
  17. 19
  18. 20
  19. 21
  20. 22
  21. 23
  22. 24
  23. 25
  24. 26
  25. 27
  26. 28
  27. 29
  28. 30
  29. 31
  30. 32
  31. 33
  32. 34
  33. 35
  34. 36
  35. 37
  36. 38
  37. 39
  38. 40
  39. 41
  40. 42
  41. 43
  42. 44
  43. 45
  44. 46
  45. 47
复制代码
  1. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {<br>    URI url = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);<br>    String schemePrefix = (String)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);<br>    if (url != null && ("lb".equals(url.getScheme()) || "lb".equals(schemePrefix))) {<br>        ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);<br>        if (log.isTraceEnabled()) {<br>            log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);<br>        }<br><br>        return this.choose(exchange).doOnNext((response) -> {<br>            if (!response.hasServer()) {<br>                throw NotFoundException.create(this.properties.isUse404(), "Unable to find instance for " + url.getHost());<br>            } else {<br>                ServiceInstance retrievedInstance = (ServiceInstance)response.getServer();<br>                URI uri = exchange.getRequest().getURI();<br>                String overrideScheme = retrievedInstance.isSecure() ? "https" : "http";<br>                if (schemePrefix != null) {<br>                    overrideScheme = url.getScheme();<br>                }<br><br>                DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(retrievedInstance, overrideScheme);<br>                URI requestUrl = this.reconstructURI(serviceInstance, uri);<br>                if (log.isTraceEnabled()) {<br>                    log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);<br>                }<br><br>                exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);<br>            }<br>        }).then(chain.filter(exchange));<br>    } else {<br>        return chain.filter(exchange);<br>    }<br>}<br><br>protected URI reconstructURI(ServiceInstance serviceInstance, URI original) {<br>    return LoadBalancerUriTools.reconstructURI(serviceInstance, original);<br>}<br><br>private Mono<Response<ServiceInstance>> choose(ServerWebExchange exchange) {<br>    URI uri = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);<br>    ReactorLoadBalancer<ServiceInstance> loadBalancer = (ReactorLoadBalancer)this.clientFactory.getInstance(uri.getHost(), ReactorServiceInstanceLoadBalancer.class);<br>    if (loadBalancer == null) {<br>        throw new NotFoundException("No loadbalancer available for " + uri.getHost());<br>    } else {<br>        return loadBalancer.choose(this.createRequest());<br>    }<br>}<br>
复制代码
  1. 1<br>2<br>3
  2. 4
  3. 5
  4. 6
  5. 7
  6. 8
  7. 9
  8. 10
  9. 11
  10. 12
  11. 13
  12. 14
  13. 15
  14. 16
  15. 17
  16. 18
  17. 19
  18. 20
  19. 21
  20. 22
  21. 23
  22. 24
  23. 25
  24. 26
  25. 27
  26. 28
  27. 29
  28. 30
  29. 31
复制代码
  1. @SuppressWarnings("rawtypes")<br>@Override<br>// see original<br>// https://github.com/Netflix/ocelli/blob/master/ocelli-core/<br>// src/main/java/netflix/ocelli/loadbalancer/RoundRobinLoadBalancer.java<br>public Mono<Response<ServiceInstance>> choose(Request request) {<br>        // TODO: move supplier to Request?<br>        // Temporary conditional logic till deprecated members are removed.<br>        if (serviceInstanceListSupplierProvider != null) {<br>                ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider<br>                                .getIfAvailable(NoopServiceInstanceListSupplier::new);<br>                return supplier.get().next().map(this::getInstanceResponse);<br>        }<br>        ServiceInstanceSupplier supplier = this.serviceInstanceSupplier<br>                        .getIfAvailable(NoopServiceInstanceSupplier::new);<br>        return supplier.get().collectList().map(this::getInstanceResponse);<br>}<br><br>private Response<ServiceInstance> getInstanceResponse(<br>                List<ServiceInstance> instances) {<br>        if (instances.isEmpty()) {<br>                log.warn("No servers available for service: " + this.serviceId);<br>                return new EmptyResponse();<br>        }<br>        // TODO: enforce order?<br>        int pos = Math.abs(this.position.incrementAndGet());<br><br>        ServiceInstance instance = instances.get(pos % instances.size());<br><br>        return new DefaultResponse(instance);<br>}<br>
复制代码
通过代码跟踪 ReactiveLoadBalancerClientFilter 与 RoundRobinLoadBalancer 可以发现,最终 我们只需要对 getInstanceResponse 进行改造 即可满足所有需要
动手!
开始修改代码

我们只需要新增一个 GlobalFilter 在 AdvanceReactiveLoadBalancerClientFilter 执行之前 ,并且对LoadBalancer 的getInstanceResponse 做一下稍微改造就OK了
复制 RoundRobinLoadBalancer 内容 并修改 getInstanceResponse() 逻辑

  1. 1<br>2<br>3
  2. 4
  3. 5
  4. 6
  5. 7
  6. 8
  7. 9
  8. 10
  9. 11
  10. 12
  11. 13
  12. 14
  13. 15
  14. 16
  15. 17
  16. 18
  17. 19
  18. 20
  19. 21
  20. 22
  21. 23
  22. 24
  23. 25
  24. 26
  25. 27
  26. 28
  27. 29
  28. 30
  29. 31
  30. 32
  31. 33
  32. 34
  33. 35
  34. 36
  35. 37
  36. 38
  37. 39
  38. 40
  39. 41
  40. 42
  41. 43
  42. 44
  43. 45
  44. 46
  45. 47
  46. 48
  47. 49
  48. 50
  49. 51
  50. 52
  51. 53
  52. 54
  53. 55
  54. 56
  55. 57
  56. 58
  57. 59
  58. 60
  59. 61
  60. 62
  61. 63
  62. 64
  63. 65
  64. 66
  65. 67
  66. 68
  67. 69
  68. 70
  69. 71
  70. 72
  71. 73
  72. 74
  73. 75
  74. 76
  75. 77
  76. 78
  77. 79
  78. 80
  79. 81
  80. 82
  81. 83
  82. 84
  83. 85
  84. 86
  85. 87
  86. 88
  87. 89
  88. 90
  89. 91
  90. 92
  91. 93
  92. 94
  93. 95
  94. 96
  95. 97
  96. 98
  97. 99
  98. 100
  99. 101
  100. 102
  101. 103
  102. 104
  103. 105
  104. 106
  105. 107
  106. 108
  107. 109
  108. 110
  109. 111
  110. 112
  111. 113
  112. 114
  113. 115
复制代码
  1. package top.lingma.gateway.loadbalancer;<br><br>import org.apache.commons.logging.Log;<br>import org.apache.commons.logging.LogFactory;<br>import org.springframework.beans.factory.ObjectProvider;<br>import org.springframework.cloud.client.ServiceInstance;<br>import org.springframework.cloud.client.loadbalancer.reactive.DefaultResponse;<br>import org.springframework.cloud.client.loadbalancer.reactive.EmptyResponse;<br>import org.springframework.cloud.client.loadbalancer.reactive.Request;<br>import org.springframework.cloud.client.loadbalancer.reactive.Response;<br>import org.springframework.cloud.loadbalancer.core.*;<br>import reactor.core.publisher.Mono;<br><br>import java.util.List;<br>import java.util.Random;<br>import java.util.concurrent.atomic.AtomicInteger;<br>import java.util.stream.Collectors;<br><br>public class AdvanceRoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {<br><br>    private static final Log log = LogFactory.getLog(AdvanceRoundRobinLoadBalancer.class);<br><br>    private final AtomicInteger position;<br>    private final AtomicInteger positionAdvance;<br><br>    @Deprecated<br>    private ObjectProvider<ServiceInstanceSupplier> serviceInstanceSupplier;<br><br>    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;<br><br>    private final String serviceId;<br><br><br>    @Deprecated<br>    public AdvanceRoundRobinLoadBalancer(String serviceId, ObjectProvider<ServiceInstanceSupplier> serviceInstanceSupplier) {<br>        this(serviceId, serviceInstanceSupplier, new Random().nextInt(1000));<br>    }<br><br>    public AdvanceRoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {<br>        this(serviceInstanceListSupplierProvider, serviceId, new Random().nextInt(1000));<br>    }<br><br><br>    public AdvanceRoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, int seedPosition) {<br>        this.serviceId = serviceId;<br>        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;<br>        this.position = new AtomicInteger(seedPosition);<br>        this.positionAdvance = new AtomicInteger(seedPosition);<br>    }<br><br>    @Deprecated<br>    public AdvanceRoundRobinLoadBalancer(String serviceId, ObjectProvider<ServiceInstanceSupplier> serviceInstanceSupplier, int seedPosition) {<br>        this.serviceId = serviceId;<br>        this.serviceInstanceSupplier = serviceInstanceSupplier;<br>        this.position = new AtomicInteger(seedPosition);<br>        this.positionAdvance = new AtomicInteger(seedPosition);<br>    }<br><br><br>    @Override<br><br>    public Mono<Response<ServiceInstance>> choose(Request request) {<br><br><br>        if (serviceInstanceListSupplierProvider != null) {<br>            ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);<br>            return supplier.get().next().map((instances) -> {<br>                // 此处做了选择逻辑的修改<br>                if (request instanceof AdvanceRequestContext) {<br>                    List<ServiceInstance> advanceInstance = instances.stream().filter(s -> s.getMetadata().getOrDefault("advance", "").equals("true")).collect(Collectors.toList());<br>                    return getInstanceResponse(advanceInstance, request);<br>                } else {<br>                    List<ServiceInstance> routineInstance = instances.stream().filter(s -> !s.getMetadata().getOrDefault("advance", "").equals("true")).collect(Collectors.toList());<br>                    return getInstanceResponse(routineInstance, request);<br>                }<br><br>            });<br>        }<br>        ServiceInstanceSupplier supplier = this.serviceInstanceSupplier.getIfAvailable(NoopServiceInstanceSupplier::new);<br>        return supplier.get().collectList().map((instances) -> {<br>            if (request instanceof AdvanceRequestContext) {<br>                // 此处做了选择逻辑的修改<br>                List<ServiceInstance> advanceInstance = instances.stream().filter(s -> s.getMetadata().getOrDefault("advance", "").equals("true")).collect(Collectors.toList());<br>                return getInstanceResponse(advanceInstance, request);<br>            } else {<br>                List<ServiceInstance> instance = instances.stream().filter(s -> !s.getMetadata().getOrDefault("advance", "").equals("true")).collect(Collectors.toList());<br>                return getInstanceResponse(instance, request);<br>            }<br><br>        });<br>    }<br><br>    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, Request request) {<br>        if (instances.isEmpty()) {<br>            if (request instanceof AdvanceRequestContext) {<br>                return new AdvanceEmptyResponse();<br>            }<br>            log.warn("No servers available for service: " + this.serviceId);<br>            return new EmptyResponse();<br>        }<br>        int pos = 1;<br>        //灰度发布选择逻辑<br>        if (request instanceof AdvanceRequestContext) {<br>            pos = Math.abs(this.positionAdvance.incrementAndGet());<br>        } else {<br>            pos = Math.abs(this.position.incrementAndGet());<br>        }<br>        ServiceInstance instance = instances.get(pos % instances.size());<br>        return new DefaultResponse(instance);<br><br>    }<br><br>}<br><br><br>
复制代码
AdvanceEmptyResponse 类是为了标识无灰度发布服务器,此时可以走正常服务器

  1. 1<br>2<br>3
  2. 4
  3. 5
  4. 6
  5. 7
  6. 8
  7. 9
  8. 10
  9. 11
  10. 12
  11. 13
复制代码
  1. package top.lingma.gateway.loadbalancer;<br><br>import org.springframework.cloud.client.ServiceInstance;<br>import org.springframework.cloud.client.loadbalancer.reactive.CompletionContext;<br>import org.springframework.cloud.client.loadbalancer.reactive.Response;<br><br>public class AdvanceEmptyResponse extends org.springframework.cloud.client.loadbalancer.EmptyResponse implements Response<ServiceInstance> {<br>    public AdvanceEmptyResponse() {<br>    }<br><br>    public void onComplete(CompletionContext completionContext) {<br>    }<br>}<br>
复制代码
AdvanceRequestContext 是为了能从 GlobalFilter 传递信息到 LoadBalancer

  1. 1<br>2<br>3
  2. 4
  3. 5
  4. 6
  5. 7
  6. 8
  7. 9
  8. 10
  9. 11
  10. 12
  11. 13
  12. 14
  13. 15
  14. 16
  15. 17
  16. 18
  17. 19
复制代码
  1. package top.lingma.gateway.loadbalancer;<br><br>import org.springframework.cloud.client.loadbalancer.reactive.Request;<br>import org.springframework.web.server.ServerWebExchange;<br><br>public class AdvanceRequestContext<T> implements Request {<br><br>    private T exchange;<br><br>    public AdvanceRequestContext(T exchange) {<br>        this.exchange = exchange;<br>    }<br><br>    @Override<br>    public T getContext() {<br>        return exchange;<br>    }<br>}<br><br>
复制代码
AdvanceReactiveLoadBalancerClientFilter 复制于 ReactiveLoadBalancerClientFilter

注意两点
第一灰度服务器选择在ReactiveLoadBalancerClientFilter 之前 LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150 - 1;
  1. 1<br>2<br>3
  2. 4
  3. 5
  4. 6
  5. 7
  6. 8
  7. 9
  8. 10
  9. 11
  10. 12
  11. 13
  12. 14
  13. 15
  14. 16
  15. 17
  16. 18
  17. 19
  18. 20
  19. 21
  20. 22
  21. 23
  22. 24
  23. 25
  24. 26
  25. 27
  26. 28
  27. 29
  28. 30
  29. 31
  30. 32
  31. 33
  32. 34
  33. 35
  34. 36
  35. 37
  36. 38
  37. 39
  38. 40
  39. 41
  40. 42
  41. 43
  42. 44
  43. 45
  44. 46
  45. 47
  46. 48
  47. 49
  48. 50
  49. 51
  50. 52
  51. 53
  52. 54
  53. 55
  54. 56
  55. 57
  56. 58
  57. 59
  58. 60
  59. 61
  60. 62
  61. 63
  62. 64
  63. 65
  64. 66
  65. 67
  66. 68
  67. 69
  68. 70
  69. 71
  70. 72
  71. 73
  72. 74
  73. 75
  74. 76
  75. 77
  76. 78
  77. 79
  78. 80
  79. 81
  80. 82
  81. 83
  82. 84
  83. 85
  84. 86
  85. 87
  86. 88
  87. 89
  88. 90
  89. 91
  90. 92
  91. 93
  92. 94
  93. 95
  94. 96
  95. 97
  96. 98
  97. 99
  98. 100
  99. 101
  100. 102
  101. 103
  102. 104
  103. 105
  104. 106
  105. 107
  106. 108
  107. 109
  108. 110
  109. 111
  110. 112
  111. 113
  112. 114
  113. 115
  114. 116
  115. 117
  116. 118
  117. 119
  118. 120
  119. 121
  120. 122
  121. 123
  122. 124
复制代码
  1. package top.lingma.gateway.loadbalancer;<br><br>import org.apache.commons.logging.Log;<br>import org.apache.commons.logging.LogFactory;<br>import org.springframework.cloud.client.ServiceInstance;<br>import org.springframework.cloud.client.loadbalancer.LoadBalancerUriTools;<br>import org.springframework.cloud.client.loadbalancer.reactive.Response;<br>import org.springframework.cloud.gateway.config.LoadBalancerProperties;<br>import org.springframework.cloud.gateway.filter.GatewayFilterChain;<br>import org.springframework.cloud.gateway.filter.GlobalFilter;<br>import org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter;<br>import org.springframework.cloud.gateway.support.DelegatingServiceInstance;<br>import org.springframework.cloud.gateway.support.NotFoundException;<br>import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;<br>import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;<br>import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;<br>import org.springframework.core.Ordered;<br>import org.springframework.stereotype.Component;<br>import org.springframework.web.server.ServerWebExchange;<br>import reactor.core.publisher.Mono;<br><br>import java.net.URI;<br>import java.util.List;<br><br>import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.*;<br><br>@Component<br>public class AdvanceReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {<br><br>    private static final Log log = LogFactory.getLog(ReactiveLoadBalancerClientFilter.class);<br><br>    private static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150 - 1;<br><br>    private final LoadBalancerClientFactory clientFactory;<br><br>    private LoadBalancerProperties properties;<br><br>    public AdvanceReactiveLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory, LoadBalancerProperties properties) {<br>        this.clientFactory = clientFactory;<br>        this.properties = properties;<br>    }<br><br>    @Override<br>    public int getOrder() {<br>        return LOAD_BALANCER_CLIENT_FILTER_ORDER;<br>    }<br><br>    @Override<br>    @SuppressWarnings("Duplicates")<br>    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {<br>        // 灰度用户专属服务器         判定是否是灰度用户,是否拥有灰度权限 不然直接进行下一步<br>        List<String> secChUa = exchange.getRequest().getHeaders().get("sec-ch-ua");<br>        if (secChUa == null || secChUa.isEmpty() || !secChUa.stream().findFirst().map(r -> r.contains("Edge")).orElse(false)) {<br>            return chain.filter(exchange);<br>        }<br><br>        URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);<br>        String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);<br>        if (url == null || (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {<br>            return chain.filter(exchange);<br>        }<br>        // preserve the original url<br>        addOriginalRequestUrl(exchange, url);<br><br>        if (log.isTraceEnabled()) {<br>            log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);<br>        }<br><br>        return choose(exchange).doOnNext(response -> {<br>            if (response instanceof AdvanceEmptyResponse) {<br>                return;<br>            }<br>            if (!response.hasServer()) {<br>                throw NotFoundException.create(properties.isUse404(), "Unable to find instance for " + url.getHost());<br>            }<br><br>            ServiceInstance retrievedInstance = response.getServer();<br><br>            URI uri = exchange.getRequest().getURI();<br><br>            // if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,<br>            // if the loadbalancer doesn't provide one.<br>            String overrideScheme = retrievedInstance.isSecure() ? "https" : "http";<br>            if (schemePrefix != null) {<br>                overrideScheme = url.getScheme();<br>            }<br><br>            DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(retrievedInstance, overrideScheme);<br><br>            URI requestUrl = reconstructURI(serviceInstance, uri);<br><br>            if (log.isTraceEnabled()) {<br>                log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);<br>            }<br>            exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);<br>        }).then(chain.filter(exchange));<br>    }<br><br>    protected URI reconstructURI(ServiceInstance serviceInstance, URI original) {<br>        return LoadBalancerUriTools.reconstructURI(serviceInstance, original);<br>    }<br><br>    @SuppressWarnings("deprecation")<br>    private Mono<Response<ServiceInstance>> choose(ServerWebExchange exchange) {<br>        URI uri = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);<br>        ReactorLoadBalancer<ServiceInstance> loadBalancer = this.clientFactory.getInstance(uri.getHost(), ReactorServiceInstanceLoadBalancer.class);<br>        if (loadBalancer == null) {<br>            throw new NotFoundException("No loadbalancer available for " + uri.getHost());<br>        }<br>        return loadBalancer.choose(createRequest(exchange));<br>    }<br><br>    /***<br>     * 此处进行了改造 传入了内容 方便后续 LoadBalancer 处理信息<br>     * @param exchange<br>     * @return<br>     */<br>    @SuppressWarnings("deprecation")<br>    private AdvanceRequestContext<ServerWebExchange> createRequest(ServerWebExchange exchange) {<br>        return new AdvanceRequestContext(exchange);<br>    }<br><br>}<br><br>
复制代码
以上已经完成了灰度发布的必要部分,再进行一下AutoConfiguration 注意,这里不能被Spring 扫描

  1. 1<br>2<br>3
  2. 4
  3. 5
  4. 6
  5. 7
  6. 8
  7. 9
  8. 10
  9. 11
  10. 12
  11. 13
  12. 14
  13. 15
  14. 16
  15. 17
  16. 18
  17. 19
  18. 20
复制代码
  1. package top.lingma.gateway.loadbalancer;<br><br>import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;<br>import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;<br>import org.springframework.cloud.client.ServiceInstance;<br>import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;<br>import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;<br>import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;<br>import org.springframework.context.annotation.Bean;<br>import org.springframework.core.env.Environment;<br><br>@ConditionalOnDiscoveryEnabled<br>public class AdvanceLoadBalancerAutoConfiguration {<br>    @Bean<br>    @ConditionalOnMissingBean<br>    public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {<br>        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);<br>        return new AdvanceRoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);<br>    }<br>}<br>
复制代码
最后 启动类配置 @LoadBalancerClients 的 defaultConfiguration

  1. 1<br>2<br>3
  2. 4
  3. 5
  4. 6
  5. 7
  6. 8
  7. 9
  8. 10
  9. 11
复制代码
  1. <br>@SpringBootApplication()<br>@LoadBalancerClients(defaultConfiguration = AdvanceLoadBalancerAutoConfiguration.class)<br>public class LingmaGatewayApplication {<br><br>    public static void main(String[] args) {<br>        SpringApplication.run(LingmaGatewayApplication.class, args);<br>    }<br><br>}<br><br>
复制代码
关注公众号 [龗孖] 或搜索公众号[lingmaW] , 获得更多新干货!!! - 本文链接: https://blog.lingma.top/2022/12/01/36d5a1ed4a38/spring-cloud-gateway基于nacos如何去做灰度发布/index.html

  • 版权声明: 本博客所有文章除特别声明外,均采用 反996许可证版本1.0 许可协议。转载请注明出处!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

种地

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表