【总结】Spring微服务

分布式理论

分布式基础理论

分布式系统目标:提升系统的整体性能和吞吐量另外还要尽量保证分布式系统的容错性;

分布式系统设计思想:中心化和去中心化;

CAP定理:一致性(Consistence)、可用性(Availability)、分区容错性(Partition tolerance) ;

BASE理论:Basically Available(基本可用)、Soft-state(软状态)、Eventually Consistent(最终一致性);


微服务基础理论

什么是微服务:小、独立、轻量级通信、无集中式管理;

微服务利弊:强模块边界 、独立部署、技术多样性;分布式复杂性、最终一致性、运维复杂性、测试复杂性;

中台战略:对后台的细分,大中台小前台,把前端的应用变得更小更灵活;

微服务分层:接入层、网关层、业务服务层(聚合服务、基础服务)、支撑服务层、平台服务、基础设施层;

微服务技术栈:服务发现、网关、配置中心、服务框架和治理、监控、限流熔断、容器部署&持续交付流水线、容器调度和发布体系;


分布式事务

产生原因:数据库分库分表导致多数据源访问;应用SOA化,每个服务都有自己的数据库;

2PC:请求阶段和提交阶段;缺点:同步阻塞、协调者单点故障、数据不一致(任一阶段发生网络故障就会导致);无法解决的问题:协调者和参与者同时出现故障时,保证事务的完整性;

3PC:准备阶段、请求阶段和提交阶段;优点:减少阻塞范围,单点故障后能达成一致;缺点:还是有不一致问题;

TCC补偿事务:Try(负责资源的检查和预留)、Confirm(执行真正的业务操作)、Cancel (执行回滚)3个方法均由业务编码实现;

业务实现TCC的注意事项:业务操作需要按Try、Confirm/Cancel两步骤完成、允许空回滚、防悬挂控制(Cancel之后不处理Try)、幂等控制;

本地消息表:发起和执行事务的服务都记录消息到本地DB;保证本地事务(消息和业务同一事务提交);更新消息状态;轮训并重试机制;

MQ事务消息:RocketMQ中间件能够支持一种事务消息机制,确保本地操作和发送消息的异步处理达到本地事务的结果一致;

最大努力通知:重复N次尝试相同动作;


分布式一致性

CAP、BASE、2PC、3PC:参考上面;

Paxos :3个角色:proposers提议,acceptors投票接收提议, learners被通知结果;绝大多数acceptors接收才通过提议;节点可身兼多角色;

Zab:为Zookeeper专门设计的一种支持崩溃恢复和原子广播协议;一种Paxos的实现和改进;主备模式即只有主节点才是proposers即leader,然后由主节点复制给其他节点follower;

消息广播:使用原子广播协议,类似2阶段提交,但只要一半以上Fllower返回ACK即提交,减少阻塞;

崩溃恢复:Leader挂了之后,自动进入崩溃恢复模式,选举新的 Leader,并完成数据同步,然后退出崩溃恢复模式进入消息广播模式;

Raft:用于管理复制日志的一致性算法,也是一个主备模型,有一个唯一的 leader 控制任务的提交;节点分为领袖、群众和候选人;每一个 leader 都有自己的任期,必须在任期内发送心跳信息给 follower 来延长自己的任期。

NWR:在分布式存储系统中控制一致性;N(备份数据数量),W(一次更新操作写入成功的数量)、R(一次读取操作读取成功的数量);NWR值的不同组合会产生不同的一致性效果,当 W+R>N 的时候,整个系统对于客户端来讲能保证强一致性;


分布式缓存

应用场景:页面缓存、应用缓存、解决Session同步、并行计算共享中间数据等;

框架主要是Memcache和Redis:Memcache不支持持久化、只支持简单keyValue数据类型、KeyValue空间较小、使用CAS保证数据一致性、内存管理采用预先分配,避免了内存碎片但不能变长会浪费;

常见问题:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级;


分布式锁

需考虑问题:分布式锁是否可重入,分布式锁的释放时机(超时),分布式锁服务端是否有单点问题等。

基于数据库(唯一索引)实现:通过唯一索引保持排他性,加锁时插入一条记录,解锁是删除这条记录;

通过判断锁持有者实现可重入,通过记录和查询锁时间实现超时,通过数据库分布式解决单点问题;

基于缓存(Redis)实现:内存操作,效率最高,利用SETNX key value命令实现;解锁使用Lua脚本实现保证原子性;

通过判断锁持有者实现可重入,通过Redis自带的Key超时机制实现锁超时,通过Redis分布式解决单点问题;

基于Zookeeper实现分布式锁:利用Zookeeper创建临时有序节点来实现分布式锁;判断节点序号最小则加锁成功,否则注册Watcher事件等待前面节点(序号小的获取到锁的)通知则获取到锁;通过客户端加锁时将主机和线程信息写入锁中,下一次再来加锁时直接和序列最小的节点对比实现可重入,ZK自动删除灰化断开的临时节点实现锁超时;ZK集群解决单点问题;通过curator框架可实现ZK分布式锁;


分布式Session

粘性session:将用户锁定到某一个服务器上,Nginx通过配置ip_hash实现;

session复制:任何一个服务器上的session发生改变(增删改),该节点会把这个 session的所有内容序列化,然后广播给所有其它节点,不管其他服务器需不需要session,以此来保证Session同步;优点:可容错;缺点:网络压力,拖慢服务器性能;可通过Tomcat集群配置实现;

session共享:将Session保存在分布式缓存Memcache或Redis中,Tomcat本身不存储session,Tomcat可通过MSM插件实现;

session持久化到数据库:数据库专门用来存储session信息,保证session的持久化;


负载均衡

负载均衡分类:按照ISO网络模型及工作的层数分为:

二层负载均衡:基于数据链路层,负载均衡服务器和业务服务器绑定同一个虚拟IP,客户端请求虚拟IP,负载均衡服务器通过改写Http请求的MAC地址实现;

三层负载均衡:基于网络层,按照不同机器不同IP地址进行转发请求到不同的机器上;

四层负载均衡:基于传输层,通过TCP/UDP协议,基于IP+端口号进行请求的转发,如LVS;

七层负载均衡:基于应用层,通过HTTP,DNS协议,基于请求的URL进行转发负载,如Nginx;

一般会采用DNS+LVS+Nginx的方式进行多层次软件层面的负债均衡,还有在前面多加一层物理负载均衡,比如知名的F5。

负载均衡算法:

静态算法:轮训、随机、源地址哈希、加权轮训、加权随机、键值范围法;

动态算法:最小连接数法、最快响应时间法、观察模式法(综合最小连接数和最快响应度,进行权重分配);


Spring

核心模块:Spring Core、Spring Context、Spring AOP、Spring DAO、Spring ORM、Spring Web、Spring MVC;

优点:低侵入、IOC降低组件的耦合、AOP提高复用、支持集成主流框架;

AOP:对OOP的补充,抽离可复用模块;采用动态代理实现,有接口采用JDK动态代理(InvocationHandler、Proxy),无接口采用基于继承的CGLib(不能Final,MethodInterceptor、Enhancer);不修改字节码,AspectJ是静态代理,需要使用特定编译器修改字节码,性能好些;

几个名词:切面(Aspect)、连接点(Join point)、通知(Advice)、切入点(Pointcut)、目标对象、织入(Weaving),关键是连接点和切入点匹配;

通知类型:前置通知、返回后通知、抛出异常后通知、后通知、环绕通知;

IOC:即创建对象的主动权和时机的权利由类本身转移给Spring容器;采用反射实现组件间松耦合;和DI一个意思只是描述角度不同;3种注入方式:构造器、Setter、实例工厂、静态工厂、注解;

BeanFactory和ApplicationContext:都是Spring容器,BeanFactory管理bean的生命周期和依赖,bean采用延迟加载;ApplicationContext是其子接口,做了扩展,增加了国际化、监听事件等功能,容器启动时一次性加载所有bean;

Bean的加载(生命周期):通过解析XML和扫描注解获取Bean定义、实例化bean、设置对象属性(DI)、处理xxAware接口、执行BeanPostProcessor的before方法、执行初始化方法init-method、执行BeanPostProcessor的after方法即完成bean的创建;销毁:调用DisposableBean的destory方法、调用destroy-method方法;

Bean作用域:singleton、prototype、request、session、global-session、application;

Bean的元数据配置:基于XML配置、基于注解配置(@Component、@Servce等)、基于JavaConfig(@Configration、@Bean)代码配置;

线程安全:默认单例,线程不安全,需要自己处理或者使用prototype;Spring内部对有状态的bean采用ThreadLocal解决线程安全问题;

自动装配:基于XML:ref、byName、byType、constructor、autodetect;基于注解:Autowired、Resource;

使用的设计模式:工厂(BeanFactory)、单例模式、代理模式(AOP)、模板方法(RestTemplate)、观察者模式(ApplicationListener);

事务:Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的;

事务种类:编程式事务(TransactionTemplate写代码手动提交)、声明式事务(Transactional注解自动提交);

事务传播行为(存在多个事务是如何处理):根据是否存在事务、当前事务是新建、不建、抛异常、嵌套、加入已有事务(默认)等分成多种;

事务隔离级别:默认使用数据库的事务隔离级别、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE;

事务超时:支持定义事务执行超时时间;

事务回滚规则:定义了哪些异常会导致事务回滚而哪些不会。默认情况下,事务只有遇到运行期异常时才会回滚;

事务是否只读:表示这个事务只读取数据但不更新数据, 这样可以帮助数据库引擎优化事务;

主要类:PlatformTransactionManager(事务管理器接口,Spring 有默认实现,或者需要其他持久层框架实现)、TransactionDefinition(事务基本属性:隔离级别、传播行为、是否只读、事务超时、回滚规则)、TransactionStatus(记录事务状态);

事件:继承ApplicationEvent ,如果实现了ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean会自动被通知,包括ContextRefreshed/Started/Stopped/ClosedEvent(上下文刷新、启动等)、RequestHandledEvent(http请求结束);


Spring MVC

流程:用户请求发送至前端控制器DispatcherServlet、DispatcherServlet调用HandlerMapping获取Handle、HandlerMapping根据URL找到handle及所有拦截器生成调用链返回给DispatcherServlet、DispatcherServlet 调用 HandlerAdapter处理器适配器执行、HandlerAdapter 调用handle执行并返回ModelAndView给DispatcherServlet、DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析、ViewResolver解析后返回具体View、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)、DispatcherServlet响应用户;

主要组件:DispatcherServlet(转发器,总调度)、HandlerMapping(处理器映射器、根据URL找Handle)、HandlerAdapter(处理器适配器,执行handle)、Handler(处理器,需要开发)、ViewResolver(视图解析器、解析成真正的视图View)、View(视图,需要开发jsp);

和Struts2区别:SpringMVC入口是DispatcherServlet、一个URL一个方法、通过请求解析器对方法形参赋值;Struts入口是过滤器、基于类开发即类属性为请求参数,需要多例,采用值栈存储数据,通过OGNL存取数据;

实现拦截器:实现接口HandlerInterceptor(方法执行顺序:preHandle、postHandle、afterCompletion)、继承HandlerInterceptorAdapter;

常用注解:@Component、@Repository、@Service、@Controller、@RestController、@Configuration 、@Bean;@Autowired、@Resource、@PostConstruct 、@PreDestroy ;@RequestMapping、@RequestParam、@PathVariable、@ResponseBody、@RequestBody、@Transactional ;


SpringBoot

优点:简化难度,提供启动器,快速上手,独立运行,简化配置,自动配置,无代码生成和XML配置,无需部署war文件;

核心注解:@SpringBootApplication,是复合注解包括@SpringBootConfiguration(复合注解即@Configuration实现配置文件的功能)、@EnableAutoConfiguration(实现自动配置)、@ComponentScan(组件扫描);

Maven中引入SpringBoot的方式:继承spring-boot-starter-parent项目、导入spring-boot-dependencies项目依赖;

兼容老Spring项目:使用 @ImportResource 导入老 Spring 项目配置文件;

配置加载:按顺序依次:命令行参数、系统环境变量、properties文件、YAML文件(先找Jar外面的,再里面的,如果指定了profile则先找profile文件再找没有的,没指定profile只找没有的),后加载的不会覆盖前面的;

热部署:在springboot的maven插件中引入springloaded插件并使用mvn spring-boot:run启动;或者引入项目依赖spring-boot-devtools并配置devtools参数实现;

读取配置:@Value(读值)、@ConfigurationProperties(指定前缀)、@PropertySource(指定文件路径)、Environment(所有配置);

启动时执行:实现ApplicationRunner 或者 CommandLineRunner接口;

自动配置原理:通过SpringBootApplication注解引入EnableAutoConfiguration(引入@Import(AutoConfigurationImportSelector.class))、AutoConfigurationImportSelector的selectImports()方法通过SpringFactoriesLoader.loadFactoryNames()扫描所有jar包的META-INF/spring.factories文件获取KeyValue即自动配置类JavaConfig、解析这些Spring容器配置类即可完成自动加载;

启动原理:第1步:通过SpringApplication.run方法进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器;第2步:实现应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块;第3步:自动化配置模块,该模块作为springboot自动配置核心;


Spring Cloud

特点:约定优于配置、开箱即用,快速启动、轻量级的组件、组件丰富,功能齐全;

和Dubbo区别:Dubbo基于RPC二进制传输,带宽占用较少,Spring基于Rest传输;Dubbo是SOA的产物,除了服务注册和服务监控没有其他网关、配置中心、断路器等组件;Dubbo需要区分服务生产者和消费者,Eureka不区分,统称Client;ZK维持与集群间的长连接,定时发送心跳,Eureka只是基于心跳超时没有长联接;ZK节点变更后会立刻反馈,Eureka基于节点定时拉取有延迟;


Spring Cloud Eureka

设计原则:AP,即可用性和分区容错性,只保证最终一致性;ZK是CP,保证强一致性,ZK选举时和节点超过一半挂掉时会不可用;

设计架构:CS架构,包含Eureka Server(注册中心)和Eureka Client(包含服务提供和消费者)两个组件;

服务提供者:启动时发送register请求,运行中定时发送renew请求,主动停止时发送cancel请求;服务消费者:启动时拉取服务注册信息,运行中定时更新服务注册信息,优先调用同区域服务,若没有同区域则负载均衡调用其他区域;注册中心:启动时从其他节点拉取服务信息,定期剔除没有renew的服务,接收到的请求会同步给其他节点;

数据存储结构:分数据存储层和缓存层两层,内部采用ConcurrentHashMap保存服务信息;

服务管理:服务注册(启动时向注册中心注册)、服务续约(注册后每隔30S发送renew请求)、服务注销(正常停止前向注册中心发送cancel请求)、服务剔除(若没有开启自我保护并且90s没收到renew请求则剔除)、服务获取(全量同步和增量同步,先从缓存中取)、服务同步(启动时同步、运行时同步:节点有register、renew、cancel 请求则构造对象加入队列等待线程处理);

自我保护:短时间15分钟内过多85%客户端失去连接(可能自身网络问题)时进入自我保护模式,不删除服务注册信息;可以继续处理注册请求,不再同步给其他节点;网络恢复后退出自我保护并同步节点;

使用:@EnableDiscoveryClient 、@EnableEurekaServer ;

和ZK区别:ZK遵循CP原则,leader选举期间集群不可用;Eureka遵循AP原则,节点平等互不影响,一个节点也能工作,通过自我保护能很好地应对网络故障;


Spring Cloud Hystrix

作用:解决服务雪崩、控制和保护第三方依赖、阻止故障的连锁反应、快速失败并迅速恢复、回退并优雅降级;

使用:继承HystrixCommand或HystrixObservableCommand,通过execute、queue、observe、toObservable方法执行;@HystrixCommand配置策略,

资源隔离:线程池隔离:将每个command放到单独的线程池中,线程池满则拒绝服务;缺点:增加了排队、调度、上下文切换的开销;信号量隔离:不启动新线程,在原有线程中执行,没有上下文切换的开销,通过信号量限制并发资源数量,拿不到信号量则拒绝进入fallback,不支持异步执行和超时;

熔断器:初始关闭状态,若统计时间窗内请求数超过阈值并且错误率超过50%则打开(请求数不够则不处理);5秒后为半开状态,允许一个请求执行;若成功则熔断器关闭,失败则打开;

回退降级:command执行抛异常、熔断器打开、线程池信号量满、命令执行超时都会进入降级;快速失败:直接抛异常;无声失败:返回空、静态或缓存数据;


Spring Cloud Ribbon

使用:客户端负载均衡,引入jar、配置参数,RestTemplate加上@LoadBalanced,通过RestTemplate的方法直接通过服务名调用接口即可;

核心组件:每个组件都有默认实现,方便开箱即用和自定义各组件功能;ILoadBalancer(负载均衡器,协调其他组件完成获取和选择服务实例的功能)、IClientConfig(客户端配置)、IRule(负载均衡策略)、IPing(实例检查策略,默认不检查都可用)、ServerList(服务实例清单维护机制)、ServerListFilter(服务实例清单过滤机制);

负载均衡策略:简单轮询roundRobin、加权响应时间(根据响应时间分配一个weight,时间越长weight越小)、随机、重试、选择一个最小的并发请求的server;


Spring Cloud Feign

使用:声明式的 Web Service 客户端,简化对第三方服务的调用方式,Spring Cloud Open Feign 对 Feign 进行增强支持 Spring MVC;使用注解@EnableFeignClients、@FeignClient(配置要调用的服务名称和地址);通过定义一个接口即可完成本地化调用,无需写代码;

工作原理:

主程序添加 @EnableFeignClients 注解开启对 Feign Client 扫描,定义接口并加 @FeignClients 注解;

扫描所有 @FeignClients 的注解的类,注入 Spring IOC 容器中,当方法被调用时,通过JDK的代理的方式,为每个接口方法生成RequestTemplate,并封装所需的所有Http请求参数;

然后由 RequestTemplate 生成 Request,把 Request 交给 Client(原生的 URLConnection或HttpClient) 去处理;

最后 Client 被封装到 LoadBalanceClient 类,结合 Ribbon 负载均衡发起服务之间的调用;


Spring Cloud Zuul

作用:身份验证、监控、动态路由、限流过滤等;

使用:引入Jar,启动类加上@EnableZuulProxy、配置路由规则即可;

工作原理:通过一系列不同类型的过滤器实现,包括pre过滤器(发送到原始服务器前)、route过滤器(发送原始服务器处理)、post过滤器(原始服务器返回后),每种都自带多个默认的过滤器;

自定义过滤器:继承ZuulFilter,filterType方法指定过滤类型(pre、route、post、error)、filterOrder指定过滤器优先级、shouldFilter开启过滤、run实现过滤逻辑;


Spring Cloud Config

使用:新建工程、引入Jar、加上@EnableConfigServer,配置文件存储参数(GIT、数据库、SVN、本地文件),自带Rest接口可通过浏览器访问获取对应服务的配置文件;

自动刷新配置:引入actuator包,在使用参数的类上加@RefreshScope,手动调用refresh Rest接口刷新配置到服务中;

解决单服务自动刷新:利用Github的Webhook机制配置刷新接口地址,做到代码更改自动调用接口;

解决多服务自动刷新:引入Sprng Cloud Bus结合消息中间件做消息广播,调用一个服务的刷新接口自动通知其他服务自动调用;


Spring Cloud Sleuth

作用:调用链监控工具的客户端,集成在各个微服务上,负责产生调用链监控数据;

概念:Span:跨度,基本工作单元;Trance:跟踪,包含一系列的span;Annotation:标注,包括CS(Client Sent 客户端发送)、SR(Server Received 服务端接收)、SS(Server Sent 服务端发送)、CR(Client Received 客户端接收);

集成Zipkin:Sleuth负责生成调用链数据,Zipkin对的各个服务的调用链数据进行采集、存储、分析和展示并提供API查询;包含采集器、

几个概念:traceId:确定一个追踪链,在某个追踪链中保持不变;spanId:区域Id,在一个追踪链中spanId可能存在多个,每个spanId用于表明在某个服务中的身份;parentId:调用自己的父spanId;


Spring Cloud Security

作用:为构建安全的SpringBoot应用提供了一系列解决方案,结合Oauth2可以实现单点登录、令牌中继、令牌交换等功能;

OAuth2:(Open Auth)

相关名词:Resource owner:资源拥有者,有访问资源的账号密码;Resource server:资源服务器,拥有受保护资源的服务器,如果请求包含正确的访问令牌,可以访问资源;Client:客户端,访问资源的客户端;Authorization server:认证服务器,用于认证用户的服务器,如果客户端认证通过,发放访问资源服务器的令牌;

授权模式:Authorization Code(授权码模式):正宗的OAuth2的授权模式,客户端先将用户导向认证服务器,登录后获取授权码,然后进行授权,最后根据授权码获取访问令牌;Implicit(简化模式):和授权码模式相比,取消了获取授权码的过程,直接获取访问令牌;Resource Owner Password Credentials(密码模式):客户端直接向用户获取用户名和密码,之后向认证服务器获取访问令牌;Client Credentials(客户端模式):客户端直接通过客户端认证(比如client_id和client_secret)从认证服务器获取访问令牌。

使用:@EnableAuthorizationServer、@EnableResourceServer,添加SpringSecurity配置,自带一个登陆界面;

JWT:(Json Web Token),解决OAuth不携带用户信息,且资源服务器无法进行本地验证,需要向认证服务器发起请求的问题;

格式:特殊的token;头部Header(加密方式)、载荷Payload(需要传输的数据)、签名Signature(防篡改) 3部分均用base64进行编码,当中用.进行分隔,加密密码在服务端保存;


Spring Cloud Stream

作用:实现消息驱动开发,抽象消息中间件,封装统一的接口方法,可以轻松与各种消息中间件对接和实现替换;

应用模型:Source(序列化消息并发送消息到Channel中)、Sink(监听并从Channel中获取消息并反序列化消息)、Channel(消息通道,通过抽象解耦具体的消息中间件)、Binder(通过不同的Binder可以实现与不同消息中间件的整合);

应用原理:提供注解@Input:创建一个消息输入通道,用于消息监听;@Output:创建一个消息输出通道,用于消息发送;@EnableBinding:建立与消息通道的绑定;提供Source、Sink接口支持开箱即用;


Spring Cloud Bus

作用:在Stream基础之上再次进行抽象封装,使得我们可以在不用理解消息发送、监听等概念的基础上使用消息来完成事件的业务逻辑的处理;

Spring的事件机制:ApplicationEvent定义事件、ApplicationListener监听事件、ApplicationContext.publishEvent()发布事件;

Bus事件机制:扩展了Spring,开启功能扫描@RemoteApplicationEventScan、继承RemoteApplicationEvent定义事件、RemoteApplicationEventPublisher.publishEvent发布事件、ApplicationListener监听事件;

你可能感兴趣的:(【总结】Spring微服务)