一、配置指南

1,客户端配置

2,服务端配置

3,典型配置

4,配置.NET垃圾收集

5,SQL系统存储

二、监控

1,运行时监视

2,silo错误代码监测

3,客户端错误代码监测

三、解决部署问题

四、异构silos

五、开始使用Azure Web Apps

六、Docker部署

七、服务结构托管

 

一、配置指南

本配置指南介绍了关键配置参数以及如何在大多数典型使用场景中使用这些参数。

Orleans Configuration xsd file is located here.

Orleans可以用于各种适合不同使用场景的配置,例如用于开发和测试的本地单节点部署,服务器群集,多实例Azure工作者角色等等。所有不同的目标场景都是通过指定特定 Orleans配置XML文件中的值。 本指南提供了使Orleans在其中一个目标方案中运行所需的关键配置参数的说明。 还有其他的配置参数,主要是为了更好地调整奥尔良的性能。 它们记录在XSD模式中,即使在生产中运行系统也不需要。

Orleans良是一个建立和运行高规模服务的框架。 Orleans应用程序的典型部署跨越了一组服务器。 在每台服务器上运行的Orleans运行时(称为silos)实例需要配置为相互连接。 除此之外,总是有一个连接到Orleans部署的客户端组件,通常是一个Web前端,需要配置它以连接到silos。 本指南的“服务器配置”和“客户端配置”部分分别介绍了这些方面。 “典型配置”部分提供了一些常见配置的摘要。

1,客户端配置

有两种方法:手动配置一个或多个网关端点,或者将客户端指向由silos的集群成员使用的Azure表。在后一种情况下,客户端会自动发现在部署中启用的客户机网关的silos,并在连接或离开集群时调整其与网关的连接。该选项是可靠的,并推荐用于生产部署。

①固定网关配置

ClientConfiguration.xml中使用一个或多个网关节点指定一组固定的网关: 

<ClientConfiguration xmlns="urn:orleans">
  <Gateway Address="gateway1" Port="30000"/>
  <Gateway Address="gateway2" Port="30000"/>
  <Gateway Address="gateway3" Port="30000"/>
</ClientConfiguration>

一个网关通常就足够了。 多个网关连接有助于提高系统的吞吐量和可靠性。

②基于群集成员的网关配置

要将客户端配置为从silo集群成员资格表中自动查找网关,您需要指定Azure表或SQL Server连接字符串以及目标部署标识

<ClientConfiguration xmlns="urn:orleans">
  <SystemStore SystemStoreType="AzureTable"
               DeploymentId="target deployment ID"
               DataConnectionString="Azure storage connection string"/>
</ClientConfiguration>

或者

<ClientConfiguration xmlns="urn:orleans">
  <SystemStore SystemStoreType="SqlServer"
               DeploymentId="target deployment ID"
               DataConnectionString="SQL connection string"/>
</ClientConfiguration>

或者

<ClientConfiguration xmlns="urn:orleans">
  <SystemStore SystemStoreType="ZooKeeper"
               DeploymentId="target deployment ID"
               DataConnectionString="ZooKeeper connection string"/>
</ClientConfiguration>

③本地silo

对于使用本地silo的本地开发/测试配置,应将客户端网关配置为“localhost”。

<ClientConfiguration xmlns="urn:orleans">
  <Gateway Address="localhost" Port="30000"/>
</ClientConfiguration>

④Web Azure中的Web角色客户端

当客户端是与silo 工作角色相同的Azure部署中运行的Web角色时,当调用OrleansAzureClient.Initialize()时,将从OrleansSiloInstances表中读取所有网关地址信息。 用于查找正确OrleansSiloInstances表的Azure存储连接字符串在部署和角色的服务配置中定义的“DataConnectionString”设置中指定。

<ServiceConfiguration  ...>
  <Role name="WebRole"> ...
    <ConfigurationSettings>
      <Setting name="DataConnectionString" value="DefaultEndpointsProtocol=https;AccountName=MYACCOUNTNAME;AccountKey=MYACCOUNTKEY" />
    </ConfigurationSettings>
  </Role>
  ...
</ServiceConfiguration>

silo 工作者角色和Web客户端角色都需要使用相同的Azure存储帐户才能成功发现彼此。

当使用OrleansAzureClient.Initialize()和OrleansSiloInstances表进行网关地址发现时,客户端配置文件中不需要额外的网关地址信息。 通常,ClientConfiguration.xml文件将只包含一些最低限度的调试/跟踪配置设置,尽管这不是必需的。

<ClientConfiguration xmlns="urn:orleans">
  <Tracing DefaultTraceLevel="Info" >
    <TraceLevelOverride LogPrefix="Application" TraceLevel="Info" />
  </Tracing>
</ClientConfiguration>

基于代码的客户端配置。 这是仅供参考的示例,不应该按原样使用 - 您可能需要针对特定环境微调客户端参数。

var dataConnection = "DefaultEndpointsProtocol=https;AccountName=MYACCOUNTNAME;AccountKey=MYACCOUNTKEY";

var config = new ClientConfiguration
{
    //一些顶级功能
    GatewayProvider = ClientConfiguration.GatewayProviderType.AzureTable,
    ResponseTimeout = TimeSpan.FromSeconds(30),
    DeploymentId = RoleEnvironment.DeploymentId,
    DataConnectionString = dataConnection,
    PropagateActivityId = true,

    // 跟踪
    DefaultTraceLevel = Severity.Info,
    TraceToConsole = false,
    TraceFilePattern = @"Client_{0}-{1}.log",
    //TraceFilePattern = "false", // 将其设置为false或none,禁用文件跟踪,有效地设置config.Defaults.TraceFileName = null;

    TraceLevelOverrides =
    {
        Tuple.Create("ComponentName", Severity.Warning),
    }
};

config.RegisterStreamProvider<AzureQueueStreamProvider>("AzureQueueStreams",
    new Dictionary<string, string>
    {
        { "PubSubType", "ExplicitGrainBasedAndImplicit" },
        { "DeploymentId", "orleans-streams" }, // 这将是您的队列的前缀名称 - 所以要小心并使用对队列名称有效的字符串
        { "NumQueues", "4" },
        { "GetQueueMessagesTimerPeriod", "100ms" },
        { "DataConnectionString", dataConnection }
    });

config.RegisterStreamProvider<SimpleMessageStreamProvider>("SimpleMessagingStreams",
    new Dictionary<string, string>
    {
        { "PubSubType", "ExplicitGrainBasedAndImplicit" }
    });

IClusterClient client = null;
while (true)
{
    try
    {
        // 构建一个客户端,然后将其连接到群集。
        client = new ClientBuilder()
            .UseConfiguration(config)
            .ConfigureServices(
                services =>
                {
                    // 服务可以在这里提供给客户。 这些服务通过依赖注入来提供。 ConfigureServices可以多次调用一个ClientBuilder实例。
                })
            .Build();

        // 将客户端连接到群集。 一旦连接成功,客户端将维护连接,根据需要自动重新连接。
        await client.Connect().ConfigureAwait(false);
        break;
    }
    catch (Exception exception)
    {
        // 如果连接尝试失败,则必须处理客户机实例。
        client?.Dispose();

        // TODO:记录异常。
        // TODO: Add a counter to break up an infinite cycle (circuit breaker pattern).
        await Task.Delay(TimeSpan.FromSeconds(5));
    }
}

// 使用客户端。
// 请注意,客户端可以在线程之间共享,并且通常是长期的。
var user client.GetGrain<IUserGrain>("leeroy77jenkins@battle.net");
Console.WriteLine(await user.GetProfile());

2,服务端配置

silo 配置有两个关键方面:

  • 连通性:silo的其他silo和客户的端点
  • 集群成员和可靠性:在部署中如何发现对方并检测节点故障。

取决于你想在这些参数中运行Orleans的环境可能重要,也可能不重要。 例如,对于单个silo开发环境,通常不需要可靠性,并且所有端点都可以是本地主机

以下部分详细介绍了上述四个关键方面的配置设置。 然后在场景部分中,可以找到最典型的部署场景的建议组合设置。

①连接

连接设置定义了两个TCP / IP端点:一个用于silo 间通信,另一个用于客户端连接,也称为客户端网关或简单的网关。

跨筒仓端点

<Networking Address=" " Port="11111" />

地址:使用的IP地址或主机名。 如果留空,silo 将选择第一个可用的IPv4地址。 Orleans支持IPv6以及IPv4。 

端口:要使用的TCP端口。 如果留空,silo将会随机选择一个端口。 如果机器上只有一个silo正在运行,建议指定一个端口以保持一致性,并便于配置防火墙。 要在同一台计算机上运行多个silo,可以为每个silo提供不同的配置文件,也可以将端口属性留空以便随机分配端口。

对于分配了多个IP地址的计算机,如果您需要从特定子网或IPv6地址中选择一个地址,则可以通过分别添加子网和PreferredFamily属性来执行此操作(请参阅XSD模式以获取准确的语法 这些属性)。

对于本地开发环境,您可以简单地使用localhost作为主机名:

<Networking Address="localhost" Port="11111" />

②客户端网关端点

除了XML元素名称之外,客户端网关端点的设置与silo间端点相同:

<ProxyingGateway Address="localhost" Port="30000" />

您必须指定与用于inter-silo端点的端口号不同的端口号。

可以将客户端配置为连接到跨站点端点而不是网关,但是这需要在客户端上打开监听套接字(因此需要在客户端计算机防火墙上启用传入连接),并且通常不建议 对于一组非常有限的场景。

③集群成员和可靠性

通常,在Orleans上构建的服务部署在专用硬件或Azure节点集群上。 对于开发和基本测试,Orleans可以部署在单个节点配置中。 在部署到一个节点集群时,Orleans在内部实现了一套协议,以发现和维护集群中Orleans silos的成员资格,包括检测节点故障和自动重新配置。

为了可靠地管理集群成员资格,Orleans使用Azure Table,SQL Server或Apache ZooKeeper进行节点同步。 可靠的成员资格设置要求在silo配置文件中配置“SystemStore”元素设置: 

<SystemStore SystemStoreType="AzureTable"
             DeploymentId="..."
             DataConnectionString="..."/>

或者

<SystemStore SystemStoreType="SqlServer"
             DeploymentId="..."
             DataConnectionString="..."/>

或者

<SystemStore SystemStoreType="ZooKeeper"
             DeploymentId="..."
             DataConnectionString="..."/>

DeploymentId是定义特定部署的唯一字符串。 将基于Orleans的服务部署到Azure时,使用辅助角色的Azure部署标识是最有意义的。

对于开发,或者如果不可能使用Azure表,可以将silos配置为使用成员grain。这样的配置是不可靠的,因为它将无法在主仓的失败中存活下来,而主仓则承载着会员的grain。“MembershipTableGrain”是LivenessType的默认值。

<Liveness LivenessType ="MembershipTableGrain" />

④主silo

在可靠的部署中,使用Azure Table,SQL Server或ZooKeeper配置成员资格,所有创建的silo都是相同的,没有主要或次要silo的概念。 这是推荐用于生产的配置,能够在任何单个节点或节点组合的故障中幸免于难。 例如,Azure会定期推出操作系统修补程序,并最终导致所有角色实例重新启动。

当使用MembershipTableGrain进行开发或非可靠部署时,必须将其中一个silo指定为主要,并且必须在加入群集之前等待主要进行初始化的其他辅助silo之前启动和初始化。 在主节点出现故障的情况下,整个部署停止正常工作,必须重新启动。

主要是在配置文件中用全局部分中的以下设置指定的。

<SeedNode Address="<host name or IP address of the primary node>" Port="11111" />

下面是一个如何配置和启动托管在工作角色内的Orleans silo的例子。 这是仅供参考的示例,不应该按原样使用 - 您可能需要针对特定环境微调客户端参数。

var dataConnection = "DefaultEndpointsProtocol=https;AccountName=MYACCOUNTNAME;AccountKey=MYACCOUNTKEY";

var config = new ClusterConfiguration
{
    Globals =
    {
        DeploymentId = RoleEnvironment.DeploymentId,
        ResponseTimeout = TimeSpan.FromSeconds(30),
        DataConnectionString = dataConnection,

        LivenessType = GlobalConfiguration.LivenessProviderType.AzureTable,
        ReminderServiceType = GlobalConfiguration.ReminderServiceProviderType.AzureTable,
    },
    Defaults =
    {
        PropagateActivityId = true,

        // 跟踪
        DefaultTraceLevel = Severity.Info,
        TraceToConsole = false,
        TraceFilePattern = @"Silo_{0}-{1}.log",
        //TraceFilePattern =“false”,//将其设置为false或none来禁用文件跟踪,有效地设置了config.Defaults。TraceFileName =零;
        TraceLevelOverrides =
        {
            Tuple.Create("ComponentName", Severity.Warning),
        }
    }
};

// 注册引导provider类
config.Globals.RegisterBootstrapProvider<AutoStartBootstrapProvider>("MyAutoStartBootstrapProvider");

// Add Storage Providers
config.Globals.RegisterStorageProvider<MemoryStorage>("MemoryStore");

config.Globals.RegisterStorageProvider<AzureTableStorage>("PubSubStore",
    new Dictionary<string, string>
    {
        { "DeleteStateOnClear", "true" },
        //{ "UseJsonFormat", "true" },
        { "DataConnectionString", dataConnection }
    });

config.Globals.RegisterStorageProvider<AzureTableStorage>("AzureTable",
    new Dictionary<string, string>
    {
        { "DeleteStateOnClear", "true" },
        { "DataConnectionString", dataConnection }
    });

config.Globals.RegisterStorageProvider<AzureTableStorage>("DataStorage",
    new Dictionary<string, string>
    {
        { "DeleteStateOnClear", "true" },
        { "DataConnectionString", dataConnection }
    });

config.Globals.RegisterStorageProvider<BlobStorageProvider>("BlobStorage",
    new Dictionary<string, string>
    {
        { "DeleteStateOnClear", "true" },
        { "ContainerName", "grainstate" },
        { "DataConnectionString", dataConnection }
    });

// Add Stream Providers
config.Globals.RegisterStreamProvider<AzureQueueStreamProvider>("AzureQueueStreams",
    new Dictionary<string, string>
    {
        { "PubSubType", "ExplicitGrainBasedAndImplicit" },
        { "DeploymentId", "orleans-streams" },
        { "NumQueues", "4" },
        { "GetQueueMessagesTimerPeriod", "100ms" },
        { "DataConnectionString", dataConnection }
    });

try
{
    _orleansAzureSilo = new AzureSilo();
    var ok = _orleansAzureSilo.Start(config, config.Globals.DeploymentId, config.Globals.DataConnectionString);

    _orleansAzureSilo.Run(); //调用将阻塞直到silo关闭。
}
catch (Exception exc)
{
    //Log "Error when starting Silo"
}

3,典型配置

以下是可用于开发和生产部署的典型配置示例。

①本地开发

对于本地开发,在程序员的机器上只有一个本地运行的silo,配置已经包含在Microsoft Orleans Visual Studio的Orleans Dev / Test Host项目模板中。 可以通过运行使用Orleans Dev / Test Host模板创建的项目来启动的本地silo在DevTestServerConfiguration.xml中配置如下。

<OrleansConfiguration xmlns="urn:orleans">
  <Globals>
    <SeedNode Address="localhost" Port="11111" />
  </Globals>
  <Defaults>
    <Networking Address="localhost" Port="11111" />
    <ProxyingGateway Address="localhost" Port="30000" />
  </Defaults>
</OrleansConfiguration>

通过代码的silo配置如下。

var config = ClusterConfiguration.LocalhostPrimarySilo(11111, 30000);

要连接到本地silo,客户端需要配置为本地主机,并且只能从同一台机器连接。 可以通过运行Orleans Dev / Test Host模板创建的项目启动的Orleans客户端在DevTestClientConfiguration.xml中配置如下

<ClientConfiguration xmlns="urn:orleans">
  <Gateway Address="localhost" Port="30000"/>
</ClientConfiguration>

通过代码进行客户端配置如下。

var config = ClientConfiguration.LocalhostSilo(30000);

②使用Azure进行可靠的生产部署

对于使用Azure进行可靠的生产部署,您需要使用Azure Table选项来获得集群成员资格。 此配置是部署到本地服务器或Azure虚拟机实例的典型配置。

DataConnection字符串的格式是“DefaultEndpointsProtocol = https; AccountName =; AccountKey =”

<OrleansConfiguration xmlns="urn:orleans">
  <Globals>
    <SystemStore SystemStoreType="AzureTable"
         DeploymentId="<your deployment ID>"
         DataConnectionString="<<see comment above>>" />
    <Liveness LivenessType ="AzureTable" />
  </Globals>
  <Defaults>
    <Networking Address="" Port="11111" />
    <ProxyingGateway Address="" Port="30000" />
  </Defaults>
</OrleansConfiguration>

客户端需要配置为使用Azure表来发现网关,Orleans 服务器的地址不是静态地被客户知道的。

<ClientConfiguration xmlns="urn:orleans">
  <SystemStore SystemStoreType="AzureTable" DeploymentId="target deployment ID" DataConnectionString="<<see comment above>>" />
</ClientConfiguration>

③使用ZooKeeper进行可靠的生产部署

为了使用ZooKeeper进行可靠的生产部署,您需要使用ZooKeeper选项来获得集群成员资格。 此配置是部署到内部部署服务器的典型配置。

在“ZooKeeper程序员指南”中记录了DataConnection字符串的格式。 建议至少5台ZooKeeper服务器。

<?xml version="1.0" encoding="utf-8"?>
<OrleansConfiguration xmlns="urn:orleans">
  <Globals>
    <SystemStore SystemStoreType="ZooKeeper"
                   DeploymentId="<your deployment ID>"
                   DataConnectionString="<<see comment above>>"/>
  </Globals>
  <Defaults>
    <Networking Address="localhost" Port="11111" />
    <ProxyingGateway Address="localhost" Port="30000" />
  </Defaults>
</OrleansConfiguration>

客户端需要配置为使用ZooKeeper来发现网关,Orleans 服务器的地址不是静态地被客户知道的。

<?xml version="1.0" encoding="utf-8" ?>
<ClientConfiguration xmlns="urn:orleans">
  <SystemStore SystemStoreType="ZooKeeper" DeploymentId="target deployment ID" DataConnectionString="<<see comment above>>"/>
</ClientConfiguration>

④使用SQL Server进行可靠的生产部署

为了使用SQL Server进行可靠的生产部署,需要提供SQL Server连接字符串。

通过代码进行筒仓配置如下,包括日志配置。

var connectionString = @"Data Source=MSSQLDBServer;Initial Catalog=Orleans;Integrated Security=True;
    Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True";

var config = new ClusterConfiguration{    
    Globals =    
    {
        DataConnectionString = connectionString,
        DeploymentId = "<your deployment ID>",

        LivenessType = GlobalConfiguration.LivenessProviderType.SqlServer,
        LivenessEnabled = true,
        ReminderServiceType = GlobalConfiguration.ReminderServiceProviderType.SqlServer
    },
    Defaults =
    {        
        Port = 11111,
        ProxyGatewayEndpoint = new IPEndPoint(address, 30000),
        PropagateActivityId = true
    }};

var siloHost = new SiloHost(System.Net.Dns.GetHostName(), config);

客户端需要配置为使用SQL服务器来发现网关,就像Azure和Zookeeper一样,Orleans服务器的地址对于客户端来说并不是静态的。

var connectionString = @"Data Source=MSSQLDBServer;Initial Catalog=Orleans;Integrated Security=True;
    Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True";

var config = new ClientConfiguration{
    GatewayProvider = ClientConfiguration.GatewayProviderType.SqlServer,
    AdoInvariant = "System.Data.SqlClient",
    DataConnectionString = connectionString,

    DeploymentId = "<your deployment ID>",    
    PropagateActivityId = true
};

var client = new ClientBuilder().UseConfiguration(config).Build();
await client.Connect();

⑤不可靠的专用服务器集群部署

要在可靠性不是问题的情况下在专用服务器集群上进行测试,可以使用MembershipTableGrain并避免依赖于Azure表。 您只需要将其中一个节点指定为主节点。

<OrleansConfiguration xmlns="urn:orleans">
  <Globals>
    <SeedNode Address="<primary node>" Port="11111" />
    <Liveness LivenessType ="MembershipTableGrain" />
  </Globals>
  <Defaults>
    <Networking Address=" " Port="11111" />
    <ProxyingGateway Address=" " Port="30000" />
  </Defaults>
</OrleansConfiguration>

对于客户:

<ClientConfiguration xmlns="urn:orleans">
  <Gateway Address="node-1" Port="30000"/>
  <Gateway Address="node-2" Port="30000"/>
  <Gateway Address="node-3" Port="30000"/>
</ClientConfiguration>

⑥Azure工作者角色部署

当Orleans部署到Azure Worker角色而不是VM实例时,大部分的服务器端配置实际上是在OrleansConfiguration之外的其他文件中完成的,如下所示:

<OrleansConfiguration xmlns="urn:orleans">
  <Globals>
    <Liveness LivenessType="AzureTable" />
  </Globals>
  <Defaults>
    <Tracing DefaultTraceLevel="Info" TraceToConsole="true" TraceToFile="{0}-{1}.log" />
  </Defaults>
</OrleansConfiguration>

一些信息保存在服务配置文件中,其中worker角色部分如下所示:

<Role name="OrleansAzureSilos">
  <Instances count="2" />
  <ConfigurationSettings>
    <Setting name="DataConnectionString" value="<<see earlier comment>>" />
    <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="<<see earlier comment>>" />
  </ConfigurationSettings>
</Role>

数据连接字符串和诊断连接字符串不必相同。

一些配置信息保存在服务定义文件中。 工作者角色也必须在那里配置:

<WorkerRole name="OrleansAzureSilos" vmsize="Large">
  <Imports>
    <Import moduleName="Diagnostics" />
  </Imports>
  <ConfigurationSettings>
    <Setting name="DataConnectionString" />
  </ConfigurationSettings>
  <LocalResources>
    <LocalStorage name="LocalStoreDirectory" cleanOnRoleRecycle="false" />
  </LocalResources>
  <Endpoints>
    <InternalEndpoint name="OrleansSiloEndpoint" protocol="tcp" port="11111" />
    <InternalEndpoint name="OrleansProxyEndpoint" protocol="tcp" port="30000" />
  </Endpoints>
</WorkerRole>

这就是托管Orleans运行时的工作者角色。 但是,在部署到Azure时,通常会有某种类型的前端,无论是网站还是Web服务,因为公开发布Orleans 并不是一个好主意。 因此,客户端配置是位于Orleans前面的Web或Worker角色(或Web站点)的配置。

重要说明:截至2017年11月,Azure云服务存在限制,如果Cloud Service中只有1个角色,则会阻止InternalEndpoint的防火墙配置。 如果您要通过虚拟网络连接到您的云服务,则必须将您的云服务扩展为两个实例,以便创建防火墙规则

假设前端是一个web角色,应该使用一个简单的ClientConfiguration文件:

<ClientConfiguration xmlns="urn:orleans">
  <Tracing DefaultTraceLevel="Info"
           TraceToConsole="true"
           TraceToFile="{0}-{1}.log"
           WriteTraces="false"/>
</ClientConfiguration>

Web角色在服务配置文件中需要与worker角色相同的连接字符串信息:

<Role name="WebRole">
  <Instances count="2" />
  <ConfigurationSettings>
    <Setting name="DataConnectionString" value="<<see earlier comment>>" />
    <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="<<see earlier comment>>" />
  </ConfigurationSettings>
</Role>

并在服务定义文件中:

<WebRole name="WebRole" vmsize="Large">
  <Imports>
    <Import moduleName="Diagnostics" />
  </Imports>
  <ConfigurationSettings>
    <Setting name="DataConnectionString" />
  </ConfigurationSettings>
  <!-- 还有其他的网络角色数据与Orleans没有任何关系 -->
</WebRole>

4,配置.NET垃圾收集

为了获得良好的性能,为silo进程配置.NET垃圾回收是非常重要的。 我们找到的设置的最佳组合是设置gcServer = true和gcConcurrent = true。 当筒仓作为独立进程运行时,通过应用程序配置文件很容易设置。 您可以使用Microsoft.Orleans.OrleansHost NuGet包中包含的OrleansHost.exe.config作为示例。

①.NET Framework

<configuration>
  <runtime>
    <gcServer enabled="true"/>
    <gcConcurrent enabled="true"/>
  </runtime>
</configuration>

②.NET Core

// .csproj
<PropertyGroup>
  <ServerGarbageCollection>true</ServerGarbageCollection>
  <ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
</PropertyGroup>

但是,如果silo作为Azure工作者角色的一部分运行,则默认情况下配置为使用工作站GC,这并不容易。 此博客文章展示了如何为Azure工作者角色设置相同的配置 - 

https://blogs.msdn.microsoft.com/cclayton/2014/06/05/server-garbage-collection-mode-in-microsoft-azure/

重要的提示服务器垃圾回收仅在多处理器计算机上可用。 因此,即使您通过应用程序配置文件(app.config或web.config)或通过引用的博客帖子上的脚本来配置垃圾收集,如果silo正在单核的(虚拟)机器上运行, 不会得到gcServer = true的好处。改善这个文件在这篇文章中.NET Framework

5,SQL系统存储

任何可靠的生产式Orleans部署都需要使用持久性存储来保持系统状态,特别是Orleans集群状态以及用于提醒功能的数据。 除了对Azure存储的开箱即用支持外,Orleans还提供了将此信息存储在SQL Server中的选项。

为了使用SQL Server作为系统存储,需要调整服务器端和客户端配置。

服务器配置应该如下所示:

<OrleansConfiguration xmlns="urn:orleans">
  <Globals>
      <SystemStore SystemStoreType ="SqlServer"
                 DeploymentId="OrleansTest"
                 DataConnectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Orleans;Integrated Security=True;Pooling=False;Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True" AdoInvariant="System.Data.SqlClient" />
  </Globals>
</OrleansConfiguration>

客户端配置应如下所示:

<ClientConfiguration xmlns="urn:orleans">
      <SystemStore SystemStoreType ="SqlServer"
                 DeploymentId="OrleansTest"
                 DataConnectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Orleans;Integrated Security=True;Pooling=False;Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True" AdoInvariant="System.Data.SqlClient" />
</ClientConfiguration>

DataConnectionString设置为任何有效的SQL Server连接字符串。 为了使用SQL Server作为系统数据存储,现在在Binaries \ OrleansServer文件夹中创建了一个脚本文件CreateOrleansTables _ *.sql(其中asterisk表示数据库供应商),该文件建立必要的数据库对象。 确保将要托管奥尔良仓库的所有服务器都可以访问数据库并拥有访问权限! 在我们的测试过程中,我们已经绊倒了几次这个看起来微不足道的问题。 请注意,在Orleans 2.0.0中,这些SQL脚本已经被分成了每个功能部件以匹配更细粒度提供者模型:集群,持久性,提醒和统计。

①SQL度量和统计表

系统表目前只能存储在Azure表或SQL服务器中。 但是,对于度量标准和统计表,我们提供一个通用的支持来将其托管在任何持久性存储中。 这是通过StatisticsProvider的概念提供的。 任何应用程序都可以编写任意提供程序来将统计信息和指标数据存储在他们选择的持久存储中。 Orleans提供了一个这样的提供者的实现:SQL Table Statistics Provider。

为了将SQL服务器用于统计和指标表,需要调整服务器端和客户端配置。

服务器配置应该如下所示:

<OrleansConfiguration xmlns="urn:orleans">
     <Globals>
         <StatisticsProviders>
             <Provider Type="Orleans.Providers.SqlServer.SqlStatisticsPublisher" Name="MySQLStatsProvider" ConnectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Orleans;Integrated Security=True;Pooling=False;Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True" />
         </StatisticsProviders>
     </Globals>
     <Defaults>
         <Statistics ProviderType="MySQLStatsProvider" WriteLogStatisticsToTable="true"/>
     </Defaults>
</OrleansConfiguration>

客户端配置应如下所示:

<ClientConfiguration xmlns="urn:orleans">
      <StatisticsProviders>
         <Provider Type="Orleans.Providers.SqlServer.SqlStatisticsPublisher" Name="SQL" ConnectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Orleans;Integrated Security=True;Pooling=False;Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True" />
      </StatisticsProviders>
      <Statistics ProviderType="MySQLStatsProvider" WriteLogStatisticsToTable="true"/>
</ClientConfiguration>

 

二、监控

1,运行时监视

[[这是需要审查]]

通过利用Orleans自动向Azure存储写入的数据,外部操作员可以监控Orleans部署的五种方式。

下面提到的表格在这里有更详细的描述。

OrleansSilosTable for cluster membership -此表列出了部署中的所有silos(分区键DeploymentID,行密钥silosID)。 操作员可以使用此表来检查群集运行状况,查看当前设置的活动silos,或了解某个silos发生故障的原因和时间。 Orleans的集群成员协议在内部使用此表,并用重要的成员事件(silos上下)更新它。

OrleansSiloMetrics表- grain性能统计 - Orleans在这个表(分区键DeplomentID,行密钥仓库id)中写入了一个小数(约10)的grain性能统计。 该表格每隔X秒(每个silo可配置)自动更新一次。 这些度量指标包括:siloCPU,内存使用情况,该silo中grain激活的数量,发送/接收队列中的消息数量等。这些数据可以用来比较筒仓,检查是否没有明显的异常值(例如, silo运行在更高的CPU上),或者只是简单地检查一下通过grains报告的指标是否在预期的范围内。 此外,如果系统过载,则可以使用此数据决定是否添加新的silos,或者如果系统大部分空闲,则可以减少silos数量。

OrleansSiloStatistics表 - 这个表格包含了更多的性能统计数字(数百个计数器),这些统计数据提供了更详细,更深入的内部silos状态视图。 目前不推荐此表格供外部操作员使用。 主要是Orleans开发商帮助他们解决复杂的生产问题。 Orleans团队正在构建工具来自动分析这些数据,并基于此向运营商提供紧凑的建议。 这些工具也可以由任何人独立建造。

Watching error codes in MDS -Orleans自动写入不同的错误消息到记录器。 该记录器可以配置为输出其数据到不同的目的地。 例如,Halo团队将生产中的所有日志重定向到MDS。 他们已经在MDS中编写了自定义警报,以监视特定的错误代码并计算它们的发生次数,并在这些阈值达到某个阈值时向其发出警报。 在这里指定要观察的重要错误代码列表:

Windows performance counters -Orleans运行时不断更新其中的一些。 CounterControl.exe帮助注册计数器,并需要以提升的权限运行。 显然,性能计数器可以使用任何标准的监视工具进行监视。

2,silo错误代码监测

Group Log Type Log Code Values Threshold Description
Azure Problems Warning or Error 100800 - 100899 Any Error or Warning 读取或写入Azure表存储的瞬间问题将被记录为警告。 瞬时读取错误将自动重试。 最终的错误日志消息意味着连接到Azure表存储存在真正的问题。
Membership Connectivity Problems Warning or Error 100600 - 100699 Any Error or Warning 警告日志是网络连接问题和/或silo重新启动/迁移的早期指示。 Ping超时和silo投票将显示为警告消息。 筒仓厌恶它被投票死了将显示为错误消息。
Grain call timeouts Warning 100157 Multiple Warnings logged in short space of time grain调用超时问题通常是由临时网络连接问题或silo重启/重启问题引起的。 系统应该在短时间后恢复(取决于Liveness配置设置),超时应该清除。 理想情况下,只监视这些警告的大量日志代码600157应该是足够的。
Silo Restart / Migration Warning 100601 or 100602 Any Warning silo检测到它在同一台机器上重新启动(100602)或迁移到其他机器(100601)
Network Socket Problems Warning or Error 101000 to 101999, 100307,100015, 100016 Any Error or Warning 套接字断开被记录为警告消息。 打开套接字或发送消息时出现的问题记录为错误。
Bulk log message compaction Any 500000 or higher Message summary based on bulk message threshold settings 如果在指定的时间间隔内出现了多个相同日志代码的日志(缺省值在1分钟内大于5),则会删除包含该日志代码的其他日志消息,并将其输出为日志代码等于原始日志的“批量”条目 代码+ 500000.例如,多个100157条目将在日志中显示为每分钟5 x 100157 + 1 x 600157条目。
Grain problems Warning or Error 101534 Any Error or Warning 检测对非折返grain的“stuck”请求。 每次请求花费超过5倍的请求超时时间执行时,都会报告错误代码。

3,客户端错误代码监测

Group Log Type Log Code Values Threshold Description
Azure Problems Warning or Error 100800 - 100899 Any Error or Warning 读取或写入Azure表存储的瞬间问题将被记录为警告。 瞬时读取错误将自动重试。 最终的错误日志消息意味着连接到Azure表存储存在真正的问题。
Gateway connectivity problems Warning or Error 100901 - 100904, 100912, 100913, 100921, 100923, 100158, 100161, 100178, , 101313 Any Error or Warning 连接到网关的问题。 Azure表中没有活动的网关。 连接到活动网关丢失。
Grain call timeouts Warning 100157 Multiple Warnings logged in short space of time grain调用超时问题通常是由临时网络连接问题或silos重启/重启问题引起的。 系统应该在短时间后恢复(取决于Liveness配置设置),超时应该清除。 理想情况下,只监视这些警告的大量日志代码600157应该是足够的。
Network Socket Problems Warning or Error 101000 to 101999, 100307, 100015, 100016 Any Error or Warning 套接字断开被记录为警告消息。 打开套接字或发送消息时出现的问题记录为错误。
Bulk log message compaction Any 500000 or higher Message summary based on bulk message threshold settings 如果在指定的时间间隔内出现了多个相同日志代码的日志(缺省值在1分钟内大于5),则会删除包含该日志代码的其他日志消息,并将其输出为日志代码等于原始日志的“批量”条目 代码+ 500000.例如,多个100157条目将在日志中显示为每分钟5 x 100157 + 1 x 600157条目。

三、解决部署问题

 本页提供了一些常规指导,可用于解决部署到Azure云服务时出现的任何问题。 这些是需要注意的常见问题。 请务必检查日志以获取更多信息。

1,获得一个SiloUnavailableException

首先检查一下,确保在尝试初始化客户端之前确实启动了筒仓。 有时silo需要很长时间才能启动,所以尝试多次初始化客户端可能会有所帮助。 如果它仍然抛出一个异常,那么silos可能会有另一个问题。检查silo配置,确保silo正确启动。

2,常见连接字符串问题

  • 部署到Azure时使用本地连接字符串 - 网站将无法连接
  • 对silos和前端(web和worker角色)使用不同的连接字符串 - 网站将无法初始化客户端,因为它无法连接到silos

可以在Azure门户中检查连接字符串配置。 如果连接字符串设置不正确,日志可能无法正确显示。

3,修改配置文件不当

确保在ServiceDefinition.csdef文件中配置了正确的端点,否则部署将不起作用。 它会给出错误,说明它不能获取端点信息。

4,缺少日志

确保连接字符串设置正确。

Web角色中的Web.config文件或worker角色中的app.config文件可能被错误地修改。 这些文件中的不正确版本可能会导致部署问题。 处理更新时要小心。

6,版本问题

确保解决方案中的每个项目都使用相同版本的Orleans。 不这样做可以导致员工角色回收。 检查日志以获取更多信息。 Visual Studio在部署历史记录中提供了一些silo启动错误消息。

7,角色不断回收

  • 检查所有合适的Orleans程序集是否在解决方案中,并将Copy Local设置为True。
  • 检查日志以查看初始化时是否有未处理的异常。
  • 确保连接字符串是正确的。
  • 查看Azure云服务疑难解答页面以获取更多信息。

8,如何检查日志

  • 使用Visual Studio中的云资源管理器导航到存储帐户中适当的存储表或blob。 WADLogsTable是查看日志的好起点。
  • 您可能只会记录错误。 如果您还需要信息日志,则需要修改配置以设置日志严重性级别。

编程配置:

  • 创建ClusterConfiguration对象时,请设置config.Defaults.DefaultTraceLevel = Severity.Info。
  • 创建ClientConfiguration对象时,请设置config.DefaultTraceLevel = Severity.Info。

声明式配置:

  • 将<Tracing DefaultTraceLevel =“Info”/>添加到OrleansConfiguration.xml和/或ClientConfiguration.xml文件中。

在Web和辅助角色的diagnostics.wadcfgx文件中,请确保将Logs元素中的scheduledTransferLogLevelFilter属性设置为Information,因为这是一个额外的跟踪筛选层,它定义将哪些跟踪发送到Azure存储中的WADLogsTable。

在“配置指南”中可以找到关于此的更多信息。

8,与ASP.NET兼容

ASP.NET中包含的razor视图引擎使用与Orleans(Microsoft.CodeAnalysis和Microsoft.CodeAnalysis.CSharp)相同的代码生成程序集。 这可能会在运行时出现版本兼容性问题。

要解决此问题,请尝试将Microsoft.CodeDom.Providers.DotNetCompilerPlatform(这是ASP.NET用来包含上述程序集的NuGet程序包)升级到最新版本,并设置绑定重定向,如下所示:

<dependentAssembly>
  <assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="1.3.1.0" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="1.3.1.0" />
</dependentAssembly>

 

四、异构silos

 概观在给定的集群上,筒仓可以支持一组不同的grain类型:

Orleans部署

在这个例子中,集群支持类型A,B,C,D,E:

  • grain种类A和B可以放置在silo1和2上。
  • grain类型C可以被放置在silo1,2或3。
  • grain类型D只能放在silo3上
  • grain类型E只能放在silo4上。

所有的silo都应该引用所有的grain类型的接口,但是grain类只应该被容纳它们的silo所引用。

客户端不知道哪个silo支持给定的grain类型。

给定的Grain Type实现必须在支持它的每个silo中相同。 以下情况无效:

在silo1和2:

public class C: Grain, IMyGrainInterface
{
   public Task SomeMethod() { … }
}

在silo3:

public class C: Grain, IMyGrainInterface, IMyOtherGrainInterface
{
   public Task SomeMethod() { … }
   public Task SomeOtherMethod() { … }
}

1,配置

不需要配置,您可以在群集中的每个silo上部署不同的二进制文件。 但是,如有必要,可以更改silos检查ClusterConfig.Globals.TypeMapRefreshInterval中支持的类型更改的时间间隔。出于测试目的,您可以在NodeConfiguration中使用ExcludedGrainTypes属性。 在基于代码的配置中,您可以在ClusterConfig.Defaults.ExcludedGrainTypes中找到它,它是要排除的类型的列表名称。

2,限制

  • 如果支持的“grain类型”集合发生更改,则不会通知连接的客户端。 在前面的例子中:
    • 如果Silo 4离开集群,客户端仍然会尝试调用E类型的grain。在运行时OrleansException会失败。
    • 如果在Silo 4加入之前,客户端连接到群集,客户端将无法调用E类型的谷物。它将失败一个ArgumentException
  • 不支持无状态grain:群集中的所有silo必须支持同一组无状态grain。

 

五、开始使用Azure Web Apps

如果您想从Azure Web App连接到Azure Silo,而不是在同一云服务中托管的Web Role,则可以。 

为了安全工作,您需要将Azure Web App和托管Silo的Worker角色分配给Azure虚拟网络。

首先,我们将设置Azure Web App,您可以按照本指南创建虚拟网络并将其分配给Azure Web App。

现在我们可以通过修改ServiceConfiguration文件来将云服务分配给虚拟网络。

<NetworkConfiguration>
  <VirtualNetworkSite name="virtual-network-name" />
  <AddressAssignments>
    <InstanceAddress roleName="role-name">
      <Subnets>
        <Subnet name="subnet-name" />
      </Subnets>
    </InstanceAddress>
  </AddressAssignments>
</NetworkConfiguration>

还要确保silo端点已配置。

<Endpoints>
  <InternalEndpoint name="OrleansSiloEndpoint" protocol="tcp" port="11111" />
  <InternalEndpoint name="OrleansProxyEndpoint" protocol="tcp" port="30000" />
</Endpoints>

最后,您需要为silos和Web应用程序客户端指定相同的部署ID。

您现在可以使用GrainClient从Web App连接到silo。

1,潜在的问题

如果Web应用程序无法连接到筒仓:

  • 确保您的Azure云服务中至少有两个角色或两个角色,或者不能生成InternalEndpoint防火墙规则。
  • 检查Web应用程序和silo是否使用相同的DeploymentId。
  • 确保网络安全组已设置为允许内部虚拟网络连接。 如果你没有一个你可以使用下面的PowerShell轻松地创建和分配一个:
New-AzureNetworkSecurityGroup -Name "Default" -Location "North Europe"
Get-AzureNetworkSecurityGroup -Name "Default" | Set-AzureNetworkSecurityGroupToSubnet -VirtualNetworkName "virtual-network-name" -SubnetName "subnet-name"

六、Docker部署

1,部署Orleans解决方案到Docker

考虑到Docker协调器和集群堆栈的设计方式,将Orleans部署到Docker可能会非常棘手。 最复杂的是从Docker Swarm和Kubernets Networking模型中理解覆盖网络的概念。

Docker容器和网络模型被设计为运行大多数无状态和不可变的容器。 因此,启动一个运行node.js或nginx应用程序的集群是相当容易的。 但是,如果您尝试使用更复杂的东西,比如真正的集群或分布式应用程序(例如基于Orleans的应用程序),您最终会遇到麻烦。 这是可能的,但不像基于网络的应用程序那样简单。

Docker集群包括将多个主机放在一起,作为使用Container Orchestrator管理的单个资源池。 Docker Inc.提供Swarm作为Container Orchestration的选项,而Google则提供Kubernetes(又名K8s)。 还有其他的Orchestrator,如DC / OS,Mesos等,但是在这个文档中我们将会讨论Swarm和K8s,因为它们被更广泛地使用。

在Orleans的任何地方运行的相同的grain接口和实现已经被支持,也将在Docker容器上运行,所以为了能够在Docker容器中运行你的应用程序,不需要特别的考虑。

Orleans-Docker示例提供了如何运行两个控制台应用程序的工作示例。 一个作为Orleans客户,另一个作为silo,细节描述如下。

这里讨论的概念可以用在Orleans的.Net Core和.Net 4.6.1版本中,但为了说明Docker和.Net Core的跨平台性质,我们将着重考虑你正在使用的例子。 净核心。 本文可能会提供特定于平台(Windows / Linux / OSX)的详细信息。

2,先决条件

本文假定您已经安装了以下先决条件:

  • Docker - Docker4X有一个易于使用的主要支持平台的安装程序。 它包含Docker引擎和Docker Swarm。
  • Kubernetes (K8s) - Google提供的Container Orchestration。 它包含安装Minikube(K8s的本地部署)和kubectl及其所有依赖项的指导。
  • .Net Core - .Net的跨平台
  • Visual Studio Code (VSCode) - 你可以使用任何你想要的IDE。 VSCode是跨平台的,所以我们正在使用它来确保它在所有平台上都能正常工作。 一旦你安装VSCode,安装 C# extension.

注意:如果您不打算使用它,则不需要安装Kubernetes。 Docker4X安装程序已经包含了Swarm,因此不需要额外安装即可使用它。

Windows用户注意事项:在Windows上,Docker安装程序将在安装过程中启用Hyper-V。 由于本文及其示例使用.Net Core,所使用的容器映像基于Windows Server NanoServer。 如果你不打算使用.Net coew,并将目标.NET 4.6.1完整的框架,使用的图像应该是Windows Server Core和Orleans的1.4 +版本(只支持.net完整框架)。

3,创建Orleans解决方案

以下说明显示了如何使用新的dotnet工具创建常规的Orleans解决方案。

注意:请根据您的平台适当调整命令。 而且,目录结构只是一个建议。 请随意调整它。

mkdir Orleans-Docker
cd Orleans-Docker
dotnet new sln
mkdir -p src/OrleansSilo
mkdir -p src/OrleansClient
mkdir -p src/OrleansGrains
mkdir -p src/OrleansGrainInterfaces
dotnet new console -o src/OrleansSilo --framework netcoreapp1.1
dotnet new console -o src/OrleansClient --framework netcoreapp1.1
dotnet new classlib -o src/OrleansGrains --framework netstandard1.5
dotnet new classlib -o src/OrleansGrainInterfaces --framework netstandard1.5
dotnet sln add src/OrleansSilo/OrleansSilo.csproj
dotnet sln add src/OrleansClient/OrleansClient.csproj
dotnet sln add src/OrleansGrains/OrleansGrains.csproj
dotnet sln add src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj
dotnet add src/OrleansClient/OrleansClient.csproj reference src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj
dotnet add src/OrleansSilo/OrleansSilo.csproj reference src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj
dotnet add src/OrleansGrains/OrleansGrains.csproj reference src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj
dotnet add src/OrleansSilo/OrleansSilo.csproj reference src/OrleansGrains/OrleansGrains.csproj

到目前为止,我们所做的仅仅是样板代码来创建解决方案结构,项目,并在项目之间添加引用。 没有什么比普通的Orleans项目不同。

在写这篇文章的时候,Orleans 2.0(这是唯一支持.Net Core和跨平台的版本)在技术预览版中,所以它的核心部分被托管在一个MyGet源中,而不是发布到Nuget.org的官方源。 为了安装预览版本,我们将使用dotnet cli强制MyGet的源代码和版本:

dotnet add src/OrleansClient/OrleansClient.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet add src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet add src/OrleansGrains/OrleansGrains.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet add src/OrleansSilo/OrleansSilo.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet add src/OrleansSilo/OrleansSilo.csproj package Microsoft.Orleans.OrleansRuntime -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000
dotnet restore

好的,现在你拥有了运行一个简单的Orleans应用程序的所有基本的依赖关系。 请注意,迄今为止,您的常规Orleans应用程序没有任何变化。 现在,让我们添加一些代码,以便我们可以做一些事情。

4,实施你的Orleans应用程序

假设您正在使用VSCode,从解决方案目录中运行代码。这将打开VSCode中的目录并加载解决方案。

这是我们以前创建的解决方案结构。

Orleans部署

我们还将Program.cs,OrleansHostWrapper,IGreetingGrain和GreetingGrain文件分别添加到接口和grain项目,这里是这些文件的代码:

IGreetingGrain.cs:

using System;
using System.Threading.Tasks;
using Orleans;

namespace OrleansGrainInterfaces
{
    public interface IGreetingGrain : IGrainWithGuidKey
    {
        Task<string> SayHello(string name);
    }
}
IGreetingGrain.cs

相关文章: