Publisher/subscriber Subscription-Release mode

Source: Internet
Author: User

Publisher/subscriber Subscription-Release mode

The follow-up will continue to collate some of these years to do some of the pre-research demo, and some of the leading-edge technology, with everyone to study technology and common progress.

There are many ways to implement a publish subscription, the following is mainly about the publication of the subscription in WCF, the main reference book "Programming WCF Services", gossip not much to get to the point. There are many drawbacks to using the traditional duplex callback (example http://www.cnblogs.com/artech/archive/2007/03/02/661969.html) to implement the publish subscription pattern, the main problem is that It introduces a high degree of coupling between publishers and subscribers. Subscribers must know where the publisher is before they can subscribe, and any service that the Subscriber does not know will not be able to notify the subscriber of the event, and it is difficult to add a new subscriber to the deployed application (or to remove an already existing subscriber). Roughly the same is the fact that the Publisher can only send notification messages to subscribers it knows, and publishers also need to manage the list of subscribers, which are unrelated to the business service, which adds to the complexity of the publisher, as well as the fact that there is a coupling between the Subscriber and the Publisher in terms of security, and when the publisher process goes down, All subscriptions will be lost.

The most common solution to solve the problems mentioned above is the publish-subscribe mode (publish-subscribe "OBSERVER"), as shown in D-1.

The Subscriber is distinguished as a temporary subscriber and a persistent subscriber, the persistent subscriber can be saved to disk, when the event is triggered to notify subscribers, it is also convenient to use the callback mechanism through the delivery callback, for the persistent subscribers, the Subscriber address needs to be recorded, when the event is triggered, the publishing service will invoke the persistent subscriber address, The event is then passed, because the persistent subscriber saves the Subscriber address to the database or disk, which improves manageability when the publishing service goes down.

The above main introduction theory, the following into the practice phase, first download Servicemodelex (programming WCF Services inside the book author provides simplified WCF programming dynamic Library), Https://github.com/CaseyBurns /servicemodelex, we do not need service bus for the time being, so we introduce Servicemodelex (. NET 4.0 no service bus), build a test server (here for the convenience of testing using GUI application as host), client.

Manage temporary subscriptions

Example D-1 managing a temporary subscriber by using the ISubscriptionService interface provided by Servicemodelex

   [ServiceContract]   Public interface ISubscriptionService   {      [operationcontract]      void Subscribe (string eventoperation);      [OperationContract]      void unsubscribe (string eventoperation);   }

As a generic interface, it does not care about the callback contract, and then adds a temporary subscriber contract that inherits the common interface and sets the callback contract

    [ServiceContract (callbackcontract = typeof (Imyevents))]    Public interface Imysubscriptionservice:isubscriptionservice    {    }

Callback Contract

    [ServiceContract]    Public interface imyevents    {        [OperationContract (IsOneWay = true)]        void OnEvent1 ();        [OperationContract (IsOneWay = true)]        void OnEvent2 (int number);        [OperationContract (IsOneWay = true)]        void OnEvent3 (int number, string text);    }

Implement a temporary subscription service.

    [ServiceBehavior (InstanceContextMode = instancecontextmode.percall)]    public class Mysubscriptionservice:subscriptionmanager<imyevents>, IMySubscriptionService, IPersistentSubscriptionService    {           }

Here are a few things to note: The service type must be a session service (InstanceContextMode = Instancecontextmode.percall), the session service is able to use callbacks, and the class in Servicemodelex Subscriptionmanager<t> has implemented the Add subscriber and unsubscribe interface defined by the common interface, so there is no need for us to write any more code. IPersistentSubscriptionService as a persistent subscriber interface,subscriptionmanager<t> also implements the interface, which is discussed next.

Configuration file configuration Publish subscriber Service

  <system.serviceModel> <servicehostingenvironment multiplesitebindingsenabled= "true"/> <bindings&gt      ; <netTcpBinding> <binding name= "Nettcpbinding_iservice1" receivetimeout= "00:25:00" maxbuffersize= " 2147483647 "maxreceivedmessagesize=" 2147483647 "transactionflow=" true "> <reliablesession inactivityTimeout= "00:25:00" enabled= "true"/> <security mode= "None"/> </binding> </nettcpbinding&gt    ; </bindings> <services> <service behaviorconfiguration= "Mybehavior" Name= "Service.sub.MySubscription Service > 

Where the Service.pub.MyPublishService service is configured for the Publisher service is described next.

This allows the temporary subscribers to implement, followed by the persistent subscribers. The common interface for persistent subscribers uses the IPersistentSubscriptionService defined in Servicemodelex

   [ServiceContract] public interface IPersistentSubscriptionService {[OperationContract (Name = "subscribepersis Tent ")] [TransactionFlow (transactionflowoption.allowed)] void Subscribe (String address,string eventscontract,str      ing eventoperation);      [OperationContract (Name = "unsubscribepersistent")] [TransactionFlow (transactionflowoption.allowed)] void unsubscribe (string address,string eventscontract,string      Eventoperation);      [OperationContract]      [TransactionFlow (transactionflowoption.allowed)]      Persistentsubscription[] Getallsubscribers ();      [OperationContract]      [TransactionFlow (transactionflowoption.allowed)]      Persistentsubscription[] Getsubscriberstocontract (string eventscontract);      [OperationContract] [TransactionFlow (transactionflowoption.allowed)] string[] Getsubscriberstocontracteventtype (String eventsContract      , string eventoperation);      [OperationContract]  [TransactionFlow (transactionflowoption.allowed)]    Persistentsubscription[] Getallsubscribersfromaddress (string address); }

Here I added the Add subscription method to [OperationContract (Name = "subscribepersistent")] to rename, To differentiate the Subscribe method of the temporary subscription interface. Persistent subscriptions do not require a callback function, and the next implementation of a durable subscription is as simple as the code above, and the subscriptionmanager<t> in Servicemodelex The IPersistentSubscriptionService interface has also been implemented so that a temporary subscription is completed with a persistent subscription, followed by the publish service.

The Publishing service should support the same event contract as the subscription service, which is the only connection point for the subscription service and the Publishing Service, using imyevents as an example, and Servicemodelex provides help classes for simplifying the publishing service publishservice<t>

    [ServiceBehavior (InstanceContextMode = instancecontextmode.percall)]    public class Mypublishservice:publishservice<imyevents>, imyevents    {public        void OnEvent1 ()        {            FireEvent ();        }        public void OnEvent2 (int number)        {            FireEvent (number);        }        public void OnEvent3 (int number, string text)        {            FireEvent (number, text);        }    }

where FireEvent () is used as an event that fires all subscribers, whether temporary or persistent, the Help class publishservice<t> has implemented and then configures the publishing service

      <service behaviorconfiguration= "Mybehavior" name= "Service.pub.MyPublishService" >        

This completes the publishing service, and using the GUI application as the host, you can use servicehost<t> as the published helper class in Servicemodelex.

    Public partial class Form1:form {public Form1 () {InitializeComponent ();        } servicehost<mypublishservice> hostpub = new servicehost<mypublishservice> ();         Servicehost<mysubscriptionservice> host = new servicehost<mysubscriptionservice> (); private void Form1_Load (object sender, EventArgs e) {try {host.                Enablemetadataexchange (); Host.                Open ();                Hostpub.enablemetadataexchange ();            Hostpub.open ();            } catch (Exception ex) {throw;            }} private void Form1_formclosed (object sender, Formclosedeventargs e) {try {host.}            Close (); } catch (Exception) {try {host.                Abort ();           } catch (Exception)     {}} try {hostpub.close ();                } catch (Exception) {try {hostpub.abort (); } catch (Exception) {}}}}

Where host. Enablemetadataexchange (); can help to publish metadata, do not need to configure the configuration, the service is configured to look at the client to use,

The client can add the service reference directly to the build service proxy, but generally I prefer to use the Svcutil tool to generate the proxy, or simply use the channel directly for service invocation, which is much more my favorite because it is more powerful and concise in code reading. Example of stealing the lazy, directly add the service reference, and then use the channel to invoke the service, so left the point to copy the configuration or interface, so see the example do not feel strange, all because lazy caused, nonsense not to say, next see temporary subscription client call

        Duplexchannelfactory<imysubscriptionservice, imysubscriptionservicecallback> channelFactory = null;        IMySubscriptionService proxy = null;        private void Btnsub_click (object sender, EventArgs e)        {            Myeventscallback callBack = new Myeventscallback ();            Callback.onresultevent + = callback_onresultevent;            instancecontext<imysubscriptionservicecallback> InstanceContext = new instancecontext< Imysubscriptionservicecallback> (callBack);            ChannelFactory = new Duplexchannelfactory<imysubscriptionservice, imysubscriptionservicecallback> ( InstanceContext, "Sub");            Proxy = Channelfactory.createchannel ();            Proxy. Subscribe (null);        }

Here, Myeventscallback implements the callback interface using the Duplexchannelfactory<t,c> type-safe bidirectional channel class that is provided in Servicemodelex to implement the following:

    Internal class Myeventscallback:imysubscriptionservicecallback {SynchronizationContext sc = Synchronizati        Oncontext.current;        public event eventhandler<eventscallbackargs> Onresultevent; public void OnEvent1 () {SC. Post (Result = = {Eventscallbackargs E = new Eventscallbackargs () {MSG = string.                Concat ("OnEvent1", System.Environment.NewLine)};            E.raise (this, ref onresultevent);        }, NULL); } public void OnEvent2 (int number) {SC. Post (Result = = {Eventscallbackargs E = new Eventscallbackargs () {MSG = string.                Concat ("OnEvent2:", Number, System.Environment.NewLine)};            E.raise (this, ref onresultevent);        }, NULL); The public void OnEvent3 (int number, string text) {SC. Post (Result = = {Eventscallbackargs E = new Eventscallbackargs () {MSG = string.                Concat ("OnEvent3:", Number, "text:", text + System.Environment.NewLine)};            E.raise (this, ref onresultevent);        }, NULL); }    }
    public static class Eventargextensions    {public        static void Raise<teventargs> (this Teventargs e, Object sender, ref eventhandler<teventargs> eventdelegate) where Teventargs:eventargs        {            eventhandler< teventargs> temp = Interlocked.compareexchange (ref eventdelegate, NULL, NULL);            if (temp! = null) Temp (sender, E);}    }

The SynchronizationContext context provides the Post method call GUI thread update ui,e.raise uses the extension to invoke the event in a thread-safe manner, and the client calls the Subscriber to finish, don't forget to close the agent, then look at the client call publisher

Client Invoke Publishing Service:

  Public partial class Pubmessageform:form {public Pubmessageform () {InitializeComponent ()        ;        } channelfactory<imyevents> channelfactory = null;        Imyevents proxy = null; private void Btnstartpub_click (object sender, EventArgs e) {channelfactory = new Channelfactory<imye            Vents> ("pubmyevents");        Proxy = Channelfactory.createchannel ();                 private void Pubmessageform_formclosed (object sender, Formclosedeventargs e) {try {            using (proxy as IDisposable) {} channelfactory.close ();            } catch {Channelfactory.abort (); }} private void Btnpub_click (object sender, EventArgs e) {proxy.        OnEvent1 (); private void Btnpub2_click (object sender, EventArgs e) {proxy.        OnEvent2 (2); }        private void Btnpub3_click (object sender, EventArgs e) {proxy.        OnEvent3 (3, Txtpubmessage.text); private void Pubmessageform_load (object sender, EventArgs e) {}}

Invoking the Publishing service using the Channelfactory<t> channel

This enables the WCF Publishing subscription service to complete, and if the Publishing Service or subscription service does not require synchronous binding, consider using MSMQ so that the publish-subscribe model has the advantage of a loosely coupled and disconnected system.

It is important to note that the queued publishing-subscription service does not support temporary subscriptions and requires a durable subscription, which is not much to be said, and can also be combined with the service discovery to implement a different mode of the publish-subscribe model, in particular, refer to the book "Programming WCF Services".

Demo Download http://files.cnblogs.com/files/skystar/Demo.7z

The book has its own gold house, the book has its own Yanruyu

Publisher/subscriber Subscription-Release mode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.