SpringCloud教程-07:网关(Zuul)

640?wx_fmt=jpeg

图片来源:pexels网站


640?wx_fmt=png java4all原创,欢迎关注 640?wx_fmt=gif

摘要:本文主要讲解SpringCloud体系中的网关服务Zuul。

640?wx_fmt=gif
 
 

在前面的系列文章中,我们介绍了注册中心负载均衡熔断机制等组件,这些组件用来搭建一套微服务体系,已经是可以胜任我们常见的业务需求了。但是,我们再思考一个问题,在单体服务时代,外部请求我们服务的接口时,一般是有个鉴权机制的,比如签名校验,权限校验等,单体服务中,我们自然是把这个部分逻辑写在项目中,请求来的时候直接调方法鉴权即可。

在微服务架构中,比如,我们现在有6个服务,我们是不是把这套鉴权机制写进6个微服务中呢?显然,这样实现不够优雅。改进一下,我们把这套鉴权抽取出来形成一个新的服务,所有的服务请求进来前,先过一下这个鉴权服务的校验。这样,听上去是个不错的主意。

如果鉴权服务挂了呢?防线就崩溃了,那鉴权又得考虑要做高可用。

上述的假想中,我们只假想了简单的鉴权,而且这样的实现,难以实现各种自定义的精准的校验和过滤,因为鉴权服务是同一套,给多个微服务使用。再延伸一下,会发现更多的问题。

幸好,SpringCloud这一套体系,封装了一套API网关的实现,给我们提供了一个更好地解决方案SpringCloud Zuul。网关就像所有微服务系统的门面一样,所有的外部访问都需要经过它来调度和过滤,它除了可以实现请求路由、负载均衡、校验过滤外,还可以和服务治理框架整合,做熔断处理,做服务聚合等。

本文先通过简单的使用示例来体验一下网关Zuul带来的快捷,深入使用,等后面进阶系列再详细介绍。本文主要分为以下几个步骤:

1.创建项目

新建一个Springboot项目zuul_server1。

2.引入依赖

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

 
 
<dependencyManagement>	
    <dependencies>	
      <dependency>	
        <groupId>org.springframework.cloud</groupId>	
        <artifactId>spring-cloud-dependencies</artifactId>	
        <version>Finchley.SR2</version>	
        <type>pom</type>	
        <scope>import</scope>	
      </dependency>	
    </dependencies>	
  </dependencyManagement>

3.修改配置文件

zuul需要注册到eureka上,然后我们配置路由,配置指定类型的请求路由到指定的服务上:

当请求path是以/api-a/开头的,就转发到feign-server1服务上;

当请求path是以/api-b/开头的,就转发到service-ribbon服务上,如果有其他路由,在routes下继续添加即可:

 
 
server:	
  port: 8018	
	
spring:	
  application:	
    name: zuul-server	
	
eureka:	
  client:	
    service-url:	
      default: http://localhost:8761/eureka	
	
zuul:	
  routes:	
    apia:	
      path: /api-a/**	
      serviceId: feign-server1	
    apib:	
      path: /api-b/**	
      serviceId: service-ribbon

4.添加启动注解

 
 
//开启zuul的功能	
@EnableZuulProxy	
@EnableEurekaClient	
@EnableDiscoveryClient	
@SpringBootApplication	
public class ZuulServer1Application {	
	
  public static void main(String[] args) {	
    SpringApplication.run(ZuulServer1Application.class, args);	
  }	
}

5.自定义Filter

zuul提供的功能,不仅仅是路由,我们还可以把所有的请求,在网关这一层,做个安全的校验,过滤,或者,也可以做一些其的处理。这里做个简单的token是否为空的校验,我们需要用到Filter.


Filter是Zuul的核心,用来实现对外服务的控制。Filter的生命周期有4个,分别是“PRE”、“ROUTING”、“POST”、“ERROR”,Zuul大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期。



我们来自定义一个Filter,用来校验token是否为空,自定义Filter,需要继承ZuulFilter,并实现其中的一些方法。我们在run中,对请求做个校验,当token为空时,就直接返回,不再向后端服务转发。

 
 
@Component	
public class RequestFilter extends ZuulFilter{	
	
  private static Logger logger = LoggerFactory.getLogger(RequestFilter.class);	
	
  /**	
   * pre 路由之前	
   * routing 路由之时	
   * post 路由之后	
   * error 发送错误调用	
   * @return	
   */	
  @Override	
  public String filterType() {	
    return "pre";	
  }	
	
  /**过滤的顺序,数字越小越先执行*/	
  @Override	
  public int filterOrder() {	
    return 0;	
  }	
	
  /**这里可以写逻辑判断,是否要过滤,true表示过滤,false表示不过滤*/	
  @Override	
  public boolean shouldFilter() {	
    return true;	
  }	
	
  /**filter需要执行的具体操作*/	
  @Override	
  public Object run() throws ZuulException {	
    RequestContext currentContext = RequestContext.getCurrentContext();	
    HttpServletRequest request = currentContext.getRequest();	
    String token = request.getParameter("token");	
    if(StringUtils.isEmpty(token)){	
      logger.warn("=======>token is empty");	
      currentContext.setSendZuulResponse(false);//不对其进行路由	
      currentContext.setResponseStatusCode(401);	
      try {	
        currentContext.getResponse().getWriter().write("token is empty");	
      }catch (Exception ex){	
        ex.printStackTrace();	
      }	
    }else {	
      currentContext.setSendZuulResponse(true);//进行路由	
      currentContext.setResponseStatusCode(200);	
    }	
    return null;	
  }	
}

6.启动项目,测试

我们需要启动前几篇文章创建的几个服务,然后启动本文的服务。然后先访问:http://localhost:8018/api-a/getCompany?id=234, 这个请求中没有带token参数的,查看结果:

640?wx_fmt=png

会发现,这个请求,并没有到后台服务,直接在网关这里就被拦截返回了。我们再请求一下:http://localhost:8018/api-b/getCompany?id=234&token=qweqew, 查看结果:

640?wx_fmt=png

由于带的有token,请求顺利的到了后台,请求到了指定服务。

SpringCloud系列:

为什么要实施微服务架构?

SpringCloud教程-01:服务注册与发现(Eureka)

SpringCloud教程-02:服务注册与消费

SpringCloud教程-03:负载均衡(Ribbon)

SpringCloud教程-04:断路器(Hystrix-Ribbon)

SpringCloud教程-05:负载均衡(Feign)

SpringCloud教程-06:断路器(Hystrix-Feign)

SpringBoot资料:SpringBoot系列教程资源


↓↓↓点击 阅读原文,查看完整源码。

640?wx_fmt=jpeg

与其相忘江湖,不如点赞关注


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值