C# NserviceBus:事件处理程序被称为15+;时间…仅当应用程序在容器中运行时

C# NserviceBus:事件处理程序被称为15+;时间…仅当应用程序在容器中运行时,c#,.net-core,rabbitmq,docker-compose,nservicebus,C#,.net Core,Rabbitmq,Docker Compose,Nservicebus,我设置了一个事件(以及一个传奇中使用的几个命令)。我有两个web应用程序和一个控制台应用程序可以注册端点。自动订阅已为所有用户关闭。一个应用程序为该事件声明一个处理程序并手动订阅该事件 当我在容器中运行应用程序并使用sqlPersistence和RabbitMq传输时,会反复调用处理程序。当我在没有容器的情况下运行并且没有显式设置任何持久性并使用LearningTransport时,代码的行为符合预期 我知道当异常发生时,处理程序会被一次又一次地调用,但这是默认的重试次数(5?),并且处理程序中

我设置了一个事件(以及一个传奇中使用的几个命令)。我有两个web应用程序和一个控制台应用程序可以注册端点。自动订阅已为所有用户关闭。一个应用程序为该事件声明一个处理程序并手动订阅该事件

当我在容器中运行应用程序并使用sqlPersistence和RabbitMq传输时,会反复调用处理程序。当我在没有容器的情况下运行并且没有显式设置任何持久性并使用LearningTransport时,代码的行为符合预期

我知道当异常发生时,处理程序会被一次又一次地调用,但这是默认的重试次数(5?),并且处理程序中没有异常发生,所以我认为这不是问题所在

从web应用程序发布事件(向其处理程序发送命令时出现相同问题)时,处理程序会针对相同的消息反复调用:消息Id、相关性Id、会话Id、发送时间,。。。一切都是一样的,我不知道为什么,也没有在互联网上找到其他的点击

我使用autofac作为容器,使用NSB 7.0.1和RabbitMq进行传输。所有应用程序、持久性(sql server)和传输都在Docker容器中运行

对于每个应用程序,我的设置都是相同的,只是我只在一个应用程序中注册了处理程序,如下所示:

谢谢你的帮助

public virtual IServiceProvider ConfigureServices(IServiceCollection services)
        {
//...
var loggerFactory = 
            container.Resolve<Microsoft.Extensions.Logging.ILoggerFactory>();
            var logFactory = LogManager.Use<MicrosoftLogFactory>();
            logFactory.UseMsFactory(loggerFactory);

            var endpointConfiguration = new EndpointConfiguration(applicationName);
            endpointConfiguration.EnableInstallers();
            endpointConfiguration.SendFailedMessagesTo("error");
            endpointConfiguration.AuditProcessedMessagesTo("audit");
            endpointConfiguration.UseSerialization<NewtonsoftSerializer>();

            endpointConfiguration.DisableFeature<AutoSubscribe>();

            EnsureSqlDatabaseExists(persistenceConnectionString, container.Resolve<ILogger<IEndpointInstance>>());

            var persistence = endpointConfiguration.UsePersistence<SqlPersistence>();
            persistence.TablePrefix("Monrovo");
            var dialect = persistence.SqlDialect<SqlDialect.MsSqlServer>();
            dialect.Schema("receiver");

            persistence.ConnectionBuilder(() => new SqlConnection(persistenceConnectionString));

            var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
            transport.UseConventionalRoutingTopology();
            transport.ConnectionString(transportConnectionString);

            endpointConfiguration.UseContainer<AutofacBuilder>(customizations =>
            {
                customizations.ExistingLifetimeScope(container);
            });

            await ScriptRunner.Install(
                sqlDialect: new SqlDialect.MsSqlServer(),
                tablePrefix: "Monrovo",
                connectionBuilder: () => new SqlConnection(persistenceConnectionString),
                scriptDirectory: Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + @"/NServiceBus.Persistence.Sql/MsSqlServer",
                shouldInstallOutbox: true,
                shouldInstallSagas: true,
                shouldInstallSubscriptions: true,
                shouldInstallTimeouts: true);

            var startableEndpoint = await Endpoint.Create(endpointConfiguration);
            var endpoint = await startableEndpoint.Start();

_endpointInstance.Subscribe<ArticleApproved>().Wait();

            var updateBuilder = new ContainerBuilder();
            updateBuilder.RegisterInstance(_endpointInstance)
                .As<IMessageSession>().As<IEndpointInstance>().SingleInstance();

            // There is currently no workaround from NServiceBus for this.
            // See https://github.com/Particular/NServiceBus/issues/4421
#pragma warning disable CS0618 // Type or member is obsolete
            updateBuilder.Update(container);
#pragma warning restore CS0618 // Type or member is obsolete

            return new AutofacServiceProvider(container);
}


private static void EnsureSqlDatabaseExists(string connectionString, ILogger<IEndpointInstance> logger)
        {
            var builder = new SqlConnectionStringBuilder(connectionString);
            var originalCatalog = builder.InitialCatalog;

            builder.InitialCatalog = "master";
            var masterConnectionString = builder.ConnectionString;

            try
            {
                using (var connection = new SqlConnection(masterConnectionString))
                {
                    connection.Open();
                    var command = connection.CreateCommand();
                    command.CommandText =
                        $"IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = '{originalCatalog}')" +
                        $"  CREATE DATABASE [{originalCatalog}]; ";
                    command.ExecuteNonQuery();
                }
            }
            catch (SqlException)
            {
                // Need to handle this better. Locally, we need to use master first. In Azure this is not possible or necessary
                // TODO: Build a sql docker container with a database already created.
                builder.InitialCatalog = originalCatalog;
                masterConnectionString = builder.ConnectionString;

                try
                {
                    using (var connection = new SqlConnection(masterConnectionString))
                    {
                        connection.Open();
                        var command = connection.CreateCommand();
                        command.CommandText =
                            $"IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = '{originalCatalog}')" +
                            $"  CREATE DATABASE [{originalCatalog}]; ";
                        command.ExecuteNonQuery();
                    }
                }
                catch (SqlException innerException)
                {
                    logger.LogCritical(innerException, $"Unable to connect to SQL Server. Check that {builder.DataSource} is available");
                }
            }

            builder.InitialCatalog = originalCatalog;
            masterConnectionString = builder.ConnectionString;

            try
            {
                using (var connection = new SqlConnection(masterConnectionString))
                {
                    connection.Open();

                    var command = connection.CreateCommand();
                    command.CommandText =
                        $"IF NOT EXISTS(SELECT 1 FROM sys.schemas WHERE name = 'receiver')" +
                        $"BEGIN EXEC sys.sp_executesql N'CREATE SCHEMA receiver;' END";
                    command.ExecuteNonQuery();
                }
            }
            catch { }
        }



public class test : IHandleMessages<ArticleApproved>
    {
        public Task Handle(RfpApproved message, IMessageHandlerContext context)
        {
            // Initially handles the published event and starts the saga
            context.SendLocal(new StartRFPSync(message.RfpId));
            return Task.CompletedTask;
        }
    }
公共虚拟iSeries Provider配置服务(iSeries收集服务)
{
//...
var loggerFactory=
container.Resolve();
var logFactory=LogManager.Use();
logFactory.UseMsFactory(loggerFactory);
var endpointConfiguration=新的endpointConfiguration(applicationName);
endpointConfiguration.EnableInstallers();
endpointConfiguration.SendFailedMessageTo(“错误”);
endpointConfiguration.AuditProcessedMessageTo(“审核”);
endpointConfiguration.UseSerialization();
endpointConfiguration.DisableFeature();
确保QLDatabaseExists(persistenceConnectionString,container.Resolve());
var persistence=endpointConfiguration.UsePersistence();
持久性。表格前缀(“蒙罗沃”);
var dialent=persistence.sqldialent();
方言图式(“接受者”);
ConnectionBuilder(()=>newSQLConnection(persistenceConnectionString));
var transport=endpointConfiguration.UseTransport();
运输。使用常规路线拓扑();
transport.ConnectionString(transportConnectionString);
endpointConfiguration.UseContainer(自定义=>
{
定制。现有LifetimeScope(容器);
});
等待ScriptRunner。安装(
SqlDialogue:新的SqlDialogue.MsSqlServer(),
表格前缀:“蒙罗沃”,
connectionBuilder:()=>新的SqlConnection(persistenceConnectionString),
scriptDirectory:Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)+@“/NServiceBus.Persistence.Sql/MsSqlServer”,
shouldInstallOutbox:true,
应该安装传奇:是的,
应该安装订阅:正确,
应安装超时:true);
var startableEndpoint=wait Endpoint.Create(endpointConfiguration);
var endpoint=await startableEndpoint.Start();
_endpointInstance.Subscribe().Wait();
var updateBuilder=new ContainerBuilder();
updateBuilder.RegisterInstance(_endpointInstance)
.As().As().SingleInstance();
//NServiceBus目前没有解决此问题的方法。
//看https://github.com/Particular/NServiceBus/issues/4421
#pragma warning disable CS0618//类型或成员已过时
updateBuilder.Update(容器);
#pragma warning restore CS0618//类型或成员已过时
返回新的AutofacServiceProvider(容器);
}
私有静态void确保QLDatabaseExists(字符串连接字符串、ILogger记录器)
{
var builder=new-SqlConnectionStringBuilder(connectionString);
var originalCatalog=builder.InitialCatalog;
builder.InitialCatalog=“master”;
var masterConnectionString=builder.ConnectionString;
尝试
{
使用(var连接=新的SqlConnection(masterConnectionString))
{
connection.Open();
var command=connection.CreateCommand();
command.CommandText=
$“如果不存在(从sys.databases中选择*,其中name='{originalCatalog}')”+
$“创建数据库[{originalCatalog}];”;
command.ExecuteNonQuery();
}
}
捕获(SqlException)
{
//需要更好地处理这个问题。在本地,我们需要首先使用master。在Azure中,这是不可能的,也不是必需的
//TODO:使用已创建的数据库构建sql docker容器。
builder.InitialCatalog=originalCatalog;
masterConnectionString=builder.ConnectionString;
尝试
{
使用(var连接=新的SqlConnection(masterConnectionString))
{
connection.Open();
var command=connection.CreateCommand();
command.CommandText=
$“如果不存在(从sys.databases中选择*,其中name='{originalCatalog}')”+
$“创建数据库[{originalCatalog}];”;
command.ExecuteNonQuery();
}
}
捕获(SqlException innerException)