Spring Cloud学习笔记(十二)服务网关Zuul

简介

Spring Cloud Zuul组件的功能是能够提供动态路由转发、安全过滤、监控等微服务架构中的一系列边缘化服务。通常情况下,后端的服务并不直接开放给前端调用,而是通过API路由的方式,将请求转发到具体的后端服务。这种情况,就类似于我们熟知的反向代理,通过API网关去具体负责由谁提供服务。Zuul利用各种Filter实现如下功能:

  • 认证和安全,识别每个需要认证的资源,拒绝不符合要求的请求。
  • 性能监测,在服务边界追踪并统计数据,提供精确的生产视图。
  • 动态路由,根据需要将请求动态路由到后端集群。
  • 压力测试,逐渐增加对集群的流量以了解其性能。
  • 负载卸载,预先为每种类型的请求分配容量,当请求超过容量时自动丢弃。
  • 静态资源处理,直接在边界返回某些响应。

 简单示意,如下图:

 

路由功能 

基于学习Eureka Server的代码,加入Zuul工程,首先在Zuul工程中,引入依赖

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

然后修改配置文件,所有访问/baidu的请求,都会重新指向baidu.com

server:
  port: 13000
spring:
  application:
    name: api-gateway-zuul 
zuul:
  routes:
    baidu:
      path: /baidu/**
      url: http://www.baidu.com

修改启动类,加入@EnableZuulProxy

package org.dothwinds.serviceprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
public class SpringCloudStudyZuulApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringCloudStudyZuulApplication.class, args);
	}

}

配置完成,启动服务,访问http://localhost:13000/baidu,访问跳转到了baidu.com

微服务架构中的应用

上面的例子,我们只是做个转发的测试,在实际微服务应用场景中,我们不能对每新增一个服务就加一段配置,这里也需要通过Eureka之类的注册中心,服务之间彼此感知,通过ServiceId等进行绑定,由于我们项目工程中已经有Eureka和Service-Provider的工程,所以在这个基础上我们改造Zuul,注册到Eureka里,把服务请求转发到Service-Provider里

修改Zuul配置文件

server:
  port: 13000
spring:
  application:
    name: api-gateway-zuul #应用名称,会显示在eureka server中
zuul:
  routes:
    api-a:
      path: /sayHi
      serviceId: service-provider
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:7001/eureka

在启动类中加入@EnableEurekaClient注解,依次启动Eureka、Service-Provider和Zuul服务

访问http://localhost:13000/sayHi?name=huxi,如下图,应用已被转发至Service-Provider服务中了

Zuul的默认路由规则

Zuul的默认路由规则是它会代理所有注册到Eureka Server的微服务,默认情况下,http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka Server上的注册serviceId/**会被转发到serviceId对应的微服务。

负载均衡效果

由于Zuul默认集成Ribbon,所以天然集成了负载均衡,不用任何配置,基于上面的例子,我们把Service-provider服务代码改造一下,在新启动一个服务测试一下负载效果,修改服务端口号和接口返回值

server:
  port: 9002
spring:
  application:
    name: service-provider #应用名称,会显示在eureka server中

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:7001/eureka #eureka server地址
package org.dothwinds.serviceprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableEurekaClient
@RestController
public class SpringCloudStudyServiceProviderApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringCloudStudyServiceProviderApplication.class, args);
	}

	@GetMapping("/sayHi")
	public String sayHi(@RequestParam(value = "name", defaultValue = "dothwinds") String name) {
		return "hi," + name + ", welcome to my world, the message from service two";
	}

}

启动此服务

访问 http://localhost:13000/sayHi?name=huxi,可以看到两种效果的互相切换

安全过滤

开篇的时候提到了Zuul本身有认证和安全的相关功能职责,都是借助Filter来实现的,接下来看一下ZuulFilter,其它核心方法如下:

                public String filterType() {
                    return null;
                }

                public int filterOrder() {
                    return 0;
                }

                public boolean isFilterDisabled() {
                    return false;
                }

                public boolean shouldFilter() {
                    return true;
                }

                public Object run() {
                    return null;
                }

含义如下:

shouldFilter:是否执行该过滤器,true执行,false不执行
run:过滤器的具体业务逻辑
filterType:返回过滤器类型
一共有4种:
1.pre:请求在被路由之前执行
2.routing:在路由请求时调用
3.post:在routing和errror过滤器之后调用
4.error:调用错误
filterOrder:过滤器的执行顺序,数字越小优先级越高,且该值不可重复
isFilterDisabled:是否禁用,默认false,true为禁用

过滤器执行生命周期 

  • 请求鉴权:一般放在pre类型,如果发现没有访问权限,直接就拦截了
  • 异常处理:一般会在error类型和post类型过滤器中结合来处理
  • 服务调用时长统计:pre和post结合使用

过滤验证的例子

1,写一个Filter,继承ZuulFilter

package org.dothwinds.serviceprovider.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.exception.ZuulException;

@Component
public class UserFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 1; //从1开始
    }

    @Override
    public boolean shouldFilter() {
        return true; //是否执行,
    }

    @Override
    public Object run() throws ZuulException {
        return null;
    }
}

实现对应的方法,修改filterType,filterOrder和shouldFilter等值,最后写具体run方法的验证逻辑

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();// 1.获取Zuul提供的请求上下文对象
        HttpServletRequest request = ctx.getRequest();
        Object token = request.getParameter("token");
        if(token == null) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            }catch (Exception e){
                System.out.println(e);
            }
            return null;
        }
        return null;
    }

 重启服务,验证一下刚才通过zuul调用的方法,访问不带token

访问带token 

可以看到,Filter起到了过滤验证作用

参考资料:

https://cloud.spring.io/spring-cloud-static/Greenwich.SR5/single/spring-cloud.html

代码地址:

https://gitee.com/dothwinds/Spring-Cloud-Study/tree/master/spring-cloud-study-zuul

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值