美文网首页
SpringCloud Finchley 实战入门(基于spri

SpringCloud Finchley 实战入门(基于spri

作者: 同学汇俱乐部 | 来源:发表于2018-08-01 16:41 被阅读72次

    网关介绍

    API网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的Facade模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤。它除了要实现请求路由、 负载均衡、 校验过滤等功能之外,还需要更多能力,比如与服务治理框架的结合、请求转发时的熔断机制、服务的聚合等一系列高级功能。

    入门例子

    创建一个moudle,命名为eureka-zuul,创建时选择一些的组件依赖:


    1533108772510.png

    pom.xml文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.example</groupId>
        <artifactId>eureka-zuul</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>eureka-zuul</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
            <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
    

    配置application.yml

    server:
      port: 1100
    spring:
      application:
        name: service-zuul
    

    application.yml只是设置基本信息,结合之前创建的配置中心,我们把主要把配置的主要信息通过eureka-config-git配置中心获取。所以添加一个bootstrap.yml配置文件。

    spring:
      cloud:
        config:
          profile: dev #dev开发环境配置文件,test测试环境配置文件,pro正式环境文件
          label: master #git仓库对应的分支名称 config-label-test
    #      label: config-label-test #git仓库对应的分支名称 config-label-test
    #      uri: http://localhost:7001/ #config-server
          name: service-zuul
          discovery:
            serviceId: config-server-git #基于服务注册发现的方式查找
            enabled: true
    eureka:
      client:
          serviceUrl:
            defaultZone: http://peer1:8762/eureka/,http://peer2:8763/eureka/
    management: #配置暴露监控节点地址
      endpoints:
        web:
          exposure:
            include: "*"
          cors:
            allowed-origins: "*"
            allowed-methods: "*"
    #注册中心eureka.client.service-url.defaultZone = 一定要放在boostrap文件中,不然启动会报错
    

    这里的配置主要就是指向配置中心。

    项目的主类添加EnableZuulProxy注解

    /*@SpringBootApplication
    EnableEurekaClient*/
    @EnableZuulProxy//注解@EnableZuulProxy以开启zuul特性
    @SpringCloudApplication //使用@SpringCloudApplication包括,
    // Springboot注解,注册服务到注册中心注解,熔断器注解
    // 在SpringCloud看来这是每一微服务所必须应有的三个注解,所以才推出了@SpringCloudApplication注解
    public class EurekaZuulApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaZuulApplication.class, args);
        }
    

    另外config-repo这个配置文件中心的项目有个zuul的配置文件bootstrap.yml主要配置的就是指向了这个config-repo的配置文件。
    service-zuul-dev.yml

    zuul:
      ignoredServices: '*' #忽略所有未配置的service,每一个微服务的路由配置都需要配置
      host:
        connect-timeout-millis: 20000
        socket-timeout-millis: 20000
      routes:
        ribbon-service: #自定义名称
          path: /ribbon/**
          serviceId: service-user-ribbon #/ribbon/开头的路径转发至service-user-ribbon微服务
          sensitiveHeaders: true #springcloud项目中经过网关zuul转发请求后发生session失效问题,这是由于zuul默认会丢弃原来的session并生成新的session
          #所以这里对制定的路由开启自定义敏感头。除了设置为true,也可以设置为空。zuul.sensitiveHeaders= 只是全局设置的做法。不推荐!破坏了默认设置的用意
    hystrix: #hystrix配置
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 2500
    ribbon: #ribbon负载均衡参数配置
      ReadTimeout: 5000
      ConnectTimeout: 5000
    eureka:
      client:
        serviceUrl:
          defaultZone: http://peer1:8762/eureka/,http://peer2:8763/eureka/
    

    相关的配置注释已经说得很清楚了

    接下来我们新建一个类来测试zuul功能。
    创建一个UserFallbackProvider类实现FallbackProvider接口

    
    @Component
    public class UserFallbackProvider implements FallbackProvider {
    
        @Override
        public String getRoute() {
            return "service-user-ribbon";
        }
    
        @Override
        public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
            return new ClientHttpResponse() {
                @Override
                public HttpStatus getStatusCode() throws IOException {
                    return HttpStatus.OK;
                }
    
                @Override
                public int getRawStatusCode() throws IOException {
                    return 200;
                }
    
                @Override
                public String getStatusText() throws IOException {
                    return "OK";
                }
    
                @Override
                public void close() {
    
                }
    
                @Override
                public InputStream getBody() throws IOException {
                    return new ByteArrayInputStream("fallback".getBytes());
                }
    
                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);
                    return headers;
                }
            };
        }
    }
    
    1533110129632.png

    依次启动服务注册中心=>configGit=>serviceUser=>serviceUserRibbon=>zuul


    1533110998412.png
    1533110900002.png
    1533111016759.png

    服务确保正常,我们访问zuul的服务地址:http://localhost:1100/ribbon/listUsersByRibbon

    1533111048541.png

    数据正常返回,说明zuul项目配置正常。

    过滤器

    上面的演示是用zuul实现一个基本的接口请映射请求,zuul主要的主要是认证和鉴权这方面的功能。我们下面实现一个过滤器的功能;在上面的项目基础上,我们新建一个过滤器AccessFilter实现ZuulFilter接口

    @Log
    public class AccessFilter extends ZuulFilter {
        @Override
        public String filterType() {
            /**
             * pre 代表请求被路由前执行
             */
            return "pre";
        }
    
        @Override
        public int filterOrder() {
            /**
             * 过滤器执行的顺序
             */
            return 0;
        }
    
        @Override
        public boolean shouldFilter() {
            /**
             * 判断过滤器是否执行
             */
            return true;
        }
    
        /**
         * 具体的过滤逻辑
         *
         * @return
         * @throws ZuulException
         */
        @Override
        public Object run() throws ZuulException {
            RequestContext currentContext = RequestContext.getCurrentContext();
            HttpServletRequest request = currentContext.getRequest();
            log.info("send " + request.getMethod() + " Request to " + request.getRequestURL().toString());
            String token = request.getParameter("token");
            if (StringUtils.isBlank(token)) {
                log.warning("access token is empty");
                currentContext.setSendZuulResponse(false);
                currentContext.setResponseStatusCode(401);
                try {
                    HttpServletResponse response = currentContext.getResponse();
                    response.setCharacterEncoding("utf-8");  //设置字符集
                    response.setContentType("text/html; charset=utf-8"); //设置相应格式
                    response.getWriter().write("token 验证失败");
                } catch (IOException e) {
                    log.info("response io异常");
                    e.printStackTrace();
                }
                return null;
            }
            return null;
        }
    }
    

    这里的过滤器主要的作用是拦截请求,然后从请求体中获取参数token。判断有没有token这个参数,如果有的话,就通过;如果获取不到token参数,就直接响应一个401的状态。
    然后在项目的主类中注入该过滤器:

    /**
         * 启用过滤器功能
         *
         * @return
         */
        @Bean
        public AccessFilter accessFilter() {
            return new AccessFilter();
        }
    

    重启zuul服务,重新访问地址:http://localhost:1100/ribbon/listUsersByRibbon
    当我们没有在请求地址中加上token的参数时,该接口响应token校验失败了。

    1533111845622.png

    我们在通过地址http://localhost:1100/ribbon/listUsersByRibbon?token=token
    在加上token参数的情况下,过滤器校验通过就可以正常的响应接口了。

    1533111890497.png

    github 项目源码

    相关文章

      网友评论

          本文标题:SpringCloud Finchley 实战入门(基于spri

          本文链接:https://www.haomeiwen.com/subject/kwervftx.html