zoukankan      html  css  js  c++  java
  • springcloud-Api网关服务Zuul

    springcloud项目例子:链接:https://pan.baidu.com/s/1O1PKrdvrq5c8sQUb7dQ5Pg 密码:ynir

    1.由来:

      如果我的微服务中有很多个独立服务都要对外提供服务,那么对于开发人员或者运维人员来说,他要如何去管理这些接口?特别是当项目非常大非常庞杂的情况下要如何管理?2.权限管理也是一个老生常谈的问题,在微服务中,一个独立的系统被拆分成很多个独立的模块,为了确保安全;

    2.功能:作为一个更智能应用服务器,类似于微服务构架系统门面,所有外部访问都经过api网关,有他来实现请求路由、负载均衡、权限验证等功能


    一:创建服务

      1.pom

    <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>springcloud</groupId>
        <artifactId>springcloud-Zuul-api-gate</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    
        <parent>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-parent</artifactId>
           <version>1.5.7.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>Dalston.SR3</spring-cloud.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <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>
        <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>
    </project>
    View Code

      2.入口类

    @SpringBootApplication
    @EnableZuulProxy //开启Zuul的API网关服务功能
    public class ApiGatewayApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ApiGatewayApplication.class, args);
        }
    }
    View Code

      3.配置路由

    # 基础信息配置
    spring.application.name=api-gateway
    server.port=2006
    # 路由规则配置
    zuul.routes.api-a.path=/api-a/**
    zuul.routes.api-a.serviceId=feign-consumer
    
    # API网关也将作为一个服务注册到eureka-server上
    eureka.client.service-url.defaultZone=http://localhost:1111/eureka/
    View Code

      我们在这里配置了路由规则所有符合/api-a/**的请求都将被转发到feign-consumer服务上,至于feign-consumer服务的地址到底是什么则由eureka-server去分析,我们这里只需要写上服务名即可。以上面的配置为例,如果我请求http://localhost:2006/api-a/hello1接口则相当于请求http://localhost:2005/hello1(我这里feign-consumer的地址为http://localhost:2005),我们在路由规则中配置的api-a是路由的名字,可以任意定义,但是一组path和serviceId映射关系的路由名要相同  

      4.测试

      依次启动我们的eureka-server、provider和feign-consumer,然后访问如下地址http://localhost:2006/api-a/hello,即可访问对应服务

    二:配置过滤

      自定义过滤器继承ZuulFilter

    public class PermisFilter extends ZuulFilter {
        @Override
        public String filterType() {
            return "pre";
        }
    
        @Override
        public int filterOrder() {
            return 0;
        }
    
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        @Override
        public Object run() {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            String login = request.getParameter("login");
            if (login == null) {
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);
                ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8");
                ctx.setResponseBody("非法访问");
            }
            return null;
        }
    }
    View Code

      解析

    1.filterType方法的返回值为过滤器的类型,过滤器的类型决定了过滤器在哪个生命周期执行,pre表示在路由之前执行过滤器,其他可选值还有post、error、route和static,当然也可以自定义。
    2.filterOrder方法表示过滤器的执行顺序,当过滤器很多时,这个方法会有意义。
    3.shouldFilter方法用来判断过滤器是否执行,true表示执行,false表示不执行,在实际开发中,我们可以根据当前请求地址来决定要不要对该地址进行过滤,这里我直接返回true。
    4.run方法则表示过滤的具体逻辑,假设请求地址中携带了login参数的话,则认为是合法请求,否则就是非法请求,如果是非法请求的话,首先设置ctx.setSendZuulResponse(false);表示不对该请求进行路由,然后设置响应码和响应值。这个run方法的返回值在当前版本(Dalston.SR3)中暂时没有任何意义,可以返回任意值。

      配置过滤器Bean,在入口类中配置相关Bean  

      此时,如果我们访问http://localhost:2006/api-a/hello,显示非法访问,此时,如果我们访问http://localhost:2006/api-a/hello?login=123通过过滤器就能访问!

    @Bean
    PermisFilter permisFilter() {
        return new PermisFilter();
    }

    三:总结

      Zuul,API网关作为系统统一入口,将微服务内部细节都屏蔽掉了,自动维护服务实例,实现负载均衡转发,通过他能提供统一的权限验证机制!,使服务本身只需要关注业务逻辑! 

    四:路由配置细节

      1.配置路由规则可替换:zuul.routes后面跟着的是服务名,服务名后面跟着的是路径规则,这种配置方式显然更简单

    zuul.routes.api-a.path=/api-a/**
    zuul.routes.api-a.serviceId=feign-consumer
    可替换为
    zuul.routes.feign-consumer=/api-a/**

      2.一般生产者的服务是不对外提供服务的,此时

    zuul.ignored-services=hello-service
    可去除这个服务接口,浏览器访问返回404

      3.使用yml可指定路由匹配顺序

    spring:
      application:
        name: api-gateway
    server:
      port: 2006
    zuul:
      routes:
        feign-consumer-hello:
          path: /feign-consumer/hello/**
          serviceId: feign-consumer-hello
        feign-consumer:
          path: /feign-consumer/**
          serviceId: feign-consumer
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:1111/eureka/

      4.网关本身的接口配置

    zuul:
      prefix: /myapi
      ignored-patterns: /**/hello/**
      routes:
        local:
          path: /local/**
          url: forward:/local

      5.在这里配置全局,特定服务的ribbon,hytrix

    #全局关闭hytrix重试机制
    zuul:
      retryable: false
    
    #关闭莫个服务hytrix重试机制
    zuul:
      routes:
        feign-consumer:
          retryable: false

    五:配置异常处理

      可创建一个Componet来处理异常信息

    @Component
    public class MyErrorAttribute extends DefaultErrorAttributes {
        @Override
        public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
            Map<String, Object> result = super.getErrorAttributes(requestAttributes, includeStackTrace);
            result.put("status", 222);
            result.put("error", "error");
            result.put("exception", "exception");
            result.put("message", "message");
            return result;
        }
    }
    View Code
  • 相关阅读:
    XML 文档的结构
    java 事件机制
    Spring 中的 Resource和ResourceLoader
    Spring PropertyPlaceholderConfigurer
    生产者——消费者模型的java代码实现
    encodeURI() 函数概述
    ECMAScript 6
    node
    AJAX常见面试题
    AJAX(Asynchronous JavaScript and XML)
  • 原文地址:https://www.cnblogs.com/xiaoping1993/p/9442284.html
Copyright © 2011-2022 走看看