【RabbitMQ】与ASP.NET Core集成

news/2025/10/28 23:48:15/文章来源:https://www.cnblogs.com/jixingsuiyuan/p/19167628

本章目标

  • 掌握在ASP.NET Core中配置和依赖注入RabbitMQ服务。

  • 学习使用IHostedService/BackgroundService实现常驻消费者服务。

  • 实现基于RabbitMQ的请求-响应模式。

  • 构建完整的微服务间异步通信解决方案。

  • 学习配置管理和健康检查。


一、理论部分

1. ASP.NET Core集成模式

将RabbitMQ集成到ASP.NET Core应用程序时,我们需要考虑几个关键方面:

  • 依赖注入:正确管理连接和通道的生命周期。

  • 托管服务:实现后台消息消费者。

  • 配置管理:从配置文件读取RabbitMQ连接设置。

  • 健康检查:监控RabbitMQ连接状态。

  • 日志记录:使用ASP.NET Core的日志系统。

2. 生命周期管理

  • IConnection:建议注册为单例,因为创建TCP连接开销大。

  • IModel:建议注册为瞬态或作用域,因为通道不是线程安全的。

  • 生产者服务:可以注册为作用域或瞬态。

  • 消费者服务:通常在托管服务中管理。

3. 托管服务(Hosted Services)

ASP.NET Core提供了IHostedService接口和BackgroundService基类,用于实现长时间运行的后台任务。这是实现RabbitMQ消费者的理想方式。

4. 微服务架构中的消息模式

  • 异步命令:发送指令但不期待立即响应。

  • 事件通知:广播状态变化。

  • 请求-响应:类似RPC,但通过消息中间件。


二、实操部分:构建订单处理微服务

我们将创建一个完整的订单处理系统,包含:

  • Order.API:接收HTTP订单请求,发布消息

  • OrderProcessor.BackgroundService:后台处理订单

  • 订单状态查询API

  • 健康检查

  • 配置管理

第1步:创建项目结构

# 创建解决方案
dotnet new sln -n OrderSystem# 创建Web API项目
dotnet new webapi -n Order.API
dotnet new classlib -n Order.Core
dotnet new classlib -n Order.Infrastructure
dotnet new classlib -n OrderProcessor.Service# 添加到解决方案
dotnet sln add Order.API/Order.API.csproj
dotnet sln add Order.Core/Order.Core.csproj
dotnet sln add Order.Infrastructure/Order.Infrastructure.csproj
dotnet sln add OrderProcessor.Service/OrderProcessor.Service.csproj# 添加项目引用
dotnet add Order.API reference Order.Core
dotnet add Order.API reference Order.Infrastructure
dotnet add OrderProcessor.Service reference Order.Core
dotnet add OrderProcessor.Service reference Order.Infrastructure
dotnet add Order.Infrastructure reference Order.Core# 添加NuGet包
cd Order.API
dotnet add package RabbitMQ.Client
dotnet add package Microsoft.Extensions.Diagnostics.HealthCheckscd ../Order.Infrastructure
dotnet add package RabbitMQ.Client
dotnet add package Microsoft.Extensions.Configurationcd ../OrderProcessor.Service
dotnet add package RabbitMQ.Client

第2步:定义领域模型(Order.Core)

Models/Order.cs

namespace Order.Core.Models
{public class Order{public string Id { get; set; } = Guid.NewGuid().ToString();public string CustomerId { get; set; }public string ProductId { get; set; }public int Quantity { get; set; }public decimal TotalAmount { get; set; }public OrderStatus Status { get; set; } = OrderStatus.Pending;public DateTime CreatedAt { get; set; } = DateTime.UtcNow;public DateTime? ProcessedAt { get; set; }}public enum OrderStatus{Pending,Processing,Completed,Failed,Cancelled}
}

Messages/OrderMessage.cs

namespace Order.Core.Messages
{public class OrderMessage{public string OrderId { get; set; }public string CustomerId { get; set; }public string ProductId { get; set; }public int Quantity { get; set; }public decimal TotalAmount { get; set; }public string Action { get; set; } // "create", "cancel"
    }public class OrderStatusMessage{public string OrderId { get; set; }public OrderStatus Status { get; set; }public string Message { get; set; }public DateTime Timestamp { get; set; } = DateTime.UtcNow;}
}

第3步:基础设施层(Order.Infrastructure)

Services/IRabbitMQConnection.cs

using RabbitMQ.Client;namespace Order.Infrastructure.Services
{public interface IRabbitMQConnection : IDisposable{bool IsConnected { get; }IModel CreateModel();bool TryConnect();}
}

Services/RabbitMQConnection.cs

using System.Net.Sockets;
using Microsoft.Extensions.Logging;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using RabbitMQ.Client.Exceptions;namespace Order.Infrastructure.Services
{public class RabbitMQConnection : IRabbitMQConnection{private readonly IConnectionFactory _connectionFactory;private readonly ILogger<RabbitMQConnection> _logger;private IConnection _connection;private bool _disposed;private readonly object _syncRoot = new object();public RabbitMQConnection(IConnectionFactory connectionFactory, ILogger<RabbitMQConnection> logger){_connectionFactory = connectionFactory;_logger = logger;}public bool IsConnected => _connection != null && _connection.IsOpen && !_disposed;public IModel CreateModel(){if (!IsConnected){throw new InvalidOperationException("No RabbitMQ connections are available to perform this action");}return _connection.CreateModel();}public bool TryConnect(){lock (_syncRoot){if (IsConnected) return true;_logger.LogInformation("RabbitMQ Client is trying to connect");try{_connection = _connectionFactory.CreateConnection();_connection.ConnectionShutdown += OnConnectionShutdown;_connection.CallbackException += OnCallbackException;_connection.ConnectionBlocked += OnConnectionBlocked;_logger.LogInformation("RabbitMQ Client acquired a persistent connection to '{HostName}' and is subscribed to failure events", _connectionFactory.HostName);return true;}catch (BrokerUnreachableException ex){_logger.LogError(ex, "RabbitMQ connection failed: {Message}", ex.Message);return false;}catch (SocketException ex){_logger.LogError(ex, "RabbitMQ connection failed: {Message}", ex.Message);return false;}}}private void OnConnectionBlocked(object sender, ConnectionBlockedEventArgs e){if (_disposed) return;_logger.LogWarning("A RabbitMQ connection is blocked. Reason: {Reason}", e.Reason);// 这里可以实现重连逻辑
            TryConnect();}private void OnCallbackException(object sender, CallbackExceptionEventArgs e){if (_disposed) return;_logger.LogWarning(e.Exception, "A RabbitMQ connection throw exception. Trying to re-connect...");// 这里可以实现重连逻辑
            TryConnect();}private void OnConnectionShutdown(object sender, ShutdownEventArgs reason){if (_disposed) return;_logger.LogWarning("A RabbitMQ connection is on shutdown. Trying to re-connect...");// 这里可以实现重连逻辑
            TryConnect();}public void Dispose(){if (_disposed) return;_disposed = true;try{_connection?.Dispose();}catch (IOException ex){_logger.LogCritical(ex, "Error disposing RabbitMQ connection");}}}
}

Services/IOrderPublisher.cs

using Order.Core.Messages;namespace Order.Infrastructure.Services
{public interface IOrderPublisher{Task PublishOrderCreatedAsync(OrderMessage order);Task PublishOrderStatusAsync(OrderStatusMessage status);}
}

Services/OrderPublisher.cs

using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Order.Core.Messages;
using RabbitMQ.Client;namespace Order.Infrastructure.Services
{public class OrderPublisher : IOrderPublisher{private readonly IRabbitMQConnection _connection;private readonly ILogger<OrderPublisher> _logger;private const string ExchangeName = "order.events";private const string OrderCreatedRoutingKey = "order.created";private const string OrderStatusRoutingKey = "order.status";public OrderPublisher(IRabbitMQConnection connection, ILogger<OrderPublisher> logger){_connection = connection;_logger = logger;// 确保交换机和队列存在
            InitializeInfrastructure();}private void InitializeInfrastructure(){using var channel = _connection.CreateModel();// 声明主题交换机channel.ExchangeDeclare(ExchangeName, ExchangeType.Topic, durable: true);// 声明订单创建队列channel.QueueDeclare("order.created.queue", durable: true, exclusive: false, autoDelete: false);channel.QueueBind("order.created.queue", ExchangeName, OrderCreatedRoutingKey);// 声明订单状态队列channel.QueueDeclare("order.status.queue", durable: true, exclusive: false, autoDelete: false);channel.QueueBind("order.status.queue", ExchangeName, OrderStatusRoutingKey);_logger.LogInformation("RabbitMQ infrastructure initialized");}public async Task PublishOrderCreatedAsync(OrderMessage order){await PublishMessageAsync(order, OrderCreatedRoutingKey, "OrderCreated");}public async Task PublishOrderStatusAsync(OrderStatusMessage status){await PublishMessageAsync(status, OrderStatusRoutingKey, "OrderStatus");}private async Task PublishMessageAsync<T>(T message, string routingKey, string messageType){if (!_connection.IsConnected){_connection.TryConnect();}using var channel = _connection.CreateModel();var json = JsonSerializer.Serialize(message);var body = Encoding.UTF8.GetBytes(json);var properties = channel.CreateBasicProperties();properties.Persistent = true;properties.ContentType = "application/json";properties.Type = messageType;try{channel.BasicPublish(exchange: ExchangeName,routingKey: routingKey,mandatory: true,basicProperties: properties,body: body);_logger.LogInformation("Published {MessageType} message for Order {OrderId}", messageType, GetOrderId(message));}catch (Exception ex){_logger.LogError(ex, "Error publishing {MessageType} message for Order {OrderId}", messageType, GetOrderId(message));throw;}await Task.CompletedTask;}private static string GetOrderId<T>(T message){return message switch{OrderMessage order => order.OrderId,OrderStatusMessage status => status.OrderId,_ => "unknown"};}}
}

第4步:Order.API项目配置

appsettings.json

{"RabbitMQ": {"HostName": "localhost","UserName": "myuser","Password": "mypassword","Port": 5672,"VirtualHost": "/"},"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": "*"
}

Program.cs

using Order.API.Controllers;
using Order.API.Services;
using Order.Core.Models;
using Order.Infrastructure.Services;
using RabbitMQ.Client;var builder = WebApplication.CreateBuilder(args);// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();// Configure RabbitMQ
builder.Services.AddSingleton<IConnectionFactory>(sp =>
{var configuration = sp.GetRequiredService<IConfiguration>();return new ConnectionFactory{HostName = configuration["RabbitMQ:HostName"],UserName = configuration["RabbitMQ:UserName"],Password = configuration["RabbitMQ:Password"],Port = int.Parse(configuration["RabbitMQ:Port"] ?? "5672"),VirtualHost = configuration["RabbitMQ:VirtualHost"] ?? "/",DispatchConsumersAsync = true};
});// Register RabbitMQ services
builder.Services.AddSingleton<IRabbitMQConnection, RabbitMQConnection>();
builder.Services.AddScoped<IOrderPublisher, OrderPublisher>();
builder.Services.AddScoped<IOrderService, OrderService>();// Add Health Checks
builder.Services.AddHealthChecks().AddRabbitMQ(provider => {var factory = provider.GetRequiredService<IConnectionFactory>();return factory.CreateConnection();}, name: "rabbitmq");// Add hosted service for status updates consumer
builder.Services.AddHostedService<OrderStatusConsumerService>();var app = builder.Build();// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();// Add health check endpoint
app.MapHealthChecks("/health");app.Run();

Services/IOrderService.cs

using Order.Core.Models;namespace Order.API.Services
{public interface IOrderService{Task<Order> CreateOrderAsync(string customerId, string productId, int quantity, decimal unitPrice);Task<Order?> GetOrderAsync(string orderId);Task UpdateOrderStatusAsync(string orderId, OrderStatus status);}
}

Services/OrderService.cs

using Order.Core.Messages;
using Order.Core.Models;
using Order.Infrastructure.Services;namespace Order.API.Services
{public class OrderService : IOrderService{private readonly IOrderPublisher _orderPublisher;private readonly ILogger<OrderService> _logger;// 内存存储用于演示(生产环境应该用数据库)private static readonly Dictionary<string, Order> _orders = new();public OrderService(IOrderPublisher orderPublisher, ILogger<OrderService> logger){_orderPublisher = orderPublisher;_logger = logger;}public async Task<Order> CreateOrderAsync(string customerId, string productId, int quantity, decimal unitPrice){var order = new Order{CustomerId = customerId,ProductId = productId,Quantity = quantity,TotalAmount = quantity * unitPrice,Status = OrderStatus.Pending};// 保存到内存_orders[order.Id] = order;// 发布订单创建事件var orderMessage = new OrderMessage{OrderId = order.Id,CustomerId = order.CustomerId,ProductId = order.ProductId,Quantity = order.Quantity,TotalAmount = order.TotalAmount,Action = "create"};await _orderPublisher.PublishOrderCreatedAsync(orderMessage);_logger.LogInformation("Order {OrderId} created and published", order.Id);return order;}public Task<Order?> GetOrderAsync(string orderId){_orders.TryGetValue(orderId, out var order);return Task.FromResult(order);}public async Task UpdateOrderStatusAsync(string orderId, OrderStatus status){if (_orders.TryGetValue(orderId, out var order)){order.Status = status;order.ProcessedAt = DateTime.UtcNow;// 发布状态更新var statusMessage = new OrderStatusMessage{OrderId = orderId,Status = status,Message = $"Order {status.ToString().ToLower()}"};await _orderPublisher.PublishOrderStatusAsync(statusMessage);_logger.LogInformation("Order {OrderId} status updated to {Status}", orderId, status);}}}
}
View Code

Services/OrderStatusConsumerService.cs

using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Options;
using Order.API.Services;
using Order.Core.Messages;
using Order.Infrastructure.Services;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;namespace Order.API.Services
{public class OrderStatusConsumerService : BackgroundService{private readonly IRabbitMQConnection _connection;private readonly IServiceProvider _serviceProvider;private readonly ILogger<OrderStatusConsumerService> _logger;private IModel _channel;private const string QueueName = "order.status.queue";public OrderStatusConsumerService(IRabbitMQConnection connection,IServiceProvider serviceProvider,ILogger<OrderStatusConsumerService> logger){_connection = connection;_serviceProvider = serviceProvider;_logger = logger;InitializeChannel();}private void InitializeChannel(){if (!_connection.IsConnected){_connection.TryConnect();}_channel = _connection.CreateModel();// 确保队列存在(已经在Publisher中声明,这里做双重保险)_channel.QueueDeclare(QueueName, durable: true, exclusive: false, autoDelete: false);_channel.BasicQos(0, 1, false); // 公平分发
            _logger.LogInformation("OrderStatusConsumerService channel initialized");}protected override async Task ExecuteAsync(CancellationToken stoppingToken){stoppingToken.ThrowIfCancellationRequested();var consumer = new AsyncEventingBasicConsumer(_channel);consumer.Received += async (model, ea) =>{var body = ea.Body.ToArray();var message = Encoding.UTF8.GetString(body);try{await ProcessMessageAsync(message);_channel.BasicAck(ea.DeliveryTag, false);}catch (Exception ex){_logger.LogError(ex, "Error processing message: {Message}", message);_channel.BasicNack(ea.DeliveryTag, false, false); // 不重新入队
                }};_channel.BasicConsume(QueueName, false, consumer);_logger.LogInformation("OrderStatusConsumerService started consuming");await Task.CompletedTask;}private async Task ProcessMessageAsync(string message){using var scope = _serviceProvider.CreateScope();var orderService = scope.ServiceProvider.GetRequiredService<IOrderService>();try{var statusMessage = JsonSerializer.Deserialize<OrderStatusMessage>(message);if (statusMessage != null){// 这里可以处理状态更新,比如更新数据库、发送通知等_logger.LogInformation("Received order status update: {OrderId} -> {Status}", statusMessage.OrderId, statusMessage.Status);// 在实际应用中,这里可能会更新数据库中的订单状态// await orderService.UpdateOrderStatusAsync(statusMessage.OrderId, statusMessage.Status);
                }}catch (JsonException ex){_logger.LogError(ex, "Error deserializing message: {Message}", message);throw;}}public override void Dispose(){_channel?.Close();_channel?.Dispose();base.Dispose();}}
}
View Code

Controllers/OrdersController.cs

using Microsoft.AspNetCore.Mvc;
using Order.API.Services;
using Order.Core.Models;namespace Order.API.Controllers
{[ApiController][Route("api/[controller]")]public class OrdersController : ControllerBase{private readonly IOrderService _orderService;private readonly ILogger<OrdersController> _logger;public OrdersController(IOrderService orderService, ILogger<OrdersController> logger){_orderService = orderService;_logger = logger;}[HttpPost]public async Task<ActionResult<Order>> CreateOrder([FromBody] CreateOrderRequest request){try{var order = await _orderService.CreateOrderAsync(request.CustomerId, request.ProductId, request.Quantity, request.UnitPrice);return Ok(order);}catch (Exception ex){_logger.LogError(ex, "Error creating order");return StatusCode(500, "Error creating order");}}[HttpGet("{orderId}")]public async Task<ActionResult<Order>> GetOrder(string orderId){var order = await _orderService.GetOrderAsync(orderId);if (order == null){return NotFound();}return Ok(order);}[HttpGet]public ActionResult<IEnumerable<Order>> GetOrders(){// 这里只是演示,实际应该从数据库获取return Ok(new List<Order>());}}public class CreateOrderRequest{public string CustomerId { get; set; }public string ProductId { get; set; }public int Quantity { get; set; }public decimal UnitPrice { get; set; }}
}
View Code

第5步:订单处理器服务(OrderProcessor.Service)

Program.cs

using Order.Core.Messages;
using Order.Infrastructure.Services;
using OrderProcessor.Service.Services;
using RabbitMQ.Client;var builder = Host.CreateApplicationBuilder(args);builder.Services.AddHostedService<OrderProcessorService>();// Configure RabbitMQ
builder.Services.AddSingleton<IConnectionFactory>(sp =>
{var configuration = sp.GetRequiredService<IConfiguration>();return new ConnectionFactory{HostName = configuration["RabbitMQ:HostName"],UserName = configuration["RabbitMQ:UserName"],Password = configuration["RabbitMQ:Password"],Port = int.Parse(configuration["RabbitMQ:Port"] ?? "5672"),VirtualHost = configuration["RabbitMQ:VirtualHost"] ?? "/",DispatchConsumersAsync = true};
});builder.Services.AddSingleton<IRabbitMQConnection, RabbitMQConnection>();
builder.Services.AddScoped<IOrderPublisher, OrderPublisher>();builder.Services.AddLogging();var host = builder.Build();
host.Run();
View Code

Services/OrderProcessorService.cs

using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Order.Core.Messages;
using Order.Infrastructure.Services;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;namespace OrderProcessor.Service.Services
{public class OrderProcessorService : BackgroundService{private readonly IRabbitMQConnection _connection;private readonly IOrderPublisher _orderPublisher;private readonly ILogger<OrderProcessorService> _logger;private IModel _channel;private const string QueueName = "order.created.queue";public OrderProcessorService(IRabbitMQConnection connection,IOrderPublisher orderPublisher,ILogger<OrderProcessorService> logger){_connection = connection;_orderPublisher = orderPublisher;_logger = logger;InitializeChannel();}private void InitializeChannel(){if (!_connection.IsConnected){_connection.TryConnect();}_channel = _connection.CreateModel();_channel.QueueDeclare(QueueName, durable: true, exclusive: false, autoDelete: false);_channel.BasicQos(0, 1, false);_logger.LogInformation("OrderProcessorService channel initialized");}protected override async Task ExecuteAsync(CancellationToken stoppingToken){stoppingToken.ThrowIfCancellationRequested();var consumer = new AsyncEventingBasicConsumer(_channel);consumer.Received += async (model, ea) =>{var body = ea.Body.ToArray();var message = Encoding.UTF8.GetString(body);try{await ProcessOrderAsync(message);_channel.BasicAck(ea.DeliveryTag, false);}catch (Exception ex){_logger.LogError(ex, "Error processing order: {Message}", message);_channel.BasicNack(ea.DeliveryTag, false, false);}};_channel.BasicConsume(QueueName, false, consumer);_logger.LogInformation("OrderProcessorService started consuming orders");await Task.CompletedTask;}private async Task ProcessOrderAsync(string message){try{var orderMessage = JsonSerializer.Deserialize<OrderMessage>(message);if (orderMessage == null){_logger.LogWarning("Received invalid order message: {Message}", message);return;}_logger.LogInformation("Processing order {OrderId} for customer {CustomerId}", orderMessage.OrderId, orderMessage.CustomerId);// 模拟订单处理逻辑await ProcessOrderBusinessLogic(orderMessage);// 发布处理完成状态var statusMessage = new OrderStatusMessage{OrderId = orderMessage.OrderId,Status = Order.Core.Models.OrderStatus.Completed,Message = "Order processed successfully"};await _orderPublisher.PublishOrderStatusAsync(statusMessage);_logger.LogInformation("Order {OrderId} processed successfully", orderMessage.OrderId);}catch (JsonException ex){_logger.LogError(ex, "Error deserializing order message: {Message}", message);throw;}}private async Task ProcessOrderBusinessLogic(OrderMessage orderMessage){// 模拟复杂的业务逻辑处理_logger.LogInformation("Starting business logic for order {OrderId}", orderMessage.OrderId);// 模拟处理时间var random = new Random();var processingTime = random.Next(2000, 5000);await Task.Delay(processingTime);// 模拟10%的失败率if (random.Next(0, 10) == 0){throw new Exception("Simulated business logic failure");}_logger.LogInformation("Business logic completed for order {OrderId}", orderMessage.OrderId);}public override void Dispose(){_channel?.Close();_channel?.Dispose();base.Dispose();}}
}
View Code

第6步:运行与测试

  1. 启动服务

    # 终端1:启动Order.API
    cd Order.API
    dotnet run# 终端2:启动OrderProcessor.Service
    cd OrderProcessor.Service
    dotnet run
  2. 测试API

    # 创建订单
    curl -X POST "https://localhost:7000/api/orders" \-H "Content-Type: application/json" \-d '{"customerId": "customer-123","productId": "product-456", "quantity": 2,"unitPrice": 29.99}'
    
    # 查询订单状态
    curl "https://localhost:7000/api/orders/{orderId}"
  3. 测试健康检查

    GET https://localhost:7000/health
  4. 观察日志输出

    • Order.API:接收HTTP请求,发布订单创建消息

    • OrderProcessor.Service:消费订单消息,处理业务逻辑,发布状态更新

    • Order.API:消费状态更新消息

  5. 测试错误场景

    • 停止RabbitMQ服务,观察重连机制

    • 停止OrderProcessor.Service,观察消息堆积

    • 重启服务,观察消息恢复处理

第7步:高级特性 - 配置重试和 resilience

在Order.Infrastructure中添加Polly支持:

// 添加NuGet包
dotnet add package Polly
dotnet add package Microsoft.Extensions.Http.Polly// 在Program.cs中添加重试策略
builder.Services.AddHttpClient("retry-client").AddTransientHttpErrorPolicy(policy => policy.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));


本章总结

在这一章中,我们成功地将RabbitMQ集成到ASP.NET Core应用程序中,构建了一个完整的微服务系统:

  1. 依赖注入配置:正确管理RabbitMQ连接和通道的生命周期。

  2. 托管服务:使用BackgroundService实现长时间运行的消费者服务。

  3. 领域驱动设计:采用分层架构,分离关注点。

  4. 消息序列化:使用JSON序列化消息体。

  5. 健康检查:集成RabbitMQ健康监控。

  6. 错误处理:实现完善的错误处理和日志记录。

  7. 配置管理:从配置文件读取连接字符串。

这个架构为构建生产级的微服务系统提供了坚实的基础。在下一章,我们将学习RabbitMQ的监控、治理和生产环境的最佳实践。

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

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

相关文章

IMO2025 Problem 1

考虑 \(n = 3\) 时的下三角,显然有三个容易构造的解,\(k = \{0, \, 1, \, 3\}\),构造如下:那么 \(n > 3\) 呢?由于下三角的点数恰好为 \(1 + 2 + \cdots + n\) 个点,对于第一条直线,有且仅有 \(3\) 中方式覆…

Day6综合案例2-注册信息

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">…

2014吉林省赛题解 | CCUT应用OJ——Sign in

题目简介题源:1035-Sign in | CCUT OJ,2014 吉林省赛 C 题 题意:给定长为 \(n\) 的序列 \(A\) 与长为 \(n-1\) 的序列 \(B\),其中 \(B\subset A\),求 \(A-B\)。即:\(B\) 中恰好只有一个元素在 \(A\) 中没出现,求…

访答知识库-可以本地使用的知识库

访答知识库-可以本地使用的知识库访答知识库,一键安装,0代码使用。 支持图片、视频、语音搜索与问答 支持多模态问答

代码大全2 第三四章

读《代码大全 2》第三、四章,感觉像听老程序员唠实用嗑,没半点虚头巴脑的理论。第三章讲代码可读性,真是说到心坎里了。以前总觉得代码能跑就行,变量随便叫个 a、b、c,注释能省就省。结果过半个月回头看,自己写的…

https代理服务器(六)再次java动态签发【成功】

https代理服务器(六)再次java动态签发【成功】1X500Name canamem = new X500Name(caCertificate.getSubjectX500Principal().getName());改为X500Name issuerName = new JcaX509CertificateHolder(caCertificate).ge…

[AGC032D] Rotation Sort 题解

QwQ[AGC032D] Rotation Sort 题解 把循环移位看作是将某个数向左或右插入到任意位置,显然一个数最多被移动一次。 那么该序列中一共有三种数:向左移动 向右移动 不动假设已知每个数属于哪一种,考虑如何判定该方案是…

[AGC024E] Sequence Growing Hard 题解

QwQ[AGC024E] Sequence Growing Hard 题解 首先手玩一下样例,考虑在哪些位置插入是合法,假设在 \(pos\) 位置前插入 \(x\),则如果 \(x > a_{pos}\),则显然字典序会变大,否则如果 \(a_{pos} = x\) 需要找到 \(p…

新学期每日总结(第15天)

今日 相较昨日 学习下载数据库

实验2 现代C++编程初体验

任务1 源代码 T.h#pragma once#include <string>// 类T: 声明 class T { // 对象属性、方法 public:T(int x = 0, int y = 0); // 普通构造函数T(const T &t); // 复制构造函数T(T &&t); /…

P7154 [USACO20DEC] Sleeping Cows P 题解

QwQP7154 [USACO20DEC] Sleeping Cows P 题解 把 \(s, t\) 升序排序。 容易发现每一个 \(t_i\) 可匹配的 \(s_j\) 对应了一个前缀。 考虑刻画极大匹配,一个匹配是极大的当且仅当最大的没有被匹配的 \(t\) 小于最小的没…

Java流程控制——switch多选择结构

Java流程控制——switch多选择结构swtich多选择语句 多选择结构的另一实现方式为switch-case语句 switch-case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支 基本结构示例 switch(expression){case…

P3607 [USACO17JAN] Subsequence Reversal P 题解

好题P3607 [USACO17JAN] Subsequence Reversal P 题解 如果我们顺序对翻转的子序列做 DP,那么在末尾新增一个数会影响前面所有数的交换对应关系。 思考这个翻转的结构,前后对应的数交换,如果我们同时加入前后两个对…

示性函数2

Problem 设有一个大小为 $ n $ 的集合,进行 $ n $ 次操作,每次从集合中随机选取一个元素并记录之,求所有操作结束后,所记录的元素中互不相同的元素的个数的期望 $ E(X) $。分析 通常示性函数在应用与解决此类问题时…

随笔/杂记

随便写写记记 罗素茶壶:一个主张的不可证伪性,并不能成为相信它的理由。

k3s 基础 —— 将 traefik 替换为 ingress-nginx

k3s 基础 —— 将 traefik 替换为 ingress-nginx部署 创建 ingress-nginx.yaml apiVersion: helm.cattle.io/v1 kind: HelmChart metadata:name: ingress-nginxnamespace: kube-system spec:chart: https://<yourcd…

使用 Swift 解析验证码(结合 Tesseract OCR)

环境准备 1.1 安装 SwiftmacOS 自带 Swift,如需更新,可使用: xcode-select --install 更多内容访问ttocr.com或联系1436423940 然后检查 Swift 版本: swift --version Linux 用户可以从 Swift 官方网站 下载对应版…

常见排序算法Java实现

/**常见排序算法汇总 */ public class SortAlgorithms { /**冒泡排序(Bubble Sort) 思想:相邻元素两两比较,大的往后沉。 时间复杂度:O(n^2) 稳定性:稳定 */ public static void bubbleSort(int[] arr) { for (i…

题解:qoj1875 Nein

题意:给出 \(k,n\),问第 \(n\) 个是 \(10^k-1\) 的倍数的且每个数字不含有 \(9\) 的数是多少。\(k\le 18,n\le 10^{18}\)。 做法: 首先先跳出一个很显然的想法,一开始看这个东西觉得应该是拆成 \(x10^k-x\) 去讨论…