应将图像调整为的分辨率存储在数据库中,Azure函数需要调用数据库以了解输入消息中应使用的分辨率。该分辨率实际上是基于输入消息来源配置的主数据。
每次调用都需要进行数据库调用,这将是昂贵的。是否有任何方法可以缓存数据并在不调用数据库的情况下使用它?例如内存缓存?
您可以自由地使用在其他 .NET 应用程序中使用的常规方法:
您可以将数据缓存在内存中。最简单的方法是声明一个静态字典,并将数据库值放入其中(如果需要,使用并发字典)。缓存的值将被重复使用于所有后续的函数执行,这些函数在同一实例上运行。如果某个实例闲置了5分钟,或者应用程序扩展到额外的实例,您将不得不重新读取数据库;
您可以使用分布式缓存,例如 Redis,通过从函数代码中使用其 SDK。可能会更好,因为您保持 Functions 的无状态性质,但可能会花费更多成本。表存储是 Redis 的一种可行替代方案,但具有更受限制的 API。
Azure Functions 本身没有“缓存”功能,没有任何额外的代码就能够使用。
您可以使用Azure Cache服务(https://azure.microsoft.com/zh-cn/services/cache/)来缓存您的数据。基本上,在您的Azure函数中,不要每次都调用数据库,而是调用Azure缓存,如果它没有过期并且未设置,则调用数据库以获取值,并使用适当的到期逻辑(在固定时间后超时或其他自定义逻辑)填充缓存。
您可以使用Durable Functions,并通过活动或子编排进行数据库调用,返回值将被缓存,每次函数重放时都会返回,而无需再次进行底层调用。
[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最佳实践中。
// 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函数实例实现中创建一个静态只读实例,传入一个Populate方法:
private static readonly FunctionInstanceCache<string[]> Fic = new FunctionInstanceCache<string[]>(PopulateCache);
private static string[] PopulateCache()
{
return DOSOMETHING HERE;
}
需要时只需调用Fic.Data即可——第一次使用时它将被填充,然后在实例仍然存在时重复使用。