LocalGrainDirectory详解

LocalGrainDirectory 详解

LocalGrainDirectory是Orleans分布式系统中负责本地Grain目录管理的核心组件,它实现了分布式哈希表(DHT)风格的Grain定位服务。

类图

LocalGrainDirectory -ILogger log -SiloAddress? seed -ISiloStatusOracle siloStatusOracle -IInternalGrainFactory grainFactory -object writeLock -IServiceProvider _serviceProvider -DirectoryMembership directoryMembership -bool Running -Catalog? _catalog +SiloAddress MyAddress +IGrainDirectoryCache DirectoryCache +LocalGrainDirectoryPartition DirectoryPartition +RemoteGrainDirectory RemoteGrainDirectory +RemoteGrainDirectory CacheValidator +GrainDirectoryHandoffManager HandoffManager +Start() : void +StopAsync() : Task +SiloStatusChangeNotification(SiloAddress, SiloStatus) : void +RegisterAsync(GrainAddress, int) : Task<AddressAndTag> +UnregisterAsync(GrainAddress, UnregistrationCause, int) : Task +LookupAsync(GrainId, int) : Task<AddressAndTag> +LocalLookup(GrainId, out AddressAndTag) : bool +CalculateGrainDirectoryPartition(GrainId) <<interface>> ILocalGrainDirectory +Start() : void +StopAsync() : Task +RegisterAsync(GrainAddress, int) : Task<AddressAndTag> +UnregisterAsync(GrainAddress, UnregistrationCause, int) : Task +LookupAsync(GrainId, int) : Task<AddressAndTag> +LocalLookup(GrainId, out AddressAndTag) : bool <<interface>> ISiloStatusListener +SiloStatusChangeNotification(SiloAddress, SiloStatus) : void <<interface>> ILifecycleParticipant<ISiloLifecycle> +Participate(ISiloLifecycle) : void LocalGrainDirectoryPartition +AddSingleActivation(GrainAddress, GrainAddress?) : AddressAndTag +RemoveActivation(GrainId, ActivationId, UnregistrationCause) : void +LookUpActivation(GrainId) : AddressAndTag +GetItems() <<interface>> IGrainDirectoryCache +AddOrUpdate(GrainAddress, int) : void +LookUp(GrainId, out GrainAddress) : bool +Remove(GrainId) : bool +KeyValues IEnumerable~(GrainAddress, int)

协作图

Client LocalGrainDirectory LocalGrainDirectoryPartition DirectoryCache RemoteGrainDirectory SiloStatusOracle Grain注册流程 RegisterAsync(grainAddress, hopCount) CalculateGrainDirectoryPartition(grainId) AddSingleActivation(address, previousAddress) AddressAndTag result AddOrUpdate(result.Address, result.VersionTag) 返回注册结果 RegisterAsync(address, previousAddress, hopCount+1) AddressAndTag result AddOrUpdate(result.Address, result.VersionTag) 返回注册结果 alt 当前Silo是Owner 需要转发到其他Silo Grain查找流程 LookupAsync(grainId, hopCount) LookUp(grainId, out address) 返回缓存地址 返回查找结果 CalculateGrainDirectoryPartition(grainId) LookUpActivation(grainId) AddressAndTag result 返回查找结果 LookupAsync(grainId, hopCount+1) AddressAndTag result AddOrUpdate(result.Address, result.VersionTag) 返回查找结果 alt 当前Silo是Owner 需要转发到其他Silo alt 缓存命中且Silo有效 缓存未命中或无效 Silo状态变化处理 SiloStatusChangeNotification(updatedSilo, status) AddServer(updatedSilo) AdjustLocalDirectory(silo, dead: false) AdjustLocalCache(silo, dead: false) RemoveServer(updatedSilo, status) AdjustLocalDirectory(silo, dead: true) AdjustLocalCache(silo, dead: true) alt Silo变为Active状态 Silo变为Terminating状态 Client LocalGrainDirectory LocalGrainDirectoryPartition DirectoryCache RemoteGrainDirectory SiloStatusOracle

核心功能详解

1. 分布式哈希表(DHT)分区算法

LocalGrainDirectory使用一致性哈希算法来确定每个Grain的目录分区所有者:

csharp 复制代码
public SiloAddress? CalculateGrainDirectoryPartition(GrainId grainId)
{
    int hash = unchecked((int)grainId.GetUniformHashCode());
    // 在排序的Silo列表中查找第一个哈希值小于等于目标哈希的Silo
    for (var index = existing.MembershipRingList.Count - 1; index >= 0; --index)
    {
        var item = existing.MembershipRingList[index];
        if (IsSiloNextInTheRing(item, hash, excludeMySelf))
        {
            return item;
        }
    }
}
2. 请求转发机制

当当前Silo不是Grain的目录所有者时,会进行请求转发:

csharp 复制代码
public SiloAddress? CheckIfShouldForward(GrainId grainId, int hopCount, string operationDescription)
{
    var owner = CalculateGrainDirectoryPartition(grainId);
    if (owner is null || owner.Equals(MyAddress)) return null;
    
    if (hopCount >= HOP_LIMIT) // 跳数限制为6
        throw new OrleansException($"Hop limit reached");
        
    return owner; // 转发到目标Silo
}
3. 缓存管理

LocalGrainDirectory维护本地缓存以提高查找性能:

csharp 复制代码
public bool LocalLookup(GrainId grain, out AddressAndTag result)
{
    // 首先检查缓存
    var address = GetLocalCacheData(grain);
    if (address != default)
    {
        result = new(address, 0);
        return true;
    }
    
    // 如果是本地分区,检查本地目录
    if (silo.Equals(MyAddress))
    {
        result = GetLocalDirectoryData(grain);
        return result.Address != null;
    }
    
    return false;
}
4. 集群成员变化处理

LocalGrainDirectory监听Silo状态变化并相应调整目录和缓存:

csharp 复制代码
public void SiloStatusChangeNotification(SiloAddress updatedSilo, SiloStatus status)
{
    if (status.IsTerminating())
    {
        CacheValidator.WorkItemGroup.QueueAction(() => RemoveServer(updatedSilo, status));
    }
    else if (status == SiloStatus.Active)
    {
        CacheValidator.WorkItemGroup.QueueAction(() => AddServer(updatedSilo));
    }
}

关键设计特点

  1. 线程安全 :使用writeLock对象确保目录操作的线程安全
  2. 容错性:支持Silo故障时的目录分区重新分配
  3. 性能优化:本地缓存减少远程查找开销
  4. 可扩展性:支持动态集群成员变化
  5. 一致性:确保目录信息在集群中的一致性

LocalGrainDirectory是Orleans分布式系统的核心组件,它通过分布式哈希表算法实现了高效的Grain定位服务,为整个系统的可扩展性和可靠性提供了基础支撑。

相关推荐
用户788477316343 小时前
WinForms 迁移 WPF:Upgrade Assistant 覆盖 30%,剩下 70% 我手写了六周
c#
寂寞的船8 小时前
【Unity知识速递】第13期 Unity 内存泄漏排查实战:从 Memory Profiler 到 Lua 引用泄漏的生产级全链路诊断
unity·junit·c#·游戏引擎·lua
用户3721574261351 天前
C# 提取 PDF 附件:包括文档附件和页面注释附件
c#
寂寞的船1 天前
【Unity Bug挑战】第12期 Awaitable 二次 await 死锁之谜 —— 为什么同一个异步操作等两次就卡死?
unity·c#·游戏引擎·bug
huaqianzkh2 天前
WinForm C#:循环修改控件UI闪烁卡顿?SuspendLayout / ResumeLayout 与 BeginUpdate 优化
开发语言·ui·c#
用户3721574261353 天前
C# 实现 Excel 单元格保护:锁定公式并允许编辑指定区域
c#·ai编程·编程语言
公子小六3 天前
基于.NET的Windows窗体编程之WinForms数据持久化(1)
windows·microsoft·c#·.net·winforms
三雷科技3 天前
第6章第4节:自定义分词器
开发语言·c#
zhanghaha13143 天前
C# 系列教程_12 字符串 string 保姆级系统教程(面向新手,大量示例 + 原理讲解)
开发语言·数据库·c#
Coder_Shenshen4 天前
罗克韦尔ACD工程归档离线变量树解析
算法·c#