3. Your First AMPS Program¶
In this chapter, we will learn more about the structure and features of the AMPS Python client and build our first Python program using AMPS.
About the client library¶
The AMPS client library is packaged as a single binary file, AMPS.so
on Linux or AMPS.pyd
on Windows. You can find the file under the
build
directory of your AMPS Python client install once you’ve
completed the build process. Every Python application you build will
need to reference this file, and the file must be deployed along with
your application in order for your application to function properly.
If you chose to install the python client into your local Python installation, then Python has access to the client library in the installation, and you do not need to include the library with each specific script. Otherwise, you will need to package and include the library with your script and ensure that the library is in the path where python looks for shared libraries.
Connecting to AMPS¶
Let’s begin by writing a simple program that connects to an AMPS server and sends a single message to a topic. This code will be covered in detail just following the example.
# These import the AMPS and sys packages. All programs written using the AMPS
# Python Client will need to include the import AMPS statement at a minimum.
import AMPS
import sys
# The URI to use to connect to AMPS. The URI consists of the transport, the
# address, and the protocol to use for the AMPS connection. In this case, the
# transport is tcp, the address is 127.0.0.1:9007, and the protocol is amps. This
# connection will be used for JSON messages. Check with the person who manages the
# AMPS instance to get the connection string to use for your programs.
uri_ = "tcp://127.0.0.1:9007/amps/json"
# This line creates a new Client object. Client encapsulates a single connection
# to an AMPS server. Methods on Client allow for connecting, disconnecting,
# publishing, and subscribing to an AMPS server. The argument to the Client
# constructor, <quote>exampleClient</quote>, is a name chosen by the client to
# identify itself to the server. Errors relating to this connection will be logged
# with reference to this name, and AMPS uses this name to help detect duplicate
# messages. AMPS enforces uniqueness for client names when a transaction log is
# configured, and it is good practice to always use unique client names.
client = AMPS.Client("examplePublisher")
# Here, we open a try block that concludes with except AMPS.AMPSException as e.
# All exceptions in AMPS derive from AMPSException. If an operation throws another
# exception, AMPS will wrap that exception into the AMPSException you receive. For
# example, if the call to connect() fails because the provided address is not
# reachable, the AMPSException will contain an inner exception from the operating
# system, likely a SocketException.
try:
# With this statement, we provide URI to the client and declare the AMPS
# connection.
client.connect(uri_)
# The AMPS logon() command connects to AMPS and creates a named connection. If we
# had provided logon credentials in the URI, the command would pass those
# credentials to AMPS. Without credentials, the client logs on to AMPS
# anonymously. AMPS versions 5.0 and later require a logon() command in the
# default configuration.
client.logon()
# Here, we publish a single message to AMPS on the messages topic, containing the
# data Hello, world!. This data is placed into a JSON message and sent to the
# server. Upon successful completion of this function, the AMPS client has
# enqueued the message to be sent to the server, and subscribers to the messages
# topic will receive this JSON message: { "hi" : "Hello, world!" }.
client.publish("messages", '{ "hi" : "Hello, world!"}')
except AMPS.AMPSException as e:
sys.stderr.write(str(e))
# Here, we call publish_flush on the client. This command waits until all messages
# from the client have been sent. If messages may still be in the process of
# transmission when your application is ready to close the client, publish_flush
# helps ensure that the messages have been sent. In this case, we allow
# publish_flush to block indefinitely. A production application might specify a
# timeout, to avoid hanging in the event that the application loses connectivity
# before the messages have been sent.
client.publish_flush()
# We close the connection to AMPS. While that doesn't matter here, since the
# application exits immediately after calling close(), it's good practice to close
# connections when you are done using them.
client.close()
Example 3.1: Connecting to AMPS
Client Names¶
AMPS uses the name of the client as a session identifier and as part of the identifier for a message. For this reason, when a transaction log is enabled in the AMPS instance (that is, when the instance is recording a sequence of publishes and attempting to eliminate duplicate publishes), an AMPS instance will only allow one application with a given client name to connect to the instance.
When a transaction log is present, AMPS requires the Client Name for a publisher to be:
- Unique within a set of replicated AMPS instances
- Consistent from invocation to invocation if the publisher will be publishing tthe same logical stream of messages
60East recommends always using consistent, unique client names. For example, the client name could be formed by combining the application name, an identifier for the host system, and the id of the user running the application. A strategy like this provides a name that will be different for different users or on different systems, but consistent for instances of the application that should be treated as equivalent to the AMPS system.
Connection Strings¶
The AMPS clients use connection strings to determine the server, port, transport, and protocol to use to connect to AMPS. When the connection point in AMPS accepts multiple message types, the connection string also specifies the precise message type to use for this connection. Connection strings have a number of elements.
Figure 3.1: Elements of a Connection String
As shown in the figure above, connection strings have the following elements:
Transport defines the network used to send and receive messages from AMPS. In this case, the transport is
tcp
. For connections to transports that use the Secure Sockets Layer (SSL), usetcps
. For connection to AMPS over a Unix domain socket, useunix
.Host address defines the destination on the network where the AMPS instance receives messages. The format of the address is dependent on the transport. For
tcp
andtcps
, the address consists of a host name and port number. In this case, the host address islocalhost:9007
. Forunix
domain sockets, a value for hostname and port must be provided to form a valid URI, but the content of the hostname and port are ignored, and the file name provided in the path parameter is used instead (by convention, many connection strings uselocalhost:0
to indicate that this is a local connection that does not use TCP/IP).Protocol sets the format in which AMPS receives commands from the client. Most code uses the default
amps
protocol, which sends header information in JSON format. AMPS supports the ability to develop custom protocols as extension modules, and AMPS also supports legacy protocols for backward compatibility.MessageType specifies the message type that this connection uses. This component of the connection string is required if the protocol accepts multiple message types and the transport is configured to accept multiple message types. If the protocol does not accept multiple message types, this component of the connection string is optional, and defaults to the message type specified in the transport.
Legacy protocols such as
fix
,nvfix
andxml
only accept a single message type, and therefore do not require or accept a message type in the connection string.
As an example, a connection string such as
tcp://localhost:9007/amps/json
would work for programs connecting from the local host to a
Transport
configured as follows:
<AMPSConfig>
...
<!-- This transport accepts any known message type for the instance: the
client must specify the message type. -->
<Transport>
<Name>any-tcp</Name>
<Type>tcp</Type>
<InetAddr>9007</InetAddr>
<Protocol>amps</Protocol>
</Transport>
...
</AMPSConfig>
See the AMPS Configuration Guide for more information on configuring transports.
Providing Credentials in a Connection String¶
When using the default authenticator, the AMPS clients support the standard format for including a username and password in a URI, as shown below:
tcp://user:password@host:port/protocol/message_type
When provided in this form, the default authenticator provides the username and password specified in the URI. If you have implemented another authenticator, that authenticator controls how passwords are provided to the AMPS server.
Connection Parameters¶
When specifying a URI for connection to an AMPS server, you may specify a number of transport-specific options in the parameters section of the URIconnection parameters. Here is an example:
tcp://localhost:9007/amps/json?tcp_nodelay=true&tcp_sndbuf=100000
In this example, we have specified the AMPS instance on localhost
,
port 9007
, connecting to a transport that uses the amps
protocol
and sending JSON messages. We have also set two parameters, tcp_nodelay
, a
Boolean (true/false) parameter, and tcp_sndbuf
, an integer parameter.
Multiple parameters may be combined to finely tune settings available on
the transport. Normally, you’ll want to stick with the defaults on your
platform, but there may be some cases where experimentation and
fine-tuning will yield higher or more efficient performance.
The AMPS client supports the value of tcp
in the scheme component
connection string for TCP/IP connections, and the value of tcps
as
the scheme for SSL encrypted connections.
For connections that use Unix domain sockets, the client supports the
value of unix
in the scheme, and requires the additional option
described below.
TCP and SSL transport options¶
The following transport options are available for TCP connections:
bind |
(ip address) Sets the interface to bind the outgoing socket to. |
tcp_rcvbuf |
(integer) Sets the socket receive buffer size. This defaults to the
system default size. (On Linux, you can find the system default size
in /proc/sys/net/core/rmem_default .) |
tcp_sndbuf |
(integer) Sets the socket send buffer size. This defaults to the
system default size. (On Linux, you can find the system default size
in /proc/sys/net/core/wmem_default .) |
tcp_nodelay |
(boolean) Enables or disables the TCP_NODELAY setting on the
socket. By default TCP_NODELAY is disabled. |
tcp_linger |
(integer) Enables and sets the SO_LINGER value for the socket
By default, SO_LINGER is enabled with a value of 10 , which
specifies that the socket will linger for 10 seconds. |
tcp_keepalive |
(boolean) Enables or disables the SO_KEEPALIVE value for the socket.
The default value for this option is true. |
Unix transport parameters¶
The unix
transport type communicates over unix domain sockets. This
transport requires the following additional option:
path |
The path to the unix domain socket to connect to. |
Unix domain sockets always connect to the local system. When the scheme
specified is unix
, the host address is ignored in the connection
string. For example, the connection string:
unix://localhost:0/amps/json?path=/sockets/the-amps-socket
and the connection string:
unix://unix:unix/amps/json?path=/sockets/the-amps-socket
are equivalent.
The other components of the connection string, including the protocol, message type, user name, and authentication token are processed just as they would be for TCP/IP sockets.
AMPS additional logon options¶
The connection string can also be used to pass logon parameters to AMPS. AMPS supports the following additional logon option:
pretty |
Provide formatted representations of binary messages rather than the original message contents. |
Next steps¶
You are now able to develop and deploy an application in Python that publishes messages to AMPS. In the following chapters, you will learn how to subscribe to messages, use content filters, work with SOW caches, and fine-tune messages that you send.