驾驭云端之风1——Spring Cloud微服务架构实践指南
- 本博客纯属个人总结,非原创。
- 喜欢技术交流的,可关注博主,武汉有后端开发群,可支持内推,了解武汉行情等。
前沿
优惠卷平台项目的整体功能和模块,以及每个功能点的技术选型和背后的依据。
搭建一个简化版的营销优惠计算系统,实现
- 优惠卷模版的创建,
- 用户领取优惠卷,
- 下单核销优惠卷
- 订单价格计算等功能。
实现一个领取优惠卷的功能,首先是要创建一个营销规则模版,这个模版就像一个模具一样,通过这个模具来铸造,并最终发放到用户手中。
.
使用模版的好处是可以对优惠卷规则做一层抽象,比如满减类,打折类,这些优惠卷是具体的优惠金额不同,但是玩法类似。我们把相类似的玩法功能抽象成一个模版,就可以简化具体优惠卷的创建和核销流程。
整个项目划分了优惠卷模版服务,计算服务,用户服务,平台类组件
优惠卷模版服务:模版规则是创建优惠卷的前置条件,每种类型的模版都是一个计算公式,这个公式约定了优惠计算的方式,模版服务实现了模版规则的创建,克隆,分页查找等功能,另外还可以在项目中定义满减,随机立减,满折,晚间双倍优惠等多种卷模版类型。
计算服务:根据用户购物车中的商品信息和优惠卷信息,来计算当前订单优惠后的价格,另外,如果用户有多张优惠卷,还提供了”优惠金额试算“,帮助用户挑选最省钱的优惠卷。
用户服务:暴露给外部用户使用的接口,它依赖于模版服务+计算服务,为了完成底层逻辑,主要业务场景是用户领卷,订单价格试算,下单核销,订单金额等功能。
平台类组件:包括一些与业务无关的中心化组件。
从整体来看,模版服务和计算服务是基础服务,用户服务是对用户开放的接口,他依赖于模版服务+计算服务来完成业务逻辑,而平台类组件提供了横向的微服务特性支持,比如微服务网关,链路追踪等功能,整体图如下:
SpringCloud实战项目全景规划
- 第一阶段:搭建基础的微服务功能,实现微服务之间的通信;
- 第二阶段:为各个模块构建服务容错,分布式配置中心,分布式链路追踪能力;
- 第三阶段:进一步实现微服务网关,消息驱动和分布式事务;
第一阶段:实现微服务通信
将用户微服务,优惠卷模版服务和订单计算服务拆分为独立部署的业务系统,通过注册中心来实现服务实现和服务发现。让各个微服务可以互相调用,涉及到的技术:nacos注册中心,loadbalance负载均衡组件,openFeign服务间调用。
- nacos注册中心:是注册中心组件,负责收集所有服务节点的地址信息,并维护服务注册表,所有服务上线后都会向他汇报状态。
- loadbalance负载均衡:在客户端发送服务调用的时候,他会负责从nacos的注册表中挑选一台目标服务器。
- openFeign:基于HTTP的远程服务调用,让我们就像本地接口一样方便地发起远程服务调用。
为什么选择nacos+loadbalance作为选型方案。
第一:早期是eureka+ribbon作为服务治理+负载均衡组件,但netfix正退出springcloud的历史舞台,eureka+Ribbon已经进入不维护状态(断更),在考虑技术选型时,选择后劲更大,更新最活跃的nacos和loadbalance组件。
服务治理:服务治理的重点是搭建基础的跨服务调用功能,把用户服务,计算服务,订单服务改造成可以独立启动的微服务,并借助nacos的服务发现功能,通过Webflux组件中的webClient实现基于HTTP的跨服务间的调用。
负载均衡
简化服务调用:使用OpenFeign组件对用户服务进行改造,将原先复杂的WebClient调用替换为简洁的OpenFeign调用。
第二阶段:服务容错,链路追踪,分布式配置
利用服务容错提高微服务架构的可用性,搭建全链路的分布式链路追踪能力,实现统一的配置管理和动态属性推送,涉及的组件:nacos config,Sentinel,Sleuth+Zipkin+Elk。
在微服务架构中,
服务容错:保证高可用的重要手段,推荐使用:Sentinel作为容错组件,可以实现降级,熔断,容量整形等多种服务容错途径。
后期会搭建:Sentinel Dashboard控制台,通过控制台将降级规则和流量整形规则应用到业务埋点中。
链路追踪:推荐使用Sleuth组件,线上异常排查全靠它,使用全局唯一标记将跨微服务调用链上的各个环节全部串联起来,结合Zipkin组件实现调用链的可视化检索,将调用链上各个阶段的请求按顺序显示在页面上,目前业界主流的ELK组合(es + logstash + kibana)作为日志检索系统。
“分布式配置”:使用Nacos Config组件,实现配置项的远程获取和动态推送。
第三阶段:统一流量入口,消息驱动,分布式事务
流量入口:采用Gateway,担任路由转发,同时它提供丰富的谓词组合实现复杂的路由判断逻辑,可以在网关层定义拦截器,做特殊处理。
消息驱动:采用Stream
分布式事务:Seata组件,保证微服务环境下的事务一致性,Seata分布式事务解决方案有两种,第一:没有代码侵入的Seata AT方案,第二:补偿性的Seata TCC方案。
项目细节
1:对于境内电商行业来说,金额往往是以分为单位的,这样我们可以直接使用 Long 类型参与金额的计算,比如 100 就代表 100 分,也就是一块钱。这比使用 Double 到处转换 BigDecimal 省了很多事儿。
2:尽可能减少级联配置,用单表查询取而代之,如果一个查询需要 join 好几张表,最好的做法就通过重构业务逻辑来简化 DB 查询的复杂度。
3:在做大型应用架构的时候,我们通常会把计算密集型服务与 IO/ 存储密集型服务分割开来,这样做的一个主要原因是提高资源利用率。
比如有两个:计算密集型的微服务A,IO密集型微服务B,大促流量来时,如果微服务A的压力比较大,我们可以调配高性能CPU和内存去定向扩容A集群,如果微服务B压力吃紧,我们可以定向分配资源给B。
计算型:不吃网络IO和磁盘空间,主要占用CPU,内存等资源。
微服务组件
服务治理
解决的首要任务就是:服务注册+服务发现,通过这两项技术,我们能让服务之间发起面对面的直接调用。
服务A怎么知道服务B中每台机器的地址呢?
我们需要搭建一个中心化的服务注册中心,服务B要将自己的信息添加到注册中心里,服务A就能从注册中心获取到服务B的所有节点。
服务B集群向注册中心发起注册,将自己的信息注册到注册中心,这个过程就是服务注册。
每隔一段时间,服务A就会从注册中心中获取服务B集群的服务列表,这个过程叫服务发现。
最后服务A根据本地负载均衡策略,从服务列表中选取某一个服务B的节点,发起服务调用。
注册中心是一个中心化的信息管理者,所有的微服务节点在启动后都会将自己的地址信息添加注册到注册中心,在服务注册的过程中,有两个关键信息很重要。
- 服务名称:服务名称通常默认是spring.application.name属性,在服务注册过程中我们必须将应用服务名上报到注册中心,这样其他服务才能根据服务名找到对应的节点列表。
- 地址信息:包括服务节点的ip地址和端口。
容错机制
所有的服务都要在注册中心注册,而且每个节点都需要每隔一段时间向注册中心同步自己当前的状态,简称:心跳。
如果节点持续发送心跳信息,则一切正常,如果注册中心有一段时间未收到心跳包,则视为下线,该服务从服务列表中剔除。
当服务节点关闭或重启的时,会发送一条**“服务下线”**指令给注册中心,也视为下线。
nacos体系架构
三个核心:领域模式,数据模型,基本架构。
领域模型
Nacos的领域模型描述了服务与实例之间的边界和层级关系。Nacos的服务领域模型是以“服务”为维度来构建的。
这个服务并不是指集群中的单个服务器,而是指微服务的服务名称。
服务,集群,实例是Nacos的核心概念。
-
服务
在服务的基础上,可以配置元数据和服务保护阈值(0~1)等信息,当服务的健康实例数/总比例数是小于保护阈值时,说明当前服务还能提供的机器已经不多了,Nacos会开启服务保护模式,不再主动剔除服务实例。 -
集群
一个服务是由多个服务实例组成的,在每个服务实例启动的时候,可以设置它所属的集群,可以配置元数据,还可以为持久化节点设置健康检查模式。 -
实例
实例对应的就是服务节点,我们可以通过Nacos控制台查看每个实例的IP地址和端口,编辑实例的元数据信息,修改它的上线/下线状态等。
上述都存在元数据,它是包含了服务描述信息和自定义标签的数据集合。
数据模型
- Namespace
命名空间,他是最顶层的数据结构,用来区分开发,预发,生产环境。
默认情况下所有的服务都部署到一个叫做“public”的公共命令空间。 - Group
在命名空间之下有一个分组结构。
默认情况下所有的服务都属于"default_group"这个分组,不同分组间的微服务是相互隔离的。 - Data ID
在分组之下,就是具体的微服务了,比如订单服务,商品服务等。
Nacos的基础架构
Nacos的两大核心:Naming Service和Config Service
一致性
Nacos的一致性保证Nacos集群中各个节点之间的数据一致性。
- 侧重一致性的Raft协议,基于集群中选举出来的Leader节点进行数据写入。
- 临时节点的Distro协议,他是最终一致性的分布式一致性协议。
自动装配原理
在早期SpringCloud版本中,需要在启动类加上@EnableDiscoveryClient注解,才能开启服务治理功能。
在新版本中,我们只需要通过配置项就可以开启。
- NacosDiscoveryAutoConfiguration
服务发现的自动装配器。
主要是:加载Nacos配置项,申明NacosService Discovery类用作服务发现。
源码如下:
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled //默认是true,可通过配置项制为false
@ConditionalOnNacosDiscoveryEnable //默认是true,可通过配置项制为false
public class NacosDiscoveryAutoConfiguration {//@ConfigurationProperties("spring.cloud.nacos.discovery")//通过上面的注解,读取配置文件中nacos相关的配置项封装进NacosDiscoveryProperties类@Bean@ConditionalOnMissingBeanpublic NacosDiscoveryProperties nacosProperties() {return new NacosDiscoveryProperties();}//如下面代码NacosServiceDiscovery类@Bean@ConditionalOnMissingBeanpublic NacosServiceDiscovery nacosServiceDiscovery(NacosDiscoveryProperties discoveryProperties,NacosServiceManager nacosServiceManager) {return new NacosServiceDiscovery(discoveryProperties, nacosServiceManager);}
}//返回值:根据服务名称获取所有已注册的服务,返回所有服务的服务名称,一般是给调用方使用的,
//提供服务发现功能。
public class NacosServiceDiscovery {// 封装了Nacos配置项的类private NacosDiscoveryProperties discoveryProperties;// 另一个自动装配器声明的核心服务治理类private NacosServiceManager nacosServiceManager;// 根据服务名称获取所有已注册服务public List<ServiceInstance> getInstances(String serviceId) throws NacosException {String group = discoveryProperties.getGroup();List<Instance> instances = namingService().selectInstances(serviceId, group,true);return hostToServiceInstanceList(instances, serviceId);}// 返回所有服务的服务名称public List<String> getServices() throws NacosException {String group = discoveryProperties.getGroup();ListView<String> services = namingService().getServicesOfServer(1,Integer.MAX_VALUE, group);return services.getData();}// 省略部分代码...
}
-
NacosServiceAutoConfiguration
声明核心服务治理类:NacosServiceManager。
主要是通过serviceId,group等一系列获取已注册的服务列表。 -
NacosServiceRegistryAutoConfiguration
Nacos服务注册的自动装配器。
关闭服务,服务下线:主要靠注解@PreDestroy实现
NacosServiceRegistryAutoConfiguration->NacosAutoServiceRegistration->AbstractAutoServiceRegistration.destroy()
Nacos服务发现底层实现
Nacos Client通过一种主动轮训的机制,从nacos server获取服务注册信息,包括地址列表,group分组,cluster名称等一系列数据。
Nacos Client会开启一个本地的定时任务,每间隔一段时间,就尝试从Nacos server查询服务注册表,并将最新的注册信息更新到本地。
负责拉取服务的任务是UpdateTask类,它实现了Runable方法,Nacos以开启线程的方式调用了UpdateTask类中的run方法,触发本地的服务发现查询请求。
首先在 spring.factory 文件中配置了 NacosDiscoveryClientConfiguration 类,用于 springboot 的初始化时的自动装配。在 NacosDiscoveryClientConfiguration 类中会向 spring 容器中添加 NacosWatch 这个 bean。顺着 NacosWatch 的 start 方法一路往下,就能看到:NacosWatch#start ->NacosNamingService#subscribe -> HostReactor#subscribe -> HostReactor#addTask;UpdateTask 就是作为 task 添加到定时执行队列里的。
相关文章:

驾驭云端之风1——Spring Cloud微服务架构实践指南
本博客纯属个人总结,非原创。喜欢技术交流的,可关注博主,武汉有后端开发群,可支持内推,了解武汉行情等。 前沿 优惠卷平台项目的整体功能和模块,以及每个功能点的技术选型和背后的依据。 搭建一个简化版的…...

【计算机网络基础】
计算机网络基础网络的基本概念网络互联网IP地址MAC地址网络协议网络分层模型网络应用程序的通信流程网络的基本概念 网络 网络是由若干结点和链接这些结点的链路组成,网络中的结点可以是计算机,交换机,路由器等设备 网络设备:交…...
grep与nm命令的应用
相关知识拓展 Linux中grep的命令使用 在Linux中,grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在&…...

【linux】软硬链接
在linux中在磁盘中定位文件并不是根据文件名而是根据文件的inode,一个文件对应一个inode但是一个inode可以对应多个文件。硬链接硬链接是通过索引节点进行的链接。在Linux中,多个文件指向同一个索引节点是允许的,像这样的链接就是硬链接。硬链…...

骨传导蓝牙耳机排行,盘点几款性能不错的骨传导耳机
随着蓝牙耳机的普及,骨传导耳机也越来越受到欢迎,很多人也都开始在了解并尝试骨传导耳机。相比于其他类型耳机,在舒适度、安全方面有一定优势。尤其是在户外运动时,或者长时间佩戴运动时,使用骨传导耳机可以避免耳朵因…...

ARM中的寄存器
ARM工作模式 ARM有8个基本的工作模式 User 非特权模式,一般在执行上层的应用程序时ARM处于该模式FIQ 当一个高优先级中断产生后ARM将进入这种模式IRQ 当一个低优先级中断产生后ARM将进入这种模式SVC 当复位或执行软中断指令后ARM将进入这种模式Abort 当产生存取异常…...
git操作修改历史版本指定tag标签的代码,并发布新标签
场景: 当项目已经迭代多个版本之后,突然发现旧版本0.0.1出现了紧急bug,需要及时处理; 如果直接用新版本替换上去是存在极大隐患的,且时间来不及; 所以需要直接在0.0.1版本的基础上去修复bug,然…...

SpringMVC——响应处理(1)【包含源码分析】
Controller public class JsonReturnController {ResponseBodyGetMapping("/getPet")public Pet getPet(){Pet petnew Pet();pet.setAge(5);pet.setName("lily");return pet;} }项目启动后 浏览器输入 http://localhost:8080/getPet 。 debug DispatcherS…...

Normalization
1、BN(Batch Normalization) 深度网络参数训练时内部存在协方差偏移(Internal Covariate Shift)现 象:深度网络内部数据分布在训练过程中发生变化的现象。训练深度网络时,神经网络隐层参数更新会导致网络输…...

27K测试老鸟分享自己6年面试心得,四种公司、四种问题…
这里总结了下自己今年的面试情况 先说一下自己的个人情况,普通二本计算机专业毕业,懂python,会写脚本,会selenium,会性能。趁着金三银四跳槽季,面试字节跳动测试岗技术面都已经过了,本来以为是…...

中小企业数字化自动化转型的方法
自动化是我们国内未来的趋势。智能制造的实现主要依托两个基础能力,一个是工业制造技术,另一个就是工业互联网。而自动化是工业制造技术的重要组成部分,是高度智能制造装备的核心部分,与承接着制造单元与工业互联网这两大核心。懂…...

利用GPT-3 Fine-tunes训练专属语言模型
利用GPT-3 Fine-tunes训练专属语言模型 文章目录什么是模型微调(fine-tuning)?为什么需要模型微调?微调 vs 重新训练微调 vs 提示设计训练专属模型数据准备清洗数据构建模型微调模型评估模型部署模型总结什么是模型微调࿰…...

kubeadm方式安装k8s高可用集群(版本1.26x)
K8S官网:https://kubernetes.io/docs/setup/ 高可用Kubernetes集群规划 配置备注系统版本CentOS 7.9Docker版本20.10.xPod网段172.16.0.0/12Service网段10.103.10.0/16 主机IP说明k8s-master01 ~ 03192.168.77.101 ~ 103master节点 * 3k8s-master-lb192.168.77.2…...

分享5款堪称神器的免费软件,建议先收藏再下载
转眼间新年已经过去一个月了,最近陆陆续续收到好多小伙伴的咨询,这边也是抓紧整理出几个好用的软件,希望可以帮到大家。 1.电脑安全管家——火绒 火绒是一款电脑安全软件,病毒库更新及时,界面清晰干净,没…...

【项目实战】从0开始入门JDK源码 - LinkedList源码
一、源码位置 一般来说IDEA配置好JDK以后 ,JDK的源码其实也配置好了,本文是基于JDK1.8的源码说明 rt - java - util - LinkedList 二、 继承关系图 LinkedList public class LinkedList<E>extends AbstractSequentialList<E>implements...
Polygon zkEVM的gas定价
1. 引言 所有的zkEVM都存在一个有趣的问题: 如何给gas定价? 在Ethereum Virtual Machine (EVM)中,gas通过为每个计算设置economic fee,来保持网络安全。恶意行为,如拒绝服务(DoS)攻击&#x…...
stl中的智能指针类详解
C98/03的尝试——std::auto_ptr C11标准废弃了std::auto_ptr(在C17标准中被移除),取而代之的是std::unique_ptr, std::auto_ptr容易让人误用的地…...

Linux 阻塞和非阻塞 IO 实验
目录 一、阻塞和非阻塞简介 1、IO 概念 2、阻塞与非阻塞 二、等待队列 1、等待队列头 2、等待队列项 3、将队列项添加/移除等待队列头 4、等待唤醒 5、等待事件 三、轮询 1、应用程序的非阻塞函数 2、Linux 驱动下的 poll 操作函数 四、阻塞IO之等待事件唤醒 添加…...
你要的react+ts最佳实践指南
本文根据日常开发实践,参考优秀文章、文档,来说说 TypeScript 是如何较优雅的融入 React 项目的。 温馨提示:日常开发中已全面拥抱函数式组件和 React Hooks,class 类组件的写法这里不提及。 前沿 以前有 JSX 语法,…...

软件测试人员会被替代吗?IT行业哪个方向的前景最好?字节12年测开是这样说的
互联网测试从业12年,前来作答。 逻辑上来说,软件工程最初始只需要两个岗位,一个是产品经理。,一个是研发(开发),剩余的 所有岗位都是由他们衍生而来的。 第三个岗位大概率就是测试,…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...