升级指南

官方升级指南
https://learn.microsoft.com/zh-cn/dotnet/orleans/migration-guide?source=recommendations
 
主要涉及以下几个改动点
  1. ConfigureApplicationParts
3.6.5版在Silo初始化的时候,会通过这个方法将指定目录下的Grain加载进来
.ConfigureApplicationParts(parts => parts.AddFromApplicationBaseDirectory())
8.0.0版就不需要了,直接去掉这个方法,因为它有另外新的加载机制,后面会说到
 
  1. JsonGrainStateSerializerOptions
3.6.5版的Grain状态消息Json序列化配置,是在Silo初始化时(比如使用MongoDB作为持久化存储)通过ConfigureJsonSerializerSettings配置的
.AddMongoDBGrainStorage("Default", (MongoDBGrainStorageOptions op) =>
{
    op.CollectionPrefix = "GrainStorage";
    op.DatabaseName = configSection.GetValue<string>("DataBase");

    op.ConfigureJsonSerializerSettings = jsonSettings =>
    {
        jsonSettings.NullValueHandling = NullValueHandling.Include;
        jsonSettings.DefaultValueHandling = DefaultValueHandling.Populate;
        jsonSettings.ObjectCreationHandling = ObjectCreationHandling.Replace;
    };

})
8.0.0版的Grain状态消息Json序列化配置,是在Silo初始化时通过配置JsonGrainStateSerializerOptions属性
.Configure<JsonGrainStateSerializerOptions>(options => options.ConfigureJsonSerializerSettings =
    settings =>
    {
        settings.NullValueHandling = NullValueHandling.Include;
        settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
        settings.DefaultValueHandling = DefaultValueHandling.Populate;
    })
但仅仅这个还不够,还需要单独实现一个Grain状态的序列化器(因为8.0.3版的Orleans.Providers.MongoDB包有Bug所以才需要这一步,这个Bug已经由我向作者反馈过,详情见https://github.com/OrleansContrib/Orleans.Providers.MongoDB/issues/136,包的作者也修复了,后续新的版本应该不用),如下
public class NewJsonGrainStateSerializer: IGrainStateSerializer
{
    private readonly JsonSerializerSettings jsonSettings;

    public NewJsonGrainStateSerializer(IOptions<JsonGrainStateSerializerOptions> options, IServiceProvider serviceProvider)
    {
        jsonSettings = OrleansJsonSerializerSettings.GetDefaultSerializerSettings(serviceProvider);
        options.Value.ConfigureJsonSerializerSettings(jsonSettings);
    }

    public T Deserialize<T>(BsonValue value)
    {
        using var jsonReader = new JTokenReader(value.ToJToken());
        var localSerializer = JsonSerializer.CreateDefault(jsonSettings);
        return localSerializer.Deserialize<T>(jsonReader);
    }

    public BsonValue Serialize<T>(T state)
    {
        var localSerializer = JsonSerializer.CreateDefault(jsonSettings);
        return JObject.FromObject(state, localSerializer).ToBson();
    }
}
并将NewJsonGrainStateSerializer注入到容器替换掉默认的序列化器
.ConfigureServices(services => services.AddSingleton<IGrainStateSerializer,NewJsonGrainStateSerializer>())
 
  1. AddSimpleMessageStreamProvider
3.6.5版中如果你使用了流式订阅,且用的是SimpleMessageStreams(也称为 SMS)
.AddSimpleMessageStreamProvider(ApplicationConsts.MessageStreamName)
8.0.0版中需要将它替换为使用MemoryStream
.AddMemoryStreams(AeFinderApplicationConsts.MessageStreamName)
 
  1. UseOrleansClient
3.6.5版初始化Orleans的客户端,是通过给IClusterClient注册一个ClientBuilder对象,如下:
context.Services.AddSingleton<IClusterClient>(o =>
{
    return new ClientBuilder()
        .ConfigureDefaults()
        // .UseRedisClustering(opt =>
        // {
        //     opt.ConnectionString = configuration["Orleans:ClusterDbConnection"];
        //     opt.Database = Convert.ToInt32(configuration["Orleans:ClusterDbNumber"]);
        // })
        .UseMongoDBClient(configuration["Orleans:MongoDBClient"])
        .UseMongoDBClustering(options =>
        {
            options.DatabaseName = configuration["Orleans:DataBase"];;
            options.Strategy = MongoDBMembershipStrategy.SingleDocument;
        })
        .Configure<ClusterOptions>(options =>
        {
            options.ClusterId = configuration["Orleans:ClusterId"];
            options.ServiceId = configuration["Orleans:ServiceId"];
        })
        .ConfigureApplicationParts(parts =>
            parts.AddApplicationPart(typeof(GrainsModule).Assembly).WithReferences())
        .AddSimpleMessageStreamProvider(ApplicationConsts.MessageStreamName)
        .ConfigureLogging(builder => builder.AddProvider(o.GetService<ILoggerProvider>()))
        .Build();
});
8.0.0版就得换一种方式了,它直接提供了UseOrleansClient扩展方法来帮助你实现,如下:
public static IHostBuilder UseOrleansClient(this IHostBuilder hostBuilder)
{
    return hostBuilder.UseOrleansClient((context, clientBuilder) =>
    {
        var configSection = context.Configuration.GetSection("Orleans");
        if (configSection == null)
            throw new ArgumentNullException(nameof(configSection), "The Orleans config node is missing");
        clientBuilder.UseMongoDBClient(configSection.GetValue<string>("MongoDBClient"))
            .UseMongoDBClustering(options =>
            {
                options.DatabaseName = configSection.GetValue<string>("DataBase");
                options.Strategy = MongoDBMembershipStrategy.SingleDocument;
            })
            .Configure<ClusterOptions>(options =>
            {
                options.ClusterId = configSection.GetValue<string>("ClusterId");
                options.ServiceId = configSection.GetValue<string>("ServiceId");
            })
            .AddMemoryStreams(AeFinderApplicationConsts.MessageStreamName)
            .AddActivityPropagation();
    });
}
 
  1. GenerateSerializer
3.6.5版的Grain类加载,是通过上面说到的ConfigureApplicationParts方法
8.0.0版不用,它会自动寻找那些引用了Microsoft.Orleans.Sdk包的程序集,找出里面的Grain类自动进行加载到Silo中
除此之外,它还需要你给每个Grain中定义的方法用到的通信类(输入和输出),都标上【GenerateSerializer】和【Id】注解,如下:
[GenerateSerializer]
public class CreateAppDto
{
    [Id(0)] public string AppId { get; set; }
    [Id(1)] public string OrganizationId { get; set; }
    [Id(2)] public string DeployKey { get; set; }
    [MinLength(2),MaxLength(20)]
    [RegularExpression("[A-Za-z0-9\\s]+" ,ErrorMessage = "The AppName can only contain letters('A'-'Z', 'a'-'z'), numbers(0-9), and spaces(' ').")]
    [Id(3)] public string AppName { get; set; }
}
 
  1. OnActivateAsync
3.6.5版中关于Grain激活和失活过程的重载方法分别是
public override async Task OnActivateAsync()
{
    await ReadStateAsync();
    await base.OnActivateAsync();
}

public override async Task OnDeactivateAsync()
{
    await WriteStateAsync();
    await base.OnDeactivateAsync();
}
8.0.0版中关于Grain激活和失活过程的重载方法分别是
public override async Task OnActivateAsync(CancellationToken cancellationToken)
{
    await ReadStateAsync();
    await base.OnActivateAsync(cancellationToken);
}

public override async Task OnDeactivateAsync(DeactivationReason reason, CancellationToken cancellationToken)
{
    await WriteStateAsync();
    await base.OnDeactivateAsync(reason, cancellationToken);
}
主要是多了一些入参

注意

我这里只是列了一些主要的改动点,实际升级过程中需要注意的其他地方可以参考官方文档。
此博客为作者原创,转载请注明出处,谢谢~
posted @ 2025-01-24 17:23 月井石 阅读(21) 评论(0) 推荐(0) 编辑
摘要: 在Mac电脑上启动Zookeeper和kafka的docker容器时报错 error while creating mount source path '/host_mnt/private/var/db/timezone/tz/2023c.1.0/zoneinfo/Asia/Shanghai': m 阅读全文
posted @ 2024-02-18 10:36 月井石 阅读(753) 评论(1) 推荐(0) 编辑
摘要: 在使用AWS(亚马逊云)的Kafka服务,即MSK时,程序生产的消息发送kafka始终不成功,收到如下报错: Producer terminating with 1 message (32 bytes) still in queue or transit: use flush() to wait f 阅读全文
posted @ 2023-03-02 15:45 月井石 阅读(892) 评论(0) 推荐(0) 编辑
摘要: 项目环境:ABP+Mysql 一、准备一个ABP项目 这里采用ABP的Samples中的一个样板项目TodoApp下的Mvc-EfCore 下载地址:https://github.com/abpframework/abp-samples/tree/master/TodoApp/Mvc-EfCore 阅读全文
posted @ 2022-12-04 22:59 月井石 阅读(928) 评论(0) 推荐(0) 编辑
摘要: 假设你已经看过上一篇Orleans基础知识,否则本篇看起来可能会稍微有些吃力,如果没看过,请点击Orleans基础知识以及使用示例 阅读 Orleans实现Event Sourcing(事件溯源)机制主要依赖于2个元素: Journaled Grains Log Consistency Provid 阅读全文
posted @ 2022-12-04 22:39 月井石 阅读(266) 评论(0) 推荐(0) 编辑
摘要: Orleans简介 Orleans 是一个与ABP齐名,支持有状态云生应用/服务水平伸缩的基于Virtual Actor 模型的.NET分布式应用框架。 Actor模型 简单来讲:Actor模型 = 状态 + 行为 + 消息。一个应用/服务由多个Actor组成,每个Actor都是一个独立的运行单元, 阅读全文
posted @ 2022-11-26 12:33 月井石 阅读(1204) 评论(0) 推荐(1) 编辑
摘要: 操作环境:Centos7.8+.net Core3.1+Docker 由于IdentityServer4的认证授权功能太过强大和复杂,实现了OAuth2.0的四种授权模式——隐式模式(implicit)、授权码模式(Authorization Code)、密码凭证模式(Resource Owner 阅读全文
posted @ 2022-05-31 01:26 月井石 阅读(617) 评论(3) 推荐(1) 编辑
摘要: 此播放音效的方法几乎针对所有Windows系统都通用,废话不多说,直接上代码 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Intero 阅读全文
posted @ 2021-03-08 15:27 月井石 阅读(434) 评论(0) 推荐(0) 编辑
摘要: 1.首先引用两个钉钉的js <script src="https://g.alicdn.com/dingding/dingtalk-jsapi/2.7.13/dingtalk.open.js"></script><!--钉钉JSAPI库(使用对象dd)--> <script type="text/j 阅读全文
posted @ 2021-01-29 18:33 月井石 阅读(4587) 评论(0) 推荐(0) 编辑
摘要: 一、本示例使用环境:Net Core3.1、WebAPI、Linux 二、使用核心类:ZipFile 三、示例代码(亲测有效) using System.Net.Http; using System.IO.Compression; [HttpGet,Route("DownFile")] [Autho 阅读全文
posted @ 2020-11-27 16:24 月井石 阅读(4364) 评论(2) 推荐(2) 编辑
点击右上角即可分享
微信分享提示