微服务实战——Spring Cloud + Zuul Gateway + Eureka集成
上一篇简单说了springcloud与eureka的集成。主要解决了微服务间的服务注册及调用的问题。这一篇集成zuul,而后结合springcloud、eureka、zuul环境下进行真实系统联调,帮助更好的对这些组件的理解。毕竟,实战才是学习最快的方法。
一、聊聊网关
上篇也提到过,微服务下,各个业务模块都被拆分成相互独立的微服务。虽然注册中心(如eureka)解决了服务内部的注册发现、健康检查等问题。但是如何与外部服务进行通信又是一个新的问题了。
举个栗子
某初创公司,刚刚经历了一次大的架构改革。将原有的单体架构分解成了很多的微服务进行独立部署。这些微服务包括用户鉴权系统、订单系统、定时任务系统等等。而原有的jsp也被改造成基于html下的静态页面进行前后端分离部署。
那么问题来了,因为前后端是分开的,前端同学在调用后端不同服务时要定义各种不同的uri进行调用,管理起来太麻烦,而且,这种情况下一旦后端服务邮编,有需要重新对域名进行解析,这也侧面增加了运维同学的工作量。而更可怕的是这又与现在大家都在提倡的devops完全相悖了。
二、说了这么多我用nginx不就行了么
是的,用nginx的确是能帮助解决服务统一入口的问题。但是因为nginx比较偏运维性质,而且其路由配置全部都是基于配置文件的硬编码方式进行处理。一旦后台服务发生变化,配置也需要及时更改。这样也没有完全解决上述问题。
这时候,网关的出现让我看到了曙光。通过服务名就可以进行路由转发,熔断限流,日志监控,最主要的是可以开发人员自己通过配置就能轻松实现,不用每次都求运维人员去做解析。这样岂不是也是更符合devops了呢。
三、zuul
zuul简单介绍
zuul在英文中是怪兽的意思,寓意看门神兽。由大名鼎鼎的netflix开源。并被pivotal集成入spring cloud体系。当前流行的为1.x与2.x系列。主要区别为zuul从2.x系列开始采用非阻塞异步模式,大大提升了其性能。他是基于filter机制进行工作。有统一入口、健康检查、蓝绿部署、金丝雀发布、日志监控、路由转发等功能。也可集成ribbon、hystrix增加负载均衡、熔断的功能。
zuul架构
spring cloud zuul
实际开发中可以根据选择去集成zuul网关。也可直接选择spring集成好的spring cloud zuul方便更快的使用起来。本篇重点是集成spring cloud zuul。
关于spring cloud zuul与netflix zuul相比还是有些许不一样的。他是基于springboot + netflix zuul内核而成,去掉了原有的动态过滤器加载。所以生产环境中还是根据需要自己选择。
四、话不多说请看代码
老规矩,附上源码地址spingcloud+zuul+eureka
操作步骤
-
还是在原来的spring-cloud-demo(上一篇地址springcloud+eureka)项目上,右键创建一个新的model.具体步骤不再赘述。创建完成后项目结构如下:
-
引入zuul依赖
主要依赖如下:<!-- 引入zuul starter --> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-netflix-zuul</artifactid> </dependency> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter</artifactid> </dependency> <!-- 连接eureka --> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-netflix-eureka-client</artifactid> </dependency>
-
创建业务模块provider、consumer,方法跟上一步一样。创建后项目结构如下:
- 其中provider为服务提供者,提供基础服务的微服务
- consumer为服务的主要调用者。下一章会讲服务之间基于接口(feign)的调用
-
配置zuul路由转发以及ribbon、hystrix
spring.application.name = zuul-gateway logging.level.org.spring.framework.security = info #hystrix设置 时间要大于ribbon时间总和 hystrix.command.default.execution.isolation.thread.timeoutinmilliseconds = 90000 eureka.instance.instance-id = ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} eureka.client.serviceurl.defaultzone = http://localhost:8761/eureka/ #通过eureka发现的服务。使用ribbon ribbon.readtimeout = 20000 ribbon.connecttimeout = 20000 zuul.ignoredservices = '*' #设置不走ribbon的time-out时间 zuul.host.connect-timeout-millis = 20000 zuul.host.socket-timeout-millis = 20000 #只要访问以/api/开头的多层目录都可以路由到服务名为kxtop-provider的服务上. zuul.routes.kxtop-provider.path = /api/** zuul.routes.kxtop-provider.service-id= kxtop-provider zuul.routes.kxtop-provider.stripprefix = false #kxtop-consumer配置 zuul.routes.kxtop-consumer.path = /consumer/** zuul.routes.kxtop-consumer.service-id = kxtop-consumer zuul.routes.kxtop-consumer.stripprefix = false server.port = 4000 management.endpoints.web.exposure.include = *
-
创建zuul启动类
@enablediscoveryclient //作为eureka发现者 @enablezuulproxy //开启zuul @springbootapplication public class zuulgatewayapplication { public static void main(string[] args) { springapplication.run(zuulgatewayapplication.class); } }
-
分别配置provider、consumer配置文件及启动类
provider
spring.application.name = kxtop-provider server.port = 5000 eureka.instance.instance-id = ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}eureka.client.serviceurl.defaultzone = http://localhost:8761/eureka/ logging.level.org.spring.framework.security = info server.servlet.context-path = /api management.endpoints.web.exposure.include = * ------------------------- @enablediscoveryclient @springbootapplication public class providerapplication { public static void main(string[] args) { springapplication.run(providerapplication.class); } }
consumer
spring.application.name = kxtop-consumer server.port = 6000 eureka.instance.instance-id = ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}eureka.client.serviceurl.defaultzone = http://localhost:8761/eureka/ logging.level.org.spring.framework.security = info server.servlet.context-path = /consumer management.endpoints.web.exposure.include = * -------------------------- @enablediscoveryclient @springbootapplication public class consumerapplication { public static void main(string[] args) { springapplication.run(consumerapplication.class); } }
-
整体测试
- 启动eureka并浏览器打开
localhost:8761
- 分别启动项目zuul、provider、consumer
- 保证每个服务都正常运行
- 服务端口对照
服务名 端口号 zuul-gateway 4000 provider 5000 consumer 6000
- 刷新浏览器查看效果(可以看到,服务都已经注册成功且处于up状态)
- postman测试网关调用
-
provider模块新建testgatewaycontroller,并重启provider
@restcontroller @requestmapping("/test-gateway") public class testgatewaycontroller { @getmapping public string testgateway() { return "hi! 我是consumer服务中的testgatewaycontroller."; } }
-
访问localhost:4000/api/test-gateway
-
出现上面这句话,访问成功。请注意:我们访问的是localhost的4000 端口,也就是配置的zuul的端口哦,而输出【hi! 我是consumer服务中的testgatewaycontroller】这句话的方法则是在端口为5000的consumer模块中定义的。这就就证明我们以配置的网关和服务注册发现是正确的。当然你也可以做更多的测试。
- 启动eureka并浏览器打开
五、后续
下一篇会针对以上的整合做更加详细的配置,我们会基于zuulgateway去做更丰富测试(比如provider、consumer模块如果是部署集群网关该怎样处理?他们之间的负载均衡策略又是怎样的?连接超时、恶意访问怎样做熔断限流?服务之间如何调用?),进行接近生产级项目的配置。敬请关注!
持续学习,记录点滴。更多文章请访问
推荐阅读
-
微服务实战——Spring Cloud + Zuul Gateway + Eureka集成
-
spring cloud gateway集成hystrix实战篇
-
Spring Cloud实战 | 第六篇:Spring Cloud Gateway+Spring Security OAuth2+JWT实现微服务统一认证授权
-
Spring Cloud实战 | 最终篇:Spring Cloud Gateway+Spring Security OAuth2集成统一认证授权平台下实现注销使JWT失效方案
-
微服务实战——Spring Cloud + Zuul Gateway + Eureka集成
-
spring cloud gateway集成hystrix实战篇