4

Web プロジェクトで使用する ServiceBus 実装として MassTransit を検討しています。

Request/Responseパターンで遊んでいますが、消費者がメッセージを受信して​​応答するまでに長い遅延が発生し、要求発行者が応答を処理します。場合によっては、応答がまったく返ってこないように見えることがあります (10 分間実行したままにしておくと、まだ応答が返されません)。応答でハンドル デリゲートが呼び出されるのを見たのは、30 秒のタイムアウト期間とタイムアウト例外がスローされた後だけです。この状況では、ハンドラー デリゲートに設定されたブレークポイントがヒットします。

セットアップは標準的なものです。Web アプリがコールバックで応答を処理するために、要求を発行する Web アプリ、要求を消費して応答を送信するコンソール アプリがあります。

Castle Windsor を使用しており、コンテナーは WebActivator を使用して Web プロジェクトで初期化されます。

[assembly: WebActivator.PreApplicationStartMethod(typeof(BootStrapper), "PreStart")]
[assembly: WebActivator.PostApplicationStartMethod(typeof(BootStrapper), "PostStart")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(BootStrapper), "Stop")]

namespace Web.App_Start
{
    public static class BootStrapper
    {
        internal static IWindsorContainer Container { get; private set; }

        public static void PreStart()
        {
            Container = new WindsorContainer().Install(FromAssembly.This());
        }

        public static void PostStart()
        {
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            ApiConfig.Configure(Container);
            MvcConfig.Configure(Container);
        }

        public static void Stop()
        {
            if (Container != null)
                Container.Dispose();
        }
    }
}

Web アプリ プロジェクト(ASP.NET Web API プロジェクト) では、MassTransit の WindsorInstaller は次のようになります。

public class MassTransitInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(AllTypes.FromThisAssembly().BasedOn<IConsumer>());

        var bus = ServiceBusFactory.New(configurator =>
        {
            configurator.UseMsmq();
            configurator.VerifyMsmqConfiguration();            
            configurator.UseMulticastSubscriptionClient();

            configurator.ReceiveFrom("msmq://localhost/web");

            configurator.EnableMessageTracing();
            configurator.Subscribe(x => x.LoadFrom(container));
        });

        container.Register(Component.For<IServiceBus>().Instance(bus));
    }
}

コンソール アプリ プロジェクトでは、WindsorInstaller は次のようになります。

public class MassTransitInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(AllTypes.FromAssemblyContaining<BasicRequestCommandHandler>().BasedOn<IConsumer>());

        var bus = ServiceBusFactory.New(configurator =>
        {
            configurator.UseMsmq();
            configurator.VerifyMsmqConfiguration();
            configurator.UseMulticastSubscriptionClient();

            configurator.ReceiveFrom("msmq://localhost/console");

            configurator.Subscribe(x => x.LoadFrom(container));
        });

        container.Register(Component.For<IServiceBus>().Instance(bus));
    }
}

私はApiController次のGETアクションメソッドを持っています

public class ExampleController : ApiController
{
    private readonly IServiceBus _bus;

    public HelloController(IServiceBus bus)
    {
        _bus = bus;
    }

    // GET api/hello?text={some text}
    public Task<IBasicResponseCommand> Get(string text)
    {
        var command = new BasicRequestCommand {Text = text};

        var tcs = new TaskCompletionSource<IBasicResponseCommand>();

        _bus.PublishRequest(command, c =>
        {
            c.Handle<IBasicResponseCommand>(r =>
            {
                tcs.SetResult(r);
            });
        });

        return tcs.Task;
    }
}

BasicRequestCommand と BasicResponseCommand は次のようになります

public interface IBasicRequestCommand
{
    Guid CorrelationId { get; set; }
    string Text { get; set; }
}

public class BasicRequestCommand :
    CorrelatedBy<Guid>, IBasicRequestCommand
{
    public Guid CorrelationId { get; set; }
    public string Text { get; set; }

    public BasicRequestCommand()
    {
        CorrelationId = Guid.NewGuid();
    }
}

public interface IBasicResponseCommand
{
    Guid CorrelationId { get; set; }
    string Text { get; set; }
}

public class BasicResponseCommand :
    CorrelatedBy<Guid>, IBasicResponseCommand
{
    public Guid CorrelationId { get; set; }
    public string Text { get; set; }
}

そして、コンソール アプリで BasicRequestCommand に応答するハンドラー:

public class BasicRequestCommandHandler : Consumes<IBasicRequestCommand>.Context
{
    public void Consume(IConsumeContext<IBasicRequestCommand> context)
    {
        Console.Out.WriteLine("received message text " + context.Message.Text);

        context.Respond(new BasicResponseCommand { Text = "Hello " + context.Message.Text, CorrelationId = context.Message.CorrelationId });
    }
}

このすべてをローカルで実行すると、要求/応答がせいぜい数秒程度になると予想していました。構成に何か不足していますか?

さらに、MassTransit を log4net に接続したいと考えました。Windsor の log4net ロギング機能を使用しており、web.config に log4net セクションがあります。これはILogger、Windsor によって提供される実装 (および NHibernate のログ) ではすべて正常に機能しますが、これをログに使用するように MassTransit を構成する方法がドキュメントから明らかではありません。何か案は?

4

3 に答える 3

4

Andrei Volkov と Chris PattersonがMassTransit の google group で議論していたように、この問題はMassTransit を usingに切り替えSynchronizationContextたことが原因のようですが、何らかの理由で期待どおりに動作しません。

当面の回避策の 1 つは、非同期 MassTransit リクエストに移行するか、問題のある を使用しない v2.1.1 に戻すことSynchronizationContextです。

(他の誰も最初にそれをしない場合は、後世のためにここにこの問題の更新を投稿します。)

于 2012-08-30T17:15:51.143 に答える
3

ASP.NET での要求/応答の応答タイムアウトの問題は、バージョン 2.6.2 で修正されています。 https://groups.google.com/d/topic/masstransit-discuss/oC1FOe6KsAU/discussion

于 2012-09-14T21:30:23.983 に答える
1

MultiCastSubscriptionClient を使用しているため、各マシンで呼び出す必要がありますSetNetwork(NETWORK_KEY)(NETWORK_KEY に同じ値を使用)。また、参加するすべてのマシンが同じサブネット上にある必要があります。http://masstransit.readthedocs.org/en/latest/overview/subscriptions.html#msmq-multicastのドキュメントを参照してください。

log4net を接続するには、使用しているバージョンによって異なりますが、最新バージョンでは、MassTransit.Log4NetIntegration アセンブリを含めてからcfg.UseLog4Net();、サービス バス構成を呼び出します。

それでも問題が解決しない場合は、MT メーリング リスト ( https://groups.google.com/forum/?fromgroups#!forum/masstransit-discuss ) に質問してください。

于 2012-08-15T16:29:05.020 に答える