什么是微服务
传统单体架构
可以从上图看出,单体架构基本上就是如上所说的:一个应用,一个数据库,一个web容器,里面集成了所有的功能。这在小型项目里面时比较好维护的,毕竟功能不多,也不复杂,但扩展性和可靠性比较差,因为所有功能集成在一个服务或者一个war包中,修改某个功能时,需要所有服务重新打包。可能前期开发比较快,后期随着功能的增长,交互的周期会变长。
微服务架构
微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微
服务提供单个业务功能的服务,一个服务做一件事情,从技术角度看就是一种小而独立的处理过程,服务之间互相协调,互相配置,为用户提供最终价值。服务之间采用轻量级的通信机制互相沟通。类似进程的概念,能够自行单独启动或销毁,可以拥有自己独立的数据库。
什么是springCloud
SpringCloud, 基于SpringBoot提供了一套微服务解决方案,SpringCloud利用SpringBoot的开发便利性,巧妙地简化了分布式系统基础设施的开发,SpringCloud为
开发人员提供了快速构建分布式系统的一些工具,包括配置管理,服务发现,断路器,路由,微代理,
事件总线,全局锁,决策竞选,分布式会话等等,他们都可以用SpringBoot的开发风格做到一键启动和
部署。
springCloud的优缺点
优点:
- 每个服务足够内聚,足够小,代码容易理解,这样能聚焦一个指定的业务功能或业务需求;
- 开发简单,开发效率提高,一个服务可能就是专一的只干一件事;
- 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的。
- 微服务能使用不同的语言开发。
- 微服务只是业务逻辑的代码,不会和 HTML , CSS 或其他界面混合
- 每个微服务都有自己的存储能力,可以有自己的数据库,也可以有统一数据库
缺点:
- 微服务过多,治理成本高,不利于维护系统
- 分布式系统开发的成本高(容错,分布式事务等)对团队挑战大
springCloud有哪些组件
eureka
我们通过RestTemplate就可以实现服务远程调用,但存在一些问题?
-
在consumer中,我们把url地址硬编码到代码中不方便后期维护
-
consumer需要记忆user-service的地址,如果出现变更,可能得不到通知,地址将失效
-
consumer不清楚user-service的状态,服务宕(dang)机
-
user-service只有1台服务器,不具备高可用
-
即便user-service形成集群,consumer还需要自己实现负载均衡
概括一下分布式服务必然需要面临的问题: -
服务管理
-
如何自动注册和发现
-
如何实现状态监管
-
如何实现动态路由
-
服务如何实现负载均衡
-
服务如何解决容灾问题
而Eureka就是实现了服务的自动注册、发现、状态监控
-
Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址
-
提供者:启动后向Eureka注册自己信息(地址,提供什么服务)
-
消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
-
心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态
大部分摘自:汪随安
Ribbon(负载均衡)
Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。主要功能是提供客户端的软件负载均衡算法。就是在配置文件中列出LoadBalancer(简称LB:负载均衡)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等等)去连接这些机器。
feign(负载均衡)
简介:
feign是声明式的web service客户端(实体类的api+消费者),它让微服务之间的调用变得更简单了,类似controller调用service。
Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。
只需要创建一个接口,然后添加注解即可!
它的出现是大家都习惯面向接口编程。所以出现了调用微服务访问两种方法
- 微服务名字 【ribbon】
- 接口和注解 【feign 】
作用:
feign负载均衡是利用Ribbon维护了微服务的列表信息,并且通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而且简单的实现了服务调用。
Hystrix(服务熔断)
什么是服务雪崩
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B 和微服务C又调用其他的微
服务,这就是所谓的 “扇出”、如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A
的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的 “雪崩效应”
在微服务架构中,一个请求需要调用多个服务是非常常见的。如客户端访问 A 服务,而 A 服务需要调用 B 服务,B 服务需要调用 C 服务,由于网络原因或者自身的原因,如果 B 服务或者 C 服务不能及时响应,A 服务将处于阻塞状态,直到 B 服务 C 服务响应。此时若有大量的请求涌入,容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,造成连锁反应,会对整个微服务系统造成灾难性的严重后果,
这就是服务故障的“雪崩”效应
什么是Hystrix
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调
用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器” 本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩.
Hystrix能干嘛
服务熔断
熔断机制是对应雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回 错误的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制。
熔断机制的注解是 @HystrixCommand
。
使用:
@RestController
public class DeptController {
@Autowired
private DeptService service;
// @RequestBody
// 如果参数是放在请求体中,传入后台的话,那么后台要用@RequestBody才能接收到
@HystrixCommand(fallbackMethod = "hystrixGet")
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
Dept dept = service.queryById(id);
if (dept == null)
throw new RuntimeException(id+"不存在,找不到");
return dept;
}
public Dept hystrixGet(@PathVariable("id") Long id) {
return new Dept().setDeptno(id).setDname("找不到该"+id+"相关的用户").setDb_source("找不到该数据库");
}
}
在提供者的controller中,定义一个自定义预期返回的方法,使用 @HystrixCommand
注释到可以能发生异常的方法上,并使用关键字fallbackMethod = ""
,值是指定熔断后所调用的方法。
服务降级
什么是服务降级,整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。
服务降级处理是在客户端实现完成的,与服务端没有关系
服务降级的使用
在改springcloud-api工程,根据已经有的DeptClientService接口新建一个实现了FallbackFactory接口的类DeptClientServiceFallbackFactory。此FallbackFactory
接口是feign.hystrix.FallbackFactory;
包下(feign也集成hystrix一些功能)
springcloud-api工程的pom.xml(没有spring-cloud-starter-hystrix)也是可以使用hystrix一些功能
<?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">
<parent>
<artifactId>springCloudTest</artifactId>
<groupId>com.zjj</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springboot-api</artifactId>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--Feign相关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
【注意:这个类上需要@Component注解!!!】
import com.zjj.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
public DeptClientService create(Throwable throwable) {
return new DeptClientService(){
public boolean addDept(Dept dept) {
return false;
}
public Dept queryById(Long id) {
return new Dept().setDname("没有对应的信息,Consumer客户端提供" +
"的降级信息,此刻服务Provider已经关闭").setDb_source("找不到该数据库");
}
public List<Dept> queryAll() {
return null;
}
};
}
}
在springcloud-api工程下DeptClientService类中@FeignClient
加上fallbackFactory = DeptClientServiceFallbackFactory.class
,而且这个
package com.zjj.service;
import com.zjj.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@PostMapping("/dept/add")
public boolean addDept(Dept dept); //添加一个部门
@GetMapping("/dept/get/{id}")
public Dept queryById(Long id); //根据id查询部门
@GetMapping("/dept/list")
public List<Dept> queryAll(); //查询所有部门
}
之后就可以运行看看了,只开启了提供者8001,可以正常运行,之后关闭提供者8001,消费者可以正常运行,不过返回的是api工程@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
中指定的方法
public Dept queryById(Long id) {
return new Dept().setDname("没有对应的信息,Consumer客户端提供" +
"的降级信息,此刻服务Provider已经关闭").setDb_source("找不到该数据库");
}
服务监控(hystrixDashboard)
Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求,多少成功,多少失败等等。
Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控,SpringCloud也提供了HystrixDashboard的整合,对监控内容转化成可视化界面!
使用:新建一个工程
在此工程中导入Hystrix和hystrix-dashboard的jar包
<!--Hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
</dependencies>
在此工程的主启动类上使用@EnableHystrixDashboard
开启服务监控
package com.zjj.springCloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableHystrixDashboard
public class DeptConsumerDashBoardApp9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashBoardApp9001.class,args);
}
}
之后运行此工程,访问http://localhost:9001/hystrix
,进入监控页面
到这里还没有结束
需要在提供者 在springcloud-provider-dept-hystrix-8001 主启动类中增加一个bean
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet() {
ServletRegistrationBean registration = new
ServletRegistrationBean(new HystrixMetricsStreamServlet());
registration.addUrlMappings("/actuator/hystrix.stream");
return registration;
}
注意提供者必须导入了`
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>`
然后运行此提供者工程,运行此urlhttp://localhost:8001/actuator/hystrix.stream
它会一直加载此页面,上面的信息看不懂吧,哪么就用到了之前创的springcloud-consumer-hystrix-dashboard-9001
工程
使用url:http://localhost:8001/actuator/hystrix.stream
传入豪猪的地址栏就可以进入可视化界面