微服务学习笔记(二)Ribbon+OpenFeign+Gateway

4 Ribbon负载均衡

概述

提供客户端的软件负载均衡算法和服务调用

eureka-client已经自带ribbon

RestTemplate

getForObject/postForObject:获取数据转化成的对象,可以理解为json

getForEntity/postForEntity:获取响应头、http状态码、响应体

流程

在这里插入图片描述

策略

默认用RoundRobinRule

轮询算法原理:rest接口第几次请求数%服务器集群总数量=实际调用服务器位置下标,每次服务重启后rest接口计数从1开始
在这里插入图片描述

配置策略

  1. 代码方式(全局配置)

在@ComponentScan扫描不到的包定义新的策略(不要跟启动类放同一个包)

启动类添加@RibbonClient注解

@Bean
public IRule randomRule() {
    return new RandomRule();
}
  1. 配置文件方式

可以根据服务名称具体配置

xxxservice: #服务名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

饥饿加载

Ribbon默认使用懒加载,第一次访问时创建对象,消耗时间较多

可以配置饥饿加载,项目启动时创建对象

ribbon:
  eager-load:
    enabled: true
    clients:
      - xxxservice

与Nginx对比

  • Ribbon:在消费者端进行的负载均衡,进程内负载均衡
    在这里插入图片描述

  • Nginx:接收了所有的请求进行负载均衡,集中式负载均衡
    在这里插入图片描述

5 OpenFeign远程调用

RestTemplate调用的问题

  • 代码可读性差,编程体验不统一

  • 参数复杂url难以维护

与Feign对比

在Feign基础上加入对SpringMVC的支持

OpenFeign基本使用

一个声明式的http客户端

  1. 添加依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 启动类添加@EnableFeignClients注解

  2. 编写FeignClient接口

@FeignClient("userservice") //userservice为服务名称
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}
  1. 使用FeignClient接口调用方法
//注入UserClient
User user = userClient.findById(id);

超时控制

Feign客户端默认等待1秒

ribbon:
  ReadTimeout: 5000 #建立连接所用时间
  ConnectTimeout: 5000 #从服务器读取到可用资源所用时间

自定义配置

在这里插入图片描述
配置日志级别:

NONE-无日志

BASIC-仅记录请求方法、URL、响应状态码及执行时间

HEADERS-除了BASIC中定义的信息之外,还有请求和响应的头信息

FULL-除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据

  • 配置文件

    feign:
      client:
        config:
          default: # default:全局配置,也可以使用服务名称
            loggerLevel: FULL
    
  • 代码

    @Configuration
    public class FeignClientConfig {
        @Bean
        public Logger.Level feignLoggerLevel() {
            return Logger.Level.FULL;
        }
    } 
    
    //加在启动类代表全局配置
    @EnableFeignClients(defaultConfiguration = FeignClientConfig.class)
    
    //加在FeignClient接口代表单个服务配置
    @FeignClient(value = "userservice", configuration = FeignClientConfig.class)
    

性能优化

  • 使用连接池(HttpClient, OKHttp)代替默认URLConnection

    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-httpclient</artifactId>
    </dependency>
    
    feign:
      httpclient:
        enabled: true # 开关
        max-connections: 200 # 最大连接数
        max-connections-per-route: 50 # 每个路径的最大连接数
    
  • 日志级别用BASIC或NONE

最佳实践

  • 给消费者的FeignClient和提供者的controller定义统一的父接口作为标准
    在这里插入图片描述

  • 将FeignClient抽取为独立模块,把接口有关的实体类、默认Feign配置放到该模块,提供给所有消费者使用
    在这里插入图片描述
    定义的FeignClient不在SpringBootApplication的扫描包范围,导致FeignClient无法注入spring容器,如何解决

  • 指定FeignClient所在包

    @EnableFeignClients(basePackages = "xxx")
    
  • 指定FeignClient字节码

    @EnableFeignClients(clients = {UserClient.class})
    

6 Gateway网关

网关功能

  • 身份认证、权限校验

  • 服务路由、负载均衡

  • 请求限流

技术实现

  • gateway:响应式编程(使用的Webflux的reactor-netty响应式编程组件,底层使用Netty通讯框架)

  • zuul:阻塞式编程

网关搭建

  1. 创建模块,引入依赖
<dependencies>
    <!--网关-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <!--nacos服务注册发现-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>2021.1</version>
    </dependency>
</dependencies>
  1. 配置

yml配置

server:
  port: 10010
spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service #路由标识,唯一
          uri: lb://userservice #路由目标地址
          predicates: #路由断言,判断请求是否符合规则
            - Path=/user/** #路径断言,判断路径是否以/user开头

编码配置

@Configuration
public class GatewayConfig {
    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        return routes.route("user-service", r -> r.path("/user/**").uri("lb://userservice")).build();
    }
}

在这里插入图片描述

路由断言工厂

作用:读取并解析配置的断言规则,转变为路由判断的条件
在这里插入图片描述
更多参考https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

时区时间点可以用ZonedDateTime类

过滤器

生命周期:pre(前置), post(后置)

种类:GatewayFilter, GlobalFilter

配置

作用:对进入网关的请求和微服务返回的响应做处理

过滤器工厂参考https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

server:
  port: 10010
spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service #路由标识,唯一
          uri: lb://userservice #路由目标地址
          predicates: #路由断言,判断请求是否符合规则
            - Path=/user/** #路径断言,判断路径是否以/user开头
          #filters:
           # - AddRequestHeader=headerName,headerValue
      # 也可以配置默认过滤器,使得所有路由都生效
      default-filters:
        - AddRequestHeader=headerName,headerValue

全局过滤器

以代码形式处理一切进入网关的请求和微服务响应

实现GlobalFilter接口,重写filter方法

//过滤器的顺序,值越小优先级越高
@Order(0)
@Component
public class AuthorizeFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> params = request.getQueryParams();
        String authorization = params.getFirst("authorization");
        if ("admin".equals(authorization)) {
            return chain.filter(exchange);
        }
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }
}

过滤器链执行顺序

请求进入网关,会将路由过滤器、默认过滤器、全局过滤器合并到一个过滤器链,排序后依次执行每个过滤器

每个过滤器指定一个int类型的order值,值越小优先级越高

全局过滤器实现Ordered接口或添加@Order注解指定order值,路由过滤器、默认过滤器的order由Spring指定,按照声明顺序从1开始

如果order值一样,按照默认过滤器>路由过滤器>全局过滤器顺序执行

跨域配置

spring:
    gateway:
      globalcors: # 全局跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求
              - "xxx"
            allowedMethods: # 允许跨域ajax请求方式
              - "GET"
              - "POST"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 允许携带cookie
            maxAge: 360000 # 跨域检测有效期(秒)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值