springcloud从入门到放弃(精通)(下)

    技术2024-05-21  80

    一.Ribbon负载均衡

       (1) 基于Netfix Tibbon实现的一套客户端负载均衡工具。

              负载均衡包括集中式LB和进程内LB

    集中式:即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件F5,也可以是软件nginx)由该设施负责把访问请求通过某种策略转发至服务的提供方。进程内:消费方从服务注册中心获知有哪些地址可用,然后自己在从这些地址中选择出一个合适的服务器。

              Ribbon就属于进程内LB,他只是一个类库,集成与消费方进程,消费方通过他来获取到服务提供方的地址。

      (2)Ribbon的配置

    在consumer项目中pom.xml文件中新增导入下面依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> 在yml文件中添加: server: port: 80 eureka: client: register-with-eureka: false service-url: defaultZone:http://eureka7001.com/eureka/, http://eureka7002.com/eureka/, http://eureka7003.com/eureka/ 在consumer项目中ConfgBean.java中修改 @Configuration public class ConfigBean{ @Bean @LoadBalanced //可以实现负载均衡 public RestTemplate getRestTemplate(){ return new RestTemplate(); } } 修改consumer项目中的启动类 @SpringBootApplication @EnableEurekaClient public class DeptConsumer80_APP { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_APP.class,args); } } 消费端合并后,不在需要ip和端口配合访问,只需要通过微服务名字来访问。 新增两个provider-8002,provier-8003项目,复制provider-8001项目,修改一些个别配置(端口,数据库连接,数据库暴露的名字一致不用改.....)。每个微服务创建各自的数据库cloudb02/cloudb03.讲这些项目启动,访问provider服务,通过刷新可以实现轮询的访问。

    (3)Ribbon的负载均衡算法

    RoundRobinRule(轮询):默认RandomRule(随机)AvailabilityFilteringRule:会先过滤掉由于多次访问故障而处于断路跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问WeightedResponseTimeRule:根据平均响应时间计算所有服务的权值,响应时间越快服务权重越大别选中的概率越高。刚启动是如果统计信息不足,则会使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule.RetryRule:先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务。BestAvailableRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。ZoneAvoidanceRule:默认规则,符合判断server所在区域的性能和server的可用性选择服务器

    (4)Ribbon的核心组件:IRule

    负载均衡算法的使用 @Configuration //@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans> public class ConfigBean{ @Bean @LoadBalanced//Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具 public RestTemplate getRestTemplate(){ return new RestTemplate(); } @Bean public IRule myRule() { return new RoundRobinRule();//用我们重新选择的随机算法替代默认的轮询。 } } 自定义负载均衡算法

             修改启动类

    @SpringBootApplication @EnableEurekaClient //在启动微服务时候就能去加载我们的自定义Ribbon配置类,从而使配置生效 @RibbonClient(name="MICROSERVICECLOUD-DPEPT",configuration=MySelfRule.class) public class DeptConsumer80_APP { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_APP.class,args); } }

    指定义配置类不能放在@ComponentScan所扫描的当前包下,以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是说我们达不到特殊定制化的目的。所以带新建一个新的包,将新建类MySelfRule放入新建的包中。

    @Configuration public class MySelfRule{ @Bean public IRule myRule(){ return new RandomRule();//Ribbon默认是轮询,我自定义为随机 } }

    二.负载均衡Feign

    Feign是一个生命是的Web服务客户端,使得编写Web服务客户端变得非常容易

       前面在使用Ribbon+RestTemplate时,利用RestTempate对http请求的封装处理,形成了一套模板化的调用方法。但是在实际类开发中,由于对服务依赖的调用可能不止一处,旺旺一个接口会被多出调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,有他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端开发量

    Feign集成了Ribbon

              利用Ribbon维护了服务列表,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通feign只需定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。

    Feign项目搭建 新建项目microservicecloud-consumer-dept-feign其他复制前面的consumer端项目内容。

    修改pom文件

    #新增 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>

         4.修改放置所有Entity类,接口,公共的一些配置的microservicecloud-api项目

         (1)修改该项目中的pom.xml文件

    #新增 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>

            (2)新建接口层如下例子

    @FeignClient(value="MICROSERVICECLOUD-DEPT") public interface DeptClientService { @RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET) public Dept get(@PathVarible("id") long id);//通过id获取Dept部门对象。 }

    修改controller层

    @RestController public class DeptController_Consumer { @Autowired private DeptClientService service; @RequestMapping(value="/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id){ return this.service.get(id); } }

    修改主启动类

    @SpringBootApplication @EnableEurekaClient @EnableFeignClients(basePackages={"com.atguigu.springcloud"}) @ComponentScan("com.atguigu.springcloud") public class DeptConsumer80_APP { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_APP.class,args); } }

    三.Hystrix断路器。 

    分布式系统中可能遇到的问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败       服务雪崩:多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B 和微服务C又调用其他的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。

            对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和,比失败更糟糕的是,这些应用程序还可能导致之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。

            Hystrix是一个用于处理分布式系统延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

               “断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过短路器的故障监控(类似熔断保险丝),向调用方法返回一个符合预期的,可处理的备选响应(FallBack) ,而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方线程不会被长时间,不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。 

    服务熔断

            熔断机制是应对雪崩效应的一种微服务链路保护机制。

           当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回“错误”的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失效的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand.

    2.Hystrix的搭建

    新建Hystrix项目,复制provider项目在项目中pom.xml文件加入      <dependency> <groupId>org.springframework</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> 修改yml文件(修改instance-id) server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis配置文件所在路径 #mapper-location: classpath:mybatis/mapper/**/*.xml #mapper映射文件 type-aliases-package: com.atguigu.springcloud.entities #所有Entity别名类所在包 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource #当前数据操作类型 driver-class-name: com.mysql.jdbc.Driver #mysql驱动包 url: jdbc:mysql://localhost:3306/cloudb01 #数据库名称 username: root password: briup dbcp2: min-idle: 5 #数据库连接池的最小维持连接数 initial-size: 5 #初始化连接数 max-total: 5 #最大连接数 max-wait-millis: 200 #等待连接获取的最大超时时间 eurka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7001/eureka, http://eureka7003.com:7001/eureka,#所要注册到的eureka的地址 instance: instance-id: microservicecloud-dept8001-hystrix #自定义hystrix相关的服务名称信息 prefer-ip-address: true #访问路径可以显示ip地址,修改部分 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ 修改该项目中的contrller层文件 @RestController public class DeptController { @Autowired private DeptServiceImpl service; @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET) @HystrixCommmand(fallbackMethod="processHystrix_Get")//当Get抛出异常,执行下面名为 processHystrix_Get的方法来进容 错。 public Dept get(@PathVariable("id")long id) { Dept dept=this.service.get(id); if(nulll==dept){ throw new RuntimeException("该ID:"+id+"没有对应的信息"); } return dept; } public Dept ProcessHystrix_Get(@PathVariable("id") Lond id){ return new Dept().setDeptno(id).setDname("该ID:"+id+ "没有相应的信息,null--@HystrixCommod").setDb_source("no this database in MySQL"); } } 修改启动类 @SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient //服务发现 @EnableCircuitBreaker //对hystrix熔断机制的支持 public class DeptConsumer80_APP { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_APP.class,args); } }

    3.服务降级

    整体资源快不够了,认同将某些服务先关掉,待度过难关,再开启回来。

    服务降级处理是在客户端实现完成的,与服务端没有关系。

    修改microservicecloud-api工程(存放Entitys,以及公共接口等)根据已有的DeptClientService接口新建一个实现了FallbackFactory接口的类DeptClientServiceFallbackFactory

    @Component public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> //千万不要忘记在该类上加@Component注解, { @Override public DeptClientService create(Throwable throwable){ return new DeptClientService(){ @Override public Dept get(long id){ return new Dept().setDeptno(id).setDname("该ID:"+id+ "没有相应的信息,null--@HystrixCommod").setDb_source("no this database in MySQL"); } }; } } 在api工程里面的DeptClientService修改注解 @FeignClient(value="MICROSERVICECLOUD-DEPT", fallbackFactory=DeptClientServiceFallbackFactory.class) public interface DeptClientService { @RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET) public Dept get(@PathVarible("id") long id);//通过id获取Dept部门对象。 }

    4.豪猪hystrixDashboard

         除了隔离依赖服务的调用以外,Hystrix还提供了准时的调用监控(Hystrix Dashboard),Hystrix会持续第记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括美妙执行多少请求多少成功,多少失败等。Netfix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Hashboard的整合。对监控内容转化成可视化界面。

           新建hystrixDashboard()监控项目步骤

    新建项目microservicecloud-consumer-hystrix-dashboardpom.xml文件中新增内容 <dependency> <groupId>org.springframework.cloud<groupId> <artifactId>spring-cloud-starter-htstrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud<groupId> <artifactId>spring-cloud-starter-htstrix-dashboard</artifactId> </dependency>  新增application.yml文件 server port:9001  新增启动类 @SpringBootApplication @EnableHystrixDashboard public class DeptConsumer80_APP { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_APP.class,args); } }  为了可以监控所有provider微服务,需要在所有provider微服务都需要在pom文件中配置依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> 启动项目Hystrix Dashboard项目,通过访问localhost:9001/hystrix,出现Hystrix Dashboard搭建成功。启动provider,和Eureka项目,通过访问provider服务,再在localhost:9001/hystrix页面上输入http://localhost:8001/hystrix.stream来显是出监控的图形化界面

    四.zuul路由网关

    Zuul包含了两个队请求的路由和过滤两个最主要的功能:其中路由功能负责将外部请求转发到具体的微服务实力上,是实现外部访问同意入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eurekah中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得搭建Zuul项目 创建新项目microservicecloud-zuul-gateway-9527修改pom文件 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>  修改yml文件 server: 9527 spring spplication: naem: microservicecloud-zuul-gateway eureka: instance:localhost #eureka服务端的实例名称 client: server-url: defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7001/eureka, http://eureka7003.com:7001/eureka,#所要注册到的eureka的地址 instance: instance-id: gateway-9527.com prefer-ip-address: true info: app.name: atguigu-microcloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$ host配置修改 127.0.0.1 myzuul.com  主启动类 @SpringBootApplication @EnableZuulProxy public class DeptConsumer80_APP { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_APP.class,args); } } 启动 ureka服务器集群,provider服务项目,一个Zuul项目。访问http://myzuul.com:9527/microservicecloud-dept/dept/get/2                                                                                                                 配置网关地址端口/         微服务地址         /controller层url

    3.路由访问的的映射规则(不暴露真实微服务地址)

    before:http://myzuul.com:9527/microservicecloud-dept/dept/get/2在yml中配置如下信息 zuul: routes: mydept.serviceId:microservicecloud-dept mydept.path:/mydept/** after:http://myzuul.com:9527/mydept/dept/get/2也可以访问。此时新,旧访问地址都可以访问解决 zuul: #设置前缀 prefix:/atguigu #ignored-services:"*"多个具体的微服务 #单个微服务 ignored-services:microservicecloud-dept routes: mydept.serviceId:microservicecloud-dept mydept.path:/mydept/**

     通过: http://myzuul.com:9527/atguigu/mydept/dept/get/2访问

     

     

    Processed: 0.017, SQL: 9