23、企业集成 - Azure 服务总线全面解析

企业集成 - Azure 服务总线全面解析

1. Azure 服务总线实体

Azure 服务总线支持三种不同类型的实体,它们在处理通信时提供了不同的选择:
- 队列(Queues) :是服务中最简单的实体。包含以下概念:
- 生产者(Producer) :向队列推送消息的应用程序或服务。
- 队列(Queue) :消息的容器。
- 消费者(Consumer) :使用拉取模型从队列读取消息的应用程序或服务。拉取模型意味着生产者需要主动请求队列接收消息。并且可以有多个生产者和多个消费者,锁定期限功能可确保同一时间只有一个消费者读取消息。
- 主题(Topics) :与队列略有不同,允许实现发布/订阅通信模型。队列是点对点通信,而主题可以将不同消息分发到不同队列,便于过滤和隔离消息,使消费者只读取感兴趣的消息。需注意,基本层不提供主题功能,至少要使用标准层。
- 中继(Relays) :队列和主题仅设计用于单向通信,若要实现双向通信,则需使用中继。Azure 中继是一个独立的服务,它能安全地暴露企业网络内托管的服务,支持单向、发布/订阅和双向通信等多种通信模型,且不像 VPN 那样改变网络,更稳定且作用于单个应用程序端点。

2. Azure 服务总线设计模式

Azure 服务总线常是众多云服务集成的核心,可用于数据集成、信息广播甚至双向通信等多种场景。凭借丰富的功能,可以实现各种职责。

3. 使用 Azure 服务总线 SDK 开发解决方案

GitHub 上有大量使用 Azure 服务总线的示例代码,这里仅介绍基本操作。
- 发送消息到队列

using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.ServiceBus;

namespace HandsOnAzure.ServiceBus
{
    internal class Program
    {
        private static void Main()
        {
            MainAsync().GetAwaiter().GetResult();
        }

        private static async Task MainAsync()
        {
            var client = new QueueClient("<connection-string>", "<queue-name>");
            var message = "This is my message!";
            await client.SendAsync(new Message(Encoding.UTF8.GetBytes(message)));
        }
    }
}

若要使用主题,可使用 TopicClient 替代 QueueClient

var client = new TopicClient("<connection-string>", "<topic-name>");

只需安装 Microsoft.Azure.ServiceBus NuGet 包即可。
- 拉取消息
- PeekAsync 示例

using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.ServiceBus.Core;

namespace HandsOnAzure.ServiceBus.Reader
{
    internal class Program
    {
        private static void Main()
        {
            MainAsync().GetAwaiter().GetResult();
            Console.ReadLine();
        }

        private static async Task MainAsync()
        {
            var receiver = new MessageReceiver("<connection-string>", "<queue-name>");
            while (true)
            {
                var message = await receiver.PeekAsync();
                if (message == null) continue;
                Console.WriteLine($"New message: [{message.ScheduledEnqueueTimeUtc}] {Encoding.UTF8.GetString(message.Body)}");
                await Task.Delay(100);
            }
        }
    }
}
- **ReceiveAsync**:仅使用 `PeekAsync` 不会创建消息存储,若要实现此功能,需使用 `ReceiveAsync`。`PeekAsync` 不会改变消息状态,而 `ReceiveAsync` 会根据 `ReceiveMode` 选项操作,可能作为原子 `CompleteAsync` 操作。使用 `PeekAsync` 后,可使用 `CompleteAsync` 标记消息为已读。
4. Azure 服务总线安全

作为企业级云服务,Azure 服务总线在安全功能方面有较高要求。除共享访问令牌外,还有一些预览中的新功能,可实现更灵活的访问管理。
- 托管服务标识(Managed Service Identity,MSI) :Azure 云中的一项功能,可简化服务间的身份验证,无需在代码中存储凭据。使用时,只需在访问控制(IAM)刀片中找到标识,示例代码如下:

var tokenProvider = TokenProvider.CreateManagedServiceIdentityTokenProvider();
var sendClient = new QueueClient($"sb://{namespace}.servicebus.windows.net/", {queue-name}, tokenProvider);
await sendClient.SendAsync(new Message(Encoding.UTF8.GetBytes(messageInfo.MessageToSend)));
await sendClient.CloseAsync();
  • 基于角色的访问控制(RBAC) :可利用 Azure AD 中定义的角色授予对服务的访问权限。首先要将用户添加到服务,使其获得访问权限并能开始推送和接收消息。此功能可更好地控制消息的发布和接收,相比 Azure 存储队列有很大改进。在 MSI 不可用时,也可使用 RBAC 身份验证授予服务对另一服务的访问权限,且无需交互式登录。
5. Azure 服务总线高级功能
  • 死信处理(Dead lettering) :队列中无人接收的消息被视为死信,有两种处理方式:永久删除或推送到死信队列。在 Azure 服务总线中,可通过设置消息的最大生命周期或使用 MessageReceiver DeadLetterAsync 方法将消息推送到死信队列。示例代码如下:
while (true)
{
    var message = await receiver.ReceiveAsync();
    if (message == null) continue;
    Console.WriteLine($"New message: [{message.ScheduledEnqueueTimeUtc}] {Encoding.UTF8.GetString(message.Body)}");
    await receiver.DeadLetterAsync(message.SystemProperties.LockToken, "HandsOnAzure - test");
    await Task.Delay(100);
}

可使用 EntityNameHelper.FormatDeadLetterPath("<entity-path>") 获取死信队列名称。
- 会话(Sessions) :用于实现先进先出(FIFO)保证。服务通常不控制消息间的关系,为将消息放入会话,需使用 SessionId 属性:

await client.SendAsync(new Message(Encoding.UTF8.GetBytes(message)) { SessionId = Guid.Empty.ToString()});

在接收端,需使用 QueueClient 实例的 RegisterSessionHandler 方法处理会话,并实现 IMessageSession
- 事务(Transactions) :涉及多个实体,包括客户端( QueueClient TopicClient )、消息(通过 Complete Defer Abandon 等操作)和会话( GetState/SetState )。拉取消息时需使用 ReceiveMode.PeekLock 模式,并在循环或 OnMessage 回调中打开事务范围。示例代码如下:

var message = receiver.Receive();
using (scope = new TransactionScope())
{
    var newMessage = // transfer
    sender.Send(newMessage);
    message.Complete();
    scope.Complete();
}

当事务实现后,只有整个事务成功时才会提交到队列日志,否则不会有处理消息的痕迹。

6. 处理中断和灾难

若将 Azure 服务总线作为架构核心,需确保其可复制且能抵御灾难,主要涉及灾难恢复和处理中断两个方面。
- 灾难恢复(Disaster recovery) :当灾难发生时,可能会丢失部分或全部数据。灾难通常指整个服务的临时或永久性丢失,且无法保证其再次可用。一般需要两个不同的数据中心来实现灾难恢复,且两个数据中心应尽量远离。实现步骤如下:
1. 创建主区域
2. 创建次区域
3. 进行配对
4. 定义故障转移触发条件
示例代码如下:

var client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
var namespace2 = await client.Namespaces.CreateOrUpdateAsync("<resource-group-name>", "<secondary-namespace>", new SBNamespace { ... params ... });
ArmDisasterRecovery drStatus = await client.DisasterRecoveryConfigs.CreateOrUpdateAsync("<resource-group-name>", "<primary-namespace>", "<alias>", new ArmDisasterRecovery { PartnerNamespace = namespace2.Id })

配对完成后,可使用以下代码触发故障转移:

client.DisasterRecoveryConfigs.FailOver("<resource-group-name>", "<secondary-namespace>", "<alias>");

故障转移完成后,可使用次区域处理消息。为应对再次中断,需设置另一个次命名空间并进行配对。
- 处理中断(Handling outages) :中断指服务暂时不可用,解决后可能需要同步两个服务总线命名空间。此过程自动但可能耗时,文档表明每分钟仅能传输 50 - 100 个实体。可考虑使用主动/被动复制概念:
- 主动复制(Active) :使用两个主动命名空间,接收器会接收两个命名空间的消息,需为消息添加相同唯一标识符以检测重复项。
- 被动复制(Passive) :仅在主命名空间无法传递消息时使用第二个队列或主题,可能会导致消息传递延迟、丢失或重复。示例代码如下:

private async Task SendMessage(BrokeredMessage message1, int maxSendRetries = 10)
{
    do
    {
        var message2 = message1.Clone();
        try
        {
            await _activeQueueClient.SendAsync(message1);
            return;
        }
        catch
        {
            if (--maxSendRetries <= 0)
            {
                throw;
            }
            lock (_swapMutex)
            {
                var client = _activeQueueClient;
                _activeQueueClient = _backupQueueClient;
                _backupQueueClient = client;
            }
            message1 = message2.Clone();
        }
    }
    while (true);
}

主动复制示例代码如下:

var task1 = primaryQueueClient.SendAsync(m1);
var task2 = secondaryQueueClient.SendAsync(m2);
try
{
    await task1;
}
catch (Exception e)
{
    exceptionCount++;
}
try
{
    await task2;
}
catch (Exception e)
{
    exceptionCount++;
}
if (exceptionCount > 1)
{
    throw new Exception("Send Failure");
}

此外,处理中断时还可考虑使用分区发送器(高级层不可用),以确保在单个消息存储中断时仍能正常发送和接收数据。示例代码如下:

var ns = NamespaceManager.CreateFromConnectionString(myConnectionString);
var td = new TopicDescription(TopicName);
td.EnablePartitioning = true;
ns.CreateTopic(td);

综上所述,Azure 服务总线是一个功能强大的服务,适用于简单和关键场景,具有较高的灵活性和易用性。通过合理使用其各种功能和特性,可以构建出可靠、高效的企业级集成解决方案。同时,在面对灾难和中断时,也有相应的应对策略和方法,保障服务的稳定性和数据的安全性。

企业集成 - Azure 服务总线全面解析

7. 总结与常见问题解答

Azure 服务总线功能丰富,涵盖了从基础的队列、主题通信,到高级的死信处理、会话管理和事务操作等多个方面。它不仅适用于简单的应用场景,在复杂的企业级集成中也能发挥重要作用。下面是一些常见问题的解答:
|问题|解答|
| ---- | ---- |
|队列和主题有什么区别?|队列是点对点通信,生产者将消息推送到队列,消费者从队列拉取消息;而主题是发布/订阅模型,可以将不同消息分发到不同队列,便于消息的过滤和隔离。|
|能否在基本层使用主题?|不能,基本层不提供主题功能,至少要使用标准层。|
|使用死信队列的原因是什么?|当队列中的消息无人接收时,可将这些消息推送到死信队列,以便后续分析或处理,避免消息永久丢失。|
|Azure 服务总线中会话的作用是什么?|会话用于实现先进先出(FIFO)保证,确保消息按顺序处理。|
|启用分区后,单个队列最大为 1GB 时,队列的最大大小是多少?|文档未提及该问题的具体答案。|
|主动复制和被动复制有什么区别?|主动复制使用两个主动命名空间,接收器接收两个命名空间的消息,并需标记消息以检测重复项;被动复制仅在主命名空间无法传递消息时使用第二个队列或主题,可能会导致消息传递延迟、丢失或重复。|
|Azure 服务总线如何实现灾难恢复?|需要创建主区域和次区域,进行配对并定义故障转移触发条件。配对完成后,在需要时触发故障转移,使用次区域处理消息。为应对再次中断,需设置另一个次命名空间并进行配对。|

8. 未来展望

Azure 服务总线作为企业集成的重要工具,未来可能会在以下几个方面继续发展和完善:
- 性能优化 :随着企业数据量的不断增长和业务复杂度的提高,对服务总线的性能要求也越来越高。未来可能会进一步优化消息处理速度、吞吐量和响应时间,以满足大规模数据传输和实时处理的需求。
- 安全增强 :安全始终是企业关注的重点。Azure 服务总线可能会引入更多先进的安全技术和功能,如更细粒度的访问控制、加密算法升级、多因素身份验证等,以保障数据的安全性和隐私性。
- 与其他服务的集成 :为了提供更全面的企业集成解决方案,Azure 服务总线可能会加强与其他 Azure 服务以及第三方服务的集成能力。例如,与 Azure Functions、Azure Logic Apps 等服务更紧密地结合,实现自动化的工作流和业务流程。
- 简化开发体验 :降低开发人员的学习成本和开发难度,提供更简洁、易用的 SDK 和工具,使开发人员能够更快速地构建和部署基于 Azure 服务总线的应用程序。

9. 流程图展示

以下是 Azure 服务总线灾难恢复的流程图:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px

    A([开始]):::startend --> B(创建主区域):::process
    B --> C(创建次区域):::process
    C --> D(进行配对):::process
    D --> E(定义故障转移触发条件):::process
    E --> F{是否发生灾难?}:::decision
    F -- 是 --> G(触发故障转移):::process
    G --> H(使用次区域处理消息):::process
    H --> I(设置新的次命名空间并配对):::process
    F -- 否 --> J([继续正常运行]):::startend
    I --> J

这个流程图清晰地展示了 Azure 服务总线灾难恢复的整个过程,从区域创建到配对,再到故障转移和后续的处理。

总之,Azure 服务总线在企业集成领域具有广阔的应用前景和发展潜力。通过不断学习和掌握其各种功能和特性,开发人员和企业可以更好地利用这一强大的工具,构建出高效、可靠、安全的企业级应用系统,应对各种复杂的业务需求和挑战。

【SCI级别】多策略改进鲸鱼优化算法(HHWOA)和鲸鱼优化算法(WOA)在CEC2017测试集函数F1-F30寻优对比内容概要:本文档主要介绍了一项关于多策略改进鲸鱼优化算法(HHWOA)与标准鲸鱼优化算法(WOA)在CEC2017测试集函数F1-F30上进行寻优性能对比的研究,属于智能优化算法领域的高水平科研工作。文中通过Matlab代码实现算法仿真,重点展示了HHWOA在收敛速度、寻优精度和稳定性方面的优势,体现了多策略改进的有效性。该研究适用于复杂优化问题求解,尤其在工程优化、参数辨识、机器学习超参数调优等领域具有应用潜力。; 适合人群:具备一定算法基础和Matlab编程能力的研究生、科研人员及从事智能优化算法开发与应用的工程技术人员,尤其适合致力于SCI论文写作与算法创新的研究者。; 使用场景及目标:①用于理解鲸鱼优化算法的基本原理及多策略改进思路(如种群初始化、非线性收敛因子、精英反向学习等);②为智能优化算法的性能测试与对比实验提供CEC2017标准测试平台的实现参考;③支撑学术研究中的算法创新与论文复现工作。; 阅读建议:建议结合提供的Matlab代码进行实践操作,重点关注HHWOA的改进策略模块与WOA的差异,通过重复实验验证算法性能,并可将其思想迁移至其他优化算法的改进中,提升科研创新能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值