ABP VNext + Akka.NET:高并发处理与分布式计算

ABP VNext + Akka.NET:高并发处理与分布式计算 🚀

Actor 模型把高并发写入“分片→串行化”,把锁与竞态压力转回到代码层面的可控顺序处理;依托 Cluster.Sharding 横向扩容,Persistence 宕机可恢复,Streams 保障背压稳定吞吐;全程采用 Akka.Hosting + 显式启动 Sharding 的写法,弱化对版本特定扩展方法的耦合。⚙️


📚 目录

  • ABP VNext + Akka.NET:高并发处理与分布式计算 🚀
    • 1)TL;DR ✍️
    • 2)适用场景 🎯
    • 3)环境与依赖 🧰
    • 4)目标架构与数据流(总览图)🗺️
    • 5)最小可跑骨架(单节点,内存持久化)🏃‍♂️
      • 5.1 消息与分片提取器(稳定哈希)🔑
      • 5.2 实体 Actor(顺序处理 + 快照 + 钝化)🧠
      • 5.3 Streams 入口 + ACK 闭环(ActorRefWithAck)🔁
        • 5.3.1 端到端背压闭环 🧨
      • 5.4 Akka.Hosting:显式启动 Sharding + DI 注入 🧩
    • 6)与 ABP 应用层对接(IRequiredActor + Ask/Tell)🔗
    • 7)生产切换:SQL Server 持久化 🧱
    • 8)序列化与安全(Hyperion)🛡️
    • 9)Actor 生命周期 🧬
    • 10)Sharding 重分布 📦
    • 11)K8s 拓扑 ☸️
    • 12)可靠性与容错 🛠️
    • 13)可观测性与日志 📊
    • 14)部署:本地多实例 & K8s 🧪
    • 15)性能调优清单 ⚡
    • 16)常见坑 & 规避 🧨


1)TL;DR ✍️

  • Actor + Sharding:按实体(DeviceId/OrderId…)顺序处理,避免热点锁与竞态;横向扩容靠分片重分布。🧩
  • Persistence(事件+快照):进程挂了可回放恢复;开发期可用内存存储,生产换 SQL/PG。💾
  • Streams 背压:入口 Source.Queue(..., Backpressure) + ActorRefWithAck 打通端到端背压闭环。🧯
  • Akka.HostingActorRegistry + IRequiredActor<T> 与 ABP/.NET 的 DI、日志无缝融合。🔌
  • 两套部署路径:本地多实例(静态种子) & K8s(Akka.Management + Cluster Bootstrap)。☸️

2)适用场景 🎯

  • IoT/日志/交易流水等 写多读少每实体需要严格顺序 的场景;
  • 需要 快速横向扩容自动失效转移进程级容错 的场景;
  • 希望把“拓扑/容错/限流/背压”收束到应用代码表达层的团队。

3)环境与依赖 🧰

  • .NET / ABP 版本矩阵

    • .NET 7 → ABP 7
    • .NET 8 → ABP 8.0+(推荐)
  • NuGet(核心)
    Akka, Akka.Hosting, Akka.Cluster, Akka.Cluster.Sharding,
    Akka.Persistence.Sql, Akka.Streams, Akka.Logger.Serilog, Akka.Serialization.Hyperion

  • 可选(K8s/管理)
    Akka.Management, Akka.Discovery.KubernetesApi

<ItemGroup><PackageReference Include="Akka" Version="1.5.*" /><PackageReference Include="Akka.Hosting" Version="1.5.*" /><PackageReference Include="Akka.Cluster" Version="1.5.*" /><PackageReference Include="Akka.Cluster.Sharding" Version="1.5.*" /><PackageReference Include="Akka.Persistence.Sql" Version="1.5.*" /><PackageReference Include="Akka.Streams" Version="1.5.*" /><PackageReference Include="Akka.Logger.Serilog" Version="1.5.*" /><PackageReference Include="Akka.Serialization.Hyperion" Version="1.5.*" /><PackageReference Include="Akka.Management" Version="1.5.*" /><PackageReference Include="Akka.Discovery.KubernetesApi" Version="1.5.*" />
</ItemGroup>

4)目标架构与数据流(总览图)🗺️

HTTP/gRPC
Tell/Ask
ACK
Tell
Persist
Domain Events
Client
ABP AppService
IngressActor
Akka.Streams Graph
ShardRegion
DeviceActor #1
DeviceActor #2
DeviceActor #N
Journal/Snapshot
ABP EventBus

5)最小可跑骨架(单节点,内存持久化)🏃‍♂️

5分钟跑通闭环(不依赖外部 DB),再切换到 SQL/PG。

5.1 消息与分片提取器(稳定哈希)🔑

// Messages.cs
public interface IDeviceMsg { string DeviceId { get; } }
public sealed record Ingest(string DeviceId, double Value, DateTimeOffset Timestamp) : IDeviceMsg;
public sealed record GetCurrent(string DeviceId) : IDeviceMsg;
public sealed record CurrentState(string DeviceId, double Avg, long Count);// 使用稳定的 HashCodeMessageExtractor,避免 string.GetHashCode() 的跨进程随机化
using Akka.Cluster.Sharding;
public sealed class DeviceMessageExtractor : HashCodeMessageExtractor
{public DeviceMessageExtractor(int shards) : base(shards) { }public override string EntityId(object message) => ((IDeviceMsg)message).DeviceId;public override object EntityMessage(object message) => message;
}

5.2 实体 Actor(顺序处理 + 快照 + 钝化)🧠

// DeviceEntityActor.cs
using Akka.Actor;
using Akka.Event;
using Akka.Persistence;
using Akka.Cluster.Sharding;public sealed class DeviceEntityActor : ReceivePersistentActor
{private readonly ILoggingAdapter _log = Context.GetLogger();private double _sum; private long _count;public override string PersistenceId { get; }public DeviceEntityActor(){var entityId = Self.Path.Name;          // Sharding 注入PersistenceId = $"device-{entityId}";Command<Ingest>(cmd =>{Persist(cmd, e =>{_sum += e.Value; _count++;if (_count % 1000 == 0) SaveSnapshot((_sum, _count));});});Command<GetCurrent>(q =>{var avg = _count == 0 ? 0 : _sum / _count;Sender.Tell(new CurrentState(q.DeviceId, avg, _count));});// 自动钝化:与 remember-entities 互斥(见“生产配置”)Context.SetReceiveTimeout(TimeSpan.FromMinutes(5));Receive<ReceiveTimeout>(_ => Context.Parent.Tell(new Passivate(PoisonPill.Instance)));Recover<Ingest>(e => { _sum += e.Value; _count++; });Recover<SnapshotOffer>(s =>{var (sum, cnt) = ((double, long))s.Snapshot;_sum = sum; _count = cnt;});}
}

5.3 Streams 入口 + ACK 闭环(ActorRefWithAck)🔁

// Ingress messages for ACK protocol
public sealed record StreamInit();
public sealed record StreamAck();
public sealed record StreamComplete();
public sealed record StreamFail(Exception Cause);// IngressActor.cs
using Akka.Actor;
using Akka.Cluster.Sharding;public sealed class IngressActor : ReceiveActor
{private readonly IActorRef _region;public IngressActor(IActorRef region){_region = region;Receive<StreamInit>(_ => Sender.Tell(new StreamAck()));         // 握手Receive<Ingest>(msg => { _region.Tell(msg); Sender.Tell(new StreamAck()); }); // 逐条ACKReceive<StreamComplete>(_ => Context.Stop(Self));Receive<StreamFail>(x => { Context.GetLogger().Error(x.Cause, "stream failed"); });}
}
// Streams wiring(Program/Module中)
using Akka.Streams;
using Akka.Streams.Dsl;// 1) Materializer
var mat = SystemMaterializer.Get(system).Materializer;// 2) Source.Queue:入口背压队列
var (queue, source) = Source.Queue<Ingest>(bufferSize: 10_000, OverflowStrategy.Backpressure).PreMaterialize(mat);// 3) 将流量通过 ActorRefWithAck 打给 IngressActor(由其负责ACK并Tell到Region)
var ingress = system.ActorOf(Props.Create(() => new IngressActor(region)), "ingress");var ackSink = Sink.ActorRefWithAck<Ingest>(target: ingress,onInitMessage: new StreamInit(),ackMessage: new StreamAck(),onCompleteMessage: new StreamComplete(),onFailureMessage: ex => new StreamFail(ex)
);// 4) 可选:分组/聚合后下发
source.GroupBy(1024, x => x.DeviceId).GroupedWithin(500, TimeSpan.FromMilliseconds(50)).MergeSubstreams().SelectMany(batch => batch) // 批内可先聚合降噪,再下发.RunWith(ackSink, mat);// 在 ABP 层/Controller 中:await queue.OfferAsync(new Ingest(deviceId, value, DateTimeOffset.UtcNow));
5.3.1 端到端背压闭环 🧨
ClientABP AppServiceSource.QueueIngressActorShardRegionDeviceEntityActorPOST /ingest (deviceId, value)Offer(Ingest)背压:当下游未ACK时队列阻塞OfferIngestTell(Ingest)Deliver(Ingest)Persisted (event/snapshot)StreamAckOffer completed (backpressure released)202 AcceptedClientABP AppServiceSource.QueueIngressActorShardRegionDeviceEntityActor

5.4 Akka.Hosting:显式启动 Sharding + DI 注入 🧩

// Program.cs / YourAbpModule.ConfigureServices(...)
using Akka.Actor;
using Akka.Cluster.Sharding;
using Akka.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;// Marker type for ActorRegistry (避免直接暴露 ActorRef 原型类型)
public sealed class DeviceRegionKey {}builder.Services.AddAkka("AppSystem", (akka, sp) =>
{// —— 统一日志到 Serilog ——akka.ConfigureLoggers(l =>{l.ClearLoggers();l.AddLogger<Akka.Logger.Serilog.SerilogLogger>();});// —— 开发环境:内存持久化(复制即可跑)——var devHocon = """akka {loglevel = "INFO"actor {provider = "cluster"default-mailbox {mailbox-type = "Akka.Dispatch.BoundedMailbox"mailbox-capacity = 20000mailbox-push-timeout-time = 2s}serializers {hyperion = "Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion"}}remote.dot-netty.tcp { hostname = "0.0.0.0", port = 4053 }cluster { seed-nodes = ["akka.tcp://AppSystem@localhost:4053"], roles = ["api"] }persistence {journal.plugin = "akka.persistence.journal.inmem"snapshot-store.plugin = "akka.persistence.snapshot-store.inmem"}cluster.sharding { passivate-idle-entity-after = 5 m }}""";akka.AddHocon(devHocon, HoconAddMode.Append);// —— 显式启动 Sharding 并注入 Region —— akka.WithActors((system, registry) =>{var sharding  = ClusterSharding.Get(system);var settings  = ClusterShardingSettings.Create(system);var region = sharding.Start(typeName: "device-entity",entityProps: Props.Create(() => new DeviceEntityActor()),settings: settings,messageExtractor: new DeviceMessageExtractor(shards: 64));registry.TryRegister<DeviceRegionKey>(region);var ingress = system.ActorOf(Props.Create(() => new IngressActor(region)), "ingress");registry.TryRegister<IngressActor>(ingress);});
});

6)与 ABP 应用层对接(IRequiredActor + Ask/Tell)🔗

// DeviceAppService.cs
using Akka.Actor;
using Akka.Hosting;
using Microsoft.Extensions.Configuration;
using Volo.Abp.Application.Services;public class DeviceAppService : ApplicationService
{private readonly IActorRef _region;private readonly IActorRef _ingress;private readonly TimeSpan _askTimeout;public DeviceAppService(IRequiredActor<DeviceRegionKey> region,IRequiredActor<IngressActor> ingress,IConfiguration cfg){_region = region.ActorRef;_ingress = ingress.ActorRef;_askTimeout = TimeSpan.FromSeconds(cfg.GetValue("Akka:AskTimeoutSeconds", 2));}// 写多:走 Streams 队列 -> IngressActor(ACK背压闭环)public async Task IngestAsync(string deviceId, double value){_ingress.Tell(new Ingest(deviceId, value, DateTimeOffset.UtcNow));await Task.CompletedTask;}// 查少:必要时 Ask(统一超时/重试策略)public Task<CurrentState> GetAsync(string deviceId)=> _region.Ask<CurrentState>(new GetCurrent(deviceId), _askTimeout);
}

7)生产切换:SQL Server 持久化 🧱

开发用内存持久化;生产切换到 SQL/PG。以 SQL Server 为例(同理可替换为 PostgreSQL/MySQL,对应 provider-name 也要换成各自 Linq2Db ProviderName)。

# appsettings.Production.hocon(或用 AddHocon Append)
akka {persistence {journal {plugin = "akka.persistence.journal.sql"sql {class = "Akka.Persistence.Sql.Journal.SqlWriteJournal, Akka.Persistence.Sql"connection-string = "Server=localhost;Database=AkkaDemo;User Id=sa;Password=Your_password123;"provider-name = "SqlServer.2019"}}snapshot-store {plugin = "akka.persistence.snapshot-store.sql"sql {class = "Akka.Persistence.Sql.Snapshot.SqlSnapshotStore, Akka.Persistence.Sql"connection-string = "Server=localhost;Database=AkkaDemo;User Id=sa;Password=Your_password123;"provider-name = "SqlServer.2019"}}}# 生产常见:开启记忆实体,禁用自动钝化cluster.sharding {remember-entities = on# passivate-idle-entity-after 将被自动禁用}
}

⚠️ 上线前:按官方脚本初始化 Journal/Snapshot 架构与索引
Remember-Entities × 钝化:开启 remember-entities=on禁用自动钝化;需要停用实体,请用 Passivate 显式停止并取消记忆。🧹


8)序列化与安全(Hyperion)🛡️

akka.actor {serializers {hyperion = "Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion"}# 建议只绑定到你的消息基类型,而不是 System.Objectserialization-bindings {"Your.Namespace.IDeviceMsg, Your.Assembly" = hyperion}serialization-settings.hyperion {# 需要时可开启版本容忍、已知类型等(示例)# version-tolerance = on# knownTypesProvider = "Your.Namespace.KnownTypesProvider, Your.Assembly"}
}

只绑定消息基类型,避免误序列化;若强 Schema 演进诉求,生产可切 Protobuf。📦


9)Actor 生命周期 🧬

First message for EntityId
Count % 1000 == 0
Snapshot saved
ReceiveTimeout / Manual Passivate
PoisonPill
Re-activation by ShardRegion (on demand)
Idle
Active
Snapshotting
Passivating
Stopped

10)Sharding 重分布 📦

Yes
No
Node Scale-out
Join Cluster
Shard Coordinator Rebalance
Hot Shards?
Move Shards to New Node
Keep Current Placement
Entities Recreated on New Host
State Restore via Events/Snapshots
Traffic Resumes

11)K8s 拓扑 ☸️

K8s
Deployment:API
Deployment:Worker
Cluster Bootstrap
Cluster Bootstrap
Gossip
Gossip
Service API
Service Management
Pod Worker-1
Pod Worker-2
Pod Worker-3
Pod API-1
Pod API-2
Client

12)可靠性与容错 🛠️

  • 监督策略:业务可恢复异常 Resume;不可恢复 Restart/Stop
  • 幂等:命令带 CommandId,Actor 内滑窗去重;
  • 熔断:外部调用 Actor 使用 CircuitBreaker
  • 死信监控:订阅 DeadLetter 输出到 Serilog(报警)。📣

13)可观测性与日志 📊

  • Akka.Logger.Serilog 与 ABP 的 Serilog 统一;
  • 日志添加 SourceContext=ActorPath 维度,便于过滤;
  • 定期拉取 GetClusterShardingStatsGetShardRegionState 观测分布/热点;
  • 流水线指标:入口队列深度、批量大小、吞吐/延迟、失败率(Prometheus/OpenTelemetry)。

14)部署:本地多实例 & K8s 🧪

本地/Compose

  • 多进程/容器静态 seed-nodes
  • 验证分片重分布、Failover、恢复时间(含快照前后对比)。

Kubernetes

  • Akka.Management + Akka.Discovery.KubernetesApiCluster Bootstrap
  • roles=["api"] / ["worker"] 分层,worker 走 HPA;
  • 健康探针 + Coordinated Shutdown,滚动升级/金丝雀发布。🌈

15)性能调优清单 ⚡

  1. 分片数:初始 = 总核数 × 2~4,压测校正(过小→热点,过大→开销增)。
  2. 消息体:短小定长;大对象走外部存储,仅传引用。
  3. 快照频率:以“重放时长目标(如 <2s)”反推,起步 500~2000 事件/快照。
  4. Ask 慎用:统一超时/重试策略;写多路径优先 Tell
  5. 邮箱一律有界;热点实体可专用 dispatcher/邮箱。
  6. 背压闭环:优先 ActorRefWithAck;配合节流/并行度/批量。

16)常见坑 & 规避 🧨

  • string.GetHashCode() 做分片哈希 → ✅ 用 HashCodeMessageExtractor(稳定)。
  • ❌ Streams 直接 Tell 到 Region → ✅ 用 ActorRefWithAck/批量 Ask 打通背压闭环
  • System.Object 绑定 Hyperion → ✅ 只绑定消息基类型,并考虑白名单/演进。
  • ❌ Remember-Entities 开启仍指望自动钝化 → ✅ 自动钝化被禁用;需要停用时用 Passivate
  • ❌ 无界邮箱 → ✅ 一律有界并观测队列深度。
  • ❌ 乱配 ABP×.NET → ✅ .NET 8 对应 ABP 8+。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/92901.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92901.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[激光原理与应用-250]:理论 - 几何光学 - 透镜成像的优缺点,以及如克服缺点

透镜成像是光学系统中应用最广泛的技术&#xff0c;其通过折射原理将物体信息转换为图像&#xff0c;但存在像差、环境敏感等固有缺陷。以下是透镜成像的优缺点及针对性改进方案&#xff1a;一、透镜成像的核心优点高效集光能力透镜通过曲面设计将分散光线聚焦到一点&#xff0…

测试匠谈 | AI语音合成之大模型性能优化实践

「测试匠谈」是优测云服务平台倾心打造的内容专栏&#xff0c;汇集腾讯各大产品的顶尖技术大咖&#xff0c;为大家倾囊相授开发测试领域的知识技能与实践&#xff0c;让测试工作变得更加轻松高效。 本期嘉宾介绍 Soren&#xff0c;腾讯TEG技术事业群质量工程师&#xff0c;负责…

用天气预测理解分类算法-从出门看天气到逻辑回归

一、生活中的决策难题&#xff1a;周末郊游的「天气判断」 周末计划郊游时&#xff0c;你是不是总会打开天气预报反复确认&#xff1f;看到 "25℃、微风、无雨" 就兴奋收拾行李&#xff0c;看到 "35℃、暴雨" 就果断取消计划。这个判断过程&#xff0c;其…

HTTPS服务

HTTPS服务 一、常见的端口 http ------ 80 明文 https ------ 443 数据加密 dns ------ 53 ssh ------ 22 telent ------ 23 HTTPS http ssl或者tls &#xff08;安全模式&#xff09; 二、原理&#xff1a; c&#xff08;客户端…

【Android笔记】Android 自定义 TextView 实现垂直渐变字体颜色(支持 XML 配置)

Android 自定义 TextView 实现垂直渐变字体颜色&#xff08;支持 XML 配置&#xff09; 在 Android UI 设计中&#xff0c;字体颜色的渐变效果能让界面看起来更加精致与现代。常见的渐变有从左到右、从上到下等方向&#xff0c;但 Android 的 TextView 默认并不支持垂直渐变。…

CANopen Magic调试软件使用

一、软件安装与硬件连接1.1 系统要求操作系统&#xff1a;Windows 7/10/11 (64位)硬件接口&#xff1a;支持Vector/PEAK/IXXAT等主流CAN卡推荐配置&#xff1a;4GB内存&#xff0c;2GHz以上CPU1.2 安装步骤运行安装包CANopen_Magic_Setup.exe选择安装组件&#xff08;默认全选&…

前端css学习笔记3:伪类选择器与伪元素选择器

本文为个人学习总结&#xff0c;如有谬误欢迎指正。前端知识众多&#xff0c;后续将继续记录其他知识点&#xff01; 目录 前言 一、伪类选择器 1.概念 2.动态选择器&#xff08;用户交互&#xff09; 3.结构伪类 &#xff1a;first-child&#xff1a;选择所有兄弟元素的…

深入探索 PDF 数据提取:PyMuPDF 与 pdfplumber 的对比与实战

在数据处理和分析领域&#xff0c;PDF 文件常常包含丰富的文本、表格和图形信息。然而&#xff0c;从 PDF 中提取这些数据并非易事&#xff0c;尤其是当需要保留格式和颜色信息时。幸运的是&#xff0c;Python 社区提供了多个强大的库来帮助我们完成这项任务&#xff0c;其中最…

Springboot注册过滤器的三种方式(Order 排序)

一、使用 Component Order&#xff08;简单但不够灵活&#xff09; 适用于全局过滤器&#xff0c;无需手动注册&#xff0c;Spring Boot 会自动扫描并注册。 Component Order(1) // 数字越小&#xff0c;优先级越高 public class AuthFilter implements Filter {Autowired /…

电脑硬件详解

前几天我的风扇转的很快&#xff0c;而且cpu占用率很高&#xff0c;然后我在想怎么回事&#xff0c;然后就浅浅研究了一下电脑的硬件。 笔记本主板&#xff1a; 台式机主板&#xff1a; 图1&#xff1a; 图2&#xff1a; 电脑硬件详解 电脑的硬件是组成计算机系统的物理设…

力扣47:全排列Ⅱ

力扣47:全排列Ⅱ题目思路代码题目 给定一个可包含重复数字的序列 nums &#xff0c;按任意顺序 返回所有不重复的全排列。 思路 又是任意顺序和所有不重复的排列&#xff0c;显而易见我们要使用回溯的办法。 首先是回溯的结束条件即新数组的长度等于nums的长度。这道题的难点…

学习笔记091——如何实现web登录时,密码复杂度校验?(后端)

1、创建工具类 /*** 密码复杂度校验* param password 密码*/ public static void validatePassword(String password) {// 至少8位if (password.length() < 8) {throw new IllegalArgumentException("密码长度至少为8位");}// 包含大小写字母if (!password.matche…

雪花算法snowflake分布式id生成原理详解,以及对解决时钟回拨问题几种方案讨论

一、前言在日趋复杂的分布式系统中&#xff0c;数据量越来越大&#xff0c;数据库分库分表是一贯的垂直水平做法&#xff0c;但是需要一个全局唯一ID标识一条数据或者MQ消息&#xff0c;数据库id自增就显然不能满足要求了。因为场景不同&#xff0c;分布式ID需要满足以下几个条…

【PCB设计经验】去耦电容如何布局?

0805 和 0603 以及更小 封装的电容用作于对中高频的去耦,其摆放位置是有要求的: 一、建议尽可能的靠近主控芯片的 电源管脚放置。 二、使用较宽和短的引线连接到电源和地过孔可以采用如下 图 4–1 中的图 ( 2 )、( 3)、 ( 4 )任意一种方式,避免使用长线或者较细的…

自动化运维实验

目录 一、实验拓扑 二、实验目的 三、实验步骤 实验思路&#xff1a; 代码部分&#xff1a; 四、实验结果&#xff1a; 一、实验拓扑 二、实验目的 利用python脚本&#xff0c;在本地&#xff0c;或者虚拟机里实现&#xff0c;设备CRC数量统计&#xff0c;并输出成表格 三、实验…

Wed前端第二次作业

一、作业1&#xff1a;完成自己学校的官网&#xff0c;动忘内容直接贴&#xff0c;至少三个不同的页面1、界面1&#xff08;1&#xff09;相关代码<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name&quo…

第5节 大模型分布式推理通信优化与硬件协同

前言 在分布式推理中,多设备(如GPU、CPU)之间的数据传输(通信)是连接计算的“桥梁”。如果通信效率低下,即使单设备计算能力再强,整体性能也会大打折扣。想象一下:如果工厂之间的物流卡车跑得比生产速度还慢,再多的工厂也无法提高整体产量。 本节将从最基础的单设备内…

XGBoost 的适用场景以及与 CNN、LSTM 的区别

XGBoost 的核心优势与适用场景XGBoost 是一种梯度提升决策树算法&#xff0c;属于集成学习方法。它在处理结构化/表格化数据方面表现极其出色&#xff0c;是 Kaggle 竞赛和工业界广泛应用的“冠军”模型。其核心优势和应用场景包括&#xff1a;1. 结构化/表格化数据数据形式&a…

快速设计简单嵌入式操作系统(3):动手实操,基于STC8编写单任务执行程序,感悟MCU指令的执行过程

引言 前面我们陆续学习了操作系统常见的基础概念&#xff0c;接着简单了解了一下8051单片机的内存结构和执行顺序切换的相关概念。接下来&#xff0c;我们就开始进行实操&#xff0c;基于8051单片机STC8来编写一个简单的操作系统&#xff0c;这里我们先实现一个单任务的执行程…

Spring AI Alibaba - 聊天机器人快速上手

本节对应 Github&#xff1a;https://github.com/JCodeNest/JCodeNest-AI-Alibaba/tree/master/spring-ai-alibaba-helloworld 本文将以阿里巴巴的通义大模型为例&#xff0c;通过 Spring AI Alibaba 组件&#xff0c;手把手带你完成从零到一的构建过程&#xff1a;首先&#…