zoukankan      html  css  js  c++  java
  • 89--spring cloud (zuul-API网关/与feign的比较)

    zuul-API网关

    zuul API 网关,为微服务应用提供统一的对外访问接口。
    zuul 还提供过滤器,对所有微服务提供统一的请求校验。

    zuul

    统一调用入口

    创建项目-zuul

    导入依赖

    Eureka Client,zuul

    导入基本commons依赖

    <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.3.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>cn.tedu</groupId>
        <artifactId>sp11-zuul</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>sp11-zuul</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            </dependency>
            <dependency>
                <groupId>cn.tedu</groupId>
                <artifactId>sp01-commons</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </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配置

    spring:
      application:
        name: zuul
    server:
      port: 3001
    eureka:
      client:
        service-url:
          defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
    zuul:
      routes:
        item-service: /item-service/**
        user-service: /user-service/**
        order-service: /order-service/**
    

    主程序

    主程序添加@EnableZuulProxy注解,启动zuul

    package cn.tedu.sp11;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @EnableZuulProxy
    @SpringBootApplication
    public class Sp11ZuulApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(Sp11ZuulApplication.class, args);
        }
    
    }
    
    

    启动测试

    统一权限校验-zuul 请求过滤

    zuul过滤器

    添加过滤器,判断用户权限

    • 自定义过滤器,继承过滤器父类 ZuulFilter
    • 只需要添加 @Component 注解,zuul会完成自动配置
    package cn.tedu.sp11.filter;
    //过滤器
    
    import cn.tedu.web.util.JsonResult;
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    @Component
    public class AccessFilter extends ZuulFilter {
        /*
        filterType 指过滤器类型  pre post routing error
         */
        @Override
        public String filterType() {
            return FilterConstants.PRE_TYPE;
        }
        /*
        filterOrder 顺序号 指定过滤器插入的位置
        在默认过滤器中,第5个过滤器在上下文对象中添加了service-id,
        在第5个过滤器之后,层能从上下文对象访问到service-id
    
         */
        @Override
        public int filterOrder() {
            return 6;
        }
        /*
            对当前请求来说,是否要进行过滤,
            如果返回true,则要进行过滤,会执行过滤的run()方法
            如果返回false,跳过过滤代码,继续执行后面的流程
         */
        @Override
        public boolean shouldFilter() {
            //判断用户调用是否是商品服务
            //如果是商品服务,则进行过滤
            //如果不是,则不过滤
            //当前请求的上下文对象
            RequestContext ctx = RequestContext.getCurrentContext();
            //从上下文对象中获取客户端调用的service id
            String serviceId =(String) ctx.get(FilterConstants.SERVICE_ID_KEY);
            return "item-service".equals(serviceId);
        }
        /*
        过滤代码
        他的返回值,在当前版本中,没有启用,返回任何数据都无效
         */
        @Override
        public Object run() throws ZuulException {
            //
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            String token = request.getParameter("token");
            if (StringUtils.isBlank(token)){
                //没有token 则阻止访问
                ctx.setSendZuulResponse(false);
    
                //直接向客户端发送响应
                //返回JsonResult : { code:400 ,msg :not log in ,data : null}
                ctx.setResponseStatusCode(JsonResult.NOT_LOGIN);
                ctx.setResponseBody(JsonResult.err()
                        .code(JsonResult.NOT_LOGIN)
                        .msg("not login")
                        .toString());
            }
    
    
            return null;
        }
    }
    
    

    集成Ribbon

    zuul + ribbon 负载均衡

    zuul 已经集成了 ribbon,默认已经实现了负载均衡

    zuul + ribbon 重试

    pom.xml 添加 spring-retry 依赖

    • 需要 spring-retry 依赖
    <dependency>
    	<groupId>org.springframework.retry</groupId>
    	<artifactId>spring-retry</artifactId>
    </dependency>
    1234
    

    配置 zuul 开启重试,并配置 ribbon 重试参数

    • 需要开启重试,默认不开启
    spring:
      application:
        name: zuul
        
    server:
      port: 3001
      
    eureka:
      client:
        service-url:
          defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
    
    zuul:
      retryable: true
    
    #  routes:
    #    item-service: /item-service/**
    #    user-service: /user-service/**
    #    order-service: /order-service/**
        
    ribbon:
      ConnectTimeout: 1000
      ReadTimeout: 1000
      MaxAutoRetriesNextServer: 1
      MaxAutoRetries: 1
    

    集成Hystrix

    默认已经启用了hystrix,不用做任何基础配置

    降级代码:

    实现 FallbackProvider 接口,按接口规则来实现降级代码,在实现类上添加 @Component 注解

    zuul + hystrix 降级

    创建降级类

    • getRoute() 方法中指定应用此降级类的服务id,**号或null值可以通配所有服务

    ItemFallBack

    package cn.tedu.sp11.fallback;
    
    import cn.tedu.web.util.JsonResult;
    import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.client.ClientHttpResponse;
    import org.springframework.stereotype.Component;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    @Component
    public class ItemFallBack implements FallbackProvider {
        /*
        返回一个servicid 表示针对哪个服务使用当前的降级类
        返回* 或者 null 值 ,表示对所有服务执行当前降级类
         */
        @Override
        public String getRoute() {
            return "item-service";
        }
        /*
        封装降级响应的对象
         */
        @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  HttpStatus.OK.value();
                }
    
                @Override
                public String getStatusText() throws IOException {
                    return  HttpStatus.OK.getReasonPhrase();
                }
    
                @Override
                public void close() {
    
                }
    
                @Override
                public InputStream getBody() throws IOException {
                    String josn = JsonResult.err().msg("调用远程商品服务失败").toString();
                    ByteArrayInputStream inputStream = new ByteArrayInputStream(josn.getBytes("UTF-8"));
    
    
                    return inputStream;
                }
    
                @Override
                public HttpHeaders getHeaders() {
                    //Content-Type:application/json
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);
    
                    return headers;
                }
            };
        }
    }
    
    

    OrderFallBack

    package cn.tedu.sp11.fallback;
    
    import cn.tedu.web.util.JsonResult;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.client.ClientHttpResponse;
    import org.springframework.stereotype.Component;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    @Component
    @Slf4j
    public class OrderFallBack implements FallbackProvider {
        @Override
        public String getRoute() {
            return "order-service"; //"*"; //null;
        }
    
        @Override
        public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
            return response();
        }
    
        private ClientHttpResponse response() {
            return new ClientHttpResponse() {
                @Override
                public HttpStatus getStatusCode() throws IOException {
                    return HttpStatus.OK;
                }
                @Override
                public int getRawStatusCode() throws IOException {
                    return HttpStatus.OK.value();
                }
                @Override
                public String getStatusText() throws IOException {
                    return HttpStatus.OK.getReasonPhrase();
                }
    
                @Override
                public void close() {
                }
    
                @Override
                public InputStream getBody() throws IOException {
                    log.info("fallback body");
                    String s = JsonResult.err().msg("后台服务错误").toString();
                    return new ByteArrayInputStream(s.getBytes("UTF-8"));
                }
    
                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);
                    return headers;
                }
            };
        }
    }
    
    

    降低 hystrix 超时时间

    在application.yml文件中添加超时配置

    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 500
    

    启动服务,测试降级

    http://localhost:3001/item-service/35

    zuul + hystrix 数据监控

    暴露 hystrix.stream 监控端点

    • zuul 已经包含 actuator 依赖
    management:
      endpoints:
        web:
          exposure:
            include: hystrix.stream
    

    测试

    开启监控

    启动 sp08-hystrix-dashboard,填入 zuul 的监控端点路径,开启监控

    http://localhost:4001/hystrix

    填入监控端点:
    http://localhost:3001/actuator/hystrix.stream

    监控

    必须通过zuul网关访问后台服务才会生成监控数据

    zuul + turbine 聚合监控

    修改 turbine 项目,聚合 zuul 服务实例

    添加zuul服务

    在turbine的application.yml配置文件中配置

    spring:
      application:
        name: turbin
        
    server:
      port: 5001
      
    eureka:
      client:
        service-url:
          defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
          
    turbine:
      app-config: order-service, zuul
      cluster-name-expression: new String("default")
    
    

    使用hystrix仪表盘, 对 turbine 监控端点进行监控, 此端点聚合了订单服务和zull网关服务的监控数据
    http://localhost:5001/turbine.stream

    监控

    熔断测试

    ab -n 20000 -c 50 http://localhost:3001/order-service/123abc
    

    熔断

    zuul和feign的比较

    • 都能做远程调用,都可以集成ribbon 和 hystrix
    • zuul 在最前面使用,做统一调用入口,而feign用在服务之间
    • zuul不推荐开启重试,feign不推荐开启hystrix(会造成程序的混乱)
  • 相关阅读:
    关于selenium无法在chrome中自动播放flash的问题
    网鼎杯题目“phone”--十六进制mysql注入
    (转)宽字节编码类型的XSS
    为什么在留言处插入<script>alert(1)</script>不弹框
    同源策略和跨域的理解
    (转)调皮的location.href
    (转)GET来的漏洞
    WEB应用安全设计思想.pdf
    Browser Security-超文本标记语言(HTML)
    大家来聊聊如何PASS 360
  • 原文地址:https://www.cnblogs.com/liqbk/p/13598598.html
Copyright © 2011-2022 走看看