Spring Cloud:第五章:Zuul服务网关

简介: Spring Cloud:第五章:Zuul服务网关

快速入门

定义user,order,pay服务,定义zull服务网关服务都注册到eureka服务上,

通过一下接口访问user,order,pay的服务,

http://localhost:7070/pay/index
http://localhost:8080/user/index
http://localhost:9090/order/index

定义服务网关服务zuul,我们看看其相关配置,zuul-service加入依赖:

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

配置文件:

spring:
  application:
    name: zuul-service
eureka:
  client:
    service-url:
     defaultZone: http://localhost:8761/eureka
  instance:
    instance-id:  ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
    prefer-ip-address: true
server:
  port: 6069

定义启动类:

package com.zhihao.miao;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
//使用@EnableZuulProxy注解开启zuul的api网关服务功能
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class,args);
    }
}

然后可以通过服务网关进行访问上面的三个服务接口,

http://localhost:6069/pay-service/pay/index
http://localhost:6069/user-service/user/index
http://localhost:6069/order-service/order/index

注意

默认的zuul结合eureka会将注册到eureka的服务名作为访问的ContextPath。

  • 也可以指定一些路由机制,application.yml中定义如下,
zuul:
  routes:
    user-service:
      path: /users/**
      serviceId: user-service

url符合/users/**规则的就被转发到user-service实例中了。

http://localhost:6069/users/user/index

之前的通过服务实例名称的也能访问

http://localhost:6069/user-service/user/index
  • 也可以忽略所有的代理,只保留自己配置的即可。
zuul:
  ignored-services: '*'
  routes:
    user-service: /users/**

此时只能访问user-service服务,并且只能以users这种路由来访问。

不能访问

http://localhost:6069/pay-service/pay/index
http://localhost:6069/order-service/order/index

之前默认的注册到eureka上的服务(user-service)也不能访问。

不能访问

http://192.168.1.57:6069/user-service/user/index

可以访问

http://192.168.1.57:6069/users/user/index

以上的配置也可以这样指定

zuul:
  ignored-services: order-service,pay-service
  routes:
    user-service: /users/**

当然此时除了http://192.168.1.57:6069/users/user/index能被代理访问到

http://192.168.1.57:6069/user-service/user/index也能访问了

请求过滤

在实现请求理由功能之后,我们的微服务应用提供的接口就可以通过统一的api网关入口被客户端访问到了。每个客户端用户请求服务应用提供的接口时,他们的访问权限往往都有一定的限制,系统并不会将所有的微服务接口对他们开放。然而,目前的服务路由并没有限制权限这样的功能,所有请求都会被毫无保留的转发到具体的应用并返回结果,为了实现对客户端请求的安全校验和权限控制,最简单和粗暴的方法就是在每个微服务应用都实现一套用于校验签名和鉴别权限的过滤器或拦截器。这样有个问题就是功能实现太过冗余。比较好的做法就是将这些校验逻辑剥离出去,构建一个独立的鉴权服务。在完成剥离之后,直接在微服务应用中通过调用鉴权系统服务来实现校验,但是这样仅仅只是解决了鉴权逻辑的分离,并没有在本质上将这部分不属于冗余的逻辑从原有的微服务应用中拆出去,冗余的拦截器或者过滤器依然会存在。

对于这样的问题,更好的做法是通过前置的网关服务来完成这些非业务性质的校验。由于网关服务的加入,外部客户端访问我们的系统已经有了统一的入口,既然这些校验与具体的业务无关,那何不在请求到达的时候就完成校验和过滤,微服务应用端就可以去除各种复杂的过滤器和拦截器了,这使得微服务应用接口的开发和测试复杂度也得到了相应的降低。这就涉及到了zuul的另一个主要功能,请求过滤。

在zuul-service服务中定义一个过滤器,

public class AccessFilter extends ZuulFilter{
    private Logger logger = LoggerFactory.getLogger(getClass());
    //过滤器的类型,它决定过滤器在请求的哪个生命周期中执行,这里定义为pre,代表会在请求被理由之前执行。
    @Override
    public String filterType() {
        return "pre";
    }
    //过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行
    @Override
    public int filterOrder() {
        return 0;
    }
    //判断该过滤器是否需要被执行。这里我们直接返回了true,因此该过滤器对所有的请求都生效。实际运行中我们可以利用该函数
    //来指定过滤器的有效范围。
    @Override
    public boolean shouldFilter() {
        return true;
    }
    //过滤器的具体执行逻辑。
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        logger.info("send {} request to {}",request.getMethod(),request.getRequestURI().toString());
        Object accessToken = request.getParameter("accessToken");
        if(accessToken == null){
            logger.warn("access token is empty");
            ctx.setSendZuulResponse(false); //令zuul过滤该请求,不对其进行路由
            ctx.setResponseStatusCode(401); //设置返回的错误码
        }
        logger.info("access token ok");
        return null;
    }
}

ZuulFilter接口中定义四个方法:

filterType:过滤器的类型,它决定过滤器在请求的哪个生命周期中执行,这里定义为pre,代表会在请求被理由之前执行。

filterOrder:过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行。

shouldFilter:判断该过滤器是否需要被执行。这里我们直接返回了true,因此该过滤器对所有的请求都生效。实际运行中我们可以利用该函数。

run:过滤器的具体执行逻辑。

在将过滤器纳入spring容器中,

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class,args);
    }
    @Bean
    public AccessFilter accessFilter(){
        return new AccessFilter();
    }
}

访问服务:

http://localhost:6069/users/user/index

状态码错误为401,正确访问姿势是

http://localhost:6069/users/user/index?accessToken=111

过滤器类型与请求生命周期

PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。

ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。

POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

ERROR:在其他阶段发生错误时执行该过滤器。

除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。

总结

就目前掌握的api网关知识,总结出四点如下

它作为系统的统一入口,屏蔽了系统内部各个微服务的细节。

它可以与服务治理框架结合,实现自动化的服务实例维护以及负载均衡的路由转发。

它可以实现接口权限校验与微服务业务逻辑的解耦。

通过服务网关中的过滤器,在各个生命周期中去校验请求的内容,将原本在对外服务层做的校验迁移,保证了微服务的无状态性,同时降低了微服务的测试难度,让服务本身更集中关注业务逻辑的处理。

相关文章
|
3天前
|
监控 负载均衡 安全
微服务(五)-服务网关zuul(一)
微服务(五)-服务网关zuul(一)
|
1月前
|
缓存 NoSQL Java
【Azure Redis 缓存】示例使用 redisson-spring-boot-starter 连接/使用 Azure Redis 服务
【Azure Redis 缓存】示例使用 redisson-spring-boot-starter 连接/使用 Azure Redis 服务
|
14天前
|
消息中间件 存储 Java
SpringCloud基础9——服务异步通信-高级篇
消息可靠性、死信交换机、惰性队列、MQ集群
SpringCloud基础9——服务异步通信-高级篇
|
3天前
|
Java API 对象存储
微服务魔法启动!Spring Cloud与Netflix OSS联手,零基础也能创造服务奇迹!
这段内容介绍了如何使用Spring Cloud和Netflix OSS构建微服务架构。首先,基于Spring Boot创建项目并添加Spring Cloud依赖项。接着配置Eureka服务器实现服务发现,然后创建REST控制器作为API入口。为提高服务稳定性,利用Hystrix实现断路器模式。最后,在启动类中启用Eureka客户端功能。此外,还可集成其他Netflix OSS组件以增强系统功能。通过这些步骤,开发者可以更高效地构建稳定且可扩展的微服务系统。
14 1
|
3天前
|
测试技术 微服务
微服务(八)-服务网关zuul(四)
微服务(八)-服务网关zuul(四)
|
3天前
|
监控 前端开发 Java
微服务(七)-服务网关zuul(三)
微服务(七)-服务网关zuul(三)
|
3天前
|
负载均衡 前端开发 安全
微服务(六)-服务网关zuul(二)
微服务(六)-服务网关zuul(二)
|
1月前
|
Java API 微服务
服务网关Gateway
该博客文章详细介绍了Spring Cloud Gateway的使用方法和概念。文章首先阐述了API网关在微服务架构中的重要性,解释了客户端直接与微服务通信可能带来的问题。接着,文章通过具体的示例代码,展示了如何在Spring Cloud Gateway中添加依赖、编写路由规则,并对路由规则中的基本概念如Route、Predicate和Filter进行了详细解释。最后,文章还提供了路由规则的测试方法。
服务网关Gateway
|
1月前
|
存储 Java Spring
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
|
2月前
|
监控 负载均衡 Java
深入理解Spring Cloud中的服务网关
深入理解Spring Cloud中的服务网关