微服务架构很流行,但本人以前从未了解过,因为实在太懒,懒得学习,技术一直菜如狗,所以想了解下,就在哔哩哔哩上找了个视频,老师讲的挺好,虽然是19年视频。主要为了学习微服务开源框架学习:ruoyi-cloud-plus,地址:https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus
课程随着架构以及需要的组件引入相关技术,笔记内容如下:
1.架构:单体架构 垂直架构 分布式架构 soap(面相服务)架构 微服务架构
2.未使用注册中心,这里使用nacos为例,使用nacos前 如何调用:
借助RestTemplate,启动application里写上
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
controller:
@Autowire
private RestTemplate restTemplate;
业务模拟:订单创建 并返回商品详情(订单服务 商品详情服务 分散到两个模块)
客户端请求 请求订单创建/order/prod/{pid} ,并请求商品详情,主要是服务之间调用
即:
Product product= restTemplate.getForObject("http://localhost:8081/product" + pid,Product.class);
总结:
a.一旦服务提供者地址信息变化,就得修改服务调用者的相关代码
b.无法提供集群,服务调用者一方无法实现负载均衡的调用
c.一旦微服务变得越来越多,如何来管理这个服务清单就成了问题3.常用注册中心:Zookeeper,Eureka,consul,nacos 这里解决2的问题 主要引入nacos
主类增加注解@EnableDiscoveryClient
上边代码就可以改成如下调用方式:
private DiscoveryCDlient discoveryClient;
List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
ServiceInstance instance = instances.get(0);
Product= restTemplate.getForObject("http://"+instance.getHost() + ":" +instance.getPort() + "/product/"+pid,Product.clss))
如果商品集群,自定义负载均衡,随机调用其中一个商品服务,上边写法改写成如下:
List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
int index = new Random().nextInt(instances.size)
ServiceInstance instance = instances.get(index);
随机策略不完美,主要引入ribbon 实现负载均衡
4.ribbon实现负载均衡 多策略 轮询 随机 hash
a.@LoadBalanced注解放到上边的RestTemplate上
yml里配置策略规则
service-product:
ribbon:
NFLoadBalancerRuleClassName:com.netflix.loadbalancer.RndomRule
b.修改服务调用方法:
Product product = RestTemplate.getForObject("http://service-product/product"+pid,Product.class);5.由于服务调用写入业务代码中,可读性差,代码风格不统一(本地一般@Autowire 这里RestTemplate)
解决这种问题引入fegin.
Feign是spring cloud 提供的声明式伪http客户端,作用使调用远程服务就像调用本地服务一样简单,只需要
创建一个接口并添加上一个注解即可
Nacos兼容feign feign默认集成了Ribbon 在nacos下使用了fegin默认就实现了负载均衡的效果
启动类application 增加注解开启fegin:@EnableFeignClients
示例代码:
service:
@FeignClient("service-product")//声明调用的提供者name
public interface ProductService{
//指定调用提供者的哪个方法
//@FeignClient +@GetMapping 就是一个完整请求路径 http:service-product/product/{pid}
@GetMapping(value="/product/{pid}")
Product findByPid(@PathVariable("pid") Integer pid)
}
controller:
@Autowired
private ProductService productService;
Product product = prodctService.findByPid(pid);
以上就像普通入门写法。
6.在微服务架构中,将业务拆成一个个服务,服务之间可以相互调用,但由于网络原因或者自身原因,服务并不能保证100%
可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量网络请求涌入,
会形成任务堆积,最终导致服务瘫痪。
由于服务与服务之间的依赖性,故障会传播,会对整个微服务造成灾难性的严重后果,这就是服务故障的“雪崩效应”
常见容错思路:隔离、限流、超时、熔断、降级。常见组件:Hystrix,Resilience4J Sentinel
那么引入服务容错组件:Sentinel(信号量隔离(并发线程数限流))
Sentinel (分布式系统的流量防卫兵)是一套服务容错综合解决方案,以流量为切入点,
从 流量控制、熔断降级,系统负载保护 等多个维度来保护服务稳定性。
Sentinel特征:丰
a.富的应用场景,秒杀(即突发流量控制在系统容量可以承受的范围)、
消息削峰填谷、集群流量控制、实时熔断下游不可用等。
b.完备的实时监控
可以看到接入应用的单台机器秒级数据,甚至500台一下规模的集群的汇总运行情况。
c.广泛的开源生态
开箱即用 与其他开源框架/库整合
d.完善的SPI扩展点
Sentinel 分为两部分:核心库(JAVA客户端)、控制台(Dashboard)
Sentinel 规则:流控规则 降级规则 热点规则 授权规则 系统规则
7.Feign整合Sentinel
a.引入sentinel依赖
b.在配置文件中开启feign对sentinel的支持
feign:
sentinel:
enabled:true
c.创建容错类
//容错类要求必须实现被容错的接口,并为每个方法实现容错方案
@Component
@slf4j
public class ProductServiceFallBack implements ProductService{
@Override
public Prodct findByPid(Integer pid)
{
return xxx;
}
}
d.为被容器的接口指定容错类
@FeignClient(value="service-product",fallback = ProductServiceFallBack.class)
public interface ProductService{
@RequestMapping("/product/{pid}")//指定请求的URI部分
Product findByPid(@PathVariable Integer pid);
}
e.修改controller
f.实现fallbackfactory 容错 获取异常
8.以上架构下的问题
a.客户端需要维护服务端的各个地址 代码困难
b.认证鉴权复杂
c.跨域问题
引出api 服务网关 Gateway(统一入口)
所谓api网关 就是系统统一入口 它封装了应用程序的内部接口 为客户端提供统一服务
一些与业务本身功能无关的公共逻辑可以在这里实现,诸如 认证 鉴权 监控 路由转发等。
流行的网关: nginx + lua Kong zuul springcloud gateway
9.在大型系统的微服务构建中 一个系统拆分成许多模块。这些模块负责不同的功能,
组合成系统,一个请求往往需要涉及多个服务。互联网应用构建在不同的软件模块集上,
这些软件模块,有可能是由不同团队开发、也可能使用不同编程语言实现,有可能部署在几千台服务器上,
横跨多个不同的数据中心,也就意味着这种架构形式也存在一些问题:
a.如何快速发现问题
b.如何判断故障影响范围
c.如何梳理服务依赖以及依赖的合理性
d.如何分析链路性能问题以及实现容错规划
由此引入链路追踪技术,就是将一次分布式请求还原成调用链路,进行日志记录,性能监控
并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪台机器上、
每个服务节点的请求状态等。
常见链路追踪技术:
cat、zipkin、pinpoint、skywalking、sleuth
springcloud alibaba技术栈中没有提供自己链路追踪技术,我们采用zipkin+sleuth解决方案.
这里使用zipkin(界面收集展示)+sleuth(产生日志)(注意:skywalking 是最流行 最火的目前)
10.rocketmq 消息驱动
应用场景:
a.异步解耦
比较耗时 不需要即时(同步)返回结果
b.流量削峰
一般在秒杀抢购高并发中
11.nacos config 服务配置
微服务架构配置文件的一些问题:
a.配置文件相对分散,随着微服务增多 配置文件增多,分散在各个微服务中不好统一配置和管理
b.配置文件无法区分环境,微服务可能多个环境例如 测试 预发布 生产环境,一旦需要修改
手动维护比较困哪
c.配置文件实时更新,修改配置文件之后 必须重启微服务才能使配置生效,对正在运行项目来说
是非不友好。
以上 引入nacos 配置中心。其他配置中心 :apollo、 disconf、 springcloud config
12 seata 分布式事务 数据库事务4大特性A 原子性C 一致性I隔离性D持久性
分布式事务三种解决方案:
一全局事务,两阶段 :预提交阶段 +执行阶段
a.优点:提高了数据一致性的概率 实现成本低
b.缺点:单点问题:事务协调者宕机;同步阻塞:延迟了提交时间,加长了资源阻塞时间;数据不一致:提交第二阶段,依然存在commit结果未知情况,有可能导致数据不一致。
二可靠消息服务:消息中间件 优点:一种非常经典的实现 实现了最终一致性 缺点 :消息表会耦合到业务系统中 如果没有封装好解决方案 会有很多杂活需要处理
三TCC事务 try confirm cancel 补偿性分布式事务
try:尝试待执行的业务 confrim确诊执行业务 cancel取消待执行的业务
TCC两阶段提交 与XA两阶段提交的区别:
XA是资源层面的分布式事务,强一致性,在两阶段提价的整个过程中,一直会持有资源锁
TCC是业务层面的分布式事务,最终一致性,不会一直持有资源的锁。
TCC事务的优缺点:
优点:把数据库层的二阶段提交到了应用层来实现,规避数据库的2pc性能底下问题
缺点:tcc的try confrim cancel操作功能需业务提供 开发成本高