开发公司SpringCloud-微服务入门之Gateway+Nginx(4)

开发公司确保你已经学完了

Gateway简介

Spring Cloud GateWay是Spring Cloud的⼀个全新项⽬,⽬标是取代Netflix ,基于Spring5.0+SpringBoot2.0+WebFlux(基于⾼性能的Reactor开发公司模式响应式通信框架Netty,异步⾮阻塞模型)开发公司等技术开发,性能⾼于Zuul,官⽅测试,GateWay是Zuul的1.6倍,开发公司旨在为微服务架构提供⼀开发公司种简单有效的统⼀的API路由管理⽅式

开发公司为什么需要网关

开发公司网关的出现的原因是微开发公司服务架构的出现,开发公司不同的微服务一般有不开发公司同的网络地址,开发公司而外部客户端可能需要开发公司调用多个服务的接口才开发公司能完成完成一个业务需求,开发公司如果让客户端直接与各开发公司个微服务通信,开发公司会出现以下的问题。

  1. 开发公司客户端会多次请求不同的微服务,开发公司增加了客户端的复杂性。
  2. 开发公司存在跨域请求,开发公司在一定场景下处理相对复制。
  3. 认证复杂,开发公司每个服务都需要独立的认证。
  4. 难以重构,开发公司随着项目的迭代。开发公司可能需要重新划分微服务。开发公司如果客户端与微服务直接通信,开发公司那么重构将会很复杂。
  5. 开发公司某些微服务可能使用了防火墙/开发公司浏览器不友好的协议,开发公司直接访问会有一定的困难。

开发公司以上的问题可以借助API开发公司网关来解决。API开发公司网关是介于客户端和服开发公司务器端之间的中间层,开发公司所有的外部请求都会先经过API开发公司网关这一层。也就是说,API开发公司网关可以完成安全、性能、开发公司监控等功能,开发公司而服务提供者可以专门开发公司的完成具体的业务逻辑。

使用API开发公司网关的优点

  1. 易于监控,开发公司可以在网关收集监控数开发公司据并将其推送到外部系开发公司统进行分析;
  2. 易于认证,开发公司可以在网关进行认证,开发公司然后再将请求转发到后开发公司端的微服务,开发公司而无需在每个微服务中进行认证;
  3. 开发公司减少客户端和各个微服务之间的交互次数。

核心三要素

项目结构图

上面这图config和controller,filter是可选的有需求的话在进行添加

搭建网关(基础)

添加依赖

    <dependencies>        <!--        添加公共模块-->        <dependency>            <groupId>org.example</groupId>            <artifactId>common</artifactId>            <version>1.0-SNAPSHOT</version>        </dependency><!--        网关依赖-->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-gateway</artifactId>        </dependency><!--        注册中心依赖-->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>        </dependency>    </dependencies>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

添加启动类

@SpringBootApplicationpublic class GatewayApplication {    public static void main(String[] args) {        SpringApplication.run(GatewayApplication.class, args);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

添加配置文件

server:  port: 10010# 设置  服务名 为gateway-servicespring:  application:    name: gateway  profiles:    active: common  cloud:    gateway:      default-filters:        # 去掉全部前缀api        - RewritePath=/api(?<segment>/?.*),/$\{segment}      routes:        - id: consumer-route # 路由id,可以随意写不影响  一般都是以要代理的服务器名称-route          uri: lb://consumer # 要访问的服务名称 (集群的时候可以防止宕机)          #我们请求http://consumer/xxxx 会被拦截          predicates: #允许的路由地址,要算上过滤器(filters)            - Path=/api/user/**
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

之前我们访问消费者地址是: http://localhost:9001/user/getUserAll,那么现在我们有了网关之后的访问地址是http://localhost:10010/api/user/getUserAll

网关的其他配置

基本配置介绍

路由(Route) 是 gateway 中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面的几个信息:

id:路由标识符,区别于其他 Route,必须唯一。
uri:路由指向的目的地 uri,即客户端请求最终被转发到的。,如果是服务名称那么需要使用lb://服务名 如果是url那么直接写就行
order:用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高。
predicate:断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。
filter:过滤器用于修改请求和响应信息。

执行顺序: uri>order>predicate>filter 只要filter后才会去请求实际的路径多个filter是从上到下依次执行的,而多个predicate必须同时都满足才行

Predicate 断言条件

在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则,有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。

说白了 Predicate 就是为了实现一组匹配规则,方便让请求过来找到对应的 Route 进行处理,接下来我们接下 Spring Cloud GateWay 内置几种 Predicate 的使用。
转发规则(predicates),假设 转发uri都设定为http://localhost:9023

规则实例说明
Path- Path=/gate/*,/rule/*当请求的路径为gate或rule开头的时,转发到http://localhost:9023服务器上
Before- Before=2017-01-20T17:42:47.789-07:00[Asia/Shanghai]在某个时间之前的请求才会被转发到 http://localhost:9023服务器上
After- After=2017-01-20T17:42:47.789-07:00[Asia/Shanghai]在某个时间之后的请求才会被转发
Between- Between=2017-01-20T17:42:47.789-07:00[Asia/Shanghai],2017-01-21T17:42:47.789-07:00[Asia/Shanghai]在某个时间段之间的才会被转发
Cookie- Cookie=sessionId, test可以接收两个参数,一个是 Cookie name ,一个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。
1. 名为sessionId的而且满足正则test的才会被匹配到进行请求转发
Header- Header=X-Request-Id, \d+接收 2 个参数,一个 header 中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。
1. 携带参数X-Request-Id而且满足\d+的请求头才会匹配
Host- Host=www.hd123.com1.当域名为www.hd123.com的时候直接转发到http://localhost:9023服务器上
Method- Method=GET可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。
1.只有GET方法才会匹配转发请求,还可以限定
Query- Query=smile
- Query=keep, pu.
支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。
1.只要请求中包含 smile 属性的参数即可匹配路由。
2.请求中包含 keep 属性并且参数值是以 pu 开头的长度为三位的字符串才会进行匹配和路由。
RemoteAddr- RemoteAddr=192.168.1.1/24设置某个 ip 区间号段的请求才会路由,
1. 如果请求的远程地址是 192.168.1.10,则此路由将匹配。

组合案例:

      routes:        - id: gateway-service          uri: https://www.baidu.com          order: 0          predicates:            - Host=**.foo.org            - Path=/headers            - Method=GET            - Header=X-Request-Id, \d+            - Query=foo, ba.            - Query=baz            - Cookie=chocolate, ch.p
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。

多路由

spring:  application:    gateway:      routes:        - id: product-route          uri: lb://product          predicates:              #  多个路由可以使用逗号分隔            - Path=/product/**,/product1/**          filters:            - StripPrefix=1        - id: order-route          uri: lb://order          predicates:            - Path=/order/**          filters:            - StripPrefix=1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

一个请求满足多个路由的断言条件时,请求只会被首个成功匹配的路由转发

过滤器规则

在满足 Predicate 断言条件下才会执行

过滤规则实例说明
PrefixPath- PrefixPath=/app在请求路径前加上app
StripPrefix- StripPrefix=1 (1,2,3,4)在请求路径前前去掉第一个路径
RewritePath- RewritePath=/test, /app/test访问localhost:9022/test,请求会转发到localhost:8001/app/test
SetPath- SetPath=/app/{path}通过模板设置路径,转发的规则时会在路径前增加app,{path}表示原请求路径
RedirectTo- RedirectTo=302, https://acme.org重定向到https://acme.org
RemoveRequestHeader去掉某个请求头信息
RemoveResponseHeader去掉某个响应头信息
RemoveRequestParameter去掉某个请求参数信息
SetRequestHeaderX-Request-Red, Blue添加请求头,X-Request-Red是键,Blue 是值

注:当配置多个filter时,优先定义的会被调用,剩余的filter将不会生效

PrefixPath

对所有的请求路径添加前缀:

      routes:      - id: prefixpath_route        uri: https://example.org        filters:        - PrefixPath=/mypath
  • 1
  • 2
  • 3
  • 4
  • 5

访问/hello的请求被发送到https://example.org/mypath/hello

StripPrefix

跳过指定路径。

      routes:        - id: consumer-route           uri: lb://consumer           predicates:             - Path=/api/consumer /**          filters: # 添加请求路径的前缀            - StripPrefix=1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

访问的时候http://consumer/api/xxx/xxx
但是实际上会将你前面的/api给去掉 http://consumer/xxx/xxx
1就是跳过一个路径,2就是跳过第二个路径…以此类推

RedirectTo

配置包含重定向的返回码和地址:

      routes:      - id: prefixpath_route        uri: https://example.org        filters:        - RedirectTo=302, https://acme.org
  • 1
  • 2
  • 3
  • 4
  • 5

当你请https://example.org那么会重定向跳转到https://acme.org

RemoveRequestHeader

去掉某个请求头信息:

      routes:      - id: removerequestheader_route        uri: https://example.org        filters:        - RemoveRequestHeader=X-Request-Foo
  • 1
  • 2
  • 3
  • 4
  • 5

去掉请求头信息 X-Request-Foo

RemoveResponseHeader

去掉某个回执头信息:

      routes:      - id: removerequestheader_route        uri: https://example.org        filters:        - RemoveResponseHeader=X-Request-Foo
  • 1
  • 2
  • 3
  • 4
  • 5

RemoveRequestParameter

去掉某个请求参数信息:

      routes:      - id: removerequestparameter_route        uri: https://example.org        filters:        - RemoveRequestParameter=red
  • 1
  • 2
  • 3
  • 4
  • 5

RewritePath

改写路径:

      routes:        - id: consumer-route           uri: lb://consumer           predicates: #允许的路由地址,要算上过滤器(filters)            - Path=/api/user/**          filters: # 添加请求路径的前缀            - RewritePath=/api/user(?<segment>/?.*),/user$\{segment}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

对于请求路径/api/user,当前的配置在请求到到达前会被重写为/user,由于YAML的语法问题,$符号后⾯应该加上\在解释正则表达式前,
(?<segment>/?.*)表达式将获取后面的路径和参数并且放入到segment里,那么我们在使用的地方通过$\{segment}就能获取到了

SetPath

设置请求路径,与RewritePath类似。

      routes:      - id: setpath_route        uri: https://example.org        predicates:        - Path=/red/{segment}        filters:        - SetPath=/{segment}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

获取/red/*请求时候的后面参数,保存到segment中,然后我们实际请求的是/{segment}
假设:我们请求/red/user/get那么实际请求/user/get

SetRequestHeader

设置请求头信息。key=value

      routes:      - id: setrequestheader_route        uri: https://example.org        filters:        - SetRequestHeader=X-Request-Red, Blue
  • 1
  • 2
  • 3
  • 4
  • 5

SetStatus

设置回执状态码。,也就是响应成功后返回的状态码

      routes:      - id: setstatusint_route        uri: https://example.org        filters:        - SetStatus=401
  • 1
  • 2
  • 3
  • 4
  • 5

RequestSize

请求大小。

      routes:      - id: request_size_route        uri: http://localhost:8080/upload        predicates:        - Path=/upload        filters:        - name: RequestSize          args:            maxSize: 5000000
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

超过5M的请求会返回413错误。

RequestRateLimiter

请求限流:

      routes:      - id: requestratelimiter_route        uri: http://example.org        filters:        - name: RequestRateLimiter          args:            redis-rate-limiter.replenishRate: 10 # 每秒执行的请求数            redis-rate-limiter.burstCapacity: 20 # 每秒最大请求数
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

replenishRate超过了那么其他请求会被缓存起来,如果超过了burstCapacity那么多余的请求直接就请求失败HTTP 429-请求太多

需要依赖

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis-reactive</artifactId></dependency>
  • 1
  • 2
  • 3
  • 4
spring:  redis:    host: localhost    port: 6379    database: 0
  • 1
  • 2
  • 3
  • 4
  • 5

Default-filters

对所有请求添加过滤器。支持以上所有过滤器的写法

spring:  cloud:    gateway:      default-filters:      - AddResponseHeader=X-Response-Default-Red, Default-Blue      - PrefixPath=/httpbin
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

通过代码进行配置路由

此方式是不受yml方式影响的,相互之间是隔离的,也就是yml里的配置不会影响到Bean的配置,但是都会起作用,谁满足条件那么就执行谁的

@Configurationpublic class GatewayConfig {    @Bean    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {        return builder.routes()                .route("consumer-route",                         r->r.path("/api/user/**")                                 .filters(f->f.rewritePath("/api(?<segment>/?.*)","/${segment}"))                                 .uri("lb://consumer"))                .build();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
	@Bean	public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {		return builder.routes()			.route("path_route", r -> r.path("/get")				.uri("http://httpbin.org"))							.route("host_route", r -> r.host("*.myhost.org")				.uri("http://httpbin.org"))							.route("rewrite_route", r -> r.host("*.rewrite.org")				.filters(f -> f.rewritePath("/foo/(?<segment>.*)", "/${segment}"))				.uri("http://httpbin.org"))							.route("hystrix_route", r -> r.host("*.hystrix.org")				.filters(f -> f.hystrix(c -> c.setName("slowcmd")))				.uri("http://httpbin.org"))							.route("hystrix_fallback_route", r -> r.host("*.hystrixfallback.org")				.filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback")))				.uri("http://httpbin.org"))							.route("limit_route", r -> r				.host("*.limited.org").and().path("/anything/**")				.filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter())))				.uri("http://httpbin.org"))			.build();	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

局部自定义过滤器

自定义过滤器的命名后缀应该为:***GatewayFilterFactory 这是必须的 否则就会找不到你定义的类,然在配置文件中filters:下面添加 - 前缀=参数

   	  routes:        # 路由id,可以随意写不影响  一般都是以要代理的服务器名称-route        - id: product-service-route          uri: lb://product-service # 要代理的服务器名称 (集群的时候可以防止宕机)          #我们请求http://127.0.0.1:10010/xxxx 会被拦截 如果路径包含指定的路径 那么就执行对应的路由地址          predicates: #允许的路由地址            - Path=/product/user1/**          filters:            - # 添加自定义局部过滤器,MyParam就是前缀,name,age就是参数            - MyParam=name,age
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

创建局部过滤器

import lombok.Data;import org.springframework.cloud.gateway.filter.GatewayFilter;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;import org.springframework.http.HttpStatus;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;import java.util.Arrays;import java.util.List;//MyParam就是我们在配置文件中的前缀@Componentpublic class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {    @Data    public static class Config {        private String param1;        private String param2;    }    public MyParamGatewayFilterFactory() {        super(Config.class);    }    @Override    public List<String> shortcutFieldOrder() {        //需要添加的参数成员变量名称        return Arrays.asList("param1","param2");    }    @Override    public GatewayFilter apply(Config config) {        GatewayFilter gatewayFilter = new GatewayFilter() {            @Override            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {                /**                 * 拦截所有请求,如果参数中包含name,把参数打印到控制台                 */                //获取请求对象                ServerHttpRequest request = exchange.getRequest();                //判断路径中key是否包含 ,如果包含那么就拦截                if (request.getQueryParams().containsKey(config.param1)&&request.getQueryParams().containsKey(config.param2)) {                    //返回一个405状态 请求的方法不允许                    exchange.getResponse().setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);                    return exchange.getResponse().setComplete();                }                return chain.filter(exchange);//放行所有请求            }        };        return gatewayFilter;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

自定义全局过滤器

全局过滤是在局部过滤之前执行的,作用全部的路由,一般用作权限效验等操作,无须其他配置直接继承GlobalFilter接口实现后就自动生效

import org.apache.commons.lang.StringUtils;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.core.Ordered;import org.springframework.http.HttpStatus;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;@Componentpublic class MyGlobalFilter implements GlobalFilter, Ordered {    @Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        System.out.println("-----------------全局过滤器MyGlobalFilter------------------- --");        // 获取路径参数中指定的key对应的value值        String token = exchange.getRequest().getQueryParams().getFirst("token");        //判断token是否为空的        if (StringUtils.isBlank(token)) {             //返回一个401状态 没有权限            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);            return exchange.getResponse().setComplete();        }        //放行        return chain.filter(exchange);    }    @Override    public int getOrder() {        //值越小越先执行        return 1;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

网关跨域

spring:  application:    name: gateway-service  cloud:    gateway:      globalcors:        cors-configurations:          '[/**]':            allow-credentials: true #允许携带认证信息Cookie            allowed-origins: "*"   # 允许所有请求            allowed-headers: "*"   #允许所有请求头            allowed-methods:  #允许指定的请求方式              - OPTIONS              - GET              - POST            max-age: 86400  # 86400 秒,也就是 24 小时 在有效时间内,浏览器无须为同一请求再次发起预检请求,可以减少发送请求的次数,减少系统部分压力。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

还可以使用代码方式进行跨域

// 解决网关跨域问题@Configurationpublic class CorsConfig {    @Bean    public CorsWebFilter corsFilter() {        CorsConfiguration config = new CorsConfiguration();        config.addAllowedMethod("*");        config.addAllowedOrigin("*");        config.addAllowedHeader("*");        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());        source.registerCorsConfiguration("/**", config);        return new CorsWebFilter(source);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

实现负载均衡器

在gateway中已经默认集成了负载均衡相关的依赖,相关配置我们在之前common模块中已经配置完毕了

那么我们在路由的时候需要指定服务名称才行

    routes:      - id: consumer-route        uri: lb://consumer  #想要负载必须指定lb://服务名称
  • 1
  • 2
  • 3

创建2个相同的consumer(消费者),都启动起来
consumer: 9001 , consumer1:9002 , consumer2:9003


然后使用网关进行访问http://localhost:10010/api/user/getUserAll,就会发现是走负载的

实现熔断降级

为什么要实现熔断降级?

在分布式系统中,网关作为流量的入口,因此会有大量的请求进入网关,向其他服务发起调用,其他服务不可避免的会出现调用失败(超时、异常),失败时不能让请求堆积在网关上,需要快速失败并返回给客户端,想要实现这个要求,就必须在网关上做熔断、降级操作。

为什么在网关上请求失败需要快速返回给客户端?

因为当一个客户端请求发生故障的时候,这个请求会一直堆积在网关上,当然只有一个这种请求,网关肯定没有问题(如果一个请求就能造成整个系统瘫痪,那这个系统可以下架了),但是网关上堆积多了就会给网关乃至整个服务都造成巨大的压力,甚至整个服务宕掉。因此要对一些服务和页面进行有策略的降级,以此缓解服务器资源的的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户的得到正确的相应,所以需要网关上请求失败需要快速返回给客户端。

添加网关的依赖

<!--        熔断器-->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

参数配置我们之前在common模块中已经配置过滤无须配置了

全局路径默认熔断器配置方式

  cloud:    gateway:      default-filters:        # 去掉全部前缀api        - RewritePath=/api(?<segment>/?.*),/$\{segment}        - name: Hystrix  # 网关名称(随意只要不重复就行)          args:            name: fallbackHystrix  # 降级名称和方法名称一样就行了            fallbackUri: forward:/fallbackHystrix  # 当发生降级后,降级回调的controller
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意: 也可以单独给指定的路由进行配置网关

@RestControllerpublic class FallbackHystrixController {    @GetMapping("/fallbackHystrix")    public ResponseEntity fallbackHystrix() {        System.out.println("发送邮件给管理员,进行处理");        //503        ResponseEntity response = new ResponseEntity(HttpStatus.SERVICE_UNAVAILABLE);        return response;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

指定路由配置熔断器方式
这样的好处就是能知道是哪里出现了问题

      routes:        - id: consumer-route # 路由id,可以随意写不影响  一般都是以要代理的服务器名称-route          uri: lb://consumer # 要访问的服务名称 (集群的时候可以防止宕机)          #我们请求http://consumer/xxxx 会被拦截          predicates: #允许的路由地址,要算上过滤器(filters)            - Path=/api/user/**          filters:            - name: Hystrix  # 网关(固定)              args:                name: consumerFallbackHystrix  # 降级名称                fallbackUri: forward:/consumerFallbackHystrix  # 当发生降级后,降级回调的controller
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
@RestControllerpublic class FallbackController {    @GetMapping("/consumerFallbackHystrix")    public ResponseEntity consumerFallbackHystrix() {        System.out.println(" consumer服务出问题了,发送邮件给管理员,进行处理");        //503        ResponseEntity response = new ResponseEntity(HttpStatus.SERVICE_UNAVAILABLE);        return response;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Gateway+进行高可用

基本上微服务到Gateway这一层,就无法在通过Ribbon进行负载了,因为这里已经是用户访问的最开始的入口了那么如果大量的请求都去访问一台Gateway肯定是扛不住的,比如双十一这种大量并发请求的场景世界上是没有这么高性能的单机服务的,解决办法通过负载均衡器Nginx进行代理,他是安装在服务器上的,来看下面一张部署图:

我么这里就不详细的介绍nginx具体的使用了,因为篇幅有点长,我们会专门拿一篇文章来讲解nginx和高可用部署的,下面就简单的使用Nginx进行负载多台Gateway,我们在创建2台Gateway

gateway:10010 ,gateway:10011 ,gateway:10012

我们可以自行安装Windows的Nginx然后在nginx.conf中进行配置

	upstream gateway-server {      server 127.0.0.1:10010;      server 127.0.0.1:10011;      server 127.0.0.1:10012;    }	 server {		listen       20202;		server_name  localhost;		  location / {			proxy_pass http://gateway-server/;		  }	 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

然后重启nginx,进行访问http://localhost:20202/api/user/getUserAll

注意事项:

  1. 配置前需要检查listen的端口是否被占了,不然是访问不通的
  2. 从新加载配置文件nginx -s reload

小提示: 以上就没问题了吗? 当然不是,可以看到Nginx现在是瓶颈了,而Nginx本身并没有能力支持集群,最多只能做主从,那么如何解决呢?
我所知道的就3种:

  1. 网络层进行负载(DNS)
  2. 硬件(F5等)来进行负载 ,一些大厂用F5的还是比较多的而小厂一般都用不起太贵了
  3. 第三方平台进行流量代理转发(收费不高,小企业是能接受的)

我推荐几个大厂的负载均衡器价格还是能接受的

阿里云SLB

腾讯云CLB

华为云ELB

点赞 -收藏-关注-便于以后复习和收到最新内容
有其他问题在评论区讨论-或者私信我-收到会在第一时间回复
如有侵权,请私信联系我
感谢,配合,希望我的努力对你有帮助^_^

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发