我正在尝试创建一个配置的对象,该对象可以在Azure Functions中随请求一起重用。下面的示例在C#中。这样做的目的是避免为每个请求创建昂贵的DocumentClient
实例。 client
字段是静态的,在本示例中从文档中重用:
using System;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
private static DocumentClient client = GetCustomClient();
private static DocumentClient GetCustomClient()
{
DocumentClient customClient = new DocumentClient(
new Uri(ConfigurationManager.AppSettings["CosmosDBAccountEndpoint"]),
ConfigurationManager.AppSettings["CosmosDBAccountKey"],
new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
// Customize retry options for Throttled requests
RetryOptions = new RetryOptions()
{
MaxRetryAttemptsOnThrottledRequests = 10,
MaxRetryWaitTimeInSeconds = 30
}
});
// Customize PreferredLocations
customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.CentralUS);
customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.NorthEurope);
return customClient;
}
[FunctionName("CosmosDbSample")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "foo/{id}")] HttpRequestMessage req,
string id,
TraceWriter log)
{
Uri documentUri = UriFactory.CreateDocumentUri("ToDoList", "Items", id);
Document doc = await client.ReadDocumentAsync(documentUri);
if (doc == null)
{
return req.CreateResponse(HttpStatusCode.NotFound);
}
return req.CreateResponse(HttpStatusCode.OK, doc);
}
为了尝试使用一个更简单的示例进行模拟,我尝试了以下代码。它正常工作:
namespace TransactionsAggregate
open Microsoft.AspNetCore.Http
open Microsoft.Azure.WebJobs
open Microsoft.Azure.WebJobs.Host
open Microsoft.Azure.WebJobs.Extensions.Http
open System.Net
open System.Net.Http
open System.Web.Http
open Newtonsoft.Json
open System.Text
module Ping =
type Name = {
First: string
Last: string
}
type Greeting = {
Greeting: string
}
let jsonFormatter = System.Net.Http.Formatting.JsonMediaTypeFormatter()
jsonFormatter.SerializerSettings.ContractResolver <- new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
[<FunctionName("Ping1")>]
let run([<HttpTrigger>] req: HttpRequest, log: TraceWriter) =
async {
log.Info("Chamando Ping 1")
let! jsonContent = req.ReadAsStringAsync() |> Async.AwaitTask
try
let name = JsonConvert.DeserializeObject<Name>(jsonContent, jsonFormatter.SerializerSettings)
let response = new HttpResponseMessage(HttpStatusCode.OK)
let body = JsonConvert.SerializeObject( { Greeting = sprintf "Hello %s %s!" name.First name.Last })
let content = new StringContent(body, Encoding.UTF8, "application/json")
response.Content <- content
return response
with _ ->
return new HttpResponseMessage(HttpStatusCode.BadRequest)
} |> Async.StartAsTask
在此F#示例中,我们具有运行在V2版本上并在.NET Core上编写的Azure函数。这是一个预编译的函数(不是脚本)。这是一个类库项目。此示例仅回显传递的参数。 jsonFormatter
是在模块级别定义和配置的,因此未标记为静态。有没有办法创建类似的静态字段,以便我可以缓存此jsonFormatter或将来的更昂贵的对象?另外,是否可以保证应用程序上只有一个该值的实例?
文档:https://docs.microsoft.com/en-us/sandbox/functions-recipes/cosmos-db
预先感谢
答案 0 :(得分:5)
您已经实现了目标。 F#模块中的let
绑定对于每个Azure Functions实例仅执行一次,这类似于C#中的静态只读字段。
Azure函数可以同时并随时间运行多个实例(服务器)。每次设置新实例时,第一次执行都会很慢,并且将包括对昂贵表达式的初始化。但是,在同一实例上的下一次执行将重用它们,因此它将更快。