• SpringCloud之Zuul


    前面的话】书接上文,前面已经讲过了SpringCloud的注册中心Eureka、Ribbon和Feign等等,如果有不清楚的也可以去看看我的微服务系列文章。这篇文章我要说的是微服务中的网关。


    壹、Zuul的简介

    Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。

    zuul有以下功能:

    Authentication
    Insights
    Stress Testing
    Canary Testing
    Dynamic Routing
    Service Migration
    Load Shedding
    Security
    Static Response handling
    Active/Active traffic management
    

    贰、准备工作

    新建一个feign子工程lovin-cloud-zuul,用于后面的操作。下面是主要的pom依赖:

    <parent>
            <artifactId>lovincloud</artifactId>
            <groupId>com.eelve.lovincloud</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>lovin-cloud-zuul</artifactId>
        <packaging>jar</packaging>
        <name>lovincloudzuul</name>
        <version>0.0.1</version>
        <description>zuul</description>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zuul</artifactId>
                <version>1.4.7.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
                <version>2.1.3.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    • 这里为了安全,我这里还是添加spring-boot-starter-security,同时配置路由规则发送/api-ribbon/打头开始的服务转发到lovinribbonclient而发送/api-feign/打头的服务转发到lovinfeignclient,可以看出这里是配置相应的路由规则。
    server:
      port: 8882   # 服务端口号
    spring:
      application:
        name: lovincloudzuul     # 服务名称
      security:
        basic:
          enabled: true
        user:
          name: lovin
          password: ${REGISTRY_SERVER_PASSWORD:lovin}
    zuul:
      routes:
        api-ribbon:
          path: /api-ribbon/**
          serviceId: lovinribbonclient
        api-feign:
          path: /api-feign/**
          serviceId: lovinfeignclient
    eureka:
      client:
        serviceUrl:
          defaultZone: http://lovin:lovin@localhost:8881/eureka/   # 注册到的eureka服务地址
      instance:
        leaseRenewalIntervalInSeconds: 10
        health-check-url-path: /actuator/health
        metadata-map:
          user.name: lovin
          user.password: lovin
    
    • 配置spring-boot-starter-security,这里为了方便我这里放开所有请求
    package com.eelve.lovin.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    /**
     * @ClassName WebSecurityConfig
     * @Description TDO
     * @Author zhao.zhilue
     * @Date 2019/8/18 12:17
     * @Version 1.0
     **/
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().anyRequest().permitAll()
                    .and().csrf().disable();
        }
    }
    
    • 在主类上添加@EnableZuulProxy ,当然也需要注册到注册中心:
    package com.eelve.lovin;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    /**
     * @ClassName LovinEurekaClientApplication
     * @Description TDO
     * @Author zhao.zhilue
     * @Date 2019/8/15 16:37
     * @Version 1.0
     **/
    @EnableZuulProxy
    @EnableEurekaClient
    @SpringBootApplication
    public class LovinCloudZuulApplication {
        public static void main(String[] args) {
            SpringApplication.run(LovinCloudZuulApplication.class,args);
        }
    }
    
    • 这里为了方便测试,这里配置相应的过滤规则:
    package com.eelve.lovin.filter;
    
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * @ClassName MyFilter
     * @Description TDO
     * @Author zhao.zhilue
     * @Date 2019/8/18 12:44
     * @Version 1.0
     **/
    @Component
    @RefreshScope // 使用该注解的类,会在接到SpringCloud配置中心配置刷新的时候,自动将新的配置更新到该类对应的字段中。
    @Slf4j
    public class MyFilter extends ZuulFilter {
    
        @Override
        public String filterType() {
            return "pre";
        }
    
        @Override
        public int filterOrder() {
            return 0;
        }
    
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        @Override
        public Object run() throws ZuulException {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
            Object accessToken = request.getParameter("token");
            if(accessToken == null) {
                log.warn("token is empty");
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);
                try {
                    ctx.getResponse().getWriter().write("token is empty");
                }catch (Exception e){}
    
                return null;
            }else if(!accessToken.equals("lovin")){
                log.warn("token is not correct");
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(403);
                try {
                    ctx.getResponse().getWriter().write("token is not correct");
                }catch (Exception e){}
    
                return null;
            }
            log.info("ok");
            return null;
        }
    }
    
        filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
            pre:路由之前
            routing:路由之时
            post: 路由之后
            error:发送错误调用
        filterOrder:过滤的顺序
        shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
        run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
    

    叁、启动测试

    • 依次启动eureka的服务端和两个客户端和lovin-feign-client、lovin-ribbon-client,以及新建的lovin-cloud-zuul
    • 然后访问http://localhost:8882/api-feign/getHello和http://localhost:8882/api-ribbon/hello,然后我们可以带上token访问来验证过滤器
      zuul网关转发结果
      zuul网关转发结果
      zuul网关转发结果
      zuul网关转发结果
      zuul网关转发结果
      zuul网关转发结果
      zuul网关转发结果
      zuul网关转发结果

    肆、网络架构

    • 我们可以看到我们调用的服务不再是像再上一篇文章中的直接访问对应的服务,而是通过feign的Ribbon的负载均衡的去调用的,而且这里说明一点,Ribbon的默认机制是轮询。
      目前的网络架构

  • 相关阅读:
    Django系列:TemplateView,ListView,DetailView
    Django系列:开发自己的RestAPI
    Django系列:Restful CBV
    Django系列:RestFul
    Django系列12:Django模型关系
    B
    All about that base
    Safe Passage
    A
    Isomorphic Inversion
  • 原文地址:https://www.cnblogs.com/eelve/p/14221148.html
Copyright © 2020-2023  润新知