You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Function中WTelegramClient会话文件被占用问题求助

解决Azure Function中WTelegram.session文件被占用的问题

问题根源

Azure Functions在高频触发(每10分钟一次)时,可能启动多个并发执行实例,或同一实例中存在未释放的文件句柄,导致多个进程同时读写同一个WTelegram.session文件引发冲突。当前session文件路径位于站点共享的wwwroot/bin目录,所有实例都会访问该文件,进一步加剧了冲突概率。

可行解决方案

1. 确保函数执行时正确释放WTelegramClient资源

使用using语句包裹WTelegramClient实例,确保执行完毕后自动释放文件句柄与相关资源,避免残留锁占用:

public async Task Run([TimerTrigger("0 */10 * * * *")] TimerInfo myTimer, ILogger log)
{
    using var client = new WTelegramClient(Config);
    try
    {
        // 执行Telegram操作逻辑
        await client.DoSomething();
        // 可选:主动登出以确保session状态正确写入
        await client.Logout();
    }
    catch (Exception ex)
    {
        log.LogError(ex, "Telegram操作失败");
    }
}

2. 改用Azure Blob Storage存储Session(推荐)

放弃本地文件存储,将session内容存入Azure Blob Storage,利用Blob的原子读写特性避免多实例冲突:

  • 在Azure Portal创建Blob存储容器,将存储连接字符串添加到Function的应用设置(例如命名为BlobStorageConnectionString)。
  • 修改WTelegramClient的session配置逻辑,实现Blob读写:
private async Task<string> LoadSessionFromBlob()
{
    var blobServiceClient = new BlobServiceClient(Environment.GetEnvironmentVariable("BlobStorageConnectionString"));
    var blobContainerClient = blobServiceClient.GetBlobContainerClient("telegram-sessions");
    await blobContainerClient.CreateIfNotExistsAsync();
    var blobClient = blobContainerClient.GetBlobClient("WTelegram.session");
    
    if (await blobClient.ExistsAsync())
    {
        using var stream = new MemoryStream();
        await blobClient.DownloadToStreamAsync(stream);
        stream.Position = 0;
        return Encoding.UTF8.GetString(stream.ToArray());
    }
    return null;
}

private async Task SaveSessionToBlob(string sessionContent)
{
    var blobServiceClient = new BlobServiceClient(Environment.GetEnvironmentVariable("BlobStorageConnectionString"));
    var blobContainerClient = blobServiceClient.GetBlobContainerClient("telegram-sessions");
    await blobContainerClient.CreateIfNotExistsAsync();
    var blobClient = blobContainerClient.GetBlobClient("WTelegram.session");
    
    using var stream = new MemoryStream(Encoding.UTF8.GetBytes(sessionContent));
    await blobClient.UploadAsync(stream, overwrite: true);
}

// 在WTelegramClient的配置回调中使用
case "session": 
    return await LoadSessionFromBlob();
case "session_save": 
    await SaveSessionToBlob(value);
    break;

该方案彻底避免本地文件锁冲突,同时支持多实例共享同一个session。

3. 使用文件独占访问模式

若必须使用本地文件,读写session时指定独占访问权限,确保同一时间仅一个进程能操作文件:

case "session_pathname": 
    var sessionPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "WTelegram.session");
    return sessionPath;

加载与保存session时,使用FileShare.None选项:

private string LoadSession(string path)
{
    if (!File.Exists(path)) return null;
    using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None);
    using var sr = new StreamReader(fs);
    return sr.ReadToEnd();
}

private void SaveSession(string path, string content)
{
    using var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
    using var sw = new StreamWriter(fs);
    sw.Write(content);
}

注:该方案仅适用于单实例部署的Function,多实例场景仍可能出现冲突。

额外建议

  • 避免在Azure Functions共享文件系统(如wwwroot)存储需频繁读写的文件,优先选用Azure Blob或Table Storage等分布式存储方案。
  • 若使用消费计划,调整实例数限制仅能缓解冲突,无法从根本解决问题。

内容的提问来源于stack exchange,提问作者FakeJoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 20:45:23