Azure函数实例共享变量吗? [英] Instances of Azure Functions are sharing variables?

查看:107
本文介绍了Azure函数实例共享变量吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不确定该问题是否有意义,但这就是我正在观察的内容.我的Azure功能使用BlobTrigger处理上传到Blob存储的PDF文件.一切正常,直到我一次上传几个Blob,在这种情况下,使用下面的代码,我观察到以下内容:

  • 第一个context.getLogger()正确记录了触发函数的每个blob.

  • 在Azure文件共享中,正确保存了每个PDF文件.

  • 在许多情况下,第二个context.getLogger()返回错误的结果(来自其他文件之一),就像变量在我的Function实例之间共享一样.请注意,行[19]对于每个PDF都是唯一的.

  • 稍后我会在代码中记录来自错误PDF的数据的类似行为.

要清楚,我知道当多个实例并行运行时,日志不会井井有条.但是,当我上载10个文件时,并没有获得10个行的唯一结果[19],而是大多数结果是重复的,这个问题后来在基​​于XI的情况下在我的代码中变得更糟,并且在10个调用中有9个产生垃圾数据.

Main.class

public class main {
   @FunctionName("veninv")
       @StorageAccount("Storage")
       public void blob(
           @BlobTrigger(
                   name = "blob",
                   dataType = "binary",
                   path = "veninv/{name}") 
               byte[] content,
           @BindingName("name") String blobname,
           final ExecutionContext context
           ) {

         context.getLogger().info("BlobTrigger by: " + blobname + "(" + content.length + " bytes)");

           //Writing byte[] to a file in Azure Functions file storage
               File tempfile = new File (tempdir, blobname);
               OutputStream os = new FileOutputStream(tempfile);
               os.write(content);
               os.close();

               String[] lines  = Pdf.getLines(tempfile);
               context.getLogger().info(lines[19]);
           }
    }

Pdf.class

   public static String[] getLines(File PDF) throws Exception {
           PDDocument doc = PDDocument.load(PDF);
           PDFTextStripper pdfStripper = new PDFTextStripper();
           String text = pdfStripper.getText(doc);
           lines = text.split(System.getProperty("line.separator"));
           doc.close();
           return lines;
   }

我不太了解这里发生了什么,因此希望获得一些帮助.

解决方案

是. Azure函数调用可以共享变量.我需要确保所有代码都是100%确定的,但是看起来lines对象声明为static,并且可以在调用之间共享它.让我们尝试从static String[]更改为String[],看看问题是否消失了吗?

Azure函数易于起步,很容易忘记执行环境.您的函数调用并不像它们看起来那样孤立.有一个父线程调用您的函数,并且静态变量不是线程安全的".静态变量表示全局状态,因此可以全局访问.而且,它不附带任何特定的对象实例. 静态"指的是静态".变量的大小与它所在的内存空间有关,而不是其值.因此,可以从引用该变量的所有类实例中访问同一变量.

PS.您已经通过减少并发性在此处的问题中解决了该问题,但这可能会损害可伸缩性.我建议进行负载测试.静态变量也可能有用.许多都是线程安全的,您想在Azure函数中使用它们,例如httpClient或sqlClient DB连接! 此处./p>

Not sure if the question makes sense, but it's what I'm observing. My Azure Function uses a BlobTrigger to process PDF files that are uploaded to a Blob Storage. Things work fine, until I upload several blobs at once, in which case, using the code below I observe the following:

  • The first context.getLogger() correctly logs each blob that triggers the Function.

  • In the Azure File Share, each PDF file is correctly saved.

  • The second context.getLogger() in many cases returns incorrect results (from one of the other files), as if variables are being shared between instances of my Function. Note that lines[19] is unique for each PDF.

  • I notice similar behavior later on in my code where data from the wrong PDF is logged.

EDIT: to be clear, I understand logs aren't going to be in order when multiple instances run in parallel. However, rather than getting 10 unique results for lines[19] when I upload 10 files, the majority of the results are duplicates and this issue worsens later on in my code when based on X I want to do Y, and 9 out of 10 invocations produce garbage data.

Main.class

public class main {
   @FunctionName("veninv")
       @StorageAccount("Storage")
       public void blob(
           @BlobTrigger(
                   name = "blob",
                   dataType = "binary",
                   path = "veninv/{name}") 
               byte[] content,
           @BindingName("name") String blobname,
           final ExecutionContext context
           ) {

         context.getLogger().info("BlobTrigger by: " + blobname + "(" + content.length + " bytes)");

           //Writing byte[] to a file in Azure Functions file storage
               File tempfile = new File (tempdir, blobname);
               OutputStream os = new FileOutputStream(tempfile);
               os.write(content);
               os.close();

               String[] lines  = Pdf.getLines(tempfile);
               context.getLogger().info(lines[19]);
           }
    }

Pdf.class

   public static String[] getLines(File PDF) throws Exception {
           PDDocument doc = PDDocument.load(PDF);
           PDFTextStripper pdfStripper = new PDFTextStripper();
           String text = pdfStripper.getText(doc);
           lines = text.split(System.getProperty("line.separator"));
           doc.close();
           return lines;
   }

I don't really understand what's going on here, so hoping for some assistance.

解决方案

Yes. Azure function invocations can share variables. I'd need to see all the code to be 100% certain, but it looks like the lines object is declared as static and it could be shared across invocations. Let's try changing from a static String[] to String[] and see if the problem goes away?

Azure functions are easy to get off the ground, it's easy to forget about the execution environment. Your functions invocations aren't as isolated as they appear. There is a parent thread calling your function, and static variables aren't "thread safe." Static variable represents a global state so it is globally accessible. Also, it is not attached with any particular object instance. The "staticness" of the variable relates to the memory space it sits in not it’s value. So, the same variable is accessible from all class instances in which it is referenced.

PS. You've solved the issue in your answer here by reducing concurrency, but that may come at a cost to scalability. I'd recommend load testing that. Also static variables can be useful. Many are thread-safe and you want to use them in Azure functions, such as your httpClient or sqlClient DB connections! Give number three a read, here.

这篇关于Azure函数实例共享变量吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆