`
jiq408694711
  • 浏览: 33641 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

Shuttle Bus之Request/Response模式简单示例

 
阅读更多

创建类库工程RequestResponse.Messages:

namespace RequestResponse.Messages
{
    public class MyMessage 
    {
        public string Text { get; set; }
    }
}

创建类库工程RequestResponse.Server:

using System;
using log4net;
using log4net.Config;
using Shuttle.Core.Host;
using Shuttle.Core.Infrastructure;
using Shuttle.Core.Infrastructure.Log4Net;
using Shuttle.ESB.Core;
using Shuttle.ESB.Modules.ActiveTimeRange;

namespace RequestResponse.Server
{
	public class ServiceBusHost : IHost, IDisposable
	{
		private static IServiceBus bus;

		public void Start()
		{
			Log.Assign(new Log4NetLog(LogManager.GetLogger(typeof(ServiceBusHost))));

			bus = ServiceBus.Create().Start();

            Console.WriteLine("#########server-end bus instance has started");
		}

		public void Dispose()
		{
			bus.Dispose();
			LogManager.Shutdown();
		}
	}
}

  

using System;
using System.Text;
using RequestResponse.Messages;
using Shuttle.Core.Infrastructure;
using Shuttle.ESB.Core;

namespace RequestResponse.Server
{
    public class ServerMessageHandler : IMessageHandler<MyMessage>
	{
		private int received;

        public void ProcessMessage(HandlerContext<MyMessage> context)
		{
            //服务器端接受到消息
            Console.WriteLine("【SERVER-END RECEIVE A MSG,Content:"+ context.Message.Text+ "】");
           
            //服务器端发送回应消息
			context.Bus.SendReply(new MyMessage
					{
						Text = "I have recwived your msg"
					});
		}

        public bool IsReusable
        {
            get { return true; }
        }
	}
}

 

<?xml version="1.0"?>
<configuration>
	<configSections>
		<section name="serviceBus" type="Shuttle.ESB.Core.ServiceBusSection, Shuttle.ESB.Core"/>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
	</configSections>

	<serviceBus>
    <control workQueueUri="msmq://./requestresponse-server-control-inbox-work" errorQueueUri="msmq://./shuttle-samples-error" durationToSleepWhenIdle="250ms*25,500ms*10,1s" threadCount="1"/>
    <inbox workQueueUri="msmq://./requestresponse-server-inbox-work" errorQueueUri="msmq://./shuttle-samples-error" durationToSleepWhenIdle="250ms,1s" durationToIgnoreOnFailure="1s" threadCount="1"/>
	</serviceBus>

  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p %c - %m%n"/>
      </layout>
    </appender>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="logs\request-response-server"/>
      <appendToFile value="true"/>
      <rollingStyle value="Date"/>
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="100000KB"/>
      <datePattern value="-yyyyMMdd.'log'"/>
      <param name="StaticLogFileName" value="false"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p %c - %m%n"/>
      </layout>
    </appender>
    <root>
      <level value="TRACE"/>
      <appender-ref ref="ConsoleAppender"/>
      <appender-ref ref="RollingFileAppender"/>
    </root>
  </log4net>

<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

   创建控制台应用程序RequestResponse.Client:

using System;
using log4net;
using RequestResponse.Messages;
using Shuttle.Core.Infrastructure;
using Shuttle.Core.Infrastructure.Log4Net;
using Shuttle.ESB.Core;

namespace RequestResponse.Client
{
	internal class Program
	{
		private static void Main()
		{
            Log.Assign(new Log4NetLog(LogManager.GetLogger(typeof(Program))));

			var bus = ServiceBus.Create().Start();

            Console.WriteLine("###### Client bus started. Press CTRL+C to stop.");
            Console.WriteLine();
			Console.WriteLine("@Press enter to send a message to the server.");
			Console.WriteLine();

            while (true)
            {
                Console.ReadLine();
                //将消息发送出去
                bus.Send(new MyMessage{Text = "Client Massage"});
            }
		}
	}
}

  

using System;
using RequestResponse.Messages;
using Shuttle.Core.Infrastructure;
using Shuttle.ESB.Core;

namespace RequestResponse.Client
{
    public class ClientMessageHandler : IMessageHandler<MyMessage>
    {
		public void ProcessMessage(HandlerContext<MyMessage> context)
    	{
            //客户端接收到消息
            Console.WriteLine("【Client-END RECEIVE A MSG, Content:"+ context.Message.Text +"】");
		}

        public bool IsReusable
        {
            get { return true; }
        }
    }
}
<?xml version="1.0"?>
<configuration>
	<configSections>
		<section name="serviceBus" type="Shuttle.ESB.Core.ServiceBusSection, Shuttle.ESB.Core"/>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>

  <serviceBus>
		<messageRoutes>
			<messageRoute uri="msmq://./requestresponse-server-inbox-work">
				<add specification="StartsWith" value="RequestResponse"/>
			</messageRoute>
		</messageRoutes>
		<inbox workQueueUri="msmq://./requestresponse-client-inbox-work" journalQueueUri="msmq://./requestresponse-client-inbox-journal" errorQueueUri="msmq://./shuttle-samples-error"/>
		<outbox workQueueUri="msmq://./requestresponse-client-outbox-work" errorQueueUri="msmq://./shuttle-samples-error"/>
	</serviceBus>

  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p %c - %m%n"/>
      </layout>
    </appender>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="logs\request-response-server"/>
      <appendToFile value="true"/>
      <rollingStyle value="Date"/>
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="100000KB"/>
      <datePattern value="-yyyyMMdd.'log'"/>
      <param name="StaticLogFileName" value="false"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p %c - %m%n"/>
      </layout>
    </appender>
    <root>
      <level value="TRACE"/>
      <appender-ref ref="ConsoleAppender"/>
      <appender-ref ref="RollingFileAppender"/>
    </root>
  </log4net>

<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

  一切就绪。

然后设置解决方案的启动顺序,将server放在client前面。

然后右击项目RequestResponse.Server,生成,再右击其属性,在启动外部程序中选择host.exe

然后便可以运行这个解决方案了。

三个问题:

1 内部运行原理?

2 适用场景?

If there is one thing that a service bus should never be used for it is querying. A service bus is geared towards instructing systems what to do (command message); notifying systems of events that have taken place using a publish / subscribe mechanism (event message); and, less frequently, transferring data (document message).

It is perfectly valid to send a command to a system to perform some calculation. The result could then be stored a result store and a notification sent that the calculation has been completed. This is quite different from sending a request for data.

Autonomous Components

With any system it is advisable to isolate tasks and decouple them. In this way each can be implemented independently and versioned independently. By using a specific endpoint / queue to handle a particular message type you have the ability to send a relevant message for processing at any time.

For example, in a tightly-coupled system you may have a process that registers a new user. So after gathering the user information from some front-end the information is submitted for processing:

  • check if the user is blacklisted
  • register the user in the database
  • send an activation e-mail


If this is done in a synchronous fashion the user presses thesubmitbutton and waits. Let's assume our mail server has gone down. Now the user cannot register. What's more is that sending e-mail by using our shared smtp server takes a couple of seconds so during periods of heavy traffic this process takes quite some time.

We could change this process to gather the user information from the front-end and submit it for registration by sending aRegisterUserCommandto our user service. The call returns immediately informing the user that there registration request has been received and they will be contact with the result via e-mail. Now our process will be as follows (autonomous components indicated byAC):

  • User Registration Service (AC) - handlesRegisterUserCommand
    • check blacklisting
      • if user blacklisted sendSendEMailCommandto then e-mail service (AC) to notify user that the details provided (user name / e-mail address / contact numbers) have been blacklisted.
      • if not blacklisted register user in database and sendSendEMailCommandto the e-mail server (AC) and publishesUserRegisteredEvent.
  • E-Mail Service (AC) - handlesSendEMailCommand
    • sends the requested e-mail via our smtp server; if the server is down the message will simply be retried until it goes through
  • CRM User Registration Service (AC) - subscribes toUserRegisteredEvent
    • registers the new user in our CRM


In this way each component can be developed, versioned, and deployed in isolation. Stopping any of the services for deployment would not result in any process breaking since the queues will continue receiving work. Even if the entire machine is brought down Shuttle ESB will still store message on the sending machine when using anoutbox.

3 与MSMQ In WCF的异同?

Web Services / WCF

Some may argue that they use web services and therefore have a service oriented architecture. They would be correct in that they have exposed a service of some sort. There are however many properties of a SOA that are not present when using only web services:

  • Noevent driven architecture(EDA)
    • WS / WCF cannot subscribe to events
  • No durability of messages
    • A message goes across the wire and is not stored anywhere
  • No recoverability
    • Once a message is lost it is gone
  • No lowtemporal coupling
    • A WS must be running in order to invoke it
  • No lowbehavioural coupling
    • We have to know what the service will do in order to invoke it
  • Nomessage routing
    • We send messages to a specific WS to invoke some action
  • No queuing
    • Calls are synchronous and blocking


These are not necessarily bad but do represent some of the properties of a WS.

This does not mean that web services have no place in a SOA. In fact, there are instances where we definitely need them. For external integration they are fine; serving as an entry point into our systems.

这里是NServiceBus与WCF的对比:http://support.nservicebus.com/customer/portal/articles/861164-nservicebus-and-wcf

(转载请注明出处)

分享到:
评论

相关推荐

    Shuttle ESB 入门实例

    本实例,使用ShuttleESB完成简单的功能。 主要功能就是:从客户端发送消息,服务端接收。 实例简单,且含源代码。 这是本实例中,项目介绍: QuickStart.Shuttle.Client:客户端 QuickStart.Shuttle.Messages:...

    微信小程序开发初体验项目-用于BJTU周末shuttle bus预定

    wxtour为前端部分,由微信开发客户端上传。 其余部分上传至服务器**(https)**即可。 初步测试在CentOS+Nginx+Mysql+PHP(腾讯云小程序解决方案)的环境下成功

    小程序-北京交通大学BJTU周末shuttle bus预定-PHP后端.rar

    本项目为一款基于PHP后端的小程序——北京交通大学BJTU周末班车预定系统,旨在解决校园内师生周末出行需求,提高班车使用效率。 项目功能介绍: ... 2. 班车信息展示:系统提供详细的班车时刻表、路线及座位数等信息,...

    Shuttle Pub Sub

    Shuttle ESB中发布订阅模式的实例介绍。功能如下: 从消息发布端Pub发布一个消息事件OrderCompletedEvent,多个客户端(如SubA和SubB)订阅该事件OrderCompletedEvent。那么当Pub发布消息后,SubA和SubB就能够收到...

    swift-Shuttle一个用于macOS的简单SSH快捷菜单

    Shuttle 一个用于macOS的简单SSH快捷菜单

    Shuttle Pro2控制手轮驱动

    Shuttle Pro2控制手轮驱动,将配置文件应用到当前的延时文件的EXE上

    欧拉公式求圆周率的matlab代码-FlightGear-Space-Shuttle-Simulation:基于MATLAB/Simulink

    欧拉公式求长期率的matlab代码FlightGear-Space-Shuttle模拟 基于MATLAB / Simulink和FlightGear的航天飞机基于真实推力数据进行发射模拟。 这是对NASA航天飞机升空80公里的模拟。 它是用MATLAB和FlightGear编写的 ...

    【JavaScript源代码】vue3+typeScript穿梭框的实现示例.docx

    vue3+typeScript穿梭框的实现示例  实现功能:模仿element穿梭框的简单功能 每周分享一个vue3+typeScript的小组件,我只想分享下自己的实现思路,楼主是个菜鸡前端,记录下实现过程,说不定对你有帮助。 预览地址...

    shuttle-cli:Shuttle SSH管理器的命令行客户端

    它会读取您的默认shuttle.json文件,并为您提供一个CLI界面。 实际上,它也不需要Shuttle客户端。 您所需要的只是homefolder中的有效.shuttle.json文件。 $ shuttle +--------+----------------------------------...

    shuttle.cpp

    NOIP2018T3

    Shuttle.Esb:高度可扩展的服务总线实施

    概述启动一个新的Console Application项目,然后从[支持的队列]({{site.baseurl}} / packages /#queues)中选择一个Shuttle.Esb队列实现: Install-Package Shuttle.Esb.Msmq 现在,我们需要选择一个: Install-...

    shuttle-cloud:Shuttle基于Spring Cloud的分布式实现

    项目介绍shuttle-cloud是项目基于Spring Cloud的分布式实现,采用了Spring Cloud Eureka , Spring Cloud Config , Spring Boot Admin , Spring Cloud Gateway , Spring Cloud OpenFeign , Docker等核心技术,...

    shuttle:Shuttle是用于测试并发Rust代码的库

    Shuttle是用于测试并发Rust代码的库。 它是许多随机并发测试技术的实现,包括。 入门 考虑以下简单的并发代码: use std :: sync :: {Arc, Mutex}; use std :: thread; let lock = Arc :: new (Mutex :: new ( 0u...

    Space Shuttle_space_HomeHome_

    Space Shuttle for home use

    pytorch_lstm-shuttle:LSTM-Shuttle的PyTorch实现

    LSTM-Shuttle的PyTorch实现 | 概述 LSTM-Shuttle是“” 和在自然语言处理的经验方法会议( EMNLP )2018中(长期) LSTM-Shuttle不仅向前读取穿梭内容,而且向后走。 向前穿梭可提高效率,向后穿梭可使模型有机会...

    Shuttle 是一个用于测试并发 Rust 代码的库

    穿梭Shuttle 是一个用于测试并发 Rust 代码的库。它是许多随机并发测试技术的实现,包括具有发现错误概率保证的随机调度程序。入门考虑这段简单的并发代码:use std:: sync:: {Arc, Mutex};use std:: thread;let ...

    shuttle:简约的部署工具

    Shuttle是用于小型应用程序和单服务器部署的简约应用程序部署工具。 配置存储为YAML编码文件,无需使用ruby代码。 在与目标服务器的SSH连接上执行操作。 安装 从Rubygems安装: gem install shuttle-deploy 或手动...

    高中英语单词天天记shuttle素材

    高中英语单词天天记shuttle素材

    Android-Shuttle.zip

    Android-Shuttle.zip,穿梭音乐播放器,安卓系统是谷歌在2008年设计和制造的。操作系统主要写在爪哇,C和C 的核心组件。它是在linux内核之上构建的,具有安全性优势。

    SHUTTLE_MOD_LIVEFIXED_sign.apk

    SHUTTLE_MOD_LIVEFIXED_sign.apk

Global site tag (gtag.js) - Google Analytics