上一篇已经讲了微服务组件中的 分布式配置中心,本章讲述 由JAVA编写的服务路由网关Zuul
…
- Zuul
路由是微服务体系结构的一个组成部分。例如 /
可以映射到您的Web应用程序,/api/users映射到用户服务,/api/shop映射到商店服务。Zuul是Netflix的基于JVM的开发的路由和服务器端负载均衡器。
为什么需要服务网关?
如果没有服务网关,多个服务提供给前端调用地址管理错综复杂,增加了客户端的复杂性,认证也相对麻烦,每个服务都需要编写相同的认证….
Zuul架构图
画图工具:https://www.processon.com/
Zuul 可以做什么?
- 身份认证
- 审查与监控
- 压力测试
- 金丝雀测试
- 动态路由
- 服务迁移
- 负载分配
- 安全
- 静态响应处理
- 主动/主动流量管理
Zuul的规则引擎允许基本上写任何JVM语言的规则和过滤器,内置Java和Groovy的支持。
注意:配置属性 zuul.max.host.connections
已被取代的两个新的属性,zuul.host.maxTotalConnections
并且zuul.host.maxPerRouteConnections
它的缺省值分别200和20。
注意:所有路线的默认Hystrix隔离模式(ExecutionIsolationStrategy)为SEMAPHORE
。zuul.ribbonIsolationStrategy
如果此隔离模式是首选,可以更改为THREAD
。
官方文档:http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#_router_and_filter_zuul
- 准备工作
1.启动Consul
2.创建 battcn-gateway-service
和 battcn-hello-service
- battcn-gateway-service
1.在项目 pom.xml 中添加 ZUUL 依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
|
2.App.java中开启 zuul 代理
1 2 3 4 5 6 7 8 9
|
@EnableZuulProxy @EnableDiscoveryClient @SpringBootApplication public class ZuulApplication {
public static void main(String[] args) { SpringApplication.run(ZuulApplication.class, args); } }
|
3.zuul.routes.routesName.ZuulProperties.ZuulRoute
配置的方式,详细可以参考源码org.springframework.cloud.netflix.zuul.filters.ZuulProperties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
server: port: 9000
zuul: routes: hello-service: #自定义的 路由名称 path: /api-hello/** #路由路径 serviceId: battcn-hello-service #VIP 模式中的 serviceId
spring: application: name: battcn-gateway-service cloud: consul: host: localhost port: 8500 enabled: true discovery: enabled: true prefer-ip-address: true
|
- battcn-hello-service
hello-service 只需要以下依赖,能注册到consul中就行(单纯的一个服务)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
|
1 2 3 4 5 6 7 8
|
@EnableDiscoveryClient @SpringBootApplication public class HelloApplication {
public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
server: port: 9001
spring: application: name: battcn-hello-service cloud: consul: host: localhost port: 8500 enabled: true discovery: enabled: true prefer-ip-address: true
|
- 测试一把
访问:http://localhost:9000/api-hello/hello 从地址中可以看出我们访问的是 battcn-gateway-service
,且满足 zuul.routes.routesName.path
规则,因此实际请求地址是http://localhost:9001/hello
1
|
hello:battcn-hello-service #表示请求成功
|
- 自定义过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/** * 网关认证过滤器(Demo演示,实际根据自身业务考虑实现) * @author Levin * @date 2017-08-14. */ @Component public class GatewayZuulFilter extends ZuulFilter {
/** * per:路由之前,如实现认证、记录调试信息等 * routing:路由时 * post:路由后,比如添加HTTP Header * error:发生错误时调用 */ @Override public String filterType() { return "pre"; }
/** * 过滤器顺序,类似@Filter中的order */ @Override public int filterOrder() { return 0; }
/** * 这里可以写逻辑判断,是否要过滤,本文true,永远过滤。 */ @Override public boolean shouldFilter() { return true; }
/** * 过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。 */ @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); String token = request.getParameter("token"); if(token == null) { ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(404); ctx.setResponseBody("token cannot be empty"); } return null; } }
|
实际开发中token
应该从请求头中获取,该处只是为了方便演示效果
访问:http://localhost:9000/api-hello/hello?token=1
1
|
hello:battcn-hello-service
|
访问:http://localhost:9000/api-hello/hello
- 路由映射流程
图不是很严谨,凑合着看看吧…
HanderMapping
初次启动项目我们可以看到
1 2 3 4
|
2017-08-14 17:19:06.090 INFO 11544 --- [nio-9000-exec-1] o.s.c.n.zuul.web.ZuulHandlerMapping : Mapped URL path [/api-hello/**] onto handler of type [class org.springframework.cloud.netflix.zuul.web.ZuulController] 2017-08-14 17:19:06.090 INFO 11544 --- [nio-9000-exec-1] o.s.c.n.zuul.web.ZuulHandlerMapping : Mapped URL path [/battcn-gateway-service/**] onto handler of type [class org.springframework.cloud.netflix.zuul.web.ZuulController] 2017-08-14 17:19:06.090 INFO 11544 --- [nio-9000-exec-1] o.s.c.n.zuul.web.ZuulHandlerMapping : Mapped URL path [/battcn-hello-service/**] onto handler of type [class org.springframework.cloud.netflix.zuul.web.ZuulController] 2017-08-14 17:19:06.090 INFO 11544 --- [nio-9000-exec-1] o.s.c.n.zuul.web.ZuulHandlerMapping : Mapped URL path [/consul/**] onto handler of type [class org.springframework.cloud.netflix.zuul.web.ZuulController]
|
有兴趣的还可以阅读下 com.netflix.loadbalancer.LoadBalancerContext
,通过它可以发现每次请求的IP和端口,需要在application.yml
中配置
1 2 3
|
logging: level: com.netflix: DEBUG
|
1 2 3 4 5 6
|
2017-08-14 17:32:16.793 DEBUG 14316 --- [nio-9000-exec-7] c.n.zuul.http.HttpServletRequestWrapper : Path = null 2017-08-14 17:32:16.793 DEBUG 14316 --- [nio-9000-exec-7] c.n.zuul.http.HttpServletRequestWrapper : Transfer-Encoding = null 2017-08-14 17:32:16.793 DEBUG 14316 --- [nio-9000-exec-7] c.n.zuul.http.HttpServletRequestWrapper : Content-Encoding = null 2017-08-14 17:32:16.793 DEBUG 14316 --- [nio-9000-exec-7] c.n.zuul.http.HttpServletRequestWrapper : Content-Length header = -1 2017-08-14 17:32:16.793 DEBUG 14316 --- [nio-9000-exec-7] c.n.loadbalancer.ZoneAwareLoadBalancer : Zone aware logic disabled or there is only one zone 2017-08-14 17:32:16.793 DEBUG 14316 --- [nio-9000-exec-7] c.n.loadbalancer.LoadBalancerContext : battcn-hello-service using LB returned Server: 192.168.31.221:9001 for request /hello
|
- Zuul Fallback
定义GatewayZuulFallback
实现 ZuulFallbackProvider
接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
/** * @author Levin * @date 2017-08-14. */ @Component public class GatewayZuulFallback implements ZuulFallbackProvider { @Override public String getRoute() { return "battcn-hello-service";//指定回退的服务名 }
@Override public ClientHttpResponse fallbackResponse() { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.INTERNAL_SERVER_ERROR; //INTERNAL_SERVER_ERROR(500, "Internal Server Error") }
@Override public int getRawStatusCode() throws IOException { return this.getStatusCode().value();// 500 }
@Override public String getStatusText() throws IOException { return this.getStatusCode().getReasonPhrase();// Internal Server Error }
@Override public void close() {}
@Override public InputStream getBody() throws IOException { return new ByteArrayInputStream(getStatusText().getBytes());//也可以随意写自己想返回的内容 }
@Override public HttpHeaders getHeaders() { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); return httpHeaders; } }; } }
|
步骤:停掉 battcn-hello-service
启动 battcn-gateway-service
访问:http://localhost:9000/api-hello/hello?token=1
显示:
1
|
Internal Server Error # 代表Fallback成功
|
- 路由配置详解
zuul 相关的官方文档还是比较其全了,本文也是参考官方然后简单讲述应用场景,具体开发请结合自身业务扩展….
1.自定义指定微服务路径,以下两种配置方式结果相同
1 2 3 4 5 6 7 8 9
|
zuul: routes: battcn-hello-service: /api-hello/** #两种配置方式结果相同 zuul: routes: hello-service: path: /api-hello/** serviceId: battcn-hello-service
|
2.忽略指定服务,多个服务逗号分隔,Set<String> ignoredServices
这样一来zuul就会忽略service1和service2,只会代理其它的
1 2
|
zuul: ignored-services: battcn-hello-service1,battcn-hello-service2
|
3.指定Path和Url
1 2 3 4 5
|
zuul: routes: hello-service: path: /api-hello/** #路由路径 url: http://localhost:9001/ #指定URL地址
|
4.使用Zuul但不指定Url(该方式在Eureka有效,Consul还未找到解决方法…)
1 2 3 4 5 6 7 8 9
|
zuul: routes: battcn-hello-service: /api-hello/** ribbon: eureka: enabled: false #为Ribbon禁用 eureka,不会破坏Zuul的Hystrix和Ribbon特性 battcn-hello-service: ribbon: listOfServers: localhost:9001,localhost:9002
|
- 玩转SpringCloud(F版本) 四.路由网关(zuul)
本篇文章基于: 01)玩转SpringCloud 一.服务的注册与发现(Eureka) 02) 玩转SpringCloud 二.服务消费者(1)ribbon+restTemplate 03) 玩转Sp ...
- 白话SpringCloud | 第十一章:路由网关(Zuul):利用swagger2聚合API文档
前言 通过之前的两篇文章,可以简单的搭建一个路由网关了.而我们知道,现在都奉行前后端分离开发,前后端开发的沟通成本就增加了,所以一般上我们都是通过swagger进行api文档生成的.现在由于使用了统一 ...
- 白话SpringCloud | 第十章:路由网关(Zuul)进阶:过滤器、异常处理
前言 简单介绍了关于Zuul的一些简单使用以及一些路由规则的简单说明.而对于一个统一网关而言,需要处理各种各类的请求,对不同的url进行拦截,或者对调用服务的异常进行二次处理等等.今天,我们就来了解下 ...
- SpringCloud学习系列之六 ----- 路由网关Zuul基础使用教程
前言 在上篇中介绍了SpringCloud Config的完美使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由网关 ...
- 白话SpringCloud | 第九章:路由网关(Zuul)的使用
前言 介绍完分布式配置中心,结合前面的文章.我们已经有了一个微服务的框架了,可以对外提供api接口服务了.但现在试想一下,在微服务框架中,每个对外服务都是独立部署的,对外的api或者服务地址都不是不尽 ...
- springCloud之路API路由网关Zuul
1.简介 简单的理解就是,相当于在所有服务的调用前加了一层防火墙, 主要就是对外提供服务接口的时候,起到了请求的路由和过滤作用,也因此能够隐藏内部服务的接口细节,提高系统的安全性: 官方文档:http ...
- 微服务之路由网关—zuul
Zuul 简介Zuul 是 Netflix 公司开发的一个开源 APIGateway,其本质上是一个 WebServlet 应用.Zuul 的核心是一系列的 Filter. 为什么要使用 Zuul微服 ...
- SpringCloud教程 | 第五篇: 路由网关(zuul)(Finchley版本)
在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: ...
- spring cloud 路由网关zuul基本使用
在微服务架构中,需要几个关键的组件,服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个组件可以组建一个简单的微服务架构.客户端的请求首先经过负载均衡(zuul.Ngnix),再 ...
- 史上最简单的SpringCloud教程 | 第五篇: 路由网关(zuul)
在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: ...
随机推荐
- java实现古堡算式
** 古堡算式** 福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式: ABCDE * ? = EDCBA 他对华生说:"ABCDE应该代表不同的数字,问号也代表某个数字!" 华生 ...
- 卷积生成对抗网络(DCGAN)---生成手写数字
深度卷积生成对抗网络(DCGAN) ---- 生成 MNIST 手写图片 1.基本原理 生成对抗网络(GAN)由2个重要的部分构成: 生成器(Generator):通过机器生成数据(大部分情况下是图像 ...
- mysql基础-数据库初始化操作必要步骤和客户端工具使用-记录(二)
0x01 mysql启动时,读取配置文件的顺序 Default options are read from the following files in the given order:/etc/my ...
- 华为EMUI在service中不能打印debug级别的日志
华为emui在service里面不能打印debug级别的日志,因为这个小问题调试了一上午,刚开始我还以为emui把系统service的启动流程都改了呢
- 【百度前端技术学院 Day7/8】布局
1. 定位 1.1 文档流 单个元素: 块级元素:内容宽度是其父元素的宽度的100%,并且与其内容一样高. 内联(行内)元素:高宽与他们的内容高宽一样.(所以不能为他们设置宽高) 元素之间的交互: 块 ...
- Java线程池简聊
在Java中,已经实现了4中内置的线程池,这四种我不多聊. 大家各种网站论坛都能查得到. 现在说一下这四种线程池的基类: ThreadPoolExecutor在ThreadPoolExecutor中你 ...
- loadrunner安装负载机
1,安装docker 2,下载最新版本的load_generator镜像,命令如下: docker pull hpsoftware/load_generator 3,load_generator镜像实 ...
- mysql explain的extra
导读 extra主要有是那种情况:Using index.Using filesort.Using temporary.Using where Using where无需多说,就是使用了where筛选 ...
- ESP8266局域网 路由器下作服务器模式串口透传 arduino uno示例 模板参考2
ESP8266服务器模式串口透传编译需要下载8266的库文件后才可以正常 准备工作 下载一个Arduino IDE,下载8266的库文件ESP8266服务器模式串口透传编译 功能说明 1.直接使用路由 ...
- CKA考试个人心得分享
考试相关准备: 真题:需要的私密: 网络:必须开启VPN,以便能访问国外网络,强烈建议在香港搭建相应FQ: 证件:考试需要出示含有拉丁文(英文)带照片的有效证件,相关有效证件参考(优先建议护照):ht ...