spring cloud笔记

来源:互联网 发布:转视频格式的软件 编辑:程序博客网 时间:2024/06/05 15:53

本文出自于EumJi的个人笔记,仅限于学习用途的转载,转载请注明出处 http://www.eumji025.com/article/details/253271

zuul介绍

Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security. It also has the ability to route requests to multiple Amazon Auto Scaling Groups as appropriate.

译:zuul是从设备和网站发起请求到netflix流应用的前置条件,作为边缘服务应用程序,Zuul旨在实现动态路由,监控,弹性和安全性。它还可以根据需要将请求路由到多个Amazon Auto Scaling Groups。

zuul的作用

Netflix API流量的数量和多样性有时会导致生产问题迅速而且没有警告。我们需要一个允许我们快速改变行为以便对这些情况作出反应的系统。

Zuul使用一系列不同类型的过滤器,使我们能够快速灵活地将功能应用于我们的边缘服务。这些过滤器可帮助我们执行以下功能:

  • 身份验证和安全 - 识别每个资源的身份验证要求,并拒绝不满足他们的请求。

  • 洞察和监测 - 跟踪边缘的有意义的数据和统计数据,以便我们准确地了解生产情况。

  • 动态路由 - 根据需要将请求动态路由到不同的后端集群。

  • 压力测试 - 逐渐增加到集群的流量,以衡量性能。

  • 负载分配 - 为每种类型的请求分配容量并删除超出限制的请求。

  • 静态响应处理 - 直接在边缘构建一些响应,而不是将它们转发到内部集群

  • 多区域弹性 - 跨AWS地区的路由请求,以使我们的ELB使用多样化,并使我们的边缘更接近我们的成员

zuul 路由使用

路由是微服务体系结构的一个组成部分。例如,/ 可以映射到您的Web应用程序,/v1/users/**映射到用户服务模块并将/v1/shop/**映射到商店服务模块。Zuul是Netflix的基于JVM的路由器和服务器端负载均衡器。并且zuul的路由可以和feign实现服务的动态映射,下面将简单介绍两种方式路由功能

路由的简单案例

本节使用到的案例需要使用到前面的 discovery-eureka-client和discovery-eureka-server
并在我们的eureka-client模块中添加被代理转发过来的测试controller

@RestControllerpublic class ProxyController {    /**     * zuul proxy first demo     * @return     */    @RequestMapping("/proxy/add")    public String addUser(){        return "add user success,  this proxy by zuul";    }    /**     * zuul proxy by serviceId     * @return     */   @RequestMapping("/add")    public String serviceIdTest(){        return "add user success,  this proxy by zuul serviceId,this pre has be ignore";    }}

zuul 路由配置

pom.xml

使用zuul组件需要在pom文件中添加spring-cloud-starter-zuul的依赖.

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

application.java

引入依赖之后在application入口类中加入 @EnableZuulProxy 注解,@EnableZuulProxy注解包括了@EnableCircuitBreaker和@EnableDiscoveryClient,如果我们不引用euraka-server的话执行中中会报错,当然他并不影响程序的效果展示.下面展示一下EnableZuulProxy的代码.application中只需要加入@EnableZuulProxy注解即可.

@EnableCircuitBreaker@EnableDiscoveryClient@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Import({ZuulProxyConfiguration.class})public @interface EnableZuulProxy {}

application.yml

在配置文件中我们需要配置路由的转发路径.

zuul:  routes:    users: /users/**ribbon:  eureka:    enabled: falseserver:  port: 8085

由于配置会忽略前缀的进行转发,上述的配置会将 http://localhost:8085/users/add 转发成http://localhost:8085/add
这是非常需要注意的一点,不然会导致404错误.

当然前面的配置太过于简陋,如果我们需要更细力度的控制我们可以如下配置

zuul:  routes:    users:      path: /users/**      url: http://localhost:8080/proxy/

上述配置就会将http://localhost:8085/users/ ** 的请求转发到 http://localhost:8080/proxy/ **

测试结果

首先我们依次启动eureka-server,eureka-client,zuul-proxy服务,
然后我们访问http://localhost:8085/users/add 可以看到如下图结果

使用feign负载均衡进行路由

前面我们直接使用url进行转发这种方式不够优雅,当我们某个服务挂掉的时候,那么转发过去就肯定会报错,所以我们需要借助我们前面使用过feign做负载均衡,我们不直接读客户端进行操作,而通过eureka server进行服务发现,这样更为灵活的进行路由功能,下面我们讲解一下如何 配置.
pom的依赖和前一个例子一样,引入spring-cloud-starter-zuulspring-cloud-starter-eureka
然后需要配置负载均衡的restTemplate.

@SpringBootApplication@EnableZuulProxypublic class SprincCloudNetflixZuulProxy2Application {    @Bean    @LoadBalanced    RestTemplate restTemplate(){        return new RestTemplate();    }    public static void main(String[] args) {        SpringApplication.run(SprincCloudNetflixZuulProxy2Application.class, args);    }}

然后需要在配置文件中声明eureka的server url以及指明serviceId,serviceId就对应feign客户端的名称.

zuul:  routes:    users:      path: /users/**      serviceId: eureka-client      #stripPrefix: falseeureka:  client:    serviceUrl:     defaultZone: http://localhost:8761/eureka/server:  port: 8085

这种配配置还是会忽略请求的前缀,如http://localhost:8085/users/add 会转发到最终的http://localhost:8080/add
这一点需要注意.
如果我们不希望前缀被取消掉,需要在后面追加 stripPrefix: false

zuul fallback

作者尝试了很久,可是并不能发生fallback事件,有待学习

更新

zuul中如果想使用fallback需要实现ZuulFallbackProvider接口并注册bean

public class MyFallbackProvider implements ZuulFallbackProvider {    //对应serviceID    @Override    public String getRoute() {        return "customers";    }    //response的内容    @Override    public ClientHttpResponse fallbackResponse() {        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 "zuul custom fallback status text"; //自定义的响应结果            }            @Override            public void close() {            }            @Override            public InputStream getBody() throws IOException {                return  new ByteArrayInputStream(getStatusText().getBytes());            }            @Override            public HttpHeaders getHeaders() {                HttpHeaders headers = new HttpHeaders();                headers.setContentType(MediaType.APPLICATION_JSON);                return headers;            }        };    }}

当zuul转发请求时,服务器发生错误时,就会返回MyFallbackProvider 对象,上面的状态是代表当前MyFallbackProvider 状态和响应值等信息.MyFallbackProvider 需要被注册哦,默认是没有被注册的,我们可以使用如下方式注册:

    @Bean    public MyFallbackProvider myFallbackProvider(){        return new MyFallbackProvider();    }

测试:
依次启动eureka-server,eureka-client1(一个就可以了,另外一个没有配置对应的controller),zuul-proxy2.
然后我们请求http://localhost:8085/customers/add?token=success_token地址,
由于我们的服务中是没有对应的控制器的,所以请求将会被zuul中MyFallbackProvider进行fallback处理.
这里写图片描述

zuul 过滤器

我们可以通过zuul的过滤器对我们所要路由的请求进行过滤,就和我们spring mvc中interceptor有着相同的功能.
原文如下

A Filter’s type is a String which can be any value that you desire. There are 2 uses for this:

2.Zuul’s primary request lifecycle consists of “pre”, “routing”, and “post” phases, in that order. All filters with these types are run for every request.

1.Filters of any type can be explicitly run using the method GroovyProcessor.runFilters(String type)

从zuul的wiki中我们可以看出我们通过filter可以进行pre,routing,post的拦截操作,我们演示一个事前拦截token的demo

zuul filter demo

application中添加filter的bean

@Bean    public CustomZuulFilter customZuulFilter(){        return new CustomZuulFilter();    }

filter的实现类

public class CustomZuulFilter extends ZuulFilter {    private Logger logger = LoggerFactory.getLogger(this.getClass());    /**     * 过滤器类型     * pre 事前     * routing 路由请求时候调用     * error 发生错误时候调用     * @return     */    @Override    public String filterType() {        return "pre" ;    }    @Override    public int filterOrder() {        return 1;    }    /**     * 是否过来     * 0 不过滤     * 1 过滤     * @return     */    @Override    public boolean shouldFilter() {        return true;    }    /**     * 拦截的具体操作     * 验证token     * @return     */    @Override    public Object run() {        RequestContext ctx = RequestContext.getCurrentContext();        HttpServletRequest request = ctx.getRequest();        logger.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));        String token = request.getParameter("token");        logger.info("token:"+token);        if (!token.equals("success_token")){            //认证失败            logger.error("token验证失败");            HttpServletResponse response = ctx.getResponse();            response.setCharacterEncoding("utf-8");  //设置字符集            response.setContentType("text/html; charset=utf-8"); //设置相应格式            response.setStatus(401);            ctx.setSendZuulResponse(false); //不进行路由            try {                response.getWriter().write("token 验证失败"); //响应体            } catch (IOException e) {                loger.error("response io异常")                e.printStackTrace();            }            ctx.setResponse(response);            return null;        }        logger.info("token验证成功");        return null;    }}

然后我们重新开启zuul proxy的服务,首先输入http://localhost:8085/users/add
将会被filter拦截由于没有filter所以会被拦截在浏览器中显示

token验证失败

当我们在浏览器地址中输入http://localhost:8085/users/add?token=success_token

此时会验证通过,请求会通过被转发到正确的地址.

结语

本文简单的介绍了zuul的路由和过滤的过程,可以通过直接通过url进行路由转发也可以通过feign进行负载均衡的转发,后面还介绍了使用过滤器进行路由条件控制.
在新版的cloud中还添加了fallback功能,只是自己实验多次也未能成功.

与君共勉

参考资料

spring-cloud文档
zuul filter wiki

源码地址

zuul基础路由

zuul-feign路由

0 0
原创粉丝点击