ceturtdiena, 2011. gada 3. novembris

Service Broker: aktivizācija

SQL Server Service Broker (SB) servisi savā starpā apmainās ar ziņojumiem. Pirms apstrādes saņemtie ziņojumi tiek glabāti servisa rindā (katram SB servisam atbilst rinda). Savukārt ziņojumu apstrādes procedūra var tikt automātiski aktivizēta.

Iepriekšējā rakstā (Service Broker: asinhrons trigeris) tiek izmantota iekšējā (internal) aktivizācija. Tādējādi tiek nodrošināts, ka tūlīt pēc ziņojuma saņemšanas tiek aktivizēta ziņojumu apstrādes procedūra.

Realitātē aktivizācijas mehānismu var neizmantot vispār. tādā gadījumā ziņojumu apstrāde notiks tikai tad, kad tiks izsaukta Recieve komanda. Kam tas vajadzīgs? Piemēram, ja ziņojumu apstrāde patērē daudz sistēmas resursu un to vēlamies darīt pa nakti.

Ja izmanto aktivizācijas mehānismu (msdn par aktivizāciju), tad izšķir divus veidus-
  • iekšējā (internal) aktivizācija
  • ārējā (external) aktivizācija. 
 Bet no sākuma- par SB darbu neizmantojot aktivizāciju.

Neizmantojot aktivizāciju
Svarīgākais- aktivizāciju neizmanto gadījumos, ja vajag apstrādāt ziņojumus vēlāk. Ziņojumu apstrādi var veikt tad, kad nepieciešams- piemēram, izmantojot SQL Server Agent un ieplānojot rindu apstrādi nakts laikā.

Lai ilustrētu SB servisu darbu bez aktivizācijas mehānisma, izmantošu jau iepriekš aprakstīto asinhrono trigieri (Service Broker: asinhrons trigeris). Tātad pieņemu, ka datu bāzē ir palaisti skripti no attiecīgā raksta un ir priekšstats ko aprakstītie servisi dara.

Kā jau minēju, rakstā tiek izmantota iekšējā aktivizācija. Lai to atslēgtu, jāizpilda šis skripts:
ALTER QUEUE dbo.MyTableQueue
    WITH ACTIVATION
    (
        STATUS=OFF
    )
ALTER QUEUE dbo.ProcessQueue
    WITH ACTIVATION
    (
        STATUS=OFF
    )
Pēc skripta izpildes, abām rindām tiek atslēgta aktivizācija. Ziņojumu sūtīšana joprojām notiek (trigerī), tomēr par saņemto ziņojumu apstrādi ir jārūpējas savādākā veidā (atkarībā no situācijas izlemjam kādā tieši).

Ievietojam rindu tabulā:
Insert Into MyTable(Number) Values(101)
Līdz ar rindas ievietošanu, trigerī tiek nosūtīts ziņojums servisam "ProcessService". Bet ziņojums netiek apstrādāts, tādēļ tas tiek uzglabāts rindā- "ProcessQueue" (par rindu monitoringu vairāk rakstā Service Broker: rindu monitorings):

Tātad- serviss ziņojumu ir saņēmis, bet nav apstrādājis.

Apstrādāsim ziņojumu manuāli izsaucot ziņojumu apstrādes procedūru manuāli:
Exec dbo.sb_ProcessService
Procedūras izpildes laikā, ziņojums tiek saņemts un apstrādāts, kā arī tiek nosūtīts ziņojums izsaucēja servisam par to, ka apstrāde ir pabeigta. Tādā veidā "ProcessQueue" vairāk nesatur ziņojumus, bet "MyTableQueue" satur divus ziņojumus- vienu atbildes ziņojumu un otru, ka "ProcessSercvice" savu darbu ir beidzis:

Pēc tam izsaucam "MyTableService" ziņojumu apstrādes procedūru:
Exec dbo.sb_MyTableService
Pēc procedūras izpildes, tabulā tiks aizpildīts "DateProcessed" laiks un nomainīti rindu statusi.

Iekšējā (internal) aktivizācija
Svarīgākais: iekšējā aktivizācija nodrošina SQL Server procedūras palaišanu gadījumā, ja ir ziņojums/ziņojumi kas jāapstrādā (msdn precīzi nosacījumi). Var tik aktivizēta viena vai vairākas SQL procedūras vienlaicīgi (SB nodrošina, ka katra procedūra apstrādā savus rindu elementus un savā starpā nekonfliktē). Jāvērš uzmanība, ka norāda maksimālo aktivizācijas procedūru skaitu- tātad, saņemot vienu ziņojumu tiks aktivizēta viena rindas apstrādes procedūra. Saņemot daudzus ziņojumus, procedūras tiks izsauktas pēc vajadzības- lai līdz galam izprastu ir jāsaprot msdn precīzi aprakstītie nosacījumi, kad notiek procedūru aktivizācija.

Lai ilustrētu SB servisu darbu ar iekšējo aktivizācijas mehānismu, izmantošu jau iepriekš aprakstīto asinhrono trigieri (Service Broker: asinhrons trigeris). Šajā rakstā katrai SB servisa rindai tika norādīta aktivizācijas procedūra un tas, ka pie nepieciešamības šo procedūru jāizsauc, ne vairāk kā vienu vienlaicīgi.

Šeit mainīšu nosacījumus- sūtītāja servisa rindas aktivizācijas procesu neaiztikšu, savukārt saņēmēja SB servisa rindai norādīšu, ka var izsaukt vienlaicīgi maksimāli piecas procedūras:
ALTER QUEUE dbo.MyTableQueue
    WITH ACTIVATION
    (
        STATUS=ON,
        PROCEDURE_NAME = dbo.sb_MyTableService,
        MAX_QUEUE_READERS = 1,
        Execute AS Self
    )
ALTER QUEUE dbo.ProcessQueue
    WITH ACTIVATION
    (
        STATUS=ON,
        PROCEDURE_NAME = dbo.sb_ProcessService,
        MAX_QUEUE_READERS = 5,
        Execute AS Self
    )
Pēc šīm izmaiņām ievietojot tabulā uzreiz lielu rindu skaitu- tās tiks apstrādātas paralēli- līdz pieciem ziņojumiem vienlaicīgi.

Ārējā (external) aktivizācija
SB rindas apstrādes loģika var tikt realizēta ārpus SQL Server. Tas ir ļoti noderīgi gadījumos, ja, piemēram, ziņojumu apstrādes loģika paredz pieslēgšanos ārējiem web servisiem vai gadījumos, kad apstrādes slodzi vēlaties pārnest uz citu dator.

Viens variants kā apstrādāt rindas elementus ir ik pa laikam pārbaudīt vai rindā ir parādījušies jauni elementi un ja ir, tad apstrādāt tos.
Otrs variants ir izmantot ārējo aktivizāciju, kas patiesībā ir tas pats pirmais variants, bet atšķirība ir tā, ka ir izveidota speciāla rinda, kurai tiek ziņots, kad ir nepieciešama jebkura servisa aktivizācija. Kad saņem uzdevumu aktivizēt kādu apstrādes procedūru, ārējais aktivators aktivizē attiecīgo procedūru. Tas ir labāks variants gadījumos, kad ir daudzi servisi vai arī nepieciešams izmantot vairākus apstrādes procesus vienlaicīgi. Šāda realizācija samazina liekus pieprasījumus serverim (pirmajā gadījumā- daudzi servisi visu laiku pārbauda vai atbilstošajās rindās ir parādījušies jauni elementi, otrajā gadījumā tikai viens to dara visu laiku, pārējie tiek aktivizēti pēc nepieciešamības. Otrais ir daudz, daudz plašākām iespējām).

Otrajam variantam ārējais aktivators ir pieejams lejupielādei šeit - SQL Server 2008 Feature Pack un neliels apraksts pieejams šeit.
[papildināts 2012-03-18] Un arī šajā emuārā plašāks apraksts: Service Broker: ārējā aktivizācija.

Nav komentāru:

Komentāra publicēšana