remote procedure call over dds - london connext dds conference
DESCRIPTION
Overview of the RPC over DDS specification (in-progress as the OMG). Significance to Industrial Internet applications. Significant to people migrating from a legacy CORBA systemTRANSCRIPT
DDS
RPC over DDSGerardo Pardo-Castellote, Ph.D.Chief Technology Officer, RTISumant Tambe, Ph.D. Senior Software Reseach Engineer, RTI
October 2014
© 2014 Real-Time Innovations, Inc.
Outline
• Goals• Background• Status• Details• More info
© 2014 Real-Time Innovations, Inc.
Goals• Provide standard and interoperable way means to
support “RPC” communication patterns in DDS• Support the Patters:
– Request/Reply– Service Invocation– Remote Procedure Call– Remote Method Invocation
• Support invocation of IDL-specified interfaces over DDS– Provide a simpler way to migrate CORBA applications to DDS– Support familiar “remote interface” programming style
equivalent to Java RMI and Apache Thrift
© 2014 Real-Time Innovations, Inc.
Advantages of RPC over DDS• Client and Servers are decoupled
– No startup dependencies• QoS enforcement to support service SLAs
– Ownership–Redundant pool of servers – Lifespan–request is only valid for the next N sec– Durability-request/replies will be eventually received and processed– Cancellation– after a good quality response has arrived
• Data-Centricity– Explicit trace-ability– Interaction state can be Monitored, Logged, Audited, Stored,
Manipulated• Watch by subscribing to requests and/or responses (wire-tap)
• One middleware – leverage DDS infrastructure – Suited for real-time systems– Multiplatform, Multilanguage, Interoperable
© 2014 Real-Time Innovations, Inc.
But I can already do it...True:• I can write my own RCP using request/reply Topics• RTI Connext already supports a “Request/Reply”
equivalent to RPC• Some other vendors do similar thingsBut…• The mapping from service to Topics and Types is ad-
hoc. • These approaches are not portable/Interoperable• Getting everything right is cumbersome at best
© 2014 Real-Time Innovations, Inc.
How can I do it myself?• Map Interfaces to types & Topics…
– One Topic per interface, one per operation?– What are the types. How to map exceptions, output
parameters, …– What happens if the interfaces change, e.g. operation is
added or moved?• Implement necessary plumbing:
• Setup request topic and type• Setup reply topic and type• Filter unwanted requests• Filter unwanted replies
© 2014 Real-Time Innovations, Inc.
Goal State
But RPC is not a good/robust idea/design pattern….• RPC versus Desired State Pattern
– Insight: Often a request-reply can be modeled as stateful data-centric interactions
write
Current State
AffectServiceClient
ServiceProvider
DesiredState
read
write
read
read
© 2014 Real-Time Innovations, Inc.
RPC vs Desired State• Desired state is good & more robust if the “request” actually
represents:– a request to change of system state– Take a long time to fulfill– Needs to be observable by others
• However:– Many requests that do not represent changes to state: Database
Query, Read a File…– People familiar for “Service” or “Request/Reply” pattern may find
Directed State cumbersome –specially if extra robustness is unwarranted
RPC over DDS provides best of both worlds!
© 2014 Real-Time Innovations, Inc.
Example: RobotControl
module robot {
@DDSServiceinterface RobotControl { void command(Command command); float setSpeed(float speed) raises (TooFast); float getSpeed(); void getStatus(out Status status);};
}
© 2014 Real-Time Innovations, Inc.
RobotControl Clientimport org.omg.dds.rpc.*;
public class TestRobot {
static void createRobotClient() {
RPCRuntime runtime = RPCRuntime.getInstance(TestRobot.class.getClassLoader()); ClientParams clientParams = runtime.createClientParams(); // optional
RobotControlSupport.Client robotClient = RobotControlSupport.createClient( clientParams.withServiceName(”TestRobot”) .withInstanceName(“iRobot”)); // more configs available robotClient.waitForService(); // optional robotClient.getSpeed();}}
© 2014 Real-Time Innovations, Inc.
RobotControl Service (Java) package robot;import robot.RobotControl;public class MyRobot implements RobotControl { public void command(Command command) { } public float setSpeed(float speed) { return 1; } public float getSpeed() { return 2; } public void getStatus(/* out */ Status status) { }}
import org.omg.dds.rpc.*;public class TestRobot {
public static void createRobotServer() { RPCRuntime runtime = RPCRuntime.getInstance(TestRobot.class.getClassLoader()); MyRobot myRobot = new MyRobot(); Server server = runtime.createServer(); // Configurable using ServerParams
RobotControlSupport.Service service = RobotControlSupport.createService(myRobot, server); // Configurable using ServiceParams
server.run(); // blocking}}
© 2014 Real-Time Innovations, Inc.
RobotControl Requesterpublic class TestRobot {
static void createRobotRequester() {
RPCRuntime runtime = RPCRuntime.getInstance(TestRobot.class.getClassLoader()); RequesterParams reqParams = runtime.createRequesterParams(); // change params here if you like Requester<RobotControlSupport.RequestType, RobotControlSupport.ReplyType> requester = runtime.createRequester( RobotControlSupport.RequestType.class, RobotControlSupport.ReplyType.class, reqParams);
RobotControlSupport.RequestType request = new RobotControlSupport.RequestType(); // populate request requester.sendRequest(request); }}
© 2014 Real-Time Innovations, Inc.
RobotControl Replierpublic class TestRobot {
static void createRobotReplier() {
RPCRuntime runtime = RPCRuntime.getInstance(TestRobot.class.getClassLoader()); ReplierParams repParams = runtime.createReplierParams(); // change params here if you like Replier<RobotControlSupport.RequestType, RobotControlSupport.ReplyType> replier = runtime.createReplier( RobotControlSupport.RequestType.class, RobotControlSupport.ReplyType.class, repParams);
Sample<RobotControlSupport.RequestType> request = replier.receiveRequest(); }}
© 2014 Real-Time Innovations, Inc.
RobotControlSupportpublic abstract class RobotControlSupport {
public final static class RequestType { // omg.dds.rpc.RequestHeader header; // robot.RobotControl_Call data; } public final static class ReplyType { // omg.dds.rpc.ReplyHeader header; // robot.RobotControl_Return data } public interface Client extends RobotControl, RobotControlAsync, ClientEndpoint { } public interface Service extends ServiceEndpoint { }
public static final RobotControlSupport.Client createClient(); public static final RobotControlSupport.Service createService(RobotControl impl);
// more client and service factory methods here}
© 2014 Real-Time Innovations, Inc.
What needs to be specified• Mapping to DDS Topics & Filters
– Each operation maps to a pair of topics?• Simplicity, Flexibility vs Scalability
– Each interface to a pair of Topics? • What are the types? Inheritance?
– Is publish-subscribe allowed? e.g. auditing, monitoring…
• Mapping to DDS Data-types– How to model operations? Parameters (in, our) return, exceptions, … – Fragility upon interfaces / operations changes?– Describable using X-TYPES?
• DDS API and DDS-RTPS impact– Are extensions required? – Deployment on top of existing DDS
• Language Bindings (C, C++, Java, C#, …)
© 2014 Real-Time Innovations, Inc.
Architecture
Service Implementation
Lang.Bind.
GUID2
Client-side Invoker
Client Application Service
Data Writer
Data Reader
Data Reader
Data Writer
GUID1 SN1 Foo
GUID2 SN2 BarGUID1 SN1
Message-id1
Message-id2
Correlation-id1
Content-based Filter for filtering unwanted replies
Language Binding
Bar Svc.method(in Foo);
Foo
Bar
GUID1
Invoke
Return
Call Topic
Return Topic
Foo
Bar
© 2014 Real-Time Innovations, Inc.
Basic and Enhanced Service Mappings• Basic
– Highest portability– Enables RPC on top of existing (v1.3 or earlier) DDS Implementations
• Enhanced– Elegant, Clean– Leverages DDS-XTypes for type matching, – Adds support for Robust service discovery, Implicit request/reply correlation
Mapping Aspect Basic Service Mapping Profile Enhanced Service Mapping Profile
Correlation Information (request-id)
Explicitly added to the data-type Implicit. They appear on the Sample meta-data.
Topic Mapping One request topic and one reply topic per interface. 2*N for a hierarchy of N interfaces.
One request and one reply topic per interface. Independent of interface hierarchy.
Type Mapping Synthesized types compatible with legacy (pre DDS-XTypes) implementations.
Use facilities of DDS-XTypes for type descriptions, annotations, and type-compatibility checks.
Discovery No special extensions. Robust service discovery (no sample loss due to transient states)
© 2014 Real-Time Innovations, Inc.
Language Bindings• Two types of language bindings
– High-level binding that provide function-call semantics– Low-level binding that are akin to send/receive (but still higher level than raw DDS
read/take/write)• Strong separation between the data model and language binding
Client Application
Function-call language binding
DDS API
Service Specification (IDL)
Client Application
Request-Reply language binding
DDS API
Service Implementation
Function call language binding
DDS API
Service Implementation
Request-Reply language binding
DDS API
Service-specific Interoperable/Evolvable Data model (DDS/RTPS)
© 2014 Real-Time Innovations, Inc.
QoS Mapping• Default strict reliable (request and reply)
– RELIABLE reliability– KEEP_ALL history– VOLATILE durability
• Can be changed by the user on a per-service level
© 2014 Real-Time Innovations, Inc.
struct RobotControl_setSpeed_In { long s;};
struct RobotControl_getSpeed_In {
boolean return_;};
@DDSServiceinterface RobotControl { float setSpeed(float speed) raises (TooFast); float getSpeed(); void start(); void stop();};
@choice @autoidstruct RobotControl_Request { RobotControl_setSpeed_In setSpeed; RobotControl_getSpeed_In getSpeed; RobotControl_start_In start; RobotControl_stop_In stop;};@empty
struct start_In { octet dummy_;};
@emptystruct stop_In { octet dummy_;};
© 2014 Real-Time Innovations, Inc.
struct RobotControl_setSpeed_Out { float return_; // Also inout and out params};…
@DDSServiceinterface RobotControl { float setSpeed(float speed) raises (TooFast); float getSpeed(); void start(); void stop();};
@choice @autoidstruct RobotControl_setSpeed_Result { RobotControl_setSpeed_Out out; SystemExceptionCode sysx_; TooFast toofast_ex;};…
@choice @autoidstruct RobotControl_Reply { RobotControl_setSpeed_Result setSpeed; RobotControl_getSpeed_Result getSpeed; RobotControl_start_Result start; RobotControl_stop_Result stop;};
© 2014 Real-Time Innovations, Inc.
Status• Ongoing standard at OMG • RFP was issued in June 2012• Initially 2 competing submissions:
1. Joint RTI + eProsima (later joined by TwinOaks)2. PrismTech
• Very different approaches – not converging– Evaluation team representing 5 companies formed to provide
feedback• Recommendation was to simplify RTI/eProsima submission• PrismTech dropped their submission and joined RTI/eProsimas’/TwinOaks
• Expected to be voted and adopted in Dec 2014• Completed Function-Call and Request/Reply language binding
– Java (https://github.com/rticommunity/dds-rpc-java)– C++* (https://github.com/rticommunity/dds-rpc-cxx)– eProsima has POC implementation of “basic” profile working with several DDS
implementations
© 2014 Real-Time Innovations, Inc.
Questions?
© 2014 Real-Time Innovations, Inc.
Find out more…www.rti.com
community.rti.com
demo.rti.com
www.youtube.com/realtimeinnovations
blogs.rti.com
www.twitter.com/RealTimeInnov
www.facebook.com/RTIsoftware
dds.omg.org
www.omg.org
© 2014 RTI
www.slideshare.net/GerardoPardowww.slideshare.net/RealTimeInnovations