路由是微服务架构中必须的一部分,好比,“/” 可能映射到你的WEB程序上,”/api/users
“可能映射到你的用户服务上,“/api/shop”可能映射到你的商品服务商。(注解:我理解这里的这几个映射就是说经过Zuul这个网关把服务映射到不一样的服务商去处理,从而变成了微服务!)java
这里只列举zuul一些配置,headers,client等等不作考虑。web
经过Zuul咱们能够完成如下功能:正则表达式
在Idea里,新建项目,选择Spring initializer.spring
下面的pomapi
<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>
</dependencies>
配置properties文件参数;浏览器
server.port=8887 spring.application.name=zuul-proxy eureka.client.service-url.defaultZone=http://localhost:8882/eureka
启动类以下:安全
@EnableZuulProxy // 启动Zuul的路由服务 @SpringBootApplication public class SpringCloundZuulDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringCloundZuulDemoApplication.class, args); } }
代码基本编写完成,下面咱们来启动项目;Eureka,service-hello(两个 + 一个实例),最后启动zuul-proxy;架构
浏览器输入:(可见,zuul也实现了负载均衡)app
可见,zuul-proxy已经帮咱们路由到相应的微服务。负载均衡
zuul.routes.service-hello = /hello/** zuul.routes.service-hello-2 = /hello2/**
所要配置的路径能够指定一个正则表达式来匹配路径,所以,/
hello/*
只能匹配一级路径,可是经过/hello/**
能够匹配全部以/hello/
开头的路径。
配置格式为: zuul.ignored-services=微服务Id1,微服务Id2...,多个微服务之间使用逗号分隔。
zuul.ignored-services = service-hello-2
可见,自定义路由依旧能够访问。
还有其余形式的路由配置,不在此一一列举。
spring-cloud-starter-zuul
自己已经集成了hystrix和ribbon,因此Zuul天生就拥有线程隔离和断路器的自我保护能力,以及对服务调用的客户端负载均衡功能。可是,咱们须要注意,当使用path与url的映射关系来配置路由规则时,对于路由转发的请求则不会采用HystrixCommand
来包装,因此这类路由请求就没有线程隔离和断路器保护功能,而且也不会有负载均衡的能力。所以,咱们在使用Zuul的时候尽可能使用path和serviceId的组合进行配置,这样不只能够保证API网关的健壮和稳定,也能用到Ribbon的客户端负载均衡功能。
咱们来看看zuul是否集成hystrix,在以前feign已经集成了hystrix,这里很少作说明。
请注意,Zuul的Hystrix监控的粒度是微服务,而不是某个API,也就是全部通过Zuul的请求都会被Hystrix保护起来。假如,咱们如今把service-hello-2服务关闭,再来访问会出现什么结果呢?结果可能不是咱们所想那样,以下:
那么如何为Zuul实现容错与回退呢?
Zuul提供了一个ZuulFallbackProvider(新版:
FallbackProvider)
接口,经过实现该接口就能够为Zuul实现回退功能。那么让咱们改造以前的Zuul-proxy
。
package com.example.zuul.fallback; 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; /** * @author sky.javaweb@qq.com * @version 1.0 * @date 2018-12-28 */ @Component public class ServiceFallbackProvider implements FallbackProvider { @Override public String getRoute() { // 代表是为哪一个微服务提供回退,*表示为全部微服务提供回退 return "*"; } @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((route + "服务暂不可用,请稍后重试!" + cause.getMessage()).getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON_UTF8); return headers; } }; } }
再打开service-hello-2服务接口