微服务
注册中心
Nacos和Eureka
-
共同点
- 都可以作为服务注册,服务拉取中心。
- 都有AP特性。
- 都支持服务提供者心跳方式做健康监测。
-
异同点
- nacos可以做配置中心。
- nacos可以支持服务提供者注册服务为非临时实例时:
- nacos为CP模式。
- nacos会主动监测服务提供者是否存活。
- nacos会主动通知服务列表的更新(更快感知服务变更)。
- 服务提供者心跳不正常AP模式会被剔除服务列表,CP模式则不会。
- 当nacos可以支持服务提供者注册服务为临时实例时,和Eureka一样。
nacos
-
服务注册
- 客户端调用api单节点put先写入到一个BlockQueue中,然后有task一直异步轮训队列将元数据注册到一个map中。
Map<namespace,Map<group::serviceName, Service>> - 如果启动了多个nacos,会启动一个异步任务和队列存储这些信息然后通过http调用发送给除自己以外的其他集群。
-
服务发现
客户端定时调用服务端api获取服务列表缓存到本地map中,同时上报udp端口给到服务端,一旦服务端有服务变动(下线和上线就会UDP发送给客户端)。
ZooKeeper则不同,是Netty长链接。 -
怎么实现多节点高并发控制?
copyonwrite机制,实现读写分离,从而没有高并发压力。 -
判断存活
客户端每隔5s发送心跳信息给服务端,依据两次心跳时间是否超过15S来判断存活与否设置为非健康节点,超过30S下线。
-
nacos服务之间通信
新的nacos服务端启动时会拉取其他节点全部的服务注册信息,并定时任务轮训发送自身的信息和状态给到其他节点。
负载均衡
Ribbon
负载均衡
-
轮询方式
-
随机方式
-
响应时间加权轮询方式
-
分区轮询方式
-
自定义轮询:
-
声明创建SpringBean(全局配置)
@Bean public IRule customRule(){ // implements IRule return new new CustomeRule(); }
-
-
在配置文件中指定服务使用自定义轮询全限定类名(局部配置)
熔断机制
hyrtix
根据10S内请求失败率是否过半来判断要不要打开熔断机制,走fallback接口服务降级机制,随后半开状态会每隔5S判断服务是否可达可用标准,如果达到则关闭熔断机制,否则继续保持服务降级。
服务限流
nginx
- 漏桶算法
以固定桶的大小来充当容器,其他的请求抛弃,同时在桶下面开启固定大小的出口来限定速率。
- 控制并发连接数
- perip
- perserver
网关
-
令牌桶算法
固定速率放入令牌桶,请求到来后看桶中的令牌数决定每秒并发,和漏桶的区别就在于令牌桶的瞬时速率可能会double(eg:一直没有请求进来,令牌桶中已经有了三个令牌,同时桶外已经有三个令牌等待入桶,此时桶中三个令牌颁发出去之后,桶会立马被补满又可以颁发三个,瞬时速率就可以double变为6)
-
自定义拦截器
guava 或者 redis ( Sorted Set )
AP&CP
CAP:分布式系统的三要素:一致性、可用性、分区容错性。
因为现在的集群大多都要保证一半以上的节点存活,所以分区容错性是保障。P
CP:当系统想要满足一致性时,节点之前的同步力度就要大很多,甚至到了一定要同步的地步,就会出现部分节点可用,部分节点不可用(对于客户端来说这部分节点都是脏数据、落后数据、甚至拒绝连接)的情景,就满足不了可用性。
AP:当系统想要满足可用性时,就要舍弃强一致性,允许部分节点同步滞后,网络宕机。
BASE则是以牺牲强一致性为代价,追求系统的可用性和分区容错性,通过保证基本可用性、软状态和最终一致性来解决CAP问题。
具体来说,BASE包含以下三个概念:
- 基本可用性(Basically Available):系统在面对异常情况时,仍然可以保证核心功能的正常运行。即使某些服务出现故障或延迟,仍然能够接收并处理部分请求。
- 软状态(Soft State):允许系统在不同节点上存在数据副本的不一致状态,即系统中的数据可能存在短暂的不一致。
- 最终一致性(Eventual Consistency):系统经过一段时间的同步与协调后,最终会达到一致的状态。即系统中的数据副本最终会在合理的时间范围内达到一致。
举例来说,一个使用BASE理论的分布式系统可以采用异步复制方式处理数据一致性问题。当用户提交数据时,系统首先对数据写入本地节点,并立即返回成功响应,保证了基本可用性。然后,系统异步地将数据复制到其他节点,以实现最终一致性。
分布式事务
MQ
使用MQ解耦各个步骤里的业务分支事务,通过MQ来通信。
SETA
通过事务协调器来协调各分支事务的提交和回滚。
接口幂等性
新增和更新实现幂等:
-
update 绝对值 而非操作符
update t1 set cost= 500 where id=1; ✔ update t2 set cost = cost - 500 where id=1; -
新增
- 使用唯一索引新增
- Token&Redis (性能最好)
- 分布式锁
服务拆分
拆分依据
- 稳定度
已经很稳定,建议拆分出来,后续上线新的功能与它无关。减小测试回归粒度。 - 是否核心
非核心系统,拆分出来,方便做资源整合(下线、扩缩容) - 复杂度、灵活
如果是很复杂和灵活经常有业务变动的也建议单独拆出来,单独上线。
拆分好处
- 拆分:解耦
- 解耦:各个系统相互独立,功能内聚。
- 系统更细,资源充分利用
- 职责单一:功能明确,更容易分配到小组,人效管理,责任到人、人效定位。
- 迭代: 功能单一,上手更快,迭代更快,更能契合业务部门的诉求。
- 功能整合: 第三方、中间件组件化后续其他系统需要功能复用性更高。
复杂度
- 偶然复杂度
非功能性复杂度:中间件、模式、高性能、高可用、可扩展、安全性、低成本 - 非偶然复杂度
功能性复杂度:人的复杂度和业务复杂度
分布式session
常用方式
- 服务器session
服务器生成cookie保存在当前服务节点的session中,发送给客户端存储在浏览器当前域的cokkie缓存中,用于下一次请求携带,不适合分布式环境。 - cookie
服务器利用个人签名加密成cookie返回给客户端,用来验签。(无session存储,加解密验证) - token(目前业界主流)
服务器生成token保存在当前服务节点的session中或者第三方存储系统中,发送给客户端存储在浏览器的localstorage中,用于下一次请求携带。
安全性
这几种都有被劫持伪造的可能 XSS,CSRF
- https请求发送防泄漏。
- 风控主动失效及失效机制。
失效机制:把请求信息加时间戳字段用一定组织方式组成字符串加上客户端和服务器端用都认可的密钥加密来生成token,解密后的数据中带有时间戳,在一定时间内认为有效。 - IP白名单
- 定期更新密钥
知识点
发布
蓝绿发布和灰度发布(也称为金丝雀发布)是两种常用的软件发布策略,它们都旨在减少发布新版本时对用户造成的影响,但在实施方式和目标上存在一些关键的区别。
蓝绿发布
蓝绿发布策略涉及维护两个完全相同的生产环境:一个蓝色环境和一个绿色环境。这两个环境在资源、基础设施和配置上是镜像的。在发布新版本时,新版本会部署到当前不活跃的环境(例如,如果蓝色环境是活跃的,那么新版本会部署到绿色环境)。这允许团队在不影响用户的情况下对新版本进行全面测试。一旦确认新版本稳定可靠,就会通过切换流量到新环境(绿色环境),使其成为新的活跃生产环境。此时,原来的活跃环境(蓝色环境)变为备用,准备接收下一次部署。
灰度发布(金丝雀发布)
灰度发布策略允许你将新软件版本逐步推出给一小部分受控的用户群体,而不是一次性部署给所有用户。这种方法的目的是在全面推出之前识别并解决新版本可能存在的任何问题,从而最小化对所有用户造成广泛问题或中断的风险。在灰度发布中,你会逐渐将新版本推出给更多的用户,同时监控反馈和性能,根据需要进行迭代。如果新版本表现良好并获得积极反馈,则可以继续向所有用户推出。如果遇到问题,可以暂停推出,解决问题后再继续。
主要区别
-
部署速度和简易性:蓝绿发布允许你几乎瞬间在两个环境之间切换,最小化停机时间,确保无缝的用户体验。而灰度发布则需要更渐进和增量的方法,可能需要更多时间来监控反馈和性能指标。
-
风险管理:蓝绿发布通过在非活跃环境中彻底测试新版本来管理风险,确保在切换流量之前发现并解决任何问题。灰度发布通过逐步推出新版本并监控反馈来管理风险,允许早期检测和解决潜在问题。
-
资源需求:蓝绿发布需要维护两个完全相同的生产环境,这可能对资源有较高的要求。灰度发布在资源上更为高效,因为它只需要为测试和初始用户群体部署新版本。
-
回滚能力:两种策略都提供了回滚能力,但蓝绿发布可以通过简单地切换流量回到之前的环境来快速回滚。灰度发布允许在检测到问题时暂停推出,解决问题后继续过程。
-
用户影响:蓝绿发布通过在非活跃环境中测试新版本来减少对用户的影响。而灰度发布通过向一小部分用户推出新版本,逐步扩大范围,从而减轻对所有用户的潜在影响。
总的来说,选择哪种发布策略取决于你的项目需求、资源限制以及对风险管理的偏好。
filter和interceptor
在Java Web开发中,Servlet的Filter和Spring框架的Interceptor都是用来处理请求的工具,但它们在使用场景、功能以及配置方式上有所不同。以下是Servlet的Filter和Spring的Interceptor之间的主要区别:
-
执行层次不同:
- Filter是基于Servlet规范的一部分,它在请求进入Servlet之前和响应发送给客户端之后起作用。Filter能够对几乎所有的请求起作用,是一种更为底层的请求处理方式。
- Interceptor是Spring框架提供的,它的作用范围限定在Spring的DispatcherServlet处理的请求中。Interceptor可以更精细地控制请求的处理,比如仅对某些Controller的请求进行拦截。
-
功能范围不同:
- Filter能够对请求和响应进行修改,比如修改请求头、响应头,甚至拦截请求不让它继续传递。
- Interceptor提供了更细粒度的控制,它不仅能够在请求处理之前、处理之后以及请求完成之后进行拦截处理,还能够访问到Spring MVC的上下文,如处理器(Controller)、模型和视图等。
-
配置方式不同:
- Filter的配置通常在web.xml文件中进行,或者通过Servlet 3.0的注解方式进行。
- Interceptor则是在Spring的配置文件中进行配置,或者通过Java配置类配置。
-
使用场景不同:
- Filter适合处理一些与业务无关的通用任务,如日志记录、请求和响应的压缩、安全性检查等。
- Interceptor适合处理与业务相关的逻辑,如权限检查、用户认证、日志记录等,特别是需要访问到Spring MVC上下文信息时。
总结来说,Filter是Servlet规范的一部分,适用于对请求和响应的通用处理,配置简单,适用范围广泛。而Interceptor是Spring框架提供的,能够提供更细粒度的请求处理能力,适合处理与业务逻辑紧密相关的任务,并且能够更好地与Spring框架集成。开发者可以根据实际的需求选择使用Filter还是Interceptor。
设计要素
设计一个好的后端微服务API系统,需要考虑以下设计要素:
- 服务划分:正确的服务边界和大小是关键。服务应该围绕业务能力构建,保持小而专注,这有助于服务的可维护性及可复用性。
- API设计:应当遵循RESTful原则或使用GraphQL,确保API易于理解和使用;定义清晰的资源、操作和表示。
- 服务发现:服务之间通常需要相互调用,因此一个健壮的服务发现机制是必要的,以便服务可以找到并与其他服务通信。
- 配置管理:集中配置管理可以让服务更容易在不同环境中迁移和部署,同时降低管理配置的复杂性。
- 容错和降级机制:设计时需考虑服务的容错性,通过熔断器、限流器等机制来提高系统的健壮性。
- 安全性:必须在设计时考虑API的安全性,包括认证、授权、加密传输、SQL注入防护等。
- 负载均衡:良好的负载均衡机制可以确保请求均匀分配到各个服务实例,提高系统的扩展性和稳定性。
- 日志记录和监控:全面的日志记录和监控可以帮助你理解系统的运行状况并快速定位问题。
- 数据管理:每个服务都应该有自己的数据库实例,以保持服务间数据的独立性。
- 通信机制:服务间的通信应确定是同步还是异步;消息队列等异步通信机制有助于解耦服务,并能提高系统的响应性。
- 版本控制和部署:微服务的持续集成和持续部署(CI/CD)流程需要管理好微服务版本,确保部署的一致性和回滚的能力。
- API文档和版本管理:API文档应详尽且易于理解,支持开发人员正确使用。同时,需要确保API的版本管理能够允许向后兼容。
这些要素并非完全独立,它们相互影响,共同作用于微服务API系统的设计。理想的架构是灵活的,并且能够随着业务需求的变化而相应地演进。
可观测性
保证系统在出现异常问题后的可观测性是确保系统健壮性的重要一环。以下是一些实践策略:
- 日志记录:系统的每个部分都应该产生详细的日志,这样当出现问题时能够追溯事件发生的原因。日志应该包括足够的上下文,如时间戳、服务标识、操作信息等。
- 监控系统:应该有一个监控系统来收集服务的度量和事件,例如响应时间、错误率、系统负载等。使用如Prometheus、Grafana之类的工具可以帮助实时监视系统状态。
- 分布式追踪:在一个微服务架构中,一个请求可能会跨越多个服务。通过实现如OpenTracing或OpenTelemetry协议的分布式追踪系统,可以追踪一个请求的完整生命周期,并且在出现异常时确定问题发生在何处。
- 健康检查:服务应该实现健康检查端点,以报告其状态。这些端点可以被监控系统定期检查,以确保服务运行正常。
- 告警系统:根据监控到的度量设置相应的告警阈值,一旦超出这些阈值,告警系统应该通知相关人员或系统。
- 异常捕获与管理:应用程序应该有异常捕获机制,将处理过程中遇到的任何异常记录下来,并在必要时触发警报。
- 应急响应计划:当发生故障时,应该有一个明确的应急响应过程,并确保所有团队成员都了解这一流程。
通过这些机制,一旦出现问题,就可以快速地定位和解决,在维护系统的稳定性和用户体验方面发挥重要作用。
OpenTracing
-
Tracer
通过api创建span,以及将
SpanContext
上下文Inject(注入)到carrier,将SpanContext
上下文从carrier 中Extract(提取)。 -
Span
- operation name, 操作名, 一个具有可读性的字符串,代表这个span所做的工作(例如:RPC方法名,方法名,或者一个大型计算中的某个阶段或子任务)。操作名应该是一个抽象、通用,明确、具有统计意义的名称。因此,
"get_user"
作为操作名,比"get_user/314159"
更好。
例如,假设一个获取账户信息的span会有如下可能的名称:
操作名 指导意见 get
太抽象 get_account/792
太明确 get_account
正确的操作名,关于 account_id=792
的信息应该使用Tag操作可选参数
- 零个或者多个关联(references)的
SpanContext
,如果可能,同时快速指定关系类型,ChildOf
还是FollowsFrom
。 - 一个可选的显性传递的开始时间;如果忽略,当前时间被用作开始时间。
- 零个或者多个tag。
- operation name, 操作名, 一个具有可读性的字符串,代表这个span所做的工作(例如:RPC方法名,方法名,或者一个大型计算中的某个阶段或子任务)。操作名应该是一个抽象、通用,明确、具有统计意义的名称。因此,
-
SpanContext
进程内部以及跨进程传递的上下文对象。
eg: java:进程内部:ThreadLoal,跨进程:塞进各种通信协议的Binary中,传递给其他SPAN。- Text Map: 基于字符串:字符串的map,对于key和value不约束字符集。
- HTTP Headers: 适合作为HTTP头信息的,基于字符串:字符串的map。(RFC 7230.在工程实践中,如何处理HTTP头具有多样性,强烈建议tracer的使用者谨慎使用HTTP头的键值空间和转义符)
- Binary: 一个简单的二进制大对象,记录
SpanContext
的信息。
本文作者:唐钰逍遥
本文链接:https://www.cnblogs.com/tyxy/p/17808323.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步