【问题标题】:Azure function return unique sequence numberAzure 函数返回唯一序列号
【发布时间】:2021-12-25 11:51:02
【问题描述】:

我是 Azure 的新手。我想创建一个返回序列号的函数。我创建了一个使用线程互斥锁来锁定序列号的函数。我用大约 10k 个并行请求测试了下面的代码。问题是我在进行测试时得到重复的序列号,互斥锁不起作用。我不确定如何避免重复,而是为每个请求生成运行编号

Public class MySharedMutexCounter { 
  public static long count = 0; 
  public static Mutex ObjMutex = new Mutex(false,"SeqGenerator"); 
}  

public long GetSequnceNo(){
    long seqId = -1;
    
    try{
     MySharedMutexCounter.ObjMutex.waitOne();
     seqId =  ++MySharedMutexCounter.count;
     if(seqId > 100){
       MySharedMutexCounter.count = 0;
       seqId =  ++MySharedMutexCounter.count;
     }
     return seqId;
    }finally{
      MySharedMutexCounter.ObjMutex.RelaseMutex();
    }
    return -1;
}

【问题讨论】:

    标签: multithreading azure azure-functions mutex azure-durable-functions


    【解决方案1】:

    问题是,一个 azure 函数可以扩展到在不同机器上运行的多个实例,因此您需要某种分布式锁或其他方式来保证不会对状态进行并发访问。

    使用Durable Entity 怎么样?它基本上是一个可以通过Durable Function 访问的状态,并且以安全的方式执行针对该状态的操作:

    为了防止冲突,保证对单个实体的所有操作都是串行执行的,即一个接一个。

    (source)

    持久实体就像一个分布式对象,因此该函数的其他实例将使用相同的实体。

    Developer Guide 演示了一个使用计数器的好例子。有点适合你的场景。

    【讨论】:

    • 请检查代码,但响应非常缓慢。
    • 你能定义慢吗?另外,请考虑到由于冷启动和初始化,第一次可能需要更长的时间。该函数的调用频率如何?
    • 如果您尝试执行以下“FunctionOrchestrator”(在答案中),大约需要 2-3 秒才能得到结果。我想尽快得到结果(1sec 生成大约或超过 50 个数字
    【解决方案2】:

    嗨@Peter Bons 我尝试了下面的代码,但花了很多时间。我的代码可能有问题。是否有可能在几分之一秒内获得值 bcos 我 shd 返回的值不到一秒。

        [FunctionName("FunctionOrchestrator")]
        public static async Task<int> RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context)
        {
            int currentValue = -1;
            var input = context.GetInput<CounterParameter>();
    
            if (input != null && !string.IsNullOrWhiteSpace(input.OperationName))
            {
        
                var entityId = new EntityId("Counter", "myCounter");
    
                // Perform the requested operation on the entity
                currentValue = await context.CallEntityAsync<int>(entityId, input.OperationName);
            }
    
            return currentValue;
        }
    
        [FunctionName("Counter")]
        public static int Counter([EntityTrigger] IDurableEntityContext ctx, ILogger log)
        {
            log.LogInformation($"Request for operation {ctx.OperationName} on entity.");
    
                switch (ctx.OperationName.Trim().ToLowerInvariant())
                {
                    case "increment":
                        ctx.SetState(ctx.GetState<int>() + 1);
                        break;
                 }
            
        // Return the latest value
        return ctx.GetState<int>();
        }
    
        [FunctionName("AutoIncrement")]
        public static async Task<HttpResponseMessage> HttpAutoIncrement(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
            [DurableClient] IDurableOrchestrationClient starter,
            [DurableClient] IDurableEntityClient client,
            ILogger log)
    
        {
    
            // Function input comes from the request content.
            var input = new CounterParameter { OperationName = "Increment" };
            string instanceId = await starter.StartNewAsync("FunctionOrchestrator", input);
    
            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
            await starter.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId);
    
            var entityId = new EntityId("Counter", "myCounter");
    
            try
            {
                // An error will be thrown if the counter is not initialised.
                var stateResponse = await client.ReadEntityStateAsync<int>(entityId);
                return new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent(stateResponse.EntityState.ToString())
                };
            }
            catch (System.NullReferenceException)
            {
                return new HttpResponseMessage(HttpStatusCode.NotFound)
                {
                    Content = new StringContent("Counter is not yet initialised. " +
                    "Initialise it by calling increment or decrement HTTP Function.")
                };
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-06
      • 1970-01-01
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-11
      • 2020-05-03
      相关资源
      最近更新 更多