sp_invoke_external_rest_endpoint 到 Azure 队列会导致有毒消息

问题描述 投票:0回答:1

使用

sp_invoke_external_rest_endpoint
从 Azure SQL 中,消息已成功在 Azure 队列中排队。有效负载是
<QueueMessage><MessageText>HelloWorld</MessageText></QueueMessage>

当队列触发的 Azure 函数使消息出队时,它最终会进入有害队列。

如果我采用相同的消息(在本例中为HelloWorld),并通过门户添加它(仅在选中“以 Base64 编码消息正文”时才有效),则消息成功出列。

我尝试了多种方法来了解后台发生的事情,但我已经没有想法了。

这感觉像是一个编码问题。关于如何最好地解决这个问题有什么想法吗?

如果想要重新创建体验,下面是一些代码。 SQL 代码(Azure SQL 数据库)

DECLARE @QueueMessage_XML nvarchar(max) = N'<QueueMessage><MessageText>HelloWorld</MessageText></QueueMessage>';
DECLARE @QueueMessage nvarchar(max) = @QueueMessage_XML;

DECLARE @Time datetime = SYSUTCDATETIME();
DECLARE @FormattedMoment nvarchar(50) = FORMAT(@Time, 'ddd, dd MMM yyyy HH:mm:ss' ) + ' GMT';

DECLARE @ContentType nvarchar(256) = N'"content-type":"application/xml"';
DECLARE @Accept nvarchar(256) = N'"accept":"application/xml"';
DECLARE @StorageApiMsVersion nvarchar(256) = N'"x-ms-version":"2023-11-03"';
DECLARE @MsDate nvarchar(256) = N'"x-ms-date":"' + @FormattedMoment + N'"';

DECLARE @HeadersArray table([HeaderItem] nvarchar(256) NOT NULL);
INSERT INTO @HeadersArray ([HeaderItem]) VALUES 
    (@ContentType), 
    (@Accept), 
    (@StorageApiMsVersion), 
    (@MsDate);
DECLARE @Headers nvarchar(4000) = N'{' + (SELECT STRING_AGG([HeaderItem], ',') FROM @HeadersArray) + N'}';

DECLARE @Method nvarchar(6) = N'POST';
DECLARE @TimeoutSeconds int = 30;
DECLARE @Response nvarchar(max) = N'';
DECLARE @VisibilityTimeoutSeconds int = 20;

DECLARE @AccountName nvarchar(256)  = N'stacctname';
DECLARE @QueueName nvarchar(256)  = N'request';
DECLARE @QueueEndpoint nvarchar(256)  = N'https://' + @AccountName + N'.queue.core.windows.net';

DECLARE @Url nvarchar(4000) = @QueueEndpoint + N'/' + @QueueName + N'/messages';

DECLARE @ReturnValue int = 0;
EXEC @ReturnValue = sp_invoke_external_rest_endpoint
  @url = @Url,
  @payload = @QueueMessage,
  @headers = @Headers,
  @method = @Method,
  @credential = [https://stacctname.queue.core.windows.net],
  @timeout = @TimeoutSeconds,
  @response = @Response OUTPUT;

SELECT @ReturnValue AS [ReturnValue], @Response AS [Response];

Azure 函数应用程序代码

  • 隔离
  • C# .NET 8
  • Visual Studio 2022 版本 17.9.0 预览版 1.0
using Azure.Storage.Queues.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace FunctionApp;

public class DequeueRequest(ILogger<DequeueRequest> logger)
{
    private readonly ILogger<DequeueRequest> _logger = logger;

    [Function(nameof(DequeueRequest))]
    public void Run([QueueTrigger("request", Connection = "AzureWebJobsStorage")] QueueMessage message)
    {
        //intentionally muted
        _ = message.Body;
    }
}

更新 我主要缩小了范围,以确保该值是从 SQL

BASE64_ENCODE(CAST(@Payload_String AS varbinary(max)))
中进行 base64 编码的。它几乎可以解决这个问题,但是当尝试 JSON 序列化从队列中拉出的字符串时,它会抛出一个我无法跟踪的错误。原始字符串是有效的并确认可以通过序列化,因此这是关于从队列中拉出并发送到 json 序列化程序时发生的转换。

IOW,如下确认反序列化成功

var request = JsonSerializer.Deserialize<Request>(
    @"{""RequestId"":80,""StartDate"":""1753-01-01T00:00:00"",""EndDate"":""9999-12-29T00:00:00""}")

下面失败并将消息变成有毒消息(其中消息正文应该是base64字符串

var request = JsonSerializer.Deserialize<Request>(message.Body.ToString());
azure-functions azure-sql-database azure-queues azure-rest-api
1个回答
0
投票

已解决至少是一个工作解决方案。作为替代工作解决方案,可能会提高效率或减少“必须做的事情”

顶级域名;DR ...

  • BASE64_ENCODE 将用作
    <MessageText>
  • 值的非 unicode 字符串
  • 将此编码后的消息放入xml格式(如下)
    <QueueMessage><MessageText>base64_encoded_value</MessageText></QueueMessage>
  • 如果字符串值来自 FOR JSON 语句,请确保编码采用该值的非 unicode 表示形式(这是关键,但作为编码问题的原因并不明显)。

我的基本经验测试表明 BASE64_ENCODE 必须 是非 unicode 值的 varbinary(至少对于我的问题所需的字符)。

© www.soinside.com 2019 - 2024. All rights reserved.