|
theLink 10.0
|
Basic information about the context usage …
MqContextC - the class known as ctx or context is the application-handle of the application-server and also the main data-handle …
The context is the package-item with the required features and created by the implementation-layer-programmer. The context can be a client or a server.
The client-context-creation is triggerd by the software-workflow on demand. The client is calling the MqLinkCreate to create a connection to the server using the connection-arguments to specify the target.
The life-cycle of a client is:
| ContextCreate | create and initialize the MqContextC ... |
| LinkCreate | make ctx to a parent-context and setup a new client-server-link … |
| SendTT | MqContextC - append a native PRIMITIVE TYPE value to the send-data-package … |
| ReadTT | read a PRIMITIVE TYPE from the read-data-package … |
| LinkDelete | close the client-server-link … |
| ContextDelete | Destructor - delete a MqContextC instance … |
| Exit | delete the context and exit the current process or thread … |
The server-context-creation is always triggerd by the MqLinkCreate command of the client. The server is usually using a factory-constructor to call the MqContextCreate and finally to call the MqContextDelete.
The server-context is fully under control of the client.
The life-cycle of a server is:
| SETUP | define a class and add the setup/cleanup code |
| MqServerSetupIF | define the server-setup-interface (callback) used on startup … |
| ServiceCreate | create a link between a service-token and a service-callback … |
| MqServerCleanupIF | define the server-cleanup-interface (callback) used on cleanup … |
| ServiceDelete | delete a service. … |
| STARTUP | define the factory and start the listener |
| FactoryAdd | Add a new MqFactoryC identified by factory-identifier and defined by factory-constructor … |
| FactoryNew | create a new MqContextC from a MqFactoryC … |
| LinkCreate | make ctx to a parent-context and setup a new client-server-link … |
| ProcessEvent | enter the event-loop and wait for an incoming service-request. … |
| WORK | process the service-calls and exit on end |
| ReadTT | read a PRIMITIVE TYPE from the read-data-package … |
| SendTT | MqContextC - append a native PRIMITIVE TYPE value to the send-data-package … |
| Exit | delete the context and exit the current process or thread … |
| command | alias |
|---|---|
(constructor,static) MqContextC [MqContextC::Create ?tmpl:MqContextC=NULL?] | myooX::NewN ::MqContextC ?tmpl:MqContextC=""? |
(destructor) MqContextC::Delete $ctx | myooX::DeleteN $ctx |
MqContextC - setup and manage a client-server-link …
The client-server-link connect two context, a client-parent-context and a server-parent-context. The link can be local (connect two context on the same host) or can be remote (connect two context on different hosts). On-Top the parent-context multiple child-context are allowed.
!on remote host! !on local host!
server1---------x x----------server2
| | | |
| child-context-1 child-context-2 |
| | | | server
parent-context-1-----x x-----parent-context-2
| |
(MqConfigS::server) (example: MqConfigS::server --fork --uds … --file …)
| |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| |
(--tcp) (--pipe, --uds, --tcp)
| |
parent-context-1-----x x-----parent-context-2
| | | | client
| child-context-1 child-context-2 |
| | | |
x------------x--------client-------x-------------x
!on local host!
Definition of a "client-context"
Definition of a "server-context"
Definition of a "parent-context"
Definition of a "child-context"
MqContextC - create and manage a slave context …
The master-slave-link is used to create a mesh of nodes defined by different parent-context. The master control the slave.
The master-slave-link is used to perform the following tasks:
In difference to the client-server-link the master-slave-link connect two independent parent-context in the same process or thread (e.g. node). This leads to the restriction that only the master-context can be a server-context because only one server-context per node is possible.
node-0 | node-1/2 | node-3/4/5
===================================================================
| <- client/server link -> | <- client/server link -> |
| <-- master/slave link --> |
|- client1-0 -|- server3 ...
|- server1 -|
| |- client1-1 -|- server4 ...
client0-0 -|
|- server2 -|- client1-2 -|- server5 ...
Definition of the "master-context"
Definition of the "slave-context"
0.Definition of the "worker-context"
0./etc/services 0 | slave-id | value | definition |
|---|---|---|
| MQ_SLAVE_MAX | 1024 | internal: the maximum slave-id … . |
| MQ_SLAVE_USER | 10 | internal: start of user-defined-slave-id . |
| MQ_SLAVE_LOOPBACK | 0 | internal: the loopback-slave-id, (call my own services) . |
| MQ_SLAVE_FILTER | 1 | internal: the filter-slave-id, (on a master get the filter-slave) . |
| MQ_SLAVE_MASTER | 1 | internal: the master-slave-id, (on a slave get the master) . |
| MQ_SLAVE_OTHER | 1 | internal: on the master-ctx get the slave-ctx and on the slave-ctx get the master-ctx . |
| range | definition |
|---|---|
| 0 <= slave-id < MQ_SLAVE_MAX | range of valid slave-id's |
| 0 <= slave-id < MQ_SLAVE_USER | internale usage |
| MQ_SLAVE_USER <= slave-id < MQ_SLAVE_MAX | external usage |
Definition of the "LOOPBACK" (0) slave
client | server |
===========================================
| <--- client/server ---> | <-- loop --> |
| <------ master/slave -----> |
client -- | -- server -- | -- client -- #
== == #
server -- | -- client -- # slave-id = 0 . MyLoopServer.atl → create a new loop-server package require lib_85 package require atlmqmsgque ::myooX::ClassN ::MyLoopServer { SuperI ::MqContextC # factory startup proc MyLoopServer {myNs {tmpl ""}} { namespace upvar $myNs my(mydata) mydata; MqContextC $myNs $tmpl ConfigSetServerSetup $myNs ServerSetup # set the "mydata" attribute to the master-context set mydata "Hello World"; } # service to serve all EXTERNAL requests for token "HLWO" proc HLWO_srv { myNs } { # get the "loopback" context set loop [SlaveGet $myNs LOOPBACK] # call the LOOP service on the SAME server MqContextC::Send $loop "W" "LOOP" # answer HLWO with string-return from LOOP Send $myNs "R" "C" [MqContextC::ReadSTR $loop] } # service to serve all INTERNAL requests for token "LOOP" proc LOOP_srv { myNs } { # get the "master" context set master [SlaveGetMaster $myNs] # answer LOOP with data from MASTER->mydata attribute namespace upvar $master my(mydata) mydata; Send $myNs "R" "C" $mydata } # setup a server-context - called for every new server-context proc ServerSetup { myNs } { # EXTERNAL: link the "HLWO" service with "HLWO_srv" ServiceCreate $myNs "HLWO" HLWO_srv # INTERNAL: link the "LOOP" service with "LOOP_srv" ServiceCreate [SlaveGet $myNs MQ_SLAVE_LOOPBACK] "LOOP" LOOP_srv } } MqMsgque::Main { # create "MyLoopServer" factory... and the instance set srv [MqFactoryC::New [MqFactoryC::Add ::MyLoopServer]] try { MqContextC::LinkCreate $srv $argv MqContextC::ProcessEvent $srv MQ_WAIT_FOREVER } on error {} { MqContextC::ErrorCatch $srv } finally { MqContextC::Exit $srv } }
Performance analyse
Nhi1Exec perfclient.c --parent --wrk ? @ perfserver.cNhi1Exec -r=uds perfserver.c --spawn|fork|threadNhi1Exec -r=uds perfclient.c --parent --wrk ? perfclient worker perfserver
========== ====== ==========
|
|- loop --wrk x
|- MqSlaveWorker(...) -> worker[1]
|- MqSend(worker[1],"E","STR0..") -> PerfWorker_I160(...)
|- loop endless
|- MqContextCreate(...)
|- MqLinkCreate(...) <-> MqContextCreate(...)
|- MqContextDelete(...) <-> MqContextDelete(...)
|- sleep x sec
|- loop --wrk x
|- MqSend(worker[1],"C"..,"END0") -> PerfWorker_END0(...)
| |- stop loop
|- "callback" - add number to all <- |- return #context | setup | –wrk | # worker-context | performance | info |
|---|---|---|---|---|
| pipe | 1 | 2500 | 1000 | the pipe start a new worker-context with spawn |
| spawn | 1 | 2500 | <1000 | same as pipe but use network-protocoll |
| fork | 1 | 3800 | 4000 | the fork is faster than spawn |
| thread | 1 | 16500 | 9000 | the thread is faster than fork |
| pipe | 4 | 8000 | 4500 | the worker scale linear up to number of processors |
| spawn | 4 | 7600 | <4500 | - |
| fork | 4 | 23200 | 11500 | - |
| thread | 4 | 55500 | 27500 | - |
| pipe | 8 | 10000 | 5500 | the additional scaling up to the max hyper-threading does not really help |
| spawn | 8 | 9100 | <5500 | - |
| fork | 8 | 23200 | 11500 | - |
| thread | 8 | 55500 | 27500 | - |