springcloud 之feignclient,Gateway

1.Client

1.使用

<dependency>
 	<groupId>org.springframework.cloud</groupId>
 	<artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>

image.png

2.优化

Feign 中默认使用 JDK 原生的 URLConnection 发送 HTTP 请求,我们可以集成别的组件来替换掉 URLConnection,比如 Apache HttpClient,OkHttp。
使用Apache HttpClient来优化

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

配置

feign:
  httpclient:
    #使用apache httpclient做请求,而不是jdk的HttpUrlConnection
    enabled: true
    # feign最大链接数 默认200
    max-connections: 200
    #feign 单个路径的最大连接数  默认 50
    max-connections-per-route: 50

配置超时时间
通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接的超时时间(ms), 默认值是 10s;第二个是请求处理的超时时间(ms),默认值是 60s。
在这里插入图片描述
(figinclient底层使用动态代理,比如下图,name是对应的服务名,getmapping是对应的调用地址,这样就可以拼接http请求,http://服务名/地址,然后如果有参数,再把参数封装进去,就形成了http请求)
image.png

2.gateway

Spring Cloud Gateway 是由 WebFlux + Netty + Reactor 实现的响应式的 API 网关。
它不能在传统的 servlet 容器中工作,也不能构建成 war 包。

1.原理图

Spring Cloud Gateway Diagram

2.使用

<dependencies>
  <!--  gateway网关-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <scope>test</scope> <!-- 特殊处理,不引入父工程依赖 -->(引入会报错)
    </dependency>
</dependencies>

配置

spring:
  application:
    name: msb-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          #默认值是false,如果设为true开启通过微服务创建路由的功能,即可以通过微服务名访问服务
          #http://localhost:13001/msb-order/order/create
          #不建议打开,因为这样暴露了服务名称
          enabled: true
      #是否开启网关
      enabled: true

3.谓词

请求匹配机制(触发路由条件)即符合Predicate的条件,就使用该路由的配置,否则对请求不做任何处理
例1
表示访问 GATEWAY_URL/order/(只有含有order) 会转发到 msb-order 微服务的 /order/

spring:
  cloud:
    gateway:
      routes:
      - id: {唯一标识}
        uri: lb://msb-order/
        predicates:
            - Path=/order/*

自定义谓词
比如我们有这样一个需求:

  • 限制08:00 - 23:00 才能访问

我们自定义一下配置:假设这个配置是这样配置的 - TimeBetween= 08:00,23:00

image.png

自定义路由断言工厂需要继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑。在 apply 方法中可以通过 exchange.getRequest() 拿到 ServerHttpRequest 对象,从而可以获取到请求的参数、请求方式、请求头等信息。
注意: 命名需要以 RoutePredicateFactory 结尾

@Component
public class TimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<TimeBetweenConfig> {

    public TimeBetweenRoutePredicateFactory() {
        super(TimeBetweenConfig.class);
    }

    @Override
    public Predicate<ServerWebExchange> apply(TimeBetweenConfig config) {
        LocalTime start = config.getStart();
        LocalTime end = config.getEnd();
        return new Predicate<ServerWebExchange>() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                LocalTime now = LocalTime.now();
                return now.isAfter(start) && now.isBefore(end);
            }
        };
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("start","end");
    }
}

需要用到泛型,这里的泛型是需要定义一个配置类来给配置参数,下面是配置类,配置开始时间和结束时间

@Data
public class TimeBetweenConfig {
    private LocalTime start;
    private LocalTime end;
}

4.过滤器

SpringCloudGateway 内置了很多的过滤器工厂,我们通过一些过滤器工厂可以进行一些业务逻辑处理器,比如添加剔除响应头,添加去除参数等
自定义过滤器

@Slf4j
@Component
public class PrintLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
    @Override
    public GatewayFilter apply(NameValueConfig config) {
        // 放到这里应用启动的时候会执行两次次,这是一个坑,需要放到方法里面
      //   log.info("打印请求信息:{}:{}",config.getName(),config.getValue());
        return new GatewayFilter() {

            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                log.info("打印请求信息:{}:{}",config.getName(),config.getValue());
                // 获取request就可以进行修改了
                ServerHttpRequest modifiedRequest = exchange.getRequest().mutate().build();
                // 设置请求值
//                ServerHttpRequest modifiedRequest = exchange.getRequest().mutate()
//                        .header(config.getName(), value).build();
                ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
                return chain.filter(modifiedExchange);
            }
        };
    }
}

image.png

自定义全局过滤器

@Slf4j
@Component
public class IPAddressStatisticsFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        InetSocketAddress host = exchange.getRequest().getHeaders().getHost();
        if (host == null || host.getHostName() == null) {
            exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
            return exchange.getResponse().setComplete();
        }
        String hostName = host.getHostName();
        AtomicInteger count = IpCache.CACHE.getOrDefault(hostName, new AtomicInteger(0));
        count.incrementAndGet();
        IpCache.CACHE.put(hostName, count);
        log.info("IP地址:" + hostName + ",访问次数:" + count.intValue());
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1;值越小越靠前
    }
}

public class IpCache {
    public static final Map<String, AtomicInteger> CACHE = new ConcurrentHashMap<>();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值