Serviciul de distribuire a datelor

De la Wikipedia, enciclopedia liberă.
Salt la navigare Salt la căutare

Serviciul de distribuție a datelor pentru sistemele în timp real (DDS) este un standard emis de Object Management Group (OMG) care definește un middleware pentru distribuirea datelor în timp real conform paradigmei de publicare / abonare .

Introducere

DDS este un middleware pentru sisteme centrate pe date (de la sistemele anglo - saxone centrate pe date ), adică sisteme distribuite a căror funcționare se bazează pe schimbul de date în timp real de la mai multe surse la destinații multiple. Exemple tipice sunt sistemele de control, sistemele de apărare, sistemele de tranzacționare financiară etc. Avantajele utilizării DDS în acest domeniu sunt următoarele:

Paradigma de publicare / abonare care stă la baza DDS.
  • Cuplare slabă între entități și ușurință în utilizare datorită utilizării paradigmei de publicare / abonare în varianta tematică;
  • Arhitectură flexibilă și adaptabilă datorită descoperirii automate;
  • Eficiență datorită comunicării directe între editor și abonat ;
  • Determinism în furnizarea datelor;
  • Scalabilitate ridicată ca urmare a cuplării libere între entități;
  • Calitate a serviciului foarte parametrizabilă;
  • Independența platformei ca interfață middleware este definită prin IDL ;

Datorită acestor caracteristici, DDS câștigă rapid teren pe piața middleware pentru sistemele distribuite în timp real, în special în domeniul aplicațiilor militare și al controlului traficului aerian.

Istoria standardului

Standardul DDS a fost emis de OMG sub presiunea a doi producători, California Real Time Innovations și grupul francez Thales , care a dezvoltat respectiv NDDS și SPLICE pentru același sector de piață. Specificația DDS 1.0 a standardizat astfel interfața de programare a acestor două produse și a contribuit la nașterea unor implementări suplimentare, cum ar fi OpenDDS de către Object Computing, Inc. (OCI), bazat pe TAO și, prin urmare, open-source .

Cu specificația DDS 1.1 (datată decembrie 2005 ) o serie de specificații sunt adăugate la standard pentru a fi respectate pentru a asigura interoperabilitatea între diferitele implementări.

Versiunea actuală a standardului este DDS 1.2 și a fost aprobată în ianuarie 2007 .

DDS SIG al OMG lucrează acum la versiunea DDS 1.3 .

Arhitectură

Arhitectura DDS.

Serviciul de distribuție a datelor este conceput ca o soluție de infrastructură pentru programarea aplicațiilor centrate pe date. Scopul său este de a ascunde complet problemele gestionării comunicațiilor în programarea aplicațiilor centrate pe date.

Standardul este reprezentat de o serie de API-uri împărțite în două niveluri:

  • DCPS , D ata C entric P ublish / S ubscribe, este nivelul inferior al DDS care definește entitățile, rolurile, interfețele și politicile QoS pentru platforma de publicare / abonare, precum și tehnicile de descoperire a participanților la comunicare. DCPS reprezintă în esență partea standardului referitoare la comunicațiile de rețea.
  • DLRL , D ata L Ocal R econstruction L ayer, este nivelul superior al DDS care definește modelul de interacțiune între lumea orientată obiect a aplicației și datele provenite de la DCPS. Prin DLRL este posibilă maparea datelor schimbate în cadrul unui subiect cu un obiect al stratului de aplicație, în așa fel încât să se propagă automat și transparent actualizările obiectului din aplicație în rețea și invers. DLRL este declarat opțional în DDS.

Entitate DCPS

Entități definite în DCPS.

În DCPS sunt definite următoarele entități:

DomainParticipantFactory
Un Singleton care acționează ca o fabrică pentru accesarea spațiului de comunicație în DDS, numit Spațiu global de date (GDS). GDS este împărțit în domenii, fiecare dintre ele fiind identificat printr-un nume. Pot exista mai multe subiecte într-un domeniu. Două subiecte cu același nume pot coexista în DDS numai în domenii diferite.
Participant la domeniu
Punct de acces pentru comunicare într-un anumit domeniu. Un DomainParticipant poate fi creat numai prin DomainParticipantFactory . La rândul său, DomainParticipant acționează ca o fabrică pentru crearea subiectului , editorului și abonatului .
Subiect
Partiție tastată a domeniului de comunicare, în cadrul căreia editorii și abonatul publică și primesc date. Fiecare subiect este caracterizat de un nume și un tip. Numele identifică subiectul din domeniu, iar tipul caracterizează datele schimbate în cadrul subiectului în sine. Tipul asociat cu un subiect este specificat prin limbajul IDL și poate fi văzut ca o structură care poate include atât tipuri primitive, cât și tipuri complexe . Pentru a face distincția între diferitele obiecte ale unui subiect, se utilizează conceptul de cheie , împrumutat din modelul entitate-relație tipic bazelor de date relaționale. Prin urmare, o cheie este compusă dintr-un membru sau o combinație de membri de tip.
Editor
Entitate responsabilă cu diseminarea datelor de la diferiții DataWriters asociați cu aceasta. Un editor acționează ca o fabrică pentru crearea DataWriter.
DataWriter
Punct de acces pentru publicarea datelor într-un subiect. DataWriter este creat pornind de la un editor, care la rândul său este asociat în mod unic cu un subiect. Din acest motiv, DataWriter este o entitate abstractă care se concretizează prin tastarea interfeței sale cu tipul de date corespunzător subiectului la care se referă DataWriter.
Abonat
Entitate responsabilă pentru primirea datelor publicate pe tema căreia îi este asociat. Acționează ca o fabrică pentru crearea de cititori de date și, în timpul rulării, se ocupă de sortarea datelor primite la diferiții cititori de date asociați acestuia.
DataReader
Punct de acces pentru primirea datelor în cadrul unui subiect. La fel ca DataWriter, DataReader este, de asemenea, o entitate abstractă care se concretizează prin tastarea interfeței sale cu tipul de date corespunzător subiectului la care se referă DataReader.

Calitatea serviciului

Serviciul de distribuție a datelor oferă o gamă largă de parametri referitori la calitatea serviciului, care pot fi setați pe baza entității unice implicate în comunicare. Această alegere de design face ca DDS să fie singurul standard disponibil în prezent pentru comunicarea în timp real de publicare / abonare.

Parametrii referitori la calitatea serviciului în DDS pot fi împărțiți în trei mari categorii:

  • Fiabilitatea comunicării
  • Persistența datelor
  • Momentul și prioritatea

Pe baza acestei clasificări, parametrii cu o importanță conceptuală mai mare sunt enumerați mai jos, indicând entitățile la care se referă parametrul.

Fiabilitatea comunicării

Fiabilitate (se aplică la Topic, DataReader, DataWriter)
Specifică dacă conexiunea dintre scriitori și cititori este fiabilă (fără pierderea mesajelor) sau nu (cel mai bun efort). Dacă această politică este setată la cel mai bun efort (setare implicită), nu există retransmisie a mesajelor. Dacă, pe de altă parte, este setat la încredere, este posibil să se specifice timpul maxim de blocare a scrierii () în cazul în care cozile de retransmisie sunt pline. Rețineți că prin acest parametru QoS este posibil să aveți livrare de date fiabilă chiar și folosind un protocol de transport nesigur (tip UDP).
COMANDĂ DE DESTINAȚIE (se aplică la Topic, DataReader)
Determină modul în care datele primite trebuie sortate în abonat, deci în ce ordine trebuie prezentate aplicației. Sortarea poate fi bazată pe timpul de publicare (timestamp scriitor) sau timpul de notificare (timestamp cititor, setare implicită).
PROPRIETATE ȘI FORȚĂ (se aplică subiectului (proprietate), DataWriter (forță))
Proprietatea specifică dacă un subiect poate fi actualizat de unul (exclusiv) sau de mai multe DataWriter (partajat). În cazul exclusiv, subiectul este actualizat de scriitorul cu cel mai mare parametru de forță. În acest fel, poate fi implementat un mecanism de toleranță la erori: atunci când scriitorul primar (cu intensitate mai mare) eșuează, subiectul continuă să fie actualizat de scriitorul secundar (cu rezistență mai mică).
VIAȚIE (se aplică la Topic, DataReader, DataWriter)
Specifică modul în care infrastructura DDS (în special serviciul Discovery) determină prezența participanților la comunicare. În termeni de implementare, reprezintă intervalul de timp în care o entitate trebuie să-și manifeste prezența printr-un semnal (HEARTBEAT), altfel este considerată că nu mai este prezentă. Sunt posibile trei valori: automat, set manual pe participant și set manual pe subiect. În cazul automat (implicit), este definit un sub-parametru care indică frecvența cu care este trimis semnalul de prezență al entității. În cazul manualului de către participant sau subiect, o entitate este considerată activă atâta timp cât participantul sau subiectul la care se referă sunt active.

Exemple de utilizare

În exemplele următoare, editorul publică date referitoare la subiectul "Exemplu HelloWorld" în fiecare secundă. Pe de altă parte, abonatul colectează datele imediat ce sunt primite și le imprimă pe ecran. Tipul de date asociat subiectului „Exemplu HelloWorld” este definit prin limbajul IDL după cum urmează:

 struct HelloWorld {
    numele șirului < 64 > ;
    string msg < 256 > ;
}

Specificația IDL este apoi tradusă în limba utilizată pentru dezvoltarea aplicației. În C și C ++ va da naștere unei structuri precum:

 struct HelloWorld {
    char * nume ;
    char * msg ;
}

în timp ce în Java veți avea următoarea clasă:

 clasă publică HelloWorld {
    numele șirului public ;
    public String msg ;
}

IDL de tip generează, de asemenea, interfețele tastate pentru citirea și scrierea datelor pe subiect, și anume HelloWorldDataReader și HelloWorldDataWriter.

Pentru simplitatea discuției, în exemplele următoare sunt utilizate politicile QoS implicite pentru fiecare entitate. Pentru informații suplimentare despre parametrizarea QoS, consultați standardul.

C ++

Partea editorului

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // necesar pentru somn ()

#include <dds_cpp.h>
folosind DDS ;

int main ( int argc , char * argv [])
{
    int domainId = 0 ;
    int sample_count = 100 ;
    Participant la domeniu * participant = NULL ;
    Editor * editor = NULL ;
    Subiect * topic = NULL ;
    DataWriter * writer = NULL ;
    HelloWorldDataWriter * helloWriter = NULL ;
    HelloWorld instanță ;
    InstanceHandle_t instance_handle = HANDLE_NIL ;
    const char * type_name = NULL ;
    int count = 0 ;

    participant = TheParticipantFactory -> create_participant (
        domainId , PARTICIPANT_QOS_DEFAULT , NULL / * ascultător * / , 
        STATUS_MASK_NONE );

    publisher = participant -> create_publisher (
        PUBLISHER_QOS_DEFAULT , NULL / * ascultător * / , 
        STATUS_MASK_NONE );

    nume_tip = HelloWorldTypeSupport :: get_type_name ();
    HelloWorldTypeSupport :: register_type (
        participant , tip_nume );

    topic = participant -> create_topic (
        „Exemplu HelloWorld” ,
        TYPE_NAME, TOPIC_QOS_DEFAULT, NULL / * ascultător * /,
        STATUS_MASK_NONE );

    writer = editor -> create_datawriter (
        subiect , DATAWRITER_QOS_DEFAULT , NULL / * ascultător * / ,
        STATUS_MASK_NONE );
    helloWriter = HelloWorldDataWriter :: narrow ( writer );

    strcpy ( exemplu . nume ,  Numele Meu” );
    instance_handle = HelloWorld_writer -> register_instance ( instanță );

    / * Buclă principală * /
    for ( count = 0 ; ( sample_count == 0 ) || ( count < sample_count ); ++ count ) {
        sprintf ( exemplu . msg , "Hello World! (count% d)" , count );
        printf ( "Scriere:% s" , instanță . msg );
        helloWriter -> write ( * instanță , instanță_handle );
        somn ( 1 );
    }

    participant -> delete_contained_entities ();
    TheParticipantFactory -> delete_participant ( participant );
}

Partea abonat

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // necesar pentru somn ()

#include <dds_cpp.h>

folosind DDS ;

/ * Ascultător folosit pentru a primi notificări privind actualizările de date * /
clasa HelloWorldListener : public DataReaderListener {
  public :
    nul virtual on_data_available ( cititor DataReader * );
};

void HelloWorldListener :: on_data_available ( cititor DataReader * )
{
    HelloWorldDataReader * HelloWorld_reader = NULL ;
    HelloWorldSeq data_seq ;
    SampleInfoSeq info_seq ;

    HelloWorld_reader = HelloWorldDataReader :: îngust ( cititor );

    retcode = HelloWorld_reader -> take (
        data_seq , info_seq , LENGTH_UNLIMITED ,
        ANY_SAMPLE_STATE , ANY_VIEW_STATE , ANY_INSTANCE_STATE );

    for ( i = 0 ; i < data_seq . length (); ++ i ) {
        if ( info_seq [ i ]. date_valide ) {
            printf ( "De la% s:% s \ n " , data_seq [ i ]. nume , data_seq [ i ]. msg );
        }
    }

    retcode = HelloWorld_reader -> return_loan ( data_seq , info_seq );
}

int main ( int argc , char * argv [])
{
    int domainId = 0 ;

    Participant la domeniu * participant = NULL ;
    Abonat * abonat = NULL ;
    Subiect * topic = NULL ;
    HelloWorldListener * reader_listener = NULL ; 
    DataReader * cititor = NULL ;
    ReturnCode_t retcode ;
    const char * type_name = NULL ;

    participant = TheParticipantFactory -> create_participant (
        domainId , participant_qos , NULL / * ascultător * / , STATUS_MASK_NONE );

    abonat = participant -> create_subscriber (
        SUBSCRIBER_QOS_DEFAULT , NULL / * ascultător * / , STATUS_MASK_NONE );

    nume_tip = HelloWorldTypeSupport :: get_type_name ();
    retcode = HelloWorldTypeSupport :: register_type (
        participant , tip_nume );

    topic = participant -> create_topic (
        „Exemplu HelloWorld” ,
        TYPE_NAME, TOPIC_QOS_DEFAULT, NULL / * ascultător * /,
        STATUS_MASK_NONE );

    / * Creați un ascultător de cititor de date * /
    reader_listener = new HelloWorldListener ();

    cititor = abonat -> create_datareader (
        subiect , DATAREADER_QOS_DEFAULT , reader_listener ,
        STATUS_MASK_ALL );

    / * Bucla principală. Nu face nimic. Acțiune luată în ascultător * /
    for ( count = 0 ; ( sample_count == 0 ) || ( count < sample_count ); ++ count ) {
        printf ( "Abonat HelloWorld dormind% d sec ... \ n " ,
               primi_perioada . sec );
        somn ( 10 );
    }

    participant -> delete_contained_entities ();
    TheParticipantFactory -> delete_participant ( participant );
}

Alte proiecte

linkuri externe