Spring Cloud微服务实战:手把手带你整合eureka&zuul&feign&hystrix(附源码)

Spring Cloud简介

Spring Cloud是一个基于Spring Boot实现的微服务架构开发工具。它为微服务架构中涉及的配置管理、服务治理、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种简单的开发方式。

Spring Cloud包含了多个子项目,比如Spring Cloud Config、Spring Cloud Netflix、Spring Cloud Bus、Spring Cloud Stream、Spring Cloud Zookeeper等等。

本文介绍基于Spring Boot 2.0.5版本,Spring Cloud Finchley.SR1版本的微服务搭建,包括eureka&zuul&feign&hystrix的整合。

最终项目结构

文末附源码地址。

服务注册发现模块

该模块对应本次搭建项目中的cloud-eureka,eureka作为服务发现注册中心首先搭建,因为后面的服务都要注册到上面。当然服务发现还可以用zookeeper、consul等等,最近阿里也启动了新的服务发现开源项目Nacos,各种服务注册发现中间件真是层出不穷。

首先使用idea生成多模块maven主工程,新建一个空白标准的maven project(不要选择Create from archetype选项)

在主工程上新建module,选择Spring Initializr

输入cloud-eureka服务注册中心模块信息

选择Cloud Discovery中的Eureka Server依赖

生成的pom文件部分配置:

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
复制代码

启动类,加上@EnableEurekaServer注解:

@SpringBootApplication
@EnableEurekaServer
public class CloudEurekaApplication {public static void main(String[] args) {SpringApplication.run(CloudEurekaApplication.class, args);}
}
复制代码

默认情况下服务注册中心会将自己作为客户端注册到Eureka Server,所以需要禁用它的客户端注册行为,配置文件application.properties添加如下配置:

#端口号.
server.port=8070
#关闭自我保护.
eureka.server.enable-self-preservation=false
#清理服务器时间间隔[5s]
eureka.server.eviction-interval-timer-in-ms=5000#主机名.
eureka.instance.hostname=localhost
#是否将自己作为客户端注册到Eureka Server[当前模块只是作为Eureka Server服务端所以设为false]
eureka.client.register-with-eureka=false
#是否从Eureka Server获取注册信息[当前是单点的Eureka Server所以不需要同步其它节点的数据]
eureka.client.fetch-registry=false#Eureka Server[查询注册服务]地址.
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
复制代码

启动工程访问:http://localhost/8070/ ,可看到如下界面,其中还没有服务实例

客服端模块(服务提供者)

该模块对应本次搭建项目中的cloud-provider,其作为服务提供者客户端在注册中心进行注册。搭建过程和cloud-eureka类似,在主工程上新建module并选择Spring Initializr即可,唯一区别是依赖选择Cloud Discovery中的Eureka Discovery:

pom文件依赖配置如下:

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
复制代码

启动类,加上@EnableDiscoveryClient,表示其作为服务发现客户端

@SpringBootApplication
@EnableDiscoveryClient
public class CloudProviderApplication {public static void main(String[] args) {SpringApplication.run(CloudProviderApplication.class, args);}
}
复制代码

application.properties添加如下配置:

#应用名称.
spring.application.name=cloud-provider
#应用端口号.
server.port=8080
#Eureka Server服务器地址.
eureka.client.serviceUrl.defaultZone=http://localhost:8070/eureka/
复制代码

通过spring.application.name指定微服务服务提供者的名称,后续使用该名称便可以访问该服务。
eureka.client.serviceUrl.defaultZone指定服务注册中心地址。

启动该工程,再次访问:http://localhost/8070/ , 可以看到出现了启动的CLOUD-PROVIDER服务:

定义MyController类,使用Rest风格请求,添加info方法如下:

@RestController
public class MyController {@RequestMapping(value = "/info", method = RequestMethod.GET)public String info() {try {//休眠2秒,测试超时服务熔断[直接关闭服务提供者亦可]Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return "Hello, cloud-provider";}
}
复制代码

访问:http://127.0.0.1:8080/info , 返回信息如下

声明式服务调用组件Feign及服务熔断组件Hystrix整合

新建服务消费者模块,该模块对应本次搭建项目中的cloud-consumer。同样,新建过程和上述模块类似,这里不再赘述。本模块将通过Feign组件调用上一个模块服务的info方法,并通过Hystrix实现服务调用失败时的服务熔断。

maven依赖配置:

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
复制代码

启动类,加上@EnableFeignClients和@EnableEurekaClient

@SpringBootApplication
@EnableFeignClients //调用者启动时,打开Feign开关
@EnableEurekaClient
public class CloudConsumerApplication {public static void main(String[] args) {SpringApplication.run(CloudConsumerApplication.class, args);}
}
复制代码

application.properties添加如下配置:

#应用名称.
spring.application.name=cloud-consumer
#端口号.
server.port=8081
#Eureka Server服务器地址.
eureka.client.serviceUrl.defaultZone=http://localhost:8070/eureka/#高版本spring-cloud-openfeign请求分为两层,先ribbon控制,后hystrix控制.
#ribbon请求处理的超时时间.
ribbon.ReadTimeout=5000
#ribbon请求连接的超时时间
ribbon.ConnectionTimeout=5000##设置服务熔断超时时间[默认1s]
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000#开启Hystrix以支持服务熔断[高版本默认false关闭],如果置为false,则请求超时交给ribbon控制.
#feign.hystrix.enabled=true
复制代码

定义服务接口类InfoClient,作为调用远程服务的本地入口:

//1.name为被调用的服务应用名称.
//2.InfoFallBack作为熔断实现,当请求cloud-provider失败时调用其中的方法.
//3.feign配置.
@FeignClient(name = "cloud-provider", fallback = InfoFallBack.class, configuration = MyFeignConfig.class)
public interface InfoClient {//被请求微服务的地址@RequestMapping("/info")String info();
}复制代码

定义熔断类InfoFallBack,如果远程服务无法成功请求,则调用指定的本地逻辑方法:

@Component
public class InfoFallBack implements InfoClient {@Overridepublic String info() {return "fallback info";}
}
复制代码

定义个性化的feign配置类MyFeignConfig:

@Configuration
public class MyFeignConfig {/*** feign打印日志等级* @return*/@BeanLogger.Level feignLoggerLeval(){return Logger.Level.FULL;}
}
复制代码

定义服务调用类ConsumerController,通过本地方法入口调用远程服务:

@RestController
@Configuration
public class ConsumerController {@AutowiredInfoClient infoClient;@RequestMapping(value = "/consumerInfo", method = RequestMethod.GET)public String consumerInfo(){return infoClient.info();}
}
复制代码

启动工程,访问:http://127.0.0.1:8081/consumerInfo , 成功调用远程服务:

服务熔断测试,application.properties配置修改如下:

  1. feign.hystrix.enabled=true注释打开,开启Hystrix以支持服务熔断,这边高版本默认为false
  2. 关闭cloud-provider服务或者去除ribbon请求处理超时时间及服务熔断超时时间的配置

重新启动cloud-consumer服务,再次访问,服务熔断成功调用了本地的方法:

服务网关组件Zuul整合

该组件提供了智能路由以及访问过滤等功能。新建服务网关模块cloud-zuul,过程和以上同样类似,这里省略。

maven依赖配置:

<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><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
复制代码

启动类,加上@EnableZuulProxy和@EnableEurekaClient注解:

@SpringBootApplication
@EnableZuulProxy //开启网关Zuul
@EnableEurekaClient
public class CloudZuulApplication {public static void main(String[] args) {SpringApplication.run(CloudZuulApplication.class, args);}
}
复制代码

application.properties添加如下配置:

#应用名称.
spring.application.name=cloud-zuul
#应用端口号.
server.port=8071
#Eureka Server服务器地址.
eureka.client.serviceUrl.defaultZone=http://localhost:8070/eureka/#通过指定URL配置了Zuul路由,则配置以下两个超时时间.
#zuul.host.connect-timeout-millis=5000
#zuul.host.socket-timeout-millis=5000#zuul使用服务发现的方式[通过serviceId路由服务],得配置ribbon的超时时间.
#官网文档已说明:http://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#_zuul_timeouts
#ribbon请求处理的超时时间.
ribbon.ReadTimeout=5000
#ribbon请求连接的超时时间.
ribbon.ConnectionTimeout=5000##设置服务熔断超时时间[默认1s]
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000#只要访问以/api/开头的多层目录都可以路由到服务名为cloud-provider的服务上.
zuul.routes.cloud-provider=/api/**
复制代码

注意zuul.routes.cloud-provider表示要访问的服务以何种路径方式路由。

定义网关过滤器AccessFilter,根据过滤器的不同生命周期在调用服务时调用过滤器中的方法逻辑。

/*** 服务网关过滤器*/
@Component
public class AccessFilter extends ZuulFilter {/*** 返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型:*  pre:可以在请求被路由之前调用*  route:在路由请求时候被调用*  post:在route和error过滤器之后被调用*  error:处理请求时发生错误时被调用* @return*/@Overridepublic String filterType() {return "pre"; //前置过滤器}@Overridepublic int filterOrder() {return 0; //过滤器的执行顺序,数字越大优先级越低}@Overridepublic boolean shouldFilter() {return true;//是否执行该过滤器,此处为true,说明需要过滤}/*** 过滤器具体逻辑* @return* @throws ZuulException*/@Overridepublic Object run() throws ZuulException {RequestContext ctx = RequestContext.getCurrentContext();HttpServletRequest request = ctx.getRequest();System.out.println(String.format("%s demoFilter request to %s", request.getMethod(), request.getRequestURL().toString()));String username = request.getParameter("username");// 获取请求的参数if(!StringUtils.isEmpty(username)&&username.equals("bright")){//当请求参数username为“bright”时通过ctx.setSendZuulResponse(true);// 对该请求进行路由ctx.setResponseStatusCode(200);ctx.set("isSuccess", true);// 设值,让下一个Filter看到上一个Filter的状态return null;}else{ctx.setSendZuulResponse(false);// 过滤该请求,不对其进行路由ctx.setResponseStatusCode(401);// 返回错误码ctx.setResponseBody("{\"result\":\"username is not correct!\"}");// 返回错误内容ctx.set("isSuccess", false);return null;}}
}
复制代码

启动该工程,访问:http://127.0.0.1:8071/api/info , 成功执行网关过滤器中的方法逻辑,请求被过滤,没有调用远程服务返回了设置的错误内容:

访问:http://127.0.0.1:8071/api/info?username=bright ,执行网关过滤器中的方法逻辑,请求参数合法,所以请求没有被过滤成功调用了远程服务:

项目源码

欢迎微信扫码关注微信公众号:后端开发者中心,不定期推送服务端各类技术文章。

转载于:https://juejin.im/post/5bb2f424e51d450e7b174a3f

Spring Cloud微服务实战:手把手带你整合eurekazuulfeignhystrix(附源码)相关推荐

  1. Spring Cloud微服务实战:外卖订餐系统

    Spring Cloud微服务实战:外卖订餐系统 项目需求 客户端:针对普通用户, 用户登录.用户退出.菜品订购.我的订单. 后台管理系统:针对管理员, 管理员登录.管理员退出.添加菜品.查询菜品.修 ...

  2. Spring Cloud微服务实战:手把手带你整合eurekazuulfeignhystrix

    转载自:https://www.jianshu.com/p/cab8f83b0f0e 代码实现:https://gitee.com/ccsoftlucifer/springCloud_Eureka_z ...

  3. Spring Cloud微服务实战pdf

    下载地址:网盘下载 内容提要 编辑 <Spring Cloud微服务实战>从时下流行的微服务架构概念出发,详细介绍了Spring Cloud针对微服务架构中几大核心要素的解决方案和基础组件 ...

  4. 疯狂Spring Cloud微服务架构实战

    网站 更多书籍点击进入>> CiCi岛 下载 电子版仅供预览及学习交流使用,下载后请24小时内删除,支持正版,喜欢的请购买正版书籍 电子书下载(皮皮云盘-点击"普通下载" ...

  5. 《Spring Cloud微服务架构实战派》PDF样章

    内容摘要: 本书针对Spring Cloud Greenwich.SR2版本+Spring Boot的2.1.x.RELEASE版本.在编写过程中,不仅考虑到在企业任职所需的技能,还考虑到求职面试时可 ...

  6. Spring Cloud 微服务项目操作实战流程(完结)

    Spring Cloud入门项目操作实战流程 Day01~02 〇.Service - 业务服务结构 商品服务 item service,端口 8001 用户服务 user service,端口 81 ...

  7. Spring Cloud 微服务开发实战

    为什么要学习微服务? 1. 求职时增强技术自信. 微服务是非常热门的话题,企业招聘中也越来越多的要求有微服务开发.架构能力,不掌握一些微服务技能找工作时也缺乏亮点,可以说微服务架构已经成为中高级后端开 ...

  8. 实战系列-Spring Cloud微服务中三把利器Feign、Hystrix、Ribbon

    导语   在之前的分享中分享过关于Fegin的底层实现原理,以及Spring Cloud OpenFegin的启动原理.在这次的分享中主要总结一下Spring Cloud 微服务架构的三把利器.对于F ...

  9. Spring Boot+Eureka+Spring Cloud微服务快速上手项目实战

    说明 我看了一些教程要么写的太入门.要么就是写的太抽象.真正好的文章应该是快速使人受益的而不是浪费时间.本文通过一个包括组织.部门.员工等服务交互的案例让刚接触spring cloud微服务的朋友快速 ...

最新文章

  1. 用java设计一个二叉树类的结构,二叉树的基本结构以及java实现
  2. C语言字符串操作常用库函数
  3. 深度学习(4)手写数字识别实战
  4. anaconda 安装在c盘_最省心的Python版本和第三方库管理——初探Anaconda
  5. java按键修改_修改键位映射,打造自己的个性键盘 [转自赵翔鹏的Blog]
  6. 分享开发HTML5手机游戏的5个注意要点
  7. 开始VC6学习之旅2
  8. Cookie和Session的关系(个人理解)
  9. learning docker steps(3) ----- docker services 初次体验
  10. mysql 大树据表update很慢
  11. Navicat 数据库可视化工具远程连接MySQL及基本操作
  12. Ubuntu下通过命令打开图片
  13. 背单词App开发日记3
  14. 系统架构设计师考点全纪要(自己整理,本人一次稳过)
  15. java++pdf文档合并_Java多个PDF文件合并成一个PDF文件-Go语言中文社区
  16. 嵌入式linux工控板,基于Linux的ARM9工业控制板设计
  17. C++string中的insert()插入函数
  18. WARNING: Device for PV 0lQ0Gl-RBe5-fPrr-OKYB-whwD-qHPF-izvEES not found or rejected by a filter
  19. C#获取本周的周一以及周日
  20. 思博伦Spirent Testcenter C50-100G以太网测试仪_双极未来

热门文章

  1. Python安装Pytorch教程(图文详解)
  2. 软件测试---正交试验法
  3. cesium加载 gltf模型
  4. nodejs redis 发布订阅_「赵强老师」Redis的消息发布与订阅
  5. lisp调用dcl单选框_AutoLISP单选按钮RADIO_BUTTON设计插入图块
  6. vim php 配置文件,spacevimsetting
  7. 字典 选取前100_100道 Python 经典练习题004
  8. pt-slot.php,Pwn In Kernel(一):基础知识
  9. 移动端html右滑空白,BootStrap.css 在手机端滑动时右侧出现空白的原因及解决办法...
  10. Caused by: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1696 1024)