当前位置: 首页 > news >正文

.Net Core微服务入门全纪录(六)——EventBus-事件总线

系列文章目录

1、.Net Core微服务入门系列(一)——项目搭建
2、.Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上)
3、.Net Core微服务入门全纪录(三)——Consul-服务注册与发现(下)
4、.Net Core微服务入门全纪录(四)——Ocelot-API网关(上)
5、.Net Core微服务入门全纪录(五)——Ocelot-API网关(下)
6、.Net Core微服务入门全纪录(六)——EventBus-事件总线
7、.Net Core微服务入门全纪录(七)——IdentityServer4-授权认证
8、.Net Core微服务入门全纪录(八)——Docker Compose与容器网络


在这里插入图片描述

文章目录

  • 系列文章目录
  • 前言📃
  • 一、EventBus-事件总线
    • 1.1 什么是事件总线?
    • 1.2 为什么要用EventBus
  • 二、CAP使用
    • 2.1 环境准备
    • 2.2 代码修改
  • 三、运行测试
  • 四、总结


前言📃

关于 微服务 的概念解释网上有很多, 个人理解微服务是一种系统架构模式,它和语言无关,和框架无关,和工具无关,和服务器环境无关。

微服务思想 是将传统的单体系统按照业务拆分成多个职责单一、且可独立运行的接口服务。至于服务如何拆分,没有明确的定义。几乎任何后端语言都能做微服务开发。微服务也并不是完美无缺的,微服务架构会带来更多的问题,增加系统的复杂度,引入更多的技术栈。

上一篇【.Net Core微服务入门全纪录(五)——Ocelot-API网关(下)】中已经完成了 Ocelot + Consul 的搭建,这一篇简单说一下 EventBus

一、EventBus-事件总线

1.1 什么是事件总线?

🌈事件总线 是对观察者(发布-订阅)模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种 解耦 的目的。

如果没有接触过 EventBus ,可能不太好理解。其实 EventBus 在客户端开发中应用非常广泛android,ios,web 前端等,用于多个组件(或者界面)之间的相互通信。

1.2 为什么要用EventBus

就拿当前的项目举例,我们有一个订单服务,一个产品服务。客户端有一个下单功能,当用户下单时,调用订单服务的下单接口,那么下单接口需要调用产品服务的减库存接口,这涉及到服务与服务之间的调用。那么服务之间又怎么调用呢?直接 RESTAPI?或者效率更高的gRPC?可能这两者各有各的使用场景,但是他们都存在一个服务之间的耦合问题,或者难以做到异步调用。

试想一下:假设我们下单时调用订单服务,订单服务需要调用产品服务,产品服务又要调用物流服务,物流服务再去调用xx服务 等等。。。如果每个服务处理时间需要2s,不使用异步的话,那这种体验可想而知。

如果使用 EventBus 的话,那么订单服务只需要向 EventBus 发一个“下单事件”就可以了。产品服务会订阅“下单事件”,当产品服务收到下单事件时,自己去减库存就好了。这样就避免了两个服务之间直接调用的耦合性,并且真正做到了异步调用。

既然涉及到多个服务之间的异步调用,那么就不得不提分布式事务。分布式事务并不是微服务独有的问题,而是所有的分布式系统都会存在的问题。

关于分布式事务,可以查一下 “CAP原则”“BASE理论” 了解更多。当今的分布式系统更多的会追求事务的最终一致性。

下面使用国人开发的优秀项目 “CAP”,来演示一下 EventBus 的基本使用。之所以使用 “CAP”是因为它既能解决分布式系统的最终一致性,同时又是一个 EventBus,它具备 EventBus 的所有功能!
作者介绍:https://www.cnblogs.com/savorboard/p/cap.html

二、CAP使用

2.1 环境准备

Docker 中准备一下需要的环境,首先是数据库,数据库我使用 PostgreSQL,用别的也行。CAP 支持:SqlServer,MySql,PostgreSql,MongoDB。

然后是MQ,这里我使用 RabbitMQKafka 也可以。

Docker运行RabbitMQ:

docker pull rabbitmq:management
docker run -d -p 15672:15672 -p 5672:5672 --name rabbitmq rabbitmq:management

🔑默认用户:guest,密码:guest

环境准备就完成了,Docker 就是这么方便。

2.2 代码修改

为了模拟以上业务,需要修改大量代码,下面代码如有遗漏的直接去github找。

NuGet安装:

Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools
Npgsql.EntityFrameworkCore.PostgreSQL

在这里插入图片描述

CAP相关:

DotNetCore.CAP
DotNetCore.CAP.RabbitMQ
DotNetCore.CAP.PostgreSql

在这里插入图片描述

Order.API/Controllers/OrdersController.cs 增加下单接口:

[Route("[controller]")]
[ApiController]
public class OrdersController : ControllerBase
{private readonly ILogger<OrdersController> _logger;private readonly IConfiguration _configuration;private readonly ICapPublisher _capBus;private readonly OrderContext _context;public OrdersController(ILogger<OrdersController> logger, IConfiguration configuration, ICapPublisher capPublisher, OrderContext context){_logger = logger;_configuration = configuration;_capBus = capPublisher;_context = context;}[HttpGet]public IActionResult Get(){string result = $"【订单服务】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}——" +$"{Request.HttpContext.Connection.LocalIpAddress}:{_configuration["ConsulSetting:ServicePort"]}";return Ok(result);}/// <summary>/// 下单 发布下单事件/// </summary>/// <param name="order"></param>/// <returns></returns>[Route("Create")][HttpPost]public async Task<IActionResult> CreateOrder(Models.Order order){using (var trans = _context.Database.BeginTransaction(_capBus, autoCommit: true)){//业务代码order.CreateTime = DateTime.Now;_context.Orders.Add(order);var r = await _context.SaveChangesAsync() > 0;if (r){//发布下单事件await _capBus.PublishAsync("order.services.createorder", new CreateOrderMessageDto() { Count = order.Count, ProductID = order.ProductID });return Ok();}return BadRequest();}}}

Order.API/MessageDto/CreateOrderMessageDto.cs:

/// <summary>
/// 下单事件消息
/// </summary>
public class CreateOrderMessageDto
{/// <summary>/// 产品ID/// </summary>public int ProductID { get; set; }/// <summary>/// 购买数量/// </summary>public int Count { get; set; }
}

Order.API/Models/Order.cs订单实体类:

public class Order
{[Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)]public int ID { get; set; }/// <summary>/// 下单时间/// </summary>[Required]public DateTime CreateTime { get; set; }/// <summary>/// 产品ID/// </summary>[Required]public int ProductID { get; set; }/// <summary>/// 购买数量/// </summary>[Required]public int Count { get; set; }
}

Order.API/Models/OrderContext.cs数据库Context:

public class OrderContext : DbContext
{public OrderContext(DbContextOptions<OrderContext> options): base(options){}public DbSet<Order> Orders { get; set; }protected override void OnModelCreating(ModelBuilder modelBuilder){}
}

Order.API/appsettings.json增加数据库连接字符串:

"ConnectionStrings": {"OrderContext": "User ID=postgres;Password=pg123456;Host=host.docker.internal;Port=5432;Database=Order;Pooling=true;"
}

Order.API/Startup.cs修改ConfigureServices方法,添加Cap配置:

public void ConfigureServices(IServiceCollection services)
{services.AddControllers();services.AddDbContext<OrderContext>(opt => opt.UseNpgsql(Configuration.GetConnectionString("OrderContext")));//CAPservices.AddCap(x =>{x.UseEntityFramework<OrderContext>();x.UseRabbitMQ("host.docker.internal");});
}

在这里插入图片描述
以上是订单服务的修改。

Product.API/Controllers/ProductsController.cs增加减库存接口:

[Route("[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{private readonly ILogger<ProductsController> _logger;private readonly IConfiguration _configuration;private readonly ICapPublisher _capBus;private readonly ProductContext _context;public ProductsController(ILogger<ProductsController> logger, IConfiguration configuration, ICapPublisher capPublisher, ProductContext context){_logger = logger;_configuration = configuration;_capBus = capPublisher;_context = context;}[HttpGet]public IActionResult Get(){string result = $"【产品服务】{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}——" +$"{Request.HttpContext.Connection.LocalIpAddress}:{_configuration["ConsulSetting:ServicePort"]}";return Ok(result);}/// <summary>/// 减库存 订阅下单事件/// </summary>/// <param name="message"></param>/// <returns></returns>[NonAction][CapSubscribe("order.services.createorder")]public async Task ReduceStock(CreateOrderMessageDto message){//业务代码var product = await _context.Products.FirstOrDefaultAsync(p => p.ID == message.ProductID);product.Stock -= message.Count;await _context.SaveChangesAsync();}}

Product.API/MessageDto/CreateOrderMessageDto.cs:

/// <summary>
/// 下单事件消息
/// </summary>
public class CreateOrderMessageDto
{/// <summary>/// 产品ID/// </summary>public int ProductID { get; set; }/// <summary>/// 购买数量/// </summary>public int Count { get; set; }
}

Product.API/Models/Product.cs产品实体类:

public class Product
{[Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)]public int ID { get; set; }/// <summary>/// 产品名称/// </summary>[Required][Column(TypeName = "VARCHAR(16)")]public string Name { get; set; }/// <summary>/// 库存/// </summary>[Required]public int Stock { get; set; }
}

Product.API/Models/ProductContext.cs数据库Context:

public class ProductContext : DbContext
{public ProductContext(DbContextOptions<ProductContext> options): base(options){}public DbSet<Product> Products { get; set; }protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);//初始化种子数据modelBuilder.Entity<Product>().HasData(new Product{ID = 1,Name = "产品1",Stock = 100},new Product{ID = 2,Name = "产品2",Stock = 100});}
}

Product.API/appsettings.json增加数据库连接字符串:

"ConnectionStrings": {"ProductContext": "User ID=postgres;Password=pg123456;Host=host.docker.internal;Port=5432;Database=Product;Pooling=true;"
}

Product.API/Startup.cs修改ConfigureServices方法,添加Cap配置:\

public void ConfigureServices(IServiceCollection services)
{services.AddControllers();services.AddDbContext<ProductContext>(opt => opt.UseNpgsql(Configuration.GetConnectionString("ProductContext")));//CAPservices.AddCap(x =>{x.UseEntityFramework<ProductContext>();x.UseRabbitMQ("host.docker.internal");});
}

在这里插入图片描述
以上是产品服务的修改。

订单服务和产品服务的修改到此就完成了,看着修改很多,其实功能很简单。就是各自增加了自己的数据库表,然后订单服务增加了下单接口,下单接口会发出 “下单事件”。产品服务增加了减库存接口,减库存接口会订阅 “下单事件”。然后客户端调用下单接口下单时,产品服务会减去相应的库存,功能就这么简单。

关于 EF数据库迁移 之类的基本使用就不介绍了。使用 Docker 重新构建镜像,运行订单服务,产品服务:

docker build -t orderapi:1.1 -f ./Order.API/Dockerfile .
docker run -d -p 9060:80 --name orderservice orderapi:1.1 --ConsulSetting:ServicePort="9060"
docker run -d -p 9061:80 --name orderservice1 orderapi:1.1 --ConsulSetting:ServicePort="9061"
docker run -d -p 9062:80 --name orderservice2 orderapi:1.1 --ConsulSetting:ServicePort="9062"docker build -t productapi:1.1 -f ./Product.API/Dockerfile .
docker run -d -p 9050:80 --name productservice productapi:1.1 --ConsulSetting:ServicePort="9050"
docker run -d -p 9051:80 --name productservice1 productapi:1.1 --ConsulSetting:ServicePort="9051"
docker run -d -p 9052:80 --name productservice2 productapi:1.1 --ConsulSetting:ServicePort="9052"

最后 Ocelot.APIGateway/ocelot.json 增加一条路由配置:

在这里插入图片描述

好了,进行到这里,整个环境就有点复杂了。确保我们的PostgreSQL,RabbitMQ,Consul,Gateway,服务实例都正常运行。

服务实例运行成功后,数据库应该是这样的:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
📃产品表种子数据:

在这里插入图片描述
cap.published 表和 cap.received 表是由 CAP自动生成的,它内部是使用本地消息表+MQ来实现异步确保。

三、运行测试

这次使用 Postman 作为客户端调用下单接口( 9070 是之前的 Ocelot 网关端口):

在这里插入图片描述
订单库 published 表:

在这里插入图片描述

订单库 order 表:

在这里插入图片描述

产品库 received 表:

在这里插入图片描述

产品库 product 表:

在这里插入图片描述

再试一下:

在这里插入图片描述
在这里插入图片描述
OK,完成。虽然功能很简单,但是我们实现了服务的解耦,异步调用,和最终一致性。

四、总结

注意,上面的例子纯粹是为了说明 EventBus 的使用,实际中的下单流程绝对不会这么做的!希望大家不要较真。

可能有人会说如果下单成功,但是库存不足导致减库存失败了怎么办,是不是要回滚订单表的数据?如果产生这种想法,说明还没有真正理解最终一致性的思想。

首先下单前肯定会检查一下库存数量,既然允许下单那么必然是库存充足的。这里的事务是指:订单保存到数据库,和下单事件保存到 cap.published 表(保存到 cap.published 表理论上就能够发送到MQ)这两件事情,要么一同成功,要么一同失败。如果这个事务成功,那么就可以认为这个业务流程是成功的,至于产品服务的减库存是否成功那就是产品服务的事情了(理论上也应该是成功的,因为消息已经确保发到了MQ,产品服务必然会收到消息),CAP也提供了失败重试,和失败回调机制。

如果非要数据回滚也是能实现的,CAPICapPublisher.Publish 方法提供一个 callbackName参数,当减库存时,可以触发这个回调。其本质也是通过发布订阅完成,这是不推荐的做法,就不详细说了,有兴趣自己研究一下。
另外,CAP 无法保证消息不重复,实际使用中需要自己考虑一下消息的重复过滤和幂等性。


在这里插入图片描述

相关文章:

.Net Core微服务入门全纪录(六)——EventBus-事件总线

系列文章目录 1、.Net Core微服务入门系列&#xff08;一&#xff09;——项目搭建 2、.Net Core微服务入门全纪录&#xff08;二&#xff09;——Consul-服务注册与发现&#xff08;上&#xff09; 3、.Net Core微服务入门全纪录&#xff08;三&#xff09;——Consul-服务注…...

QD Laser携“Lantana”激光器参展SPIE光子学西部展2025,聚焦紧凑型设计

据悉&#xff0c;QD Laser公司将在2025年SPIE光子学西部展览会上展出其最新产品——世界最小一体化紧凑型可见光激光器“Lantana”。该展会将于1月28日至30日在旧金山的Moscone中心举行。 在展会期间&#xff0c;QD Laser公司将现场展示这款超小型、轻便设备—— “Lantana”。…...

Docker + Nginx 部署个人静态博客指南

本文是一个使用 Docker 和 Nginx 部署个人静态博客的指南。通过本指南&#xff0c;您可以快速了解如何使用 Docker 和 Nginx 部署自己的静态博客网站。 前提 在开始使用本指南之前&#xff0c;请具备以下前提&#xff1a; 首先你得有个服务器服务器已经安装好Git、Vim等工具一…...

springboot3 集成 knife4j(接口文档)

提示&#xff1a;文章是集成 knife4j&#xff0c;而非 swagger2 或者 swagger3&#xff0c;效果如图 文章目录 前言一、添加依赖二、如何集成1.配置文件2.注解部分1.Tag2.Operation3.Parameter4.Schema 3.使用 总结 前言 提示&#xff1a;&#xff1a;大家在开发阶段&#xff…...

批量创建ES索引

7.x from elasticsearch import Elasticsearch# 配置 Elasticsearch 连接 # 替换为你的 Elasticsearch 地址、端口、用户名和密码 es Elasticsearch([http://10.10.x.x:43885],basic_auth(admin, XN272G9THEAPYD5N5QORX3PB1TSQELLB) )# # 测试连接 # try: # # 尝试获取集…...

单路由及双路由端口映射指南

远程登录总会遇到登陆不上的情况&#xff0c;可能是访问的大门没有打开哦&#xff0c;下面我们来看看具体是怎么回事&#xff1f; 当软件远程访问时&#xff0c;主机需要两个条件&#xff0c;一是有一个唯一的公网IP地址&#xff08;运营商提供&#xff09;&#xff0c;二是开…...

基于Springboot + vue实现的民俗网

“前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff1a;人工智能学习网站” &#x1f496;学习知识需费心&#xff0c; &#x1f4d5;整理归纳更费神。 &#x1f389;源码免费人人喜…...

動態住宅IP提升網站訪問成功率

動態住宅IP通常與普通家庭用戶的網路連接相關聯。這種IP地址的特點在於&#xff0c;它是動態變化的&#xff0c;用戶在每次連接時可能會獲得不同的IP地址。這與靜態IP形成了鮮明對比&#xff0c;後者在連接期間保持不變。傳統上&#xff0c;IP地址分為住宅IP和數據中心IP兩類。…...

Java集合学习:HashMap的原理

一、HashMap里的Hash是什么&#xff1f; 首先&#xff0c;我们先要搞清楚HashMap里的的Hash是啥意思。 当我们在编程过程中&#xff0c;往往需要对线性表进行查找操作。 在顺序表中查找时&#xff0c;需要从表头开始&#xff0c;依次遍历比较a[i]与key的值是否相等&#xff…...

使用rsync+inotify简单实现文件实时双机双向同步

使用rsyncinotify简单实现文件实时双机双向同步 实现思路 使用inotify-tools的inotifywait工具监控文件变化&#xff0c;触发后使用rsync做同步。加入系统服务项&#xff0c;实现实时监听&#xff0c;方便管理。 以下配置操作&#xff0c;单向同步&#xff0c;只需在单边部…...

[JavaScript] ES6及以后版本的新特性

文章目录 箭头函数&#xff08;Arrow Functions&#xff09;为什么需要箭头函数&#xff1f;箭头函数的完整语法箭头函数中的 this实用场景 解构赋值&#xff08;Destructuring Assignment&#xff09;为什么需要解构赋值&#xff1f;数组解构赋值的完整用法对象解构赋值的完整…...

IO进程 寒假作业

一、请使用消息队列实现2个终端之间互相聊天 #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/wait.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> …...

无公网IP 外网访问媒体服务器 Emby

Emby 是一款多媒体服务器软件&#xff0c;用户可以在 Emby 创建自己的个人多媒体娱乐中心&#xff0c;并且可以跨多个设备访问自己的媒体库。它允许用户管理传输自己的媒体内容&#xff0c;比如电影、电视节目、音乐和照片等。 本文将详细的介绍如何利用 Docker 在本地部署 Emb…...

【2025小年源码免费送】

&#x1f496;学习知识需费心&#xff0c; &#x1f4d5;整理归纳更费神。 &#x1f389;源码免费人人喜&#xff0c; &#x1f525;码农福利等你领&#xff01; &#x1f496;山高路远坑又深&#xff0c; &#x1f4d5;大军纵横任驰奔&#xff0c; &#x1f389;谁敢横刀立马行…...

哈希表示例

示例1 两数之和 "两数之和"&#xff08;Two Sum&#xff09;是LeetCode上的一个经典算法问题&#xff0c;编号为1&#xff0c;它要求在一个整数数组nums中找到两个不同的索引i和j&#xff0c;使得nums[i] nums[j] target。 问题描述&#xff1a; 给定一个整数数…...

VS企业版和专业版的区别

网上查询vs分析dump文件&#xff0c;查找托管内存泄露&#xff0c;需要使用“调试托管内存”功能&#xff0c;当前安装的vs2022 专用版找不到这个选项&#xff0c;vs2015是ok的&#xff0c;比较版本发现2022是专业版&#xff0c;2015是企业版。网上搜索专业版和企业版差异如下&…...

YOLOv10-1.1部分代码阅读笔记-train.py

train.py ultralytics\models\yolov10\train.py 目录 train.py 1.所需的库和模块 2.class YOLOv10DetectionTrainer(DetectionTrainer): 1.所需的库和模块 from ultralytics.models.yolo.detect import DetectionTrainer from .val import YOLOv10DetectionValidator fr…...

autogen 自定义agent (1)

目录 第一个自定义agent&#xff1a;CountDownAgent代码运行逻辑1. 创建 CountDownAgent 代理2. 处理消息3. 运行 CountDownAgent 另一种调用方式类似的agent: CountUpAgent 第一个自定义agent&#xff1a;CountDownAgent from typing import AsyncGenerator, List, Sequence,…...

ssh密钥登录GitHub时一直提示“Error: Permission denied (publickey)”

起因 环境&#xff1a;Windows10 背景&#xff1a;之前就是按照官方说明创建个rsa密钥&#xff0c;在git后台添加上&#xff0c;就行了&#xff0c;近期怎么添加怎么失败&#xff0c;总是“Error: Permission denied (publickey)”的提示&#xff01; 尝试 各种尝试&#xf…...

多模态数据融合的基本流程与关键环节

多模态数据融合作为人工智能的重要技术方向&#xff0c;不仅整合了视觉、语言、语音、传感器等多种模态的数据&#xff0c;还通过合理的融合方法让机器获得更全面的感知能力。那么&#xff0c;多模态数据融合的过程是怎样的&#xff1f;有哪些关键环节需要注意&#xff1f;今天…...

k8s 蓝绿发布、滚动发布、灰度发布

在Kubernetes&#xff08;k8s&#xff09;中&#xff0c;蓝绿发布、滚动发布、灰度发布&#xff08;金丝雀发布&#xff09;是三种常见的应用部署和更新策略。下面将分别对这几种发布方式进行说明&#xff0c;并给出相应的例子。 蓝绿发布 蓝绿发布是一种无缝切换版本的部署策…...

【PyCharm】连接Jupyter Notebook

【PyCharm】相关链接 【PyCharm】连接 Git【PyCharm】连接Jupyter Notebook【PyCharm】快捷键使用【PyCharm】远程连接Linux服务器【PyCharm】设置为中文界面 【PyCharm】连接Jupyter Notebook PyCharm连接Jupyter Notebook的过程可以根据不同的需求分为 本地连接 和 远程连…...

【miniconda】:langraph的windows构建

langraph需要python3.11 langraph强烈建议使用py3.11 默认是3.12 官方 下载仓库 下载老版本的python (后续发现新版miniconda也能安装老版本的python) 在这里...

NRF52840 USB Dongle 进行蓝牙抓包

1、可视化抓包 官方的工具 链接&#xff1a;RF Connect for Desktop &#xff0c;之后使用 bluetooth Low Energy 即可查看抓包数据。不做说明。 本节主要说明&#xff0c;使用wireshark进行抓包数据的显示。 1.1、硬件 Nordic Semiconductor 官网链接 的截图如下。国内封装…...

【C++】详细讲解继承(下)

本篇来继续说说继承。上篇可移步至【C】详细讲解继承&#xff08;上&#xff09; 1.继承与友元 友元关系不能继承 &#xff0c;也就是说基类友元不能访问派⽣类私有和保护成员。 class Student;//前置声明class Same //基类 { public:friend void Fun(const Same& p, con…...

OS Copilot功能测评:智能助手的炫彩魔法

简介&#xff1a; OS Copilot 是一款融合了人工智能技术的智能助手&#xff0c;专为Linux系统设计&#xff0c;旨在提升系统管理和运维效率。本文详细介绍了在阿里云ECS实例上安装和体验OS Copilot的过程&#xff0c;重点评测了其三个核心参数&#xff1a;-t&#xff08;模式…...

Gin 学习笔记

教程地址&#xff1a;https://www.bilibili.com/video/BV1FV4y1C72M?spm_id_from333.788.videopod.sections&vd_source707ec8983cc32e6e065d5496a7f79ee6 01-项目搭建 各常用目录的说明&#xff1a; https://github.com/golang-standards/project-layout/blob/master/REA…...

windows在命令行中切换盘符

一、问题描述 我们在使用windows的cmd&#xff08;命令行&#xff09;时&#xff0c;经常需要用cd命令在不同盘之间切换路径。但有时在不同盘之间切换时&#xff0c;会发现命令不起作用。 如下图所示&#xff0c;直接切换目录还是停留在原来的位置。 二、解决方法 首先切换盘符…...

OpenAI模块重构

文章目录 1.common-openai-starter1.目录结构2.OpenAiProperties.java 新增apiUrl3.OpenAIAutoConfiguration.java4.OpenAiClient.java 使用gson重构 2.common-openai-starter-demo1.目录结构2.application.yml 新增api-url3.OpenAiController.java4.OpenAiApplication.java5.测…...

表的增删改查(MySQL)

1. 表的增删改查 CRUD : Create(创建), Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete&#xff08;删除&#xff09; 1.1 Create 语法&#xff1a; INSERT [INTO] table_name [(column [, column] ...)] VALUES (value_list) [, (value_list)] ...value_list:…...

Go 不可重复协程安全队列

代码实现 package dataStructimport ("errors""sync" )// GenericQueue 是一个支持泛型的不可重复队列&#xff0c;具有最大长度限制 // T 是泛型参数 type GenericQueue[T comparable] struct {items map[T]struct{} // 使用 map 来存储元素order []…...

每日一题 419. 棋盘上的战舰

419. 棋盘上的战舰 简单 class Solution { public:int countBattleships(vector<vector<char>>& board) {int ans 0;for(int i0;i<board.size();i){for(int j0;j<board[0].size();j){if(board[i][j] X){dfs(board,i,j);ans;}}}return ans;}void dfs(…...

spring cloud alibaba 使用示例

spring cloud alibaba example spring cloud alibaba nacos 配置中心、spring cloud alibaba nacos 服务注册与发现、openfeign 服务调用、spring cloud loadbalancer 负载均衡、spring cloud alibaba sentinel 限流降级、spring cloud alibaba seata 分布式事务、spring clou…...

Python数据分析-Python语法基础,IPython和Jupyter-Notebooks(二)

title: ‘Python数据分析:Python语法基础&#xff0c;IPython和Jupyter Notebooks&#xff08;二&#xff09;’ tags: python数据分析 categories:python数据分析 keywords:python数据分析 cover: …/img/404_icecream_whale.png description: 本文介绍python的基础语法和jup…...

领域驱动设计(DDD)Spring Boot 3 实现 二

使用 Spring Boot 3 实现领域驱动设计&#xff08;DDD&#xff09;是一种很自然的选择&#xff0c;因为 Spring 提供了良好的生态支持&#xff0c;特别是在分层架构、依赖管理、事件驱动等方面。以下是如何在 Spring Boot 3 中结合 DDD 进行开发的详细指南&#xff1a; 项目结构…...

Vue.js 高级组件开发

Vue.js 高级组件开发&#xff1a;构建一个智能动态表单生成器 ——从可复用架构到性能优化的全链路实践 引言&#xff1a;为什么需要高级组件&#xff1f; 在现代前端开发中&#xff0c;组件不仅是UI的封装&#xff0c;更是业务逻辑的载体。一个“高级”Vue组件应当具备&…...

wangEditor富文本编辑器,Laravel上传图片配置和使用

文章目录 前言步骤1. 构造好前端模版2. 搭建后端存储3. 调试 前言 由于最近写项目需要使用富文本编辑器&#xff0c;使用的是VUE3.0版本所以很多不兼容&#xff0c;实际测试以后推荐使用wangEditor 步骤 构造好前端模版搭建后端存储调试 1. 构造好前端模版 安装模版 模版安…...

Hive之加载csv格式数据到hive

场景&#xff1a; 今天接了一个需求&#xff0c;将测试环境的hive数据导入到正式环境中。但是不需要整个流程的迁移&#xff0c;只需要迁移ads表 解决方案&#xff1a; 拿到这个需求首先想到两个方案&#xff1a; 1、将数据通过insert into语句导出&#xff0c;然后运行脚本 …...

0164__【GNU】gcc -O编译选项 -Og -O0 -O1 -O2 -O3 -Os

【GNU】gcc -O编译选项 -Og -O0 -O1 -O2 -O3 -Os_gcc -o0-CSDN博客...

《DiffIR:用于图像修复的高效扩散模型》学习笔记

paper&#xff1a;2303.09472 GitHub&#xff1a;GitHub - Zj-BinXia/DiffIR: This project is the official implementation of Diffir: Efficient diffusion model for image restoration, ICCV2023 目录 摘要 1、介绍 2、相关工作 2.1 图像恢复&#xff08;Image Rest…...

[Datawheel]利用Zigent框架编写智能体-2

书接上回 1. Zigent实现教程编写智能体 本节将通过 Zigent 框架实现一个教程编写智能体&#xff0c;其主要功能是输入教程主题&#xff0c;然后自动生成完整的教程内容。 设计思路&#xff1a; 先通过 LLM 大模型生成教程的目录&#xff0c;再对目录按照二级标题进行分块&…...

cursor重构谷粒商城05——docker容器化技术快速入门【番外篇】

前言&#xff1a;这个系列将使用最前沿的cursor作为辅助编程工具&#xff0c;来快速开发一些基础的编程项目。目的是为了在真实项目中&#xff0c;帮助初级程序员快速进阶&#xff0c;以最快的速度&#xff0c;效率&#xff0c;快速进阶到中高阶程序员。 本项目将基于谷粒商城…...

Django项目的创建及运行——Django学习日志(一)

1.命令行创建 &#xff08;1&#xff09;创建项目 django-admin startproject HelloWorld&#xff08;这里的名称任意&#xff09; &#xff08;2&#xff09;创建应用&#xff08;app&#xff09; 首先要进入到项目目录&#xff0c;比如我这里的项目目录为HelloWorld cd …...

gesp(C++六级)(1)洛谷:P10250:[GESP样题 六级] 下楼梯

gesp(C六级)&#xff08;1&#xff09;洛谷&#xff1a;P10250&#xff1a;[GESP样题 六级] 下楼梯 题目描述 顽皮的小明发现&#xff0c;下楼梯时每步可以走 1 1 1 个台阶、 2 2 2 个台阶或 3 3 3 个台阶。现在一共有 N N N 个台阶&#xff0c;你能帮小明算算有多少种方案…...

1.23学习

misc buuctf-小明的保险箱 打开附件是一个在线图片首先将其另存为&#xff0c;然后仅仅只是一个图片&#xff0c;而无其他信息&#xff0c;那么我们再进行binwalk或者foremost文件分离&#xff0c;得到了一个文件夹&#xff0c;其中含有一个压缩包但是是一个加密的&#xff0…...

atheris从安装到fuzz输入输出解读

1. 引入 模糊测试是一种自动化的软件测试技术&#xff0c;它通过自动生成大量随机数据作为输入来测试程序&#xff0c;以发现潜在的错误、漏洞或崩溃。atheris是一个专门用于CPython&#xff08;Python的C语言实现&#xff09;的模糊测试框架。 2. 安装atheris 参考1&#x…...

基于自然语言处理的垃圾短信识别系统

基于自然语言处理的垃圾短信识别系统 &#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 目录 设计题目设计目的设计任务描述设计要求输入和输出…...

PAT甲级-1022 Digital Libiary

题目 题目大意 一个图书有图书id&#xff0c;书名&#xff0c;作者&#xff0c;关键字&#xff0c;出版商&#xff0c;出版时间6个信息。现要查询图书的ID&#xff0c;1对应通过书名查询&#xff0c;2对应作者&#xff0c;3对应关键字&#xff08;不需要完全一致&#xff0c;包…...

GD32F470 USB虚拟串口

1. 硬件连接 确保GD32F470开发板的USB接口连接到PC的USB端口。开发板通常提供USB FS&#xff08;全速&#xff09;接口&#xff0c;可以直接使用。 2. 配置USB功能 需要配置USB时钟、GPIO和中断&#xff0c;以支持全速USB设备模式。 2.1 配置USB时钟 c复制 void usb_rcu_…...

25美赛ABCDEF题详细建模过程+可视化图表+参考论文+写作模版+数据预处理

详情见该链接&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 25美国大学生数学建模如何准备&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;-CSDN博客文章浏览阅读791次&#xff0c;点赞13次&#xff0c;收藏7次。通过了解比赛基本…...