Azure功能和缓存

时间:2017-12-08 21:54:49

标签: c# azure caching azure-functions

我们计划开发一个Azure函数,其输入触发器是服务总线消息,输出将是blob存储。服务总线消息将包含一个图像URL,该功能将图像调整为预定义的分辨率,并上传到azure blob存储。

应将图像调整大小的分辨率存储在数据库中,Azure函数需要调用数据库以了解应该用于输入消息中图像的分辨率。该分辨率实际上是基于输入消息源配置的主数据。

进行数据库调用将是一项昂贵的调用,因为每次调用都必须转到数据库。有没有办法缓存数据并在不调用数据库的情况下使用它。就像在内存缓存中一样?

6 个答案:

答案 0 :(得分:14)

您可以自由使用在其他.NET应用程序中使用的常用方法:

  • 您可以将其缓存在内存中。最简单的方法是声明一个静态字典并将数据库值放入其中(如果需要,使用并发字典)。缓存的值将重用于在同一实例上运行的所有后续Function执行。如果实例空闲5分钟,或者App扩展到额外的实例,则必须再次读取数据库;

  • 您可以使用分布式缓存,例如Redis,使用功能代码中的SDK。可能会更好一些,因为你保持函数的无状态特性,但可能会花费更多。表存储是Redis的可行替代方案,但API有限。

没有"缓存" Azure函数本身的功能,可以在没有任何额外代码的情况下使用。

答案 1 :(得分:4)

您可以使用Azure缓存服务(https://azure.microsoft.com/en-us/services/cache/)来缓存数据。基本上,在Azure函数中而不是一直调用数据库,调用Azure缓存并使用它,如果它没有过期,如果它已过期或未设置,则调用数据库获取值并使用适当的到期逻辑填充缓存(超时后固定时间或其他一些自定义逻辑。)

答案 2 :(得分:4)

您可以使用Durable Functions并通过活动或子Orchestration进行数据库调用,然后返回值基本上被缓存,并且每次函数重放时都将返回而不再进行基础调用。

答案 3 :(得分:1)

Redis是内存缓存,您可以使用自定义输出绑定来保持您的功能清洁:

[FunctionName("SetPoco")]
public static async Task<IActionResult> SetPoco(
    [HttpTrigger("POST", Route = "poco/{key}")] HttpRequest request,
    [Redis(Key = "{key}")] IAsyncCollector<CustomObject> collector)
{
    string requestBody;
    using (var reader = new StreamReader(request.Body))
    {
        requestBody = reader.ReadToEnd();
        var value = JsonConvert.DeserializeObject<CustomObject>(requestBody);
        await collector.AddAsync(value);
    }
    return new OkObjectResult(requestBody);
}

项目链接:https://github.com/daulet/Indigo.Functions#redis

但是,如果通过内存缓存你的意思是在函数的内存中我强烈建议,否则因为函数意味着无状态,你将无法在运行函数的多个主机之间共享该内存。在Azure Functions best practices

中也不建议这样做

答案 4 :(得分:0)

考虑像Cloudfront或Cloudflare之类的东西。我不确定微软到底提供什么。

这将位于您的API之上并缓存请求,并为您在全球范围内分发它们。

除了这里介绍的其他解决方案外,还可以使用它,但是它必须是最简单的饮食方式之一

答案 5 :(得分:0)

这里我创建了一个小类,以简化正在运行的实例保持活动状态时在运行中的内存中存储和重用对象的任务。当然,这意味着每个新实例都需要填充自己,但这可以提供一些有用的优化。

// A simple light-weight cache, used for storing data in the memory of each running instance of the Azure Function.
// If an instance gets idle (for 5 minutes or whatever the latest time period is) or if the Function App scales out to an extra instance then the cache is re-populated.
// To use, create a static readonly instance of this class in the Azure Function class, in the constructor pass a function which populates the object to cache.
// Then simply reference the Data object.  It will be populated on the first call and re-used on future calls whilst the same instance remains alive.
public class FunctionInstanceCache<T>
{
    public FunctionInstanceCache(Func<T> populate)
    {
        Populate = populate;
        IsInit = false;
    }

    public Func<T> Populate { get; set; }

    public bool IsInit { get; set; }

    private T data;

    public T Data
    {
        get
        {
            if (IsInit == false)
            {
                Init();
            };
            return data;
        }

    }

    public void Init()
    {
        data = Populate();
        IsInit = true;
    }
}

然后在您的Azure Function实例实现中创建一个静态的只读实例,并传入Populate方法:

    private static readonly FunctionInstanceCache<string[]> Fic = new FunctionInstanceCache<string[]>(PopulateCache);

然后实施

private static string[] PopulateCache()
{
    return DOSOMETHING HERE;
}

然后在需要时简单地调用Fic.Data-它将在首次使用时填充,然后在实例保持活动状态时重新使用。