简体   繁体   English

Azure Web 作业/队列 - DecoderFallbackException

[英]Azure Web Jobs / Queue - DecoderFallbackException

I am using the Azure Web Jobs Feature.我正在使用 Azure Web 作业功能。 Here is what I do.这就是我所做的。

Step 1第1步

  • I got an Web Api Project which receives always the same string from the same client application.我有一个 Web Api 项目,它总是从同一个客户端应用程序接收相同的字符串。
  • I have a simple class called SimpleClass which has just one property with always the same string from the same client application.我有一个名为SimpleClass的简单类,它只有一个属性,并且始终具有来自同一客户端应用程序的相同字符串。 (The string is APA91bELkr6CyBmqLbWomwkI2zw_GkXGVsblYH60l4hERXw9ZkCcXufjJM_7IZXI5_Ry9aze6AhYRVzBfl6CYq0kxrdV4ViPkW5hK2Rd2HlsZCDfhnOc3PGLt_SzIMjfbMRug_eK_di2YbJTA6weczoTyb-dKuvnwg ) (该字符串是APA91bELkr6CyBmqLbWomwkI2zw_GkXGVsblYH60l4hERXw9ZkCcXufjJM_7IZXI5_Ry9aze6AhYRVzBfl6CYq0kxrdV4ViPkW5hK2Rd2HlsZCDfhnOc3PGLt_SzIMjfbMRug_eK_di2YbJTA6weczoTyb-dKuvnwg
  • I serialize it using JsonConvert into a JSON string我使用 JsonConvert 将其序列化为 JSON 字符串
  • I write this into the Azure Storage Queue我将其写入 Azure 存储队列

Step 2第2步

  • I have create a very simple Azure Web Job Demo Job to process the queue我创建了一个非常简单的 Azure Web 作业演示作业来处理队列
  • The Job deserialize the object作业反序列化对象

But I got an exception sometime (only sometimes, this sucks)但有时我会遇到一个例外(只是有时,这很糟糕)

Unhandled Exception: System.Text.DecoderFallbackException: Unable to translate bytes [FF] at index 4 from specified code page to Unicode.
at System.Text.DecoderExceptionFallbackBuffer.Throw(Byte[] bytesUnknown, Int32 index)
at System.Text.DecoderExceptionFallbackBuffer.Fallback(Byte[] bytesUnknown, Int32 index)
at System.Text.DecoderFallbackBuffer.InternalFallback(Byte[] bytes, Byte* pBytes)
at System.Text.UTF8Encoding.GetCharCount(Byte* bytes, Int32 count, DecoderNLS baseDecoder)
at System.String.CreateStringFromEncoding(Byte* bytes, Int32 byteLength, Encoding encoding)
at System.Text.UTF8Encoding.GetString(Byte[] bytes, Int32 index, Int32 count)
at Microsoft.WindowsAzure.Storage.Queue.CloudQueueMessage.get_AsString()
at Microsoft.Azure.Jobs.QueueCausalityHelper.GetOwner(CloudQueueMessage msg)
at Microsoft.Azure.Jobs.Host.Runners.Worker.GetFunctionInvocation(FunctionDefinition func, RuntimeBindingProviderContext context, CloudQueueMessage msg)
at Microsoft.Azure.Jobs.Host.Runners.Worker.MyInvoker.Microsoft.Azure.Jobs.ITriggerInvoke.OnNewQueueItem(CloudQueueMessage msg, QueueTrigger trigger, RuntimeBindingProviderContext context)
at Microsoft.Azure.Jobs.Host.Triggers.PollQueueCommand.TryExecute()
at Microsoft.Azure.Jobs.LinearSpeedupTimerCommand.Execute()
at Microsoft.Azure.Jobs.IntervalSeparationTimer.RunTimer(Object state)
at System.Threading.TimerQueueTimer.CallCallbackInContext(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireQueuedTimerCompletion(Object state)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

Here is my code这是我的代码

Web API Controller Web API 控制器

public class TestController : ApiController
{
    public HttpResponseMessage Post(Model model)
    {
        // Retrieve storage account from connection string.
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
            CloudConfigurationManager.GetSetting("StorageConnectionString"));

        // Create the queue client.
        CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

        // Retrieve a reference to a queue.
        CloudQueue queue = queueClient.GetQueueReference("webjobsqueue");

        // Create the queue if it doesn't already exist.
        queue.CreateIfNotExists();

        // Create a message and add it to the queue.
        CloudQueueMessage message = new CloudQueueMessage(JsonConvert.SerializeObject(new SimpleClass { SimpleStringProperty = Model.Value }));
        queue.AddMessage(message);

        return new HttpResponseMessage(HttpStatusCode.OK);
    }
}

Web Job网络工作

class Program
{
    static void Main(string[] args)
    {
        var host = new JobHost();
        host.RunAndBlock();
    }

    public static void WaitForMessageInQueue([QueueTrigger("webjobsqueue")]
                                       string message)
    {
        var simpleClass = JsonConvert.DeserializeObject<SimpleClass >(message);
        Console.Out(simpleClass.SimpleStringProperty );
    }
}

###There is a post in the MSDN Forum with the same problem but no solution WebJobs Feedback ###MSDN 论坛有帖子有同样问题但没有解决方案WebJobs 反馈

Not every sequence of bytes is valid UTF-8 text.并非每个字节序列都是有效的 UTF-8 文本。 If you're receiving a valid random Unicode/UTF-8 string, everything should work correctly.如果您收到一个有效的随机 Unicode/UTF-8 字符串,则一切都应该正常工作。 But if you're receiving random bytes (not UTF-8 text), this behavior is expected.但是,如果您收到随机字节(不是 UTF-8 文本),则会出现这种行为。 CloudQueueMessage, the Azure Storage SDK's API for dealing with queue messages, kindly validates that it has valid text before handing it back to you. CloudQueueMessage 是用于处理队列消息的 Azure 存储 SDK 的 API,在将其交还给您之前,请先验证它是否具有有效文本。 Apparently some of the other classes do not do that kind of validation and instead silently ignore invalid text.显然,其他一些类不进行这种验证,而是默默地忽略无效文本。

I'd suggest validating Model.Value in your Web API action to ensure it's valid Unicode text before adding the message to the queue.我建议在您的 Web API 操作中验证 Model.Value 以确保在将消息添加到队列之前它是有效的 Unicode 文本。 I'd suggest using the result from model.Value.Normalize(), which says it will throw if the string contains invalid Unicode data.我建议使用来自 model.Value.Normalize() 的结果,它表示如果字符串包含无效的 Unicode 数据,它将抛出。

I am using the latest version of the Webjob SDK and every thing work fine for me using your code:我正在使用最新版本的Webjob SDK,并且使用您的代码对我来说一切正常:

I've created a simple model:我创建了一个简单的模型:

public class SimpleClass
{
    public string SimpleStringProperty { get; set; }
}

A class Function: A类功能:

public class Function
{
    public void WaitForMessageInQueue([QueueTrigger("webjobsqueue")] string message)
    {
        Console.Out.WriteLine(message);
    }
}

And here is my sample web job program:这是我的示例网络作业程序:

class Program
{
    // Please set the following connection strings in app.config for this WebJob to run:
    // AzureWebJobsDashboard and AzureWebJobsStorage
    static void Main()
    {

        // Retrieve storage account from connection string.
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
            CloudConfigurationManager.GetSetting("MyConnectionString"));

        // Create the queue client.
        CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

        // Retrieve a reference to a queue.
        CloudQueue queue = queueClient.GetQueueReference("webjobsqueue");

        // Create the queue if it doesn't already exist.
        queue.CreateIfNotExists();

        // Create a message and add it to the queue.
        CloudQueueMessage message = new CloudQueueMessage(JsonConvert.SerializeObject(new SimpleClass { SimpleStringProperty = "APA91bELkr6CyBmqLbWomwkI2zw_GkXGVsblYH60l4hERXw9ZkCcXufjJM_7IZXI5_Ry9aze6AhYRVzBfl6CYq0kxrdV4ViPkW5hK2Rd2HlsZCDfhnOc3PGLt_SzIMjfbMRug_eK_di2YbJTA6weczoTyb-dKuvnwg" }));
        queue.AddMessage(message);

        var host = new JobHost();
        host.RunAndBlock();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM