Zuul包含了对请求的路由和过滤两个最主要的功能:
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础.
Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。
注意:Zuul服务最终还是会注册进Eureka
项目加入依赖:
<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>
因为上文说过Zuul最终会注册进eureka 所以我们这里也依赖了eureka
YML
server:
port: 9000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:3000/eureka/
instance:
instance-id: zuul-1
prefer-ip-address: true
spring:
application:
name: zuul
启动类:
@SpringBootApplication
@EnableZuulProxy
public class AppZuul {
public static void main(String[] args) {
SpringApplication.run(AppZuul.class);
}
}
这样 简单的zuul就搭建好了, 启动项目 我们就可以通过zuul然后加上对应的微服务名字访问微服务:
看看eureka上面的微服务名称
调用:
到这里 一个简单的zuul已经搭建好了
在实际开发当中我们肯定不会是这样通过微服务调用,比如我要调用power 可能只要一个/power就好了 而不是/server-power
在yml加入以下配置即可:
zuul:
routes:
mypower:
serviceId: server-power
path: /power/**
myorder:
serviceId: server-order
path: /order/**
讲道理看意思都看得出来把,my***是自己制定的名字 这个就不解释了
注意/ **代表是所有层级 / * 是代表一层。 如果是/ * 的话 /power/admin/getUser.do 就不会被路由 。
来看效果:
这时候我们能通过我们自定义的规则来访问了,但是还有一个问题,就是我们现在依然能用之前的微服务名调用,这样子是不合理的,第一是有多重地址了, 第二,一般微服务名这种最好不要暴露在外。所以我们一般会禁用微服务名方式调用。
加入配置:
ignored-services: server-power
这里咱们先禁用power的看看:
这里能发现我们不能通过微服务名来调用了, 不过这个配置
如果一个一个通过微服务名来配置难免有点复杂,所以一般这样配置来禁用所有:
ignored-services: "*"
可能有时候我们的接口调用需要一定的规范,譬如调用微服务的API URL前缀需要加上/api 对于这种情况, zuul也考虑到了并给出了解决方案:
zuul:
prefix: /api
ignored-services: "*"
routes:
mypower:
serviceId: server-power
path: /power/**
myorder:
serviceId: server-order
path: /order/**
加上一个prefix 即定义好了一个前缀, 那么我们每次需要路由的时候需要加上一个/api的前缀
但是 这样有一个问题,就是这个/api前缀 会不会出现在我们路由后的IP地址中呢?因为有可能我们微服务提供的接口也是含有/api前缀的
答案是不会的。 但是可以进行配置
zuul:
prefix: /api
strip-prefix: false
ignored-services: "*"
routes:
mypower:
serviceId: server-power
path: /power/**
myorder:
serviceId: server-order
path: /order/**
过滤器(filter)是zuul的核心组件 zuul大部分功能都是通过过滤器来实现的。 zuul中定义了4种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。 PRE:这种过滤器在请求被路由之前调用。可利用这种过滤器实现身份验证、在 集群中选择请求的微服务、记录调试信息等。 ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服 务的请求,并使用 Apache HttpCIient或 Netfilx Ribbon请求微服务 POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准 的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。 ERROR:在其他阶段发生错误时执行该过滤器。
如果要编写一个过滤器,则需继承ZuulFilter类 实现其中方法:
@Component
public class LogFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.ROUTE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
String remoteAddr = request.getRemoteAddr();
System.out.println("访问者IP:"+remoteAddr+"访问地址:"+request.getRequestURI());
return null;
}
}
由代码可知,自定义的 zuul Filter需实现以下几个方法。
filterType:返回过滤器的类型。有 pre、 route、 post、 error等几种取值,分别对应上文的几种过滤器。
详细可以参考 com.netflix.zuul.ZuulFilter.filterType()中的注释。
filter0rder:返回一个 int值来指定过滤器的执行顺序,不同的过滤器允许返回相同的数字。
shouldFilter:返回一个 boolean值来判断该过滤器是否要执行, true表示执行, false表示不执行。
run:过滤器的具体逻辑。
禁用zuul过滤器 Spring Cloud默认为Zuul编写并启用了一些过滤器,例如DebugFilter、 FormBodyWrapperFilter等,这些过滤器都存放在spring-cloud-netflix-core这个jar包 里,一些场景下,想要禁用掉部分过滤器,该怎么办呢? 只需在application.yml里设置zuul…disable=true 例如,要禁用上面我们写的过滤器,这样配置就行了: zuul.LogFilter.pre.disable=true
zuul默认是整合了hystrix和ribbon的, 提供降级回退,那如何来使用hystrix呢?
我们自行写一个类,继承FallbackProvider 类 然后重写里面的方法
@Override
public String getRoute() {
return null;
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return null;
}
这里 会发现有这2个方法需要重写, 那么如何来写呢? 我们可以查阅官方文档:
这是官方提供的demo
代码:
class MyFallbackProvider implements FallbackProvider {
@Override
public String getRoute() {
//制定为哪个微服务提供回退(这里写微服务名 写*代表所有微服务)
return "*";
}
//此方法需要返回一个ClientHttpResponse对象 ClientHttpResponse是一个接口,具体的回退逻辑要实现此接口
//route:出错的微服务名 cause:出错的异常对象
@Override
public ClientHttpResponse fallbackResponse(String route, final Throwable cause) {
//这里可以判断根据不同的异常来做不同的处理, 也可以不判断
//完了之后调用response方法并根据异常类型传入HttpStatus
if (cause instanceof HystrixTimeoutException) {
return response(HttpStatus.GATEWAY_TIMEOUT);
} else {
return response(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
private ClientHttpResponse response(final HttpStatus status) {
//这里返回一个ClientHttpResponse对象 并实现其中的方法,关于回退逻辑的详细,便在下面的方法中
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
//返回一个HttpStatus对象 这个对象是个枚举对象, 里面包含了一个status code 和reasonPhrase信息
return status;
}
@Override
public int getRawStatusCode() throws IOException {
//返回status的code 比如 404,500等
return status.value();
}
@Override
public String getStatusText() throws IOException {
//返回一个HttpStatus对象的reasonPhrase信息
return status.getReasonPhrase();
}
@Override
public void close() {
//close的时候调用的方法, 讲白了就是当降级信息全部响应完了之后调用的方法
}
@Override
public InputStream getBody() throws IOException {
//吧降级信息响应回前端
return new ByteArrayInputStream("降级信息".getBytes());
}
@Override
public HttpHeaders getHeaders() {
//需要对响应报头设置的话可以在此设置
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
文章浏览阅读2.9k次,点赞2次,收藏3次。需求当在MySQL数据库之间进行数据迁移时(数据量不大时,且表字段名称不相同时),便可以采用生成SQL 插入语句,然后在新数据库上之间SQL语句便可以完成插入。(Navicat工具可以实现,此处不表演了)仅演示使用select语句查询出结果,然后生成insert SQL ,最后执行SQL。操作通过select方式生成insert into语句# 通过select 将结果拼接成新的insert into语句,用于迁移使用。# 参考链接:https://www.jianshu.com/p/0937_mysql select生成 insert语句
文章浏览阅读307次。题目描述一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。编程思想因为n级台阶,第一步有n种跳法:跳1级、跳2级、到跳n级跳1级,剩下n-1级,则剩下跳法是f(n-1)跳2级,剩下n-2级,则剩下跳法是f(n-2)所以f(n)=f(n-1)+f(n-2)+...+f(1)因为f(n-1)=f(n-2)..._关于链表的编程题一共10个台阶,青蛙每次跳一个或者两个台阶,正好跳够10个为准,然
文章浏览阅读1.1k次。Templates are great. They provide a useful starting point for projects and can cut out common setup and configuration work. We can also enhance them with tools that promote good habits and processes b..._create-react-app template 怎么制作
文章浏览阅读791次。js自定义上传文件按钮样式_自定义按钮触发文件上传—label
文章浏览阅读109次。节点访问的次序,忽略打印行为如果将打印安排在同个数字第一次被访问时,即先序遍历第二次即中序遍历第三次即后序遍历现二叉树的先序、中序、后序遍历,包括递归方式和非递归方式二叉树结构定义public static class Node { public int value..._二叉树常用算法
文章浏览阅读71次。istio(1):ServiceMesh解决方案-k8s安装istio_tack servicemesh status is failed
文章浏览阅读1.1w次。之前介绍了get请求不需要传递token的 也介绍了post请求,下面简介一下post请求需要token的方式。首先获取到之前创建的token接下来创建字典格式将请求头赋给变量header作为头文件2.创建session服务器连接,把请求数据传输方式和token传入3.post请求把URI和数据传入4.判断响应状态码是否为2005.将响应格式转换为json格式6.判_robotframework post请求加token
文章浏览阅读1k次。Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象。要求被传递的对象必须实现上述2种接口中的一种才能通过Intent直接传递。Intent中传递这2种对象的方法:Bundle.putSerializable(Key,Object); //实现Serializable接口的_intent object实例
文章浏览阅读1.4w次,点赞2次,收藏3次。pyhton的定时任务写法:#!/usr/bin/env python#-- encoding:utf-8 --import timedef task(): print "task ..."def timer(n): while True: print time.strftime('%Y-%m-%d %X',time.localtime_env.task(0, 1)
文章浏览阅读2.6k次。package com.taotao.common.utils;import java.util.Random;/** * 各种id生成策略 * Title: IDUtils * @date 2017年7月16日下午2:32:10 * @version 1.0 */public class IDUtils { /** * 图片名生成 */ public stati_idutils
文章浏览阅读238次。1 $('#defaultForm').bootstrapValidator({ 2 message: 'This value is not valid', 3 feedbackIcons: { 4 valid: 'glyphicon glyphicon..._bootstrapvalidator 自动提交
文章浏览阅读124次。查询条件动态生成报表、注册码、打印问题、模式使用示例、C#.Net的WinForm以及Asp.Net中的使用、程序发布与部署1、水晶报表注册码在使用Vs.net自带的水晶报表时,请注册,否则只能使用30次,水晶报表注册码如下:注册号:6707437608密码:AAP5GKS0000GDE100DS2、Asp.Net中使用水晶报表..._水晶报表 printlayoutsettings