一 feign

集成了ribbon负载均衡功能,集成了hystrix熔断器功能。支持请求压缩

1 使用feign替代resttemplate发送rest请求

1)在consumer中导入依赖openfeign
2)创建feign客户端,面向接口编程,@feignclient注解,属性赋值服务名;方法上写方法请求映射。feign通过动态代理生成实现类
3) 控制层,注入Feign客户端接口,面向接口编程调用方法实现远程调用服务提供者的对应方法
4)启动类使用 `@EnableFeignClients`注解开启feign
接收路径携带参数变量不能省略赋值,@PathVariable路径变量、@RequestParam请求参数
int login(@RequestParam("s") String s); //这里是参数变量用@RequestParam("s")注解,路径变量则用@PathVariable("s")
//可以传递普通参数,不能传递Java对象,Java对象只能转换为json字符串格式

2 负载均衡

用resttemplate还要加上@loadbalanced注解
配置文件
# 修改服务地址轮询策略,默认是轮询,配置之后变随机
# MaxAutoRetriesNextServer: 0 # 最大重试下一个服务次数(集群的情况才会用到,一起来规律是1=2,2 2=2,4 3=4,4 4=4,6 5=6,6)
user-provider:
  ribbon:
    #轮询
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
    ConnectTimeout: 10000 # 连接超时时间,比如修改服务提供者的ip让你连不上那你消费者肯定连接超时报错
    ReadTimeout: 2000 # 数据读取超时时间,这个是连上服务提供者,然后服务器提供者程序执行超过2秒报错
    MaxAutoRetries: 1 # 最大重试次数(第一个服务),比如连上了,但读取超时再重去尝试读取1次,控制器被访问↓
    MaxAutoRetriesNextServer: 0 # 最大重试下一个服务次数(集群的情况才会用到,一起来规律在上↑)
    OkToRetryOnAllOperations: false # 无论是请求超时或者socket read timeout等情况都进行重试

 

3 熔断器

也就是发生故障不走动态代理生成的实现类,走自定义的接口实现类来降级
1)配置文件开启feign熔断器支持
feign:
  hystrix:
    enabled: true # 开启Feign的熔断功能
 
2)熔断降级类
实现接口:自定义方法体。注意实现类需加上@component注解,才能把对象交给spring容器。
也可以采用内部类方式
3)在接口@feignclient注解内给属性fallback赋值来指定降级类
 

4 feign压缩yml配置

对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
通过配置开启请求与响应的压缩功能compression:
feign:
    compression:
        request:
            enabled: true # 开启请求压缩
        response:
            enabled: true # 开启响应压缩

 

也可对请求数据类型,及触发压缩上下限进行设置
 

5 feign日志级别配置类

普通日志等级配置
# com.ywj 包下的日志级别都为Debug
logging:
  level:
    com.ywj: debug
feign日志等级配置。除了使用配置类,也可以在启动类内通过@bean注入给spring容器管理。
@Configuration//配置类注解!
public class FeignConfig {
    /**
     * 日志级别
     * @return
     */
    @Bean
    public Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

 

二 spring cloud gateway网关

核心:过滤,路由
同样作为一个微服务,需注册到eureka;工程pom文件导入网关依赖及eureka客户端依赖;启动类添加开启发现客户端注解;配置文件,端口,应用名,eureka地址

1 路由配置

静态路由--动态路由
局部过滤器--全局过滤器
 
spring:
  cloud:
    gateway:
      routes:
        # id唯一标识,可自定义
        - id: gate-service-route
          #路由服务地址
          #静态路由策略
          # uri: http://localhost:18081
          #动态,lb协议表示从Eureka注册中心获取服务请求地址,应该用服务名集群访问,会使用负载均衡访问对应服务,负载均衡LoaderBalance
          uri: lb://user-provider
          #路由拦截地址配置(断言)
          predicates:
            - Path=/**   #注意首字母P要是大写的,2个*
          # 配置局部过滤器
          filters:
            # 请求地址添加路径前缀过滤器
            #- PrefixPath=/user
            # 去除路径前缀过滤器
            - StripPrefix=1
            - My
       # 配置全局默认过滤器
      default-filters:
            # 往响应过滤器中加入信息
        - AddResponseHeader=X-Response-Default-MyName,ywj

 

 
注意:断言,过滤器等关键字key首字母大写。- Path=/** #注意首字母P要是大写的,2个*

2 自定义过滤器

1)全局过滤器

 
package com.zl.filter;
 
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.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component//这个不能少,创建对象才能调用下面的非静态方法↓
public class LoginGlobalFilter implements GlobalFilter, Ordered {
    /**
     * 过滤拦截
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求参数
        //千万不要点错用这个方法String token =    request.getQueryParams().get("token").get(0);//NullPointerException,否则出现空指针异常
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        System.out.println("通过全局过滤器");
        //如果token为空,则表示没有登录
        if(StringUtils.isEmpty(token)){
            //没登录,状态设置413
            exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
            //结束请求
            return exchange.getResponse().setComplete();
        }
 
        //放行
        return chain.filter(exchange);
    }
 
    /**
     * 定义过滤器执行顺序
     * 返回值越小,越靠前执行,可以理解为默认从小到大执行
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
 

2)局部过滤器

自定义局部拦截器,要注意自定义类的前缀用在配置文件,后缀必须是指定工厂后缀
 
package com.zl.filter;
 
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.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
 
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {
    public MyGatewayFilterFactory() {
        super(MyGatewayFilterFactory.Config.class);
    }
 
    @Override
    public GatewayFilter apply(Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("通过局部过滤器");
                MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
                String token = queryParams.getFirst("token");
                ServerHttpResponse response = exchange.getResponse();
                if (token == null) {
                    return response.setComplete();
                }
                return chain.filter(exchange);
            }
        };
    }
 
    public static class Config {
    }
}
 

 

posted on 2020-12-05 12:50  JustCrazy  阅读(379)  评论(0编辑  收藏  举报