SpringCloud+Eureka初识+Ribbon+Feign+Hystrix(服务熔断,服务降级)+hashbroad
Eureka注册中心
1.导包
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.1.2.RELEASE</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions> </dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka --> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependencies>
2.配置文件
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka服务器的实例
client:
register-with-eureka: false
fetch-registry: false service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
3.主启动类:
package com.lian.springcloud; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; //启动之后,访问http://localhost:7001/
@SpringBootApplication
@EnableEurekaServer//服务端的启动类
public class EurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_7001.class,args);
}
}
报错1:Caused by: java.lang.ClassNotFoundException: org.springframework.boot.actuate.health.CompositeHealthContributor
解决方法:原因是eureka依赖包的版本和我的spring-boot-starter-web冲突了,讲eureka版本降成2.1.2.RELEASE
报错2:集成eureka报错 main] org.apache.catalina.core.ContainerBase : A child container failed duri
2023-05-20 10:39:31.626 ERROR 22292 --- [ main] org.apache.catalina.core.ContainerBase : A child container failed during start
解决方法:原因是jar包冲突,排除依赖的包servlet-api
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
访问成功:
在provider配置注册中心:
上面我们已经成功连接上了eureka的服务中心,下面我们需要在启动provider模块时使其自动注册进eureka的服务中心
1.导包:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<!-- #监视器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.配置类
这里info要导入依赖spring-boot-starter-actuator才能使用
3.主启动类开启注解
测试访问:先启动eureka-7001,再启动provider-8001
成功拿到
Eureka的自我保护机制:
当某个服务断电了等原因不能用了,eruka不会立即清理数据,依旧会对微服务的信息进行保存
扩展:在公司团队协作中:添加微服务列表清单
测试结果:成功访问
Eureka集群配置
CAP原则:C一致性 A可用性 P容错性
zookeeper保证一致性和容错性
eureka保证可用性和容错性
因此 Eureka可以很好的应对网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使得整个注册服务瘫痪。
客户端负载均衡及Ribbon
测试1.保证消费者模块成功注册到eureka注册中心
1.导入依赖包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent> <artifactId>springcloud-consumer-dept-80</artifactId> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies> </project>
2.配置文件 application.yaml
server:
port: 80
#配置 ure
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7003.com:7003/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7001.com:7001/eureka/
3.配置类添加注解开启Ribbon
3.controller类请求
package com.lian.springcloud.controller; import com.lian.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import java.util.List; @RestController
public class DeptConsumerController {
//消费层,不应该有service,消费者只和前端打交道
//所以要调用方法,通过RestTemplate..供我们调用
@Autowired
private RestTemplate restTemplate;
//通过ribbon实现,我们这里应该是一个变量
private static final String REST_URL_PREFIX="http://SPRINGCLOUD-PROVIDER-DEPT";
// private static final String REST_URL_PREFIX="http://localhost:8080";
@RequestMapping("/consumer/dept/add")
//增
public Boolean add(Dept dept){
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
}
//删
//通过id获取用户
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id")int id){
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
} //查询全部用户
@RequestMapping("/consumer/dept/list")
public List<Dept> list(){
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
}
}
4.主启动类开启euraka注解
5.测试顺序:
开启eurka的三个注册中心,开启provider,开启consumer
报错1:
springcloud报错Caused by: java.lang.NoClassDefFoundError: org/hibernate/validator/internal/engine/DefaultClockProvider
原因是忘记在主启动类开启注解
报错2:
2023-05-20 14:29:39.083 ERROR 9264 --- [p-nio-80-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException$MethodNotAllowed: 405 null] with root cause
org.springframework.web.client.HttpClientErrorException$MethodNotAllowed: 405 null
原因是,我在前端访问的是http://localhost/consumer/dept/list,但是这个方法我在模块provider的dao底层用的是post请求,解决方法是把底层的post改成get
测试2:Ribbon轮循算法
Ribbon默认的是轮循算法,即假设我们有多个provider服务器,消费者通过80端口访问时候,根据轮循算法去访问一个provider服务器,如消费者相同的url请求,第一次访问到的是1号provider,消费者刷新一次页面,访问到的是2号provider,消费者再刷新一次页面,访问到的又是1号provider,如此循环即为轮循。轮询算法如果一个provider崩了,那么只会对其他provider进行轮循
实现步骤:
1.首先我们建了三个不同数据库,三个库都有一张dept表,这三张表只有字段db_source不同
2.接着我们创建了2号provider和3号provider,同时更改配置的yaml文件分别连接2号数据库和3号数据库,
启动测试:
启动eruka7001注册中心-->启动provider1号,2号,3号-->启动consumer模块-->访问“http://localhost/consumer/dept/get/1”
开始我并没有看到轮循效果,因为我的DeptMapper.xml文件中,把要查询的数据库定死了,如下把first删掉即可
再刷新:可以看到现在是second数据库了
测试3:实现Ribbon自定义算法
负载均衡默认算法是轮循,但是我们可以自定义我们自己的算法,官方文档明确指出我们不应该在主启动类的同一个包下自定义ribbon算法,应该另开一个包
步骤:
1.创建配置类LianRule,思想是实现接口IRule,记得注解
@Configuration
public class LianRule {
@Bean
public IRule myRule(){//我们要自定义自己的ribbon算法,只需要实现官方的IRule接口
//LianRandomRule()对应官方的RandomRule()
return new LianRandomRule();
}
}
2.具体实现类LianRandomRule,
LianRandomRule()对应官方的RandomRule()
package com.lian.myrule; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server; import java.util.List;
import java.util.concurrent.ThreadLocalRandom; public class LianRandomRule extends AbstractLoadBalancerRule { /**
* Randomly choose from all living servers
*/
// @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null; while (server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers(); //活着的服务
List<Server> allList = lb.getAllServers(); int serverCount = allList.size();
if (serverCount == 0) {
/*
* No servers. End regardless of pass, because subsequent passes
* only get more restrictive.
*/
return null;
} int index = chooseRandomInt(serverCount); //生成随机数
server = upList.get(index); if (server == null) {
/*
* The only time this should happen is if the server list were
* somehow trimmed. This is a transient condition. Retry after
* yielding.
*/
Thread.yield();
continue;
} if (server.isAlive()) {
return (server);
} // Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
} return server;
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
} @Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
} @Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// TODO Auto-generated method stub }
}
3.参考官方文档在主启动类添加注解
4.启动测试:启动eruka7001注册中心-->启动provider1号,2号,3号-->启动consumer模块-->访问“http://localhost/consumer/dept/list”
不断刷新,随机连接不同的provider,使用的数据库随机变化
Feign介绍:
feign是面向接口的编程架构,而前面的resttemplate是restful风格架构;OpenFeign 底层内置了 Ribbon 框架,因此Feign本质还是调用了Ribbon 负载均衡。
Feign原理
例子演示:我们靠Frign的方式,实现前端获取数据库用户记录
步骤:
1.给springcloud-api导依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
开始的报错:
Caused by: java.io.FileNotFoundException: class path resource [org/springframework/boot/autoconfigure/web/ServerPropertiesAutoConfiguration.class] cannot be opened because it does not exist
原因是:导入的feign依赖和原本springboot的依赖版本冲突,换成下面这个就可以了
2.在springcloud-api创建服务接口
3.为了方便对比,新建一个consumer-dept-feign模块,给consumer-dept-feign模块导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent> <groupId>com.lian</groupId>
<artifactId>springcloud-consumer-dept-feign</artifactId> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-feign -->
<!-- 替代ribbon-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.2.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies> </project>
4.controller类方法:
4.主启动类
5.测试访问成功
服务降级:
客户端从整体网站请求负载考虑,当某个服务熔断或者关闭之后,服务将不再被调用,此时在客户端,我们可以准备一个FallbackFactory,返回一个默认的值,整体的服务水平下降了,但是系统还能正常运行
1.springcloud-api写一个降级类
2.在springcloud-api模块的service目录下的接口要绑定我们写的降级类
3.在消费者模块的配置文件中增加服务降级的配置
4.启动测试
未关闭后端的provider时若前端访问空白的用户id,则网页没有报错只是空白
关闭后端的provider后的页面提示
小总结:这几天学了:
eureka是注册中心,服务提供者和消费者都需要去注册中心注册,关于分布式系统的CAP理论告诉我们:一个分布式系统只能同时满足其中两个。eurka保证的是AP,就是可用性和容错性,我们可以有多个注册中心,防止单个注册中心崩溃;我们可以搭建集群,多个注册中心,多个provider提供者,但是消费者只能一个;
erueka还有自我保护机制,这个机制使得加入有某个服务器断电或者故障了,eureka还是能够保留原来的数据不丢失。
Ribbon和负载均衡,我们通过Ribbon将用户的访问交给到不同的provider处理,类似于分流,防止服务器压力过大,Ribbon本身默认的是轮循算法,我们可以通过实现接口IRule来自定义我们的算法,但是需要注意的是官网提到了不能把自定义的轮循算法放在和主启动类同一个包下,因此我们需要自己建一个包编写我们自定义算法同时把它注册到spring容器里
Feign:开发人员习惯面向接口编程而来,是为了我们在消费者的controller更方便调用,而不使用RestTemplate模板类,实现过程:导包(注意版本)我们需要在api内定义服务接口,同时在接口上开启注解@FeignClient,在消费者模块也要导入feign依赖包,编写更简便的controller方法然后在主启动类开启支持feign注解
服务熔断:服务器之间,依赖包之间等可能存在相互调用的关系,即provider1需要调用provider2,provider2需要调用provider3,当provider2出现故障后,任务无法正常进行,后面用户的请求全部阻塞在了provider1,同时容易级联其他的问题,在高并发情况下非常容易导致整个系统雪崩,因此我们通过Hystrix技术栈有效处理服务熔断的情况。
服务降级:有时候单个服务器收到非常非常多用户的访问,而另些服务器基本无人问津,那么我们就关闭这些无人问津的服务器,把更多资源分配给火爆的服务器,来降低受很多人访问的服务器的压力,我们需要在springcloud-api的service目录写降级类实现接口FallbackFactory,我使用的是feign进行的测试,所以在我原本写的接口DeptClientService需要通过注解绑定降级类,测试:开启eruaka7001->开启provider8001->开启 FeignDeptConsumer_80 当我们关闭provider8001查看页面是否有打印出提示信息。
SpringCloud+Eureka初识+Ribbon+Feign+Hystrix(服务熔断,服务降级)+hashbroad的更多相关文章
- 微服务:Eureka+Zuul+Ribbon+Feign+Hystrix构建微服务架构
原文地址:http://blog.csdn.net/qq_18675693/article/details/53282031 本案例将打架一个微服务框架,参考来源官方参考文档 微服务:是什么?网上有一 ...
- Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul)
Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul) 1.Eureka Eureka是Netflix的一个子模块,也是核心模块之一.Eureka是 ...
- Spring-cloud微服务实战【七】:服务熔断与降级hystrix
在之前的文章中,我们先后介绍了eureka,ribbon,feign,使用eureka集群的方式来保证注册中心的高可用,在eureka中使用ribbon进行负载均衡,使用feign接口替换手动编码 ...
- java框架之SpringCloud(5)-Hystrix服务熔断、降级与监控
前言 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败.不做任何处理的情况下,很容易导致服务雪崩. 服务雪崩:多个微服务之间调用的时候,假设 ...
- (万字好文)Dubbo服务熔断与降级的深入讲解&代码实战
原文链接:(万字好文)Dubbo服务熔断与降级的深入讲解&代码实战 一.Dubbo服务降级实战 1 mock 机制 谈到服务降级,Dubbo 本身就提供了服务降级的机制:而 Dubbo 的服务 ...
- 【springcloud】服务熔断与降级(Hystrix)
转自:https://blog.csdn.net/pengjunlee/article/details/86688858 服务熔断 服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的 ...
- springcloud组件之hystrix服务熔断,降级,限流
hystrix 简介 Hystrix是什么 在分布式环境中,许多服务依赖项中的一些必然会失败.Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互.Hystrix通过 ...
- ②SpringCloud 实战:引入Feign组件,完善服务间调用
这是SpringCloud实战系列中第二篇文章,了解前面第一篇文章更有助于更好理解本文内容: ①SpringCloud 实战:引入Eureka组件,完善服务治理 简介 Feign 是一个声明式的 RE ...
- 【五】服务熔断、降级 —— Hystrix(豪猪)
分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖,每个依赖关系将在某些时候将不可避免地失败. 服务雪崩 多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务 B和微服务 ...
- 服务熔断、降级、限流、异步RPC -- HyStrix
背景 伴随着业务复杂性的提高,系统的不断拆分,一个面向用户端的API,其内部的RPC调用层层嵌套,调用链条可能会非常长.这会造成以下几个问题: API接口可用性降低 引用Hystrix官方的一个例子, ...
随机推荐
- DVWA-XSS(DOM)
漏洞详解. DOM XSS(Cross-site scripting)是一种Web安全漏洞,它利用了浏览器的DOM(文档对象模型)解析机制,通过注入恶意代码来攻击用户. DOM XSS与传统的反射型或 ...
- Apinto Dashboad V2.0 发布:可视化控制台让配置更轻松!
大家好, Eolink 旗下开源网关 Apinto 本次带来了 Apinto Dashboad V2.0 的版本发布. Dashboad 需要与 Apinto 主版本一起使用,目前 Dashboad ...
- NodeJs的模块化和包
模块化的基本概念 什么是模块化? 模块化是解决一个复杂问题时,自顶向下逐层把系统划分为若干个模块的过程,编程中,就是遵守一定规则,把一个大文件拆成独立并相互依赖的多个小模块. 模块化规范 使用什么样的 ...
- 案例: 利用 Hugging Face 进行复杂文本分类
Witty 与 Hugging Face 专家加速计划的成功案例 如果你对如何更快构建 ML 解决方案感兴趣,请访问 专家加速计划 登陆页面并通过 填写表单 联系我们! 业务背景 随着 IT 技术不断 ...
- 最新centos7 部署 k8s v1.26,简单易懂,跟着命令敲就完事
其实没什么好说的,搭环境搞了一整天,人已经麻了,踩了很多坑,网上教程的版本大都比较旧,总是和最新版本各种地方不兼容,把坑踩完了,k8s目前最新的版本是v1.26,跟着命令敲就行了,我已经重复部署了很多 ...
- tcp,udp tcp三次握手四次挥手,基于套接字进行简单通信
1.应用层: 应用层功能:规定应用程序的数据格式. 例:TCP协议可以为各种各样的程序传递数据,比如Email.WWW.FTP等等.那么,必须有不同协议规定电子邮件.网页.FTP数据的格式,这些应用程 ...
- Junit5 pom依赖
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter- ...
- 在idea中将一个javase项目转成ee项目
在idea中将java项目转成web项目 1.创建一个java项目,new一个directory名为web(与src同级) 2. 为web指定根目录:ctrl+shift+alt+s,在module中 ...
- v-if与v-for的优先级
在Vue2中 v-for的优先级要高于v-if 在Vue3中 v-if 的优先级要高于v-for
- 明修"栈"道——越过Android启动栈陷阱
作者:vivo 互联网大前端团队- Zhao Kaiping 本文从一例业务中遇到的问题出发,以FLAG_ACTIVITY_NEW_TASK这一flag作为切入点,带大家探究Activity启动前的一 ...