SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]
个人微信公众号:程序猿的月光宝盒
[toc]
## 前提:本篇是基于
SpringCloud+Eureka+Feign+Ribbon的简化搭建流程和CRUD练习[1]
的修改与拓展
1.修改consumer
的CenterFeign.java
,把返回值全部设置为String
/**
* 是consumer调用provider(需要指定provider的名字)
* 请求的清单列表:规定调用地址、参数、返回值
* 在正常走通的时候不走CenterFeignFallBack,当provider down的时候走熔断器,相当于是类的try-catch
*/
@FeignClient(name = "provider",fallback = CenterFeignFallBack.class)
public interface CenterFeign {
@GetMapping("/optionData.do")
public String optionData();
@PostMapping("/showEmpData.do")
//Feign:不支持对象传参,所以要用@RequestBody
public String showEmpData(@RequestBody Emp emp);
@PostMapping("/add.do")
public String add(@RequestBody Emp emp);
@PostMapping("/edit.do")
public String edit(@RequestBody Emp emp);
@GetMapping("/del.do")
public String del(@RequestParam("empno") Integer empno);
}
2.在CenterFeign.java
的同包下创建实现了CenterFeign
接口的CenterFeignFallBack.java
作为熔断器
@Component
public class CenterFeignFallBack implements CenterFeign {
@Override
public String optionData() {
return "provider-optionData-error";
}
@Override
public String showEmpData(Emp emp) {
return "provider-showEmpData-error";
}
@Override
public String add(Emp emp) {
return "provider-add-error";
}
@Override
public String edit(Emp emp) {
return "provider-edit-error";
}
@Override
public String del(Integer empno) {
return "provider-del-error";
}
}
3.修改consumer
的CenterController.java
,返回值全改为String
@RestController
public class CenterController{
@Resource
private CenterFeign centerFeign;
@GetMapping("/optionData-consumer.do")
public String optionData() {
return centerFeign.optionData();
}
@PostMapping("/showEmpData-consumer.do")
public String showEmpData(@RequestBody Emp emp) {
return centerFeign.showEmpData(emp);
}
@PostMapping("/add-consumer.do")
public String add(@RequestBody Emp emp) {
return centerFeign.add(emp);
}
@PostMapping("/edit-consumer.do")
public String edit(@RequestBody Emp emp) {
return centerFeign.edit(emp);
}
@GetMapping("/del-consumer.do")
public String del(@RequestParam("empno") Integer empno) {
return centerFeign.del(empno);
}
}
4.确认consumer
中的配置文件application.properties
中有没有开启熔断feign.hystrix.enabled=true
,没有的话加上
#端口号
server.port=8764
#应用名
spring.application.name=consumer
#eureka客户端服务url默认区域
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
#开启熔断器
feign.hystrix.enabled=true
#下线名称.ribbon.NF加载平衡规则类名,这里先注释
provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
5.开启服务测试
访问http://localhost:8761/
发现所有服务已经注册
正常走provider没有问题
走consumer也没有问题,只是返回的格式是字符串类型,不是json类型,但是没关系,格式还是json的格式,前台该怎么转还能怎么转,不影响
那怎么走容错?
现在手动停止一个provider
因为这里我开了负载均衡策略(在consumer中的配置文件中provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
),所以有一定几率触发熔断器,
这就相当于类之间的try-catch,没有熔断器的话这里百分百是报错误代码.那这里我先把负载均衡关掉,在测试有没有走容错,(猜一下,会走吗?)
这里我测了这么多次,都没有走熔断,所以显然不走,为何?
因为没有手动设置负载均衡策略的话,默认走的是轮询.机制,啥是Ribbon轮询机制?
简单的说就是有abc三台服务器,正常的情况下走a->b->c,在有一台down了的时候,那台就自动跳过,比如b down了,那么就是a->c
以上,个人理解,若有误请指正,よろしくお願いします~
现在,既然一台服务器工作是没有问题 那我两台provider全部停止呢?
那答案是肯定的,绝壁走容错~~
6.测试完没有问题,现在添加网关功能模块
新建模块(Spring initializr)zuul-client
7.编辑配置文件application.properties
#网关端口
server.port=8765
#应用名
spring.application.name=zuul
#网关路径提供者,后面的**表示:xxx.do
zuul.routes.provider=/pro/**/
#网关路径消费者,后面的**表示:xxx.do
zuul.routes.consumer=/con/**/
#网关走熔断机制
#ribbon超时设置
ribbon.ReadTimeout=30000
ribbon.ConnectTimeout=30000
8.在启动类上添加注解
//开启网关代理
@EnableZuulProxy
//开启eureka客户端
@EnableEurekaClient
@SpringBootApplication
public class ZuulClientApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulClientApplication.class, args);
}
}
9.开启服务测试
测试provider
测试consumer
10.网关作用
统一了所有客户端的ip地址和端口号,我们只要给不同层级的应用起别名就ok了(就是这里的)
11.加入Redis缓存
11.1在provider-one
模块的pom文件中加入redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
11.2修改provider-one
模块的DeptServiceImpl
文件,加入 @Autowired private RedisTemplate redisTemplate;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Autowired
private RedisTemplate redisTemplate;
@Override
public Map<String, Object> optionData() {
Map<String, Object> map=new HashMap<>();
List<Map<String, Object>> list = deptMapper.selAllDeptData();
// 定义Redis存储集合的对象
ListOperations<String,Map<String,Object>> redisList = redisTemplate.opsForList();
//拼接Redis中存储数据对应的key
String key = "depts";
//判断Redis中是否有key,没有就说明是第一次访问,将数据放入Redis
if(!redisTemplate.hasKey(key)){
//直接将数据库查询出来的值放入Redis
System.out.println("provider-one-optionData的值已经放入Redis");
redisList.leftPushAll(key,list);
}
map.put("data",list);
return map;
}
}
11.3对应的 修改DeptService
,返回值变成map
public interface DeptService {
Map<String,Object> optionData();
}
11.4修改CenterController
,把返回值类型改为Map
public Map<String, Object> optionData() {
return deptService.optionData();
}
11.5同样的在provider-two
的pom.xml中加入redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
11.6修改provider-two
模块的DeptServiceImpl
文件,加入 @Autowired private RedisTemplate redisTemplate;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Autowired
private RedisTemplate redisTemplate;
@Override
public Map<String, Object> optionData() {
Map<String, Object> map=new HashMap<>();
List<Map<String, Object>> list = deptMapper.selAllDeptData();
// 定义Redis存储集合的对象
ListOperations<String,Map<String,Object>> redisList = redisTemplate.opsForList();
//拼接Redis中存储数据对应的key
String key = "depts";
//判断Redis中是否有key,没有就说明是第一次访问,将数据放入Redis
if(!redisTemplate.hasKey(key)){
//直接将数据库查询出来的值放入Redis
System.out.println("provider-two-optionData的值已经放入Redis");
redisList.leftPushAll(key,list);
}
map.put("data",list);
return map;
}
}
11.7对应的 修改DeptService
,返回值变成map
public interface DeptService {
Map<String,Object> optionData();
}
11.8修改CenterController
,把返回值类型改为Map
public Map<String, Object> optionData() {
return deptService.optionData();
}
11.9更新provider-one
模块的配置文件application.properties
,加入Redis配置
#服务端口号
server.port=8762
#应用名
spring.application.name=provider
#eureka客户端服务url默认区域
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
#数据源驱动类名
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#数据源url
spring.datasource.url=jdbc:mysql:///kh75
#数据源用户名
spring.datasource.username=root
#数据源密码
spring.datasource.password=admin
#后期会写mapper.xml,这里先注释
#mybatis.mapper-locations=classpath:mapper/*.xml
#给实体类起别名,同样这里先注释
#mybatis.type-aliases-package=cn.kgc.vo
#配置Redis
spring.redis.port=6379
#redis所在的主机地址
spring.redis.host=xxx.xxx.xxx
spring.redis.database=0
11.10更新provider-two
模块的配置文件application.properties
,加入Redis配置
#服务端口号
server.port=8763
#应用名
spring.application.name=provider
#eureka客户端服务url默认区域
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
#数据源驱动类名
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#数据源url
spring.datasource.url=jdbc:mysql:///kh75
#数据源用户名
spring.datasource.username=root
#数据源密码
spring.datasource.password=admin
#后期会写mapper.xml,这里先注释
#mybatis.mapper-locations=classpath:mapper/*.xml
#给实体类起别名,同样这里先注释
#mybatis.type-aliases-package=cn.kgc.vo
#配置Redis
spring.redis.port=6379
#redis所在的主机地址
spring.redis.host=xxx.xxx.xx
spring.redis.database=0
11.11更新consumer
的CenterFeign,所有返回值都是map
@FeignClient(name = "provider",fallback = CenterFeignFallBack.class)
public interface CenterFeign {
@GetMapping("/optionData.do")
Map<String,Object> optionData();
@PostMapping("/showEmpData.do")
//Feign:不支持对象传参,所以要用@RequestBody
Map<String,Object> showEmpData(@RequestBody Emp emp);
@PostMapping("/add.do")
Map<String,Object> add(@RequestBody Emp emp);
@PostMapping("/edit.do")
Map<String,Object> edit(@RequestBody Emp emp);
@GetMapping("/del.do")
Map<String,Object> del(@RequestParam("empno") Integer empno);
}
11.12更新CenterFeignFallBack
@Component
public class CenterFeignFallBack implements CenterFeign {
private Map<String, Object> map = new HashMap<> ();
@Autowired
private RedisTemplate redisTemplate;
@Override
public Map<String,Object> optionData() {
ListOperations<String,Map<String,Object>> redisList = redisTemplate.opsForList();
map.put("msg","provider-optionData-error");
map.put("feign-data",redisList.range("depts",0,-1));
return map;
}
@Override
public Map<String,Object> showEmpData(Emp emp) {
ListOperations<String,Map<String,Object>> redisList = redisTemplate.opsForList();
map.put("msg","provider-showEmpData-error");
//这里对应的serviceImp里面还没修改成Redis,先放着
map.put("feign-data",redisList.range("emps",0,-1));
return map;
}
@Override
public Map<String,Object> add(Emp emp) {
map.put("msg","provider-add-error");
return map;
}
@Override
public Map<String,Object> edit(Emp emp) {
map.put("msg","provider-edit-error");
return map;
}
@Override
public Map<String,Object> del(Integer empno) {
map.put("msg","provider-del-error");
return map;
}
}
11.13再修改consumer中的CenterController,返回值也全改成Map
@RestController
public class CenterController{
@Resource
private CenterFeign centerFeign;
@GetMapping("/optionData-consumer.do")
public Map<String,Object> optionData() {
return centerFeign.optionData();
}
@PostMapping("/showEmpData-consumer.do")
public Map<String,Object> showEmpData(@RequestBody Emp emp) {
return centerFeign.showEmpData(emp);
}
@PostMapping("/add-consumer.do")
public Map<String,Object> add(@RequestBody Emp emp) {
return centerFeign.add(emp);
}
@PostMapping("/edit-consumer.do")
public Map<String,Object> edit(@RequestBody Emp emp) {
return centerFeign.edit(emp);
}
@GetMapping("/del-consumer.do")
public Map<String,Object> del(@RequestParam("empno") Integer empno) {
return centerFeign.del(empno);
}
}
11.14检查consumer的pom文件里是否有加入Redis依赖,没有加上...
11.15 打开所有模块进行测试
把提供者断掉,理论上走熔断和redis数据
以上....
SpringCloud+Eureka+Feign+Ribbon的简化搭建流程,加入熔断,网关和Redis缓存[2]的更多相关文章
- SpringCloud+Eureka+Feign+Ribbon的简化搭建流程和CRUD练习
作者:个人微信公众号:程序猿的月光宝盒 环境:win10--idea2019--jdk8 1.搭建Eureka服务模块 1.1 新建eureka服务模块(Sping Initializr) 取名为eu ...
- SpringCloud+Eureka+Feign+Ribbon+zuul的简化搭建流程和CRUD练习
环境:win10--idea2019--jdk8 1.搭建Eureka服务模块 1.1 新建eureka服务模块(Sping Initializr) 取名为eureka-server,并添加如下Dep ...
- springCloud——Eureka、Ribbon理解
一. 服务注册中心.服务提供者.服务消费者 如何通信? 客户端: 应用主类中配置@EnableDiscoveryClient application.properties中配置defaultZone指 ...
- springcloud微服务实战:Eureka+Zuul+Feign/Ribbon+Hystrix Turbine+SpringConfig+sleuth+zipkin
相信现在已经有很多小伙伴已经或者准备使用springcloud微服务了,接下来为大家搭建一个微服务框架,后期可以自己进行扩展.会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新 ...
- SpringCloud基础概念学习笔记(Eureka、Ribbon、Feign、Zuul)
SpringCloud基础概念学习笔记(Eureka.Ribbon.Feign.Zuul) SpringCloud入门 参考: https://springcloud.cc/spring-cloud- ...
- SpringCloud学习笔记(六):Feign+Ribbon负载均衡
简介 官网解释: http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign Feign是一个声明式WebS ...
- springcloud微服务实战:Eureka+Zuul+Ribbon+Hystrix+SpringConfig
原文地址:http://blog.csdn.net/yp090416/article/details/78017552 springcloud微服务实战:Eureka+Zuul+Ribbon+Hyst ...
- springCloud系列教程01:Eureka 注册中心集群搭建
springCloud系列教程包含如下内容: springCloud系列教程01:Eureka 注册中心集群搭建 springCloud系列教程02:ConfigServer 配置中心server搭建 ...
- SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用、Ribbon 负载均衡、自定义 Ribbon 配置、禁用 Eureka 实现 Ribbon 调用)
1.概念:Ribbon 负载均衡 2.具体内容 现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册的目的是希望所有的服务都统一归属到 Eureka 之中进 行处理,但是现 ...
随机推荐
- UVA10600 ACM Contest and Blackout
用prim算法求最小生成树和次小生成树~ #include<cstdio> #include<algorithm> #include<cstring> using ...
- 解析C语言编程对缓冲区的理解
转载自:http://soft.chinabyte.com/database/47/12481547.shtml 下面介绍缓冲区的知识. 一.什么是缓冲区 缓冲区又称为缓存,它是内存空间的一部分.也就 ...
- yii2.0框架安装
通过 Composer 安装 如果还没有安装 Composer,你可以按 getcomposer.org 中的方法安装. 在 Linux 和 Mac OS X 中可以运行如下命令: curl -sS ...
- 1、MyBatis框架底层初涉
1.拜年 哈哈,现在是过年了,祝大家新年好. 本来大过年的是不打算碰电脑的,(抢票除外,三疯同学现在还没抢到票,然后突然又延长假期了).现在疫情严重,被堵家里不能出去了.不能为国家做贡献,但是起码不能 ...
- java并发基础知识
这几天全国都是关键时候,放假了,还是要学习啊!很久没有写博客了,最近看了一本书,有关于java并发编程的,书名叫做“java并发编程之美”,讲的很有意思,这里就做一个笔记吧! 有需要openjdk8源 ...
- 小白学 Python 爬虫:自动化测试框架 Selenium 从入门到实战
引言 前面连续几篇爬虫实战不知道各位同学玩的怎么样,小编是要继续更新了,本篇我们来介绍一个前面已将安装过的工具: Selenium ,如果说是叫爬虫工具其实并不合适,在业界很多时候是拿来做自动化测试的 ...
- 4_4 信息解码(UVa213)<二进制:输入技巧与调试技巧>
消息编码方案要求在两个部分中发送一个被编码的消息.第一部分:称为头,包含消息的字符.第二部分包含一个模式 表示信息.你必须写一个程序,可以解码这个消息. 你的程序的编码方案的核心是一个序列的“0和1” ...
- 创业学习---今日头条创业过程分析---HHR计划
本文搜集和整理了今日头条创业的一些关键点的资料------by 春跃(本文的主要观点都是搜集整理,所以不得本人同意不得转载) 一,18年之前的今日头条创业时间表: 1,张一鸣参与创业的履历:酷讯,饭否 ...
- numpy中的max()函数
1.ndarray.max([int axis]) 函数功能:求ndarray中指定维度的最大值,默认求所有值的最大值. axis=0:求各column的最大值 axis=1:求各row的最大值
- 批处理执行Testng
@echo off set LIB=项目的jar路径 set CLASSPATH=%LIB%\jar\commons-beanutils-.jar;%LIB%\jar\testng.jar;%LIB% ...