<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    superwei

    導(dǎo)航

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    統(tǒng)計(jì)

    常用鏈接

    留言簿(4)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    Microsoft .Net Remoting系列專題之二:Marshal、Disconnect與生命周期以及跟蹤服務(wù)(轉(zhuǎn)載)

    Microsoft .Net Remoting系列專題之二 

    一、遠(yuǎn)程對(duì)象的激活

    在Remoting中有三種激活方式,一般的實(shí)現(xiàn)是通過(guò)RemotingServices類的靜態(tài)方法來(lái)完成。工作過(guò)程事實(shí)上是將該遠(yuǎn)程對(duì)象注冊(cè)到通道中。由于Remoting沒(méi)有提供與之對(duì)應(yīng)的Unregister方法來(lái)注銷遠(yuǎn)程對(duì)象,所以如果需要注冊(cè)/注銷指定對(duì)象,微軟推薦使用Marshal(一般譯為編組)和Disconnect配對(duì)使用。在《Net Remoting基礎(chǔ)篇》中我已經(jīng)談到:Marshal()方法是將MarshalByRefObject類對(duì)象轉(zhuǎn)化為ObjRef類對(duì)象,這個(gè)對(duì)象是存儲(chǔ)生成代理以與遠(yuǎn)程對(duì)象通訊所需的所有相關(guān)信息。這樣就可以將該實(shí)例序列化以便在應(yīng)用程序域之間以及通過(guò)網(wǎng)絡(luò)進(jìn)行傳輸,客戶端就可以調(diào)用了。而Disconnect()方法則將具體的實(shí)例對(duì)象從通道中斷開(kāi)。

    根據(jù)上述說(shuō)明,Marshal()方法對(duì)遠(yuǎn)程對(duì)象以引用方式進(jìn)行編組(Marshal-by-Reference,MBR),并將對(duì)象的代理信息放到通道中??蛻舳丝梢酝ㄟ^(guò)Activator.GetObject()來(lái)獲取。如果用戶要注銷該對(duì)象,則通過(guò)調(diào)用Disconnect()方法。那么這種方式對(duì)于編組的遠(yuǎn)程對(duì)象是否存在生命周期的管理呢?這就是本文所要描述的問(wèn)題。

    二、生命周期

    在CLR中,框架提供了GC(垃圾回收器)來(lái)管理內(nèi)存中對(duì)象的生命周期。同樣的,.Net Remoting使用了一種分布式垃圾回收,基于租用的形式來(lái)管理遠(yuǎn)程對(duì)象的生命周期。

    早期的DCOM對(duì)于對(duì)象生命周期的管理是通過(guò)ping和引用計(jì)數(shù)來(lái)確定對(duì)象何時(shí)應(yīng)當(dāng)作為垃圾回收。然而ping引起的網(wǎng)絡(luò)流量對(duì)分布式應(yīng)用程序的性能是一種痛苦的負(fù)擔(dān),它大大地影響了分布式處理的整體性能。.Net Remoting在每個(gè)應(yīng)用程序域中都引入一個(gè)租用管理器,為每個(gè)服務(wù)器端的SingleTon,或每個(gè)客戶端激活的遠(yuǎn)程對(duì)象保存著對(duì)租用對(duì)象的引用。(說(shuō)明:對(duì)于服務(wù)器端激活的SingleCall方式,由于它是無(wú)狀態(tài)的,對(duì)于每個(gè)激活的遠(yuǎn)程對(duì)象,都由CLR的GC來(lái)自動(dòng)回收,因此對(duì)于SingleCall模式激活的遠(yuǎn)程對(duì)象,不存在生命周期的管理。)

    1、租用

    租用是個(gè)封裝了TimeSpan值的對(duì)象,用以管理遠(yuǎn)程對(duì)象的生存期。在.Net Remoting中提供了定義租用功能的ILease接口。當(dāng)Remoting通過(guò)SingleTon模式或客戶端激活模式來(lái)激活遠(yuǎn)程對(duì)象時(shí),租用對(duì)象調(diào)用從System.MarshalByRefObject繼承的InitializeLifetimeService方法,向?qū)ο笳?qǐng)求租用。

    ILease接口定義了有關(guān)生命周期的屬性,均為T(mén)imeSpan值。如下:
    InitialLeaseTime:初始化有效時(shí)間,默認(rèn)值為300秒,如果為0,表示永不過(guò)期;
    RenewOnCallTime:調(diào)用遠(yuǎn)程對(duì)象一個(gè)方法時(shí)的租用更新時(shí)間,默認(rèn)值為120秒;
    SponsorshipTimeout:超時(shí)值,通知Sponsor(發(fā)起人)租用過(guò)期后,Remoting會(huì)等待的時(shí)間,默認(rèn)值為120秒;
    CurrentLeaseTime:當(dāng)前租用時(shí)間,首次獲得租用時(shí),為InitializeLeaseTime的值。

    Remoting的遠(yuǎn)程對(duì)象因?yàn)槔^承了MarshalByRefObject,因此默認(rèn)繼承了InitializeLifetimeService方法,那么租用的相關(guān)屬性為默認(rèn)值。如果要改變這些設(shè)置,可以在遠(yuǎn)程對(duì)象中重寫(xiě)該方法。例如:
     public override object InitializeLifetimeService()
     {
      ILease lease = (ILease)base.InitializeLifetimeService();
      if (lease.CurrentState == LeaseState.Initial)
      {
       lease.InitialLeaseTime = TimeSpan.FromMinutes(1);
       lease.RenewOnCallTime = TimeSpan.FromSeconds(20);
      }
      return lease;  
     }

    也可以忽略該方法,將對(duì)象的租用周期改變?yōu)闊o(wú)限:
     public override object InitializeLifetimeService()
     {
      return null;
     }

    2、租用管理器

    如果是前面所說(shuō)的租用主要是應(yīng)用在每個(gè)具體的遠(yuǎn)程對(duì)象上,那么租用管理器是服務(wù)器端專門(mén)用來(lái)管理遠(yuǎn)程對(duì)象生命周期的管理器,它維持著一個(gè)System.Hashtable成員,將租用映射為System.DateTime實(shí)例表示每個(gè)租用何時(shí)應(yīng)過(guò)期。Remoting采用輪詢的方式以一定的時(shí)間喚醒租用管理器,檢查每個(gè)租用是否過(guò)期。默認(rèn)為每10秒鐘喚醒一次。輪詢的間隔可以配置,如將輪詢間隔設(shè)置為5分鐘:LifetimeService.LeaseManagerPollTime = System.TimeSpan.FromMinutes(5);

    我們還可以在租用管理器中設(shè)置遠(yuǎn)程對(duì)象租用的屬性,如改變遠(yuǎn)程對(duì)象的初始有效時(shí)間為永久有效:
    LifetimeServices.LeaseTime = TimeSpan.Zero;

    我們也可以通過(guò)配置文件來(lái)設(shè)置生命周期,如:
    &lt;configuration&gt;
     &lt;system.runtime.remoting&gt;
      &lt;application name = "SimpleServer"&gt;
       &lt;lifetime leaseTime = "0" sponsorshipTimeOut = "1M" renewOnCallTime = "1M" pollTime = "30S"/&gt;       
      &lt;/application&gt;
     &lt;/system.runtime.remoting&gt;
    &lt;/configuration&gt;

    注:配置文件中的pollTime即為上面所說(shuō)的租用管理器的輪詢間隔時(shí)間LeaseManagerPollTime。

    租用管理器對(duì)于生命周期的設(shè)置是針對(duì)服務(wù)器上所有的遠(yuǎn)程對(duì)象。當(dāng)我們通過(guò)配置文件或租用管理器設(shè)置租用的屬性時(shí),所有遠(yuǎn)程對(duì)象的生命周期都遵循該設(shè)置,除非我們對(duì)于指定的遠(yuǎn)程對(duì)象通過(guò)重寫(xiě)InitializeLifetimeService方法,改變了相關(guān)配置。也就是說(shuō),遠(yuǎn)程對(duì)象的租用配置優(yōu)先級(jí)高于服務(wù)器端配置。

    3、發(fā)起人(Sponsor)

    發(fā)起人是針對(duì)客戶端而言的。遠(yuǎn)程對(duì)象就是發(fā)起人要租用的對(duì)象,發(fā)起人可以與服務(wù)器端簽訂租約,約定租用時(shí)間。一旦到期后,發(fā)起人還可以續(xù)租,就像現(xiàn)實(shí)生活中租方的契約,房東、租房者之間的關(guān)系一樣。

    在.Net Framework中的System.Runtime.Remoting.Lifetime命名空間中定義了ClientSponsor類,該類繼承了System.MarshalByRefObject,并實(shí)現(xiàn)了ISponsor接口。ClientSponsor類的屬性和方法,可以參考MSDN。

    客戶端要使用發(fā)起人機(jī)制,必須創(chuàng)建ClientSponsor類的一個(gè)實(shí)例。然后調(diào)用相關(guān)方法如Register()或Renewal()方法來(lái)注冊(cè)遠(yuǎn)程對(duì)象或延長(zhǎng)生命周期。如:
    RemotingObject obj = new RemotingObject();
    ClientSponsor sponsor = new ClientSponsor();
    sponsor.RenewalTime = TimeSpan.FromMinutes(2);
    sponsor.Register(obj);

    續(xù)租時(shí)間也可以在ClientSponsor的構(gòu)造函數(shù)中直接設(shè)置,如:
    ClientSponsor sponsor = new ClientSponsor(TimeSpan.FromMinutes(2));
    sponsor.Register(obj);

    我們也可以自己編寫(xiě)Sponsor來(lái)管理發(fā)起人機(jī)制,這個(gè)類必須繼承ClientSponsor并實(shí)現(xiàn)ISponsor接口。

    三、跟蹤服務(wù)

    如前所述,我們要判斷通過(guò)Marshal編組遠(yuǎn)程對(duì)象是否存在生命周期的管理。在Remoting中,可以通過(guò)跟蹤服務(wù)程序來(lái)監(jiān)視MBR對(duì)象的編組進(jìn)程。

    我們可以創(chuàng)建一個(gè)簡(jiǎn)單的跟蹤處理程序,該程序?qū)崿F(xiàn)接口ITrackingHandler。接口ITrackingHandler定義了3個(gè)方法,MarshalObject、UnmarshalObject和DisconnectedObject。當(dāng)遠(yuǎn)程對(duì)象被編組、解組和斷開(kāi)連接時(shí),就會(huì)調(diào)用相應(yīng)的方法。下面是該跟蹤處理類的代碼:public class MyTracking:ITrackingHandler
    {
     public MyTracking()
     {
      //
      // TODO: 在此處添加構(gòu)造函數(shù)邏輯
      //
     }

     public void MarshaledObject(object obj,ObjRef or)
     {
      Console.WriteLine();
      Console.WriteLine("對(duì)象" + obj.Tostring() + " is marshaled at " + DateTime.Now.ToShortTimeString());
     }

     public void UnmarshaledObject(object obj,ObjRef or)
     {
      Console.WriteLine();
      Console.WriteLine("對(duì)象" + obj.Tostring() + " is unmarshaled at " + DateTime.Now.ToShortTimeString());
     }

      public void DisconnectedObject(object obj)
     {
      Console.WriteLine(obj.ToString() + " is disconnected at " + DateTime.Now.ToShortTimeString());
     }
    }

    然后再服務(wù)器端創(chuàng)建該跟蹤處理類的實(shí)例,并注冊(cè)跟蹤服務(wù):
    TrackingServices.RegisterTrackingHandler(new MyTracking());

    四、測(cè)試

    1、建立兩個(gè)遠(yuǎn)程對(duì)象,并重寫(xiě)InitializeLifetimeService方法:

    對(duì)象一:AppService1
    初始生命周期:1分鐘

     public class AppService1:MarshalByRefObject
     {
      public void PrintString(string contents)
      {
       Console.WriteLine(contents);   
      }

      public override object InitializeLifetimeService()
      {
       ILease lease = (ILease)base.InitializeLifetimeService();
       if (lease.CurrentState == LeaseState.Initial)
       {
        lease.InitialLeaseTime = TimeSpan.FromMinutes(1);
        lease.RenewOnCallTime = TimeSpan.FromSeconds(20);
       }
       return lease;
       
      }
     }

    對(duì)象二:AppService2
    初始生命周期:3分鐘

     public class AppService2:MarshalByRefObject
     {
      public void PrintString(string contents)
      {
       Console.WriteLine(contents);   
      }

      public override object InitializeLifetimeService()
      {
       ILease lease = (ILease)base.InitializeLifetimeService();
       if (lease.CurrentState == LeaseState.Initial)
       {
        lease.InitialLeaseTime = TimeSpan.FromMinutes(3);
        lease.RenewOnCallTime = TimeSpan.FromSeconds(40);
       }
       return lease;
       
      }
     }

    為簡(jiǎn)便起見(jiàn),兩個(gè)對(duì)象的方法都一樣。

    2、服務(wù)器端

    (1) 首先建立如上的監(jiān)控處理類;

    (2) 注冊(cè)通道:
    TcpChannel channel = new TcpChannel(8080);
    ChannelServices.RegisterChannel(channel);

    (3) 設(shè)置租用管理器的初始租用時(shí)間為無(wú)限:
    LifetimeServices.LeaseTime = TimeSpan.Zero;

    (4) 創(chuàng)建該跟蹤處理類的實(shí)例,并注冊(cè)跟蹤服務(wù):
    TrackingServices.RegisterTrackingHandler(new MyTracking());

    (5) 編組兩個(gè)遠(yuǎn)程對(duì)象:
    ServerAS.AppService1 service1 = new ServerAS1.AppService1();
    ObjRef objRef1 = RemotingServices.Marshal((MarshalByRefObject)service1,"AppService1");

    ServerAS.AppService2 service2 = new ServerAS1.AppService2();
    ObjRef objRef2 = RemotingServices.Marshal((MarshalByRefObject)service2,"AppService2");

    (6) 使服務(wù)器端保持運(yùn)行:
    Console.WriteLine("Remoting服務(wù)啟動(dòng),按退出..."); 
    Console.ReadLine();

    3、客戶端

    通過(guò)Activator.GetObject()獲得兩個(gè)遠(yuǎn)程對(duì)象,并調(diào)用其方法PrintString。代碼略。

    4、運(yùn)行測(cè)試

    運(yùn)行服務(wù)器端和客戶端,由于監(jiān)控程序?qū)⒈O(jiān)視遠(yuǎn)程對(duì)象的編組進(jìn)程,因此在運(yùn)行開(kāi)始,就會(huì)顯示遠(yuǎn)程對(duì)象已經(jīng)被Marshal:

    然后再客戶端調(diào)用這兩個(gè)遠(yuǎn)程對(duì)象的PrintString方法,服務(wù)器端接受字符串:

    一分鐘后,遠(yuǎn)程對(duì)象一自動(dòng)被Disconnect:

    此時(shí)客戶端如要調(diào)用遠(yuǎn)程對(duì)象一,會(huì)拋出RemotingException異常;

    又一分鐘后,遠(yuǎn)程對(duì)象二被Disconnect了:

    align="center">

    用戶還可以根據(jù)這個(gè)代碼測(cè)試RenewOnCallTime的時(shí)間是否正確。也即是說(shuō),在對(duì)象還未被Disconnect時(shí),調(diào)用對(duì)象,則從調(diào)用對(duì)象的這一刻起,其生命周期不再是原來(lái)設(shè)定的初始有效時(shí)間值(InitialLeaseTime),而是租用更新時(shí)間值(RenewOnCallTime)。另外,如果這兩個(gè)遠(yuǎn)程對(duì)象沒(méi)有重寫(xiě)InitializeLifetimeService方法,則生命周期應(yīng)為租用管理器所設(shè)定的值,為永久有效(設(shè)置為0)。那么這兩個(gè)對(duì)象不會(huì)被自動(dòng)Disconnect,除非我們顯式指定關(guān)閉它的連接。當(dāng)然,如果我們顯式關(guān)閉連接,跟蹤程序仍然會(huì)監(jiān)視到它的變化,然后顯示出來(lái)。

    五、結(jié)論

    通過(guò)我們的測(cè)試,其實(shí)結(jié)論已經(jīng)很明顯了。通過(guò)Marshal編組的對(duì)象要受到租用的生命周期所控制。注意對(duì)象被Disconnect,并不是指這個(gè)對(duì)象被GC回收,而是指這個(gè)對(duì)象保存在通道的相關(guān)代理信息被斷開(kāi)了,而對(duì)象本身仍然在服務(wù)器端存在。

    所以我們通過(guò)Remoting提供服務(wù),應(yīng)根據(jù)實(shí)際情況指定遠(yuǎn)程對(duì)象的生命周期,如果不指定,則為Remoting默認(rèn)的設(shè)定。要讓所有的遠(yuǎn)程對(duì)象永久有效,可以通過(guò)配置文件或租用管理器將初始有效時(shí)間設(shè)為0。

    posted on 2007-05-08 12:03 小辭猬 閱讀(211) 評(píng)論(0)  編輯  收藏 所屬分類: DoNet

    主站蜘蛛池模板: 99免费视频观看| 亚洲国产区男人本色在线观看| 欧美日韩国产免费一区二区三区| 国产线视频精品免费观看视频| 亚洲精品无码国产片| 久久精品国产亚洲AV嫖农村妇女| 亚洲另类少妇17p| 国产精品视频免费一区二区三区| 免费观看黄色的网站| 日韩精品无码免费一区二区三区| 9久热这里只有精品免费| 免费无遮挡无码视频在线观看| 亚洲日产乱码一二三区别| 亚洲国产精品线观看不卡| 亚洲成人在线电影| 亚洲成A人片在线观看WWW| 久久精品国产精品亚洲人人 | 免费黄色小视频网站| 成视频年人黄网站免费视频| 老汉精品免费AV在线播放| 国产精品免费AV片在线观看| 免费无码又爽又刺激一高潮| 中文字幕成人免费高清在线| 一级毛片免费在线播放| 小说专区亚洲春色校园| 精品免费AV一区二区三区| 国产精品亚洲精品日韩动图| 亚洲av无码专区在线观看下载 | 又黄又爽又成人免费视频| 伊人久久免费视频| 一级毛片不卡片免费观看| 国产成人精品一区二区三区免费| 91在线免费观看| 日本视频免费高清一本18| 人妻无码一区二区三区免费| 免费无遮挡无码永久视频| www.免费在线观看| 中文字幕无码免费久久99| 免费观看的a级毛片的网站| 日本免费一区二区三区最新vr| 国产成人免费片在线视频观看|