​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的更多相关文章

  1. 微服务:Eureka+Zuul+Ribbon+Feign+Hystrix构建微服务架构

    原文地址:http://blog.csdn.net/qq_18675693/article/details/53282031 本案例将打架一个微服务框架,参考来源官方参考文档 微服务:是什么?网上有一 ...

  2. Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul)

    Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul) 1.Eureka Eureka是Netflix的一个子模块,也是核心模块之一.Eureka是 ...

  3. Spring-cloud微服务实战【七】:服务熔断与降级hystrix

      在之前的文章中,我们先后介绍了eureka,ribbon,feign,使用eureka集群的方式来保证注册中心的高可用,在eureka中使用ribbon进行负载均衡,使用feign接口替换手动编码 ...

  4. java框架之SpringCloud(5)-Hystrix服务熔断、降级与监控

    前言 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败.不做任何处理的情况下,很容易导致服务雪崩. 服务雪崩:多个微服务之间调用的时候,假设 ...

  5. (万字好文)Dubbo服务熔断与降级的深入讲解&代码实战

    原文链接:(万字好文)Dubbo服务熔断与降级的深入讲解&代码实战 一.Dubbo服务降级实战 1 mock 机制 谈到服务降级,Dubbo 本身就提供了服务降级的机制:而 Dubbo 的服务 ...

  6. 【springcloud】服务熔断与降级(Hystrix)

    转自:https://blog.csdn.net/pengjunlee/article/details/86688858 服务熔断 服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的 ...

  7. springcloud组件之hystrix服务熔断,降级,限流

    hystrix 简介 Hystrix是什么 在分布式环境中,许多服务依赖项中的一些必然会失败.Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互.Hystrix通过 ...

  8. ②SpringCloud 实战:引入Feign组件,完善服务间调用

    这是SpringCloud实战系列中第二篇文章,了解前面第一篇文章更有助于更好理解本文内容: ①SpringCloud 实战:引入Eureka组件,完善服务治理 简介 Feign 是一个声明式的 RE ...

  9. 【五】服务熔断、降级 —— Hystrix(豪猪)

    分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖,每个依赖关系将在某些时候将不可避免地失败. 服务雪崩 多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务 B和微服务 ...

  10. 服务熔断、降级、限流、异步RPC -- HyStrix

    背景 伴随着业务复杂性的提高,系统的不断拆分,一个面向用户端的API,其内部的RPC调用层层嵌套,调用链条可能会非常长.这会造成以下几个问题: API接口可用性降低 引用Hystrix官方的一个例子, ...

随机推荐

  1. Javaweb学习笔记第九弹

    MyBatis案例--环境准备 1.依据之前在Navicat建立数据表的方法,新建立一个数据表 2.将数据表的相关内容表现在Java文件的实例上:即成员变量和set.get成员方法 3.new一个测试 ...

  2. hdu 4870 Rating(概率dp)

    题意:给你两个初始分数为0的账号让你去打比赛,每场比赛赢的概率为p,赢了加50分,输了-100分,当然你不会负分,每次你会用分低的账号去打比赛,问你把一个账号打到1000分的需要参加比赛次数的期望值. ...

  3. 从零开始,开启属于你的 RTE 漫游之旅!丨漫游指南 x 即将启航

    什么是「开发者漫游指南」? 「开发者漫游指南」邀请热爱前端开发.关心音视频领域发展.希望进入音视频行业.乐于和大家一起交流成长的小伙伴,通过「开发者漫游指南」与社区共同成长,帮助更多的开发者在实时音视 ...

  4. java数组使用、Arrays类使用 、排序方法

    数组使用 数组的基本使用: package charpter4; public class ArrayDemo2 { public static void main(String[] args) { ...

  5. 最大流应用(Maximum Flow Application)

    1. 二分图匹配(Bipartite Matching) 1.1 匹配(Matching) Def. Given an undirected graph \(G = (V, E)\), subset ...

  6. Linux RedHat 利用 ISO镜像文件制作本地 yum源

    RedHat 利用ISO镜像文件制作本地yum源 [1]创建iso存放目录和挂载目录 1 [root@desktop ~]# cd /mnt/ 2 [root@desktop mnt]# mkdir ...

  7. Kafka 集群调优

    更多内容,前往 IT-BLOG 单个 kafka服务器足以满足本地开发或 POC要求,使用集群的最大好处是可以跨服务器进行负载均衡,再则就是可以使用复制功能来避免因单点故障造成的数据丢失.在维护 Ka ...

  8. JMM知识点总结

    JMM知识点总结 一.什么是JMM? 不知道大家在学习的过程有没有思考过这两个问题 为什么说java是跨平台语言 导致并发问题的原因是什么 第一个问题,我是这么理解的,代码运行本质上是将我们写的语言转 ...

  9. Go语言实现TCP通信

    TCP协议为传输控制协议,TCP协议有以下几个特点:1. TCP是面向连接的传输层协议:2. 每条TCP连接只能有两个端点,每条TCP连接是点到点的通信:3. TCP提供可靠的交付服务,保证传送的数据 ...

  10. VUE中的next({ ...to, replace: true })

    beforeEach((to, from, next) => { next('/logon') } 上面这串代码我们可以看成为 beforeEach((to, from, next) => ...