微服务网关zuul总结

微服务是无状态的,是不存在session的,session需要存放在网关中。

网关的职责:

1.统一入口:为全部微服务提供唯一的入口点,网关起到外部和内部隔离,保障了后台服务的安全性。

2.鉴权校验:识别每个请求的权限,拒绝不符合要求的请求。

3.动态路由:动态地将请求路由到不同的后端集群中。

3.减少客户端与服务的耦合,服务可以独立发展,通过网管层来做映射。

集成网关的步骤:

1.加入eureka依赖,网关依赖

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

2.在网关项目的启动类上添加@EnableZuulProxy

通过网关访问其他微服务的方法:网关服务ip/网关服务端口/要调用的微服务名/微服务路径

=============网关的路由器==============

zuul可以有四种路由规则:

1.采用url指定路由方法

2.采用服务指定路由方法

3.路由的排除方法

4.路由的添加前缀方法

四种方法均无须代码实现,在配置文件中配置即可

1)url配置,匹配关键字,如果包含关键字就跳转到指定的url中

zuul.routes.book-product.path=/book-product/**

zuul.routes.book-product.url=http://127.0.0.1:8083/

通过以上配置,例如访问网关ip/网关端口/book-product/product/list就会跳转到127.0.0.1:8083/product/list

2)路由服务指定

#将路径/book/product/引到eureka的e-book-product服务上

#规则:zuul.routes.路径名.path=[自定义路径]

             zuul.routes.路径名.serviceId=[eureka上注册的服务名]

zuul.routes.book-product.path=/book-product/**

zuul.routes.book-product.serviceId=e-book-product

例如访问:localhost:9010/book-product/product/list => localhost:9010/e-book-prouct/product/list

服务指定更为简单的方式:

zuul.routes.[eureka上注册的服务名].path=[路径规则] => zuul.routes.e-book-product.path=/book-product/**

3.路由排除:排除某几个服务

zuul.ignored-services=e-book-product

#排除e-book-product服务之后,http://127.0.0.1/e-book-product/product/list这个地址将为空,需要排除多个服务时,多个服务之间用逗号隔开。

路由排除:首先排除所有服务,随后针对需要添加服务

#先排除所有服务,后根据需要添加服务

zuul.ignored-services=*

zuul.routes.e-book-consumer-hystrix.path=/book-consumer/**

路由排除:排除指定关键字的路径

#排除所有包括/list/list的路径

zuul.ignored-patterns=/**/list/**

4.路由的添加前缀

zuul.prefix=/api

zuul.routes.e-book-product.path=/book-product/**

此种情况下请求地址:

#http://127.0.0.1:9010/book-product/list => http://127.0.0.1:9010/api/book-product/list

========================过滤器==================

搭建过滤器的步骤:

1.创建过滤器类并继承抽象类ZuulFilter,并实现其中的方法。

2.在实现的run方法中定义过滤器要做的事情。

     网关的过滤器有四种类型:pre,routing,post,error

          pre:在请求被路由之前被调用,一般用于身份权限认证,记录调用日志等等。

          routing:在路由执行之后被调用。

          post:在routing和error过滤器之后被调用,可用于信息搜集,统计信息例如性能指标,对response的结构做特殊处理。

          error:处理请求发生错误时被调用,用于异常处理封装。

===============采用网关过滤器对系统异常统一处理=================

权限认证:一般选用"pre"模式,即在请求被路由之前执行过滤器,从请求中获取token(登录验证功能)

1.在过滤器的run方法中,首先获取请求上下文对象RequestContext,再从请求上下文对象中获取到HttpServletRequest对象,在HttpServletRequest对象中包含了请求的token。

public Object run() {
    logger.info("----------------------AccessFilter------------------------");
    RequestContext rc = RequestContext.getCurrentContext();
    HttpServletRequest request = rc.getRequest();
    String token = request.getParameter("token");
    if (token == null){
        logger.info("token is null");
        rc.setSendZuulResponse(false);//表示结束请求,不再往下层传递
        rc.setResponseStatusCode(401);
        rc.setResponseBody("{\"result\":\"token is null\"}");
        rc.getResponse().setContentType("text/html;charset=utf-8");
    }else{
        // TODO: 2020/3/6 到redis中验证token
        logger.info("token is ok");
    }
    return null;
}

2.在网关过滤器中对异常做统一处理,添加一个类实现ErrorController

@RestController
public class ErrorGatewayController implements ErrorController{
    @Override
    public String getErrorPath() {
        return "/error";
    }

    @RequestMapping("/error")
    public String error(){
        return "{\"result\":\"500 error!!!\"}";
    }
}

使用网关的过滤器做异常的统一处理,需要定义一个/error页面来返回错误信息。

如果把某个过滤器定义为"post"类型,它将在最后被调用。

================网关容错=================

zuul包本身就以来了hystrix的包:网关IP:网关端口/hystrix.stream

网关如何实现服务降级

1.创建类实现ZuulFallbackProvider接口

@Component
public class ProductFallbackProvider implements ZuulFallbackProvider{
    @Override
    public String getRoute() {
        //需要为哪一个服务提供降级
        return "e-book-product";
    }

    @Override
    public ClientHttpResponse fallbackResponse() {
        return new ClientHttpResponse() {
            //httpresponse的fallback的状态码,HttpStatus的值
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            //httpresponse的fallback的状态码,int值
            @Override
            public int getRawStatusCode() throws IOException {
                return this.getStatusCode().value();
            }
            //httpresponse的fallback状态码,string类型
            @Override
            public String getStatusText() throws IOException {
                return this.getStatusCode().getReasonPhrase();
            }

            @Override
            public void close() {

            }
            //告知触发fallback的原因
            @Override
            public InputStream getBody() throws IOException {
                String input = "服务不可用,请联系管理员";
                return new ByteArrayInputStream(input.getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                MediaType mt = new MediaType("application","json", Charset.forName("UTF-8"));
                headers.setContentType(mt);
                return headers;
            }
        };
    }
}

----------------------------------------------------------------------------

Zuul请求的生命周期

一个Http请求首先经过pre类型的过滤器(即在路由转发之前),在路由执行之后routing类型的过滤器被调用,接着进入post类型的过滤器,这中间一旦发生异常,将会进入error类型的过滤器,post类型总是在最后的(即便是有error)。

在高并发的情况下,网关如何实现限流达到自我保护

1.限制某个ip在某个时间段的请求(ratelimit)

加入zuul的限流jar包

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-zuul-ratelimit</artifactId>
</dependency>

2.在配置文件中加入限流配置

#开启限流

zuul.ratelimit.enable=true

#60s内请求超过三次,服务端就抛出异常,60s后可恢复正常请求

zuul.ratelimit.policies.book-product.limit=3

zuul.ratelimit.policies.book-product.refresh-interval=60

#针对某个IP进行限流,不影响其他IP

zuul.ratelimit.policies.book-product.type=origin

以上是针对book-product服务的限流,以下是全局配置限流:

zuul.ratelimit.enabled=true

zuul.ratelimit.default-policy.limit=3

zuul.ratelimit.default-policy.refresh-interval=60

zuul.ratelimit.default-policy.type=origin

=======zuul性能调优:网关的2层超时调优========

zuul的底层采用了ribbon和hystrix进行通信

hystrix默认情况下采用线程池隔离,超时时间是1000ms

ribbon的默认超时时间是5s,ribbon超时会进行集群重试

如果把服务端的接口中睡眠2s,hystrix就会超时,以至于请求到达不了ribbon

所以在这时,ribbon的超时时间必须小于hystrix的超时时间。请求时先经过hystrix,再经过ribbon,如果hystrix的超时时间大于ribbon,请求有可能在通过hystrix的时候,ribbon已经超时了。

在配置文件中配置超时时间。

          #第一层hystrix超时时间设置

          hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=8000

          #ribbon请求连接的超时时间,默认5秒

          ribbon.connectTimeout=5000

          #ribbon请求处理的超时时间,默认5秒

          ribbon.ReadTimeout=5000

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值