第一章
传统应用问题
传统的系统架构是一个单体架构
经典的基于B/S的系统架构,将三层交互统一再一个war包部署在容器里。
项目过于庞大,用户量达到上万和上百万时,传统项目有如下不足:
- 开发相对困难:模块之间的强耦合性过多
- 项目管理相对困难:远程仓库有很多不同分支点,可能需要多个分支点进行代码维护
- 测试相对困难:测试人员针对多个模块需要对不同生产环境进行测试
- 代码可读性差:后期需求模块的叠加,可能会出现代码冗余,新来的开发人员接受时可能不适应
- 高并发的处理:随着用户越来越多,累计的业务需求,不断增多,带来的问题更多
架构演进
引入给予ESB总线的SOA架构
特点
- 将业务模块服务化,统一注册到ESB中,降低各模块的耦合度
- ESB将会成为性能额度瓶颈
微服务
将单体应用划分为更小的服务单元,为服务之间使用HTTP的API进行资源访问和操作
微服务的特点
- 通过服务实现组件化
开发者不再需要协调其他服务部署对本服务的影响 - 按业务能力来划分服务和开发团队
开发者可以自由选择开发技术,提供API服务 - 去中心化
每个微服务有自己私有的数据库持久化业务数据
每个微服务只能访问自己的数据库,而不能访问其他服务的数据库
某些业务场景下,需要在一个事务中更新多个数据库。这种情况也不能直接访问其他微服务的数据库,而是通过对于微服务进行操作
数据的去中心化,进一步降低了微服务之间的耦合度,不同服务可以采用不同的数据库技术。在复杂的业务环境下,如果包含多个微服务,常常在哭护短或者中间层(网关)处理 - 基础设施自动化(devops、自动化部署)
微服务架构=80%SOA服务架构思想+100%组件化架构思想+80%领域建模思想
springcloud实现微服务
springcloud封装netflix的多个框架(OSS)
- Eureka:给予REST服务的分布式中间件,主要服务管理
- Hystrix:容错框架,监控和断路器。只需要在服务接口上添加Hystrix标签,就可以实现对这个接口的监控和断路器功能
- Feign:服务客户端,服务之间如果互相访问,就可以使用RestTemplate,也可以使用Feign客户端访问。它默认会使用Ribbon来实现负载均衡。
- Zuul:网关,所有的客户端请求通过这个网关访问后台的服务。它可以使用一定的路由配置来判断某一个URL由哪个服务来处理。并由Eureka获取注册服务来转发请求
- Ribbon:即负载均衡,Zuul网关将一个请求发送给某一个服务的应用的使用,如果一个服务启动了多个实例,就会通过Ribbon来通过一定的负载均衡策略来发送给某一个服务实例
开发简单微服务应用
实现以下应用服务架构
第二章 微服务发布与调用
集群与分布式
集群:同一个业务部署在多个服务器上
集群模式是不同服务器部署同一套服务对外访问,实现服务的负载均衡
集群方式特点是根据部署堕胎服务器业务是否相同
Nignx是一种非常灵活的反响代理软件,可以自由定制化转发策略,分配服务器流量的权重等 起到负载均衡服务
分布式:一个业务拆分成多个子业务,部署在不同的服务器上
将一个大的系统划分为多个业务模块,业务模块分别部署到不同机器上,各个业务模块之间通过接口进行数据交互。
分布式方式特点是根据不同机器不同业务
区别:
- 分布式是将不同的业务分布在不同的地方。而集群指的是将几台服务器集中在一起,实现同一业务。
- 分布式是以缩短单个任务的执行时间来提升效率的,而集群是通过提高单位时间内执行的任务数来提升效率
设计原则:
好的设计应该是分布式和集群的结合,先分布式再集群
而具体实现就是业务拆分成很多个子业务,然后针对每个子业务进行集群部署,这样每个子业务如果出了问题,整个系统完全不会受到影响。
Eureka集群搭建
- 构建两个服务器实例并且相互注册
- 构建两个服务发布者都要分别注册到服务器
- 构建一个服务调用者
- 创建HttpClient客户端访问服务调用者
第三章 Ribbon负载均衡
负载均衡:解决整个服务集群的性能与稳定
负载均衡提供以下功能:
维护各个服务器的IP地址信息
根据特定逻辑选取服务器
Ribbon:是Netflix下的负载均衡框架,支持可插拔式的负载均衡规则。它在微服务集群中为各个客户端提供通信的支持。是客户端的负载均衡器
特点:
- 支持多种协议:HTTP(TCP),UDP协议等
- 提供负载均衡客户端
- 既可以调用Ribbon原生的API,也可以使用spring封装好的RIbbonAPI实现负载均衡
开发简单Ribbon程序
Ribbon负载均衡机制
负载均衡器(接口)
Ribbon自带的负载规则
自定义负载规则
Ping机制
在负载均衡中,使用Ping机制,每隔一段时间去Ping服务器,判断服务器是否存活。使用IPing接口的实现类完成
第四章 在springcloud中使用Ribbon
Eureka使用Ribbon架构
Ribbon工作时分为两步:
第一步选择EurekaServer,它优先选择在统一Zone且负载较少的Server
第二步再根据用户指定的策略,再从Server取到可用服务注册列表,从中选择一个服务地址。其中RIbbon提供了很多策略,例如轮询,随机,根据响应时间加权。
- 创建eureka服务器
- 创建eureka服务提供者
- 创建eureka服务调用者
- 将自定义的负载规则myrule和myping放到服务调用者中
- 为服务提供者指定ribbon配置类,指定myrule和myping;也可以使用配置文件设置ribbon
- 测试负载均衡
利用拦截机制,实现一个简单的resttemplate
- 模仿@LoadBalanced注解,编写一个自定义注解
- 对原来的请求URI进行拦截并改写,所有的请求都会转移到指定的uri中
- 将原来的HttpRequest请求对象转换成自定义的MyHttpRequest
- 再spring容器中使用了@MyLoadBalanced修饰的RestTemplate实例,该实例会被加入配置类的RestTemplate集合中
- 根据名称调用服务,这个URI会被拦截器所置换,参考2
第五章 REST客户端Feign
rest客户端
使用CSF调用/发布REST服务
apachecxf是一个开源的web Service框架,CSF可以用来构建和开发WebService,这些服务可以支持多种协议,比如SOAP、POST/HTTP、CXF大大简化了webService冰球额可以和spring进行无缝集成
CSF是celtrix(esb框架)和xfire(webservice)合并拼成,核心是org.apache.cxf.Bus(总线),类似于spring的ApplicationContext,CXF默认是依赖于spring的
CXF内置了Jetty服务器,他是servlet容器
使用CXF调用REST服务
Restlet调用/发布REST服务
Restlet是一个轻量级的REST框架,可以发布或调用REST风格的WebService
Feign框架
Feign是一个GIthub的开源项目,目的是为了简化WebSerivce客户端的开发, 在使用feign时,可以使用注解来修饰接口,被注解修饰的接口具有访问WebService的能力,这些注解中既包括了feign自带的注解,也支持使用第三方的注解。除此之外,feign还支持使用插件式的编码器和解码器,使用者可以通过该特性,对请求和响应进行不同的封装和解析
springcloud将feign集成到netflix项目中,当与eureka、ribbon集成时,feign就具有负载均衡的功能,feign本身在使用上的简便性,加上与springcloud的高度整合,使用该框架在springcloud中调用集群服务,将会大大降低开发的工作量。
第一个Feign程序
l利用Feign框架开发REST客户端
在接口中使用@RequestLine区注册方法sayHello和请求的类型
通过调用sayHello,产生动态代理发出请求,方法的返回值就是请求处理后的响应
请求参数与返回对象
声明请求类型和注册方法
给属性添加注入器、
增加GsonDecoder解码器,会将返回的响应JSON字符串转换为接口方法返回的对象
编码器
向服务器发送请求的过程中,客户端使用的数据格式与服务端使用的格式不一致,使用编码器
consume是指定请求内容的类型
produces是指定返回内容类型
@Heads注解声明请求类型为JSON
在构建方法中使用编码其将请求对象转换成JSON字符串
XML的编码与解码
除了提供支持JSON处理外,Feign为XML处理提供了相应的编码器与解码器
JAXBEncoder与JAXBDecoder
注意:在SpringBoot进行Web构建时,默认情况下不支持XML接口,在pom。xml中添加依赖
Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 4 counts of IllegalAnnotationExceptions
类的两个属性具有相同名称 "age"
第六章 REST客户端Feign
自定义编码器与解码器
Feign的编码器、解码器都是支持自定义拓展,可以对请求以及结果和发起请求进行自定义实现
Feign默认支持JSON格式的编码器和解码器,如果希望支持其他的或者自定义格式就需要编写自己的编码器和解码器
自定义编码器需要实现Encoder接口
自定义解码器需要实现Decoder接口
自定义Feign客户端
Feign使用一个feign.Client接口来发送请求,默认实现是使用HttpURLConnection连接http服务
我们可以实现这个接口来完成自定义Feign客户端的开发,该接口只有一个方法execute,用于执行请求
Feign解析第三方注解
利用注解修饰接口方法,可以让接口方法获得访问服务的能力
也可以使用第三方注解或自定义注解来修饰接口方法,同样使得接口方法获得访问服务的能力
设置了JAXRSContract类,Feign就知道如何处理JAXRS的相关注解
JAXRSContract继承了BaseContract类,BASEContract类实现了Contract接口
简单来说,一个COntract就相当于一个翻译器
Feign本身并不知道第三方注解的含义,而是通过实现一个翻译器来告诉Feign
设计自定义注解告诉Feign,然后Feign通过翻译器Contarct解析自定义的注解
- 自定义注解
- 注解客户端接口
- 自定义翻译器
contract实际上承担的是一个翻译的作用,将第三方注解的作用告诉Feign
第七章 spirngcloud的保护机制
概述-实际问题(雪崩效应)
分布式系统环境下,服务间依赖非常常见,一个业务调用通常依赖多个基础服务。对于同步调用,当库存服务不可用时,商品服务请求县城被阻塞,当有大批量请求调用库存服务时,最终可能导致整个撒谎给你怕服务资源耗尽,无法继续对外提供服务。
并且这种不可用可能沿着请求调用链向上传递,这种现象被称为雪崩效应
产生原因
- 硬件故障(服务宕机)
- 流量激增(异常流量增加)
- 缓存穿透(一般发生在应用重启,所有缓存失效时,以及短时间内大量缓存失败时。大量的缓存不明中,使请求直击后端服务,造成服务提供者超负荷运行,引起服务不可用)
- 程序bug导致内存泄漏
- 同步等待造成资源耗尽
集群容错
如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就出在被拖垮的风险中。因此为了构建稳定、可靠的分布式集群系统,所设计服务应该具有自我保护能力
Hystrix
这是netflix开源的一款容错框架,具有自我保护能力
通过添加延迟阈值以及容错逻辑,控制分布式系统间组件的交互
通过隔离服务见的访问点、停止服务之间的级联故障、提供可回退操作来实现容错
实现的功能
- 当依赖的网络服务发送延迟或失败时,对访问的客户端程序进行保护
- 在分布式系统中,停止级联故障
- 网络服务恢复正常后,可以快速回复客户端的访问能力
- 调用失败时执行服务的回退
- 可支持实时的监控、报警等操作
分析流程
Hystrix使用-命令执行
提供四种执行命令的方法
execute()和queue()适用于HystrixCommand对象
observe()和toObservable()适用于HystrixObervableCommand对象
测试一下断路器被打开时的回退
第八章 springcloud的保护机制(Hystrix)
第九章 在springcloud中使用Hystrix