Architecture and Design of the Synapse ESB mediation framework

This paper is designed to capture the overall architecture and design of the Synapse ESB mediation framework. The aim is to provide clear architectural and design guidance and direction as we move towards Synapse 1.0.

Introduction

Synapse has a few simple design goals:

Synapse is designed to help intermediate messages as they pass through it from a service requester or client to a service provider or server, and back again.

Synapse is designed to support any message exchange pattern (MEP).

Synapse supports Connecting systems, Managing interactions and Transforming messages. The main function of Synapse can be categorized into these three areas.

Synapse is inherently extensible, but is designed to support a large set of useful function out-of-the-box.

Synapse is designed to work with BPM/BPEL solutions, and explicitly leaves stateful process-based integration out of scope.

This paper describes the architecture, design and framework, and also aims to capture the intended 1.0 function. Not everything in this is available in the current release.

Use cases and capabilities: Connect, Manage, Transform

Connect

Synapse is designed to support connecting systems across different transports and with different protocols and Quality of Service (QoS) applied. For example, Synapse will support the inter-connection of any of the following models:

Manage

Synapse supports the collection and usage of stats (hit rate, failure rate, latency, etc) to monitor and manage the use of services.

It allows the logging and tracing of services.

It supports fault handling.

It allows the securing of services including XML schema validation, authentication, authorization – including both service, operation and content based access control.

Transform

Synapse supports transforming messages using:

XSLT,

simple scripting languages (such as Javascript/E4X), and

hand-coded Java.

Transformations include namespace changes, handling different versions, thru to full XML rewriting.

What Synapse doesn’t support:

Synapse is designed to be per-message stateless. Mediators can aggregate information (e.g. statistics) across messages, but there is NO support in the framework for message level state. Synapse is not designed to support business process management, or complex stateful message flows. Synapse mediators written to perform correlation or use per-message state must do their own management of state and are not guaranteed to be clusterable. Synapse is designed to work with other engines such as BPEL managers that support complex stateful message flow. The reason for this is that Synapse is designed to be embedded in routers, clustered and to perform very fast, and also is designed to address the simple “router” style case.

Mediation architecture

Synapse supports a very simple model for mediation. Each instance of a Synapse engine has a single “master” mediator through which every message flows. That master mediator may be comprised of one or more sub-mediators. Each mediator simply takes a message, reads or modifies it, and passes it on.

There are three main types of mediators:

Grouping mediators (e.g. a list mediator which passes the message through a list of sub-mediators in turn),

Condition mediators (e.g. a mediator which only passes the message through the sub-mediators if the condition is true), and

Leaf mediators – i.e. mediators that actually do something like logging the message.

Each mediator (see org.apache.synapse.api.Mediator) must be thread-safe as many messages may be simultaneously sent through the same instance of a mediator. It is up to the implementor of the mediator to ensure it is threadsafe.

Mediators are effectively JavaBeans which implement the mediate() interface.

Any properties on a mediator are set() on them using the appropriate method. For example the list of sub-mediators is set on a ListMediator by calling setList(List mediators).

The properties on a mediator are set before any mediate messages are passed through it. The properties are not per-message.

Mediators are independent of any XML configuration format. There is an XML configuration format but it is just one potential way of configuring those mediators.

The simplest way of configuring mediators is simply the Java new instantiation. A key design point of Synapse is that there is a programmatic way of instantiating a Synapse instance (This is analogous to the Axis2 model where you can create an empty configuration and populate it).

The XML configuration model (see package org.apache.synapse.xml) is independent of the mediator model. The XML configuration model is based on an xml.MediatorFactory, which simply takes an XML tree and creates a mediator object. This is done recursively until the tree is built. The Java2 JAR file service provider model (see http://java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html#Service%20Provider) is used to automatically register new XML syntaxes.

Relationship to Axis2

The default distribution of Synapse is based on Axis2. The inbound and outbound service listeners and invokers are Axis2 based. However, Synapse has a clean API model that is independent of Axis2. Therefore alternative implementations are possible. However the main aim of this is to make it unnecessary to understand the details of Axis2 to configure or code to Synapse – i.e. this is about providing a clear separation of concerns.

Note - there are some mediators that are dependent on being run in an Axis2 environment (e.g. RM, Sec, Addressing). Any Axis2 dependencies are captured in the packages named *.axis2.*.

Configuration scenarios

Synapse is embedded inside another system and is configured programmatically without any XML or config file, and

Synapse reads its config from an XML file.

However, Synapse is also designed so that it could be embedded in another solution, and might be configured using JMX, WSDM or any other model.

Deployment patterns

Synapse supports several models of deployment:

Explicit proxy or gateway: In this model, service requests are targeted at the Synapse instances endpoint. Synapse must be configured with explicit rules that identify the actual destination of a message and route it there.

HTTP Proxy: In this model, clients are configured to use the Synapse instances endpoint as an HTTP proxy. All messages are sent via Synapse and the actual endpoint of the request is available to the Synapse engine, which it uses to route the message on. This is a simple way of adding Synapse into an existing infrastructure because most service clients allow the configuration of an HTTP proxy without code changes.

Transparent proxy: this is an extension of the previous model, where a network level router transparently routes messages to Synapse. At this level, Synapse can mediate messages without any change to an existing infrastructure.

“SOAP Intermediary”. In this model, the service client explicitly uses WS-A “To” headers, but delivers the message to Synapse to route on. This model is the replacement for the now dead WS-Routing. In Axis2 this can be enabled by explicitly setting the transport headers to pass the message to the Synapse endpoint.

Embedded: In this model Synapse is embedded in a client or server and takes the place of a “smart” or rules-based handler.

SynapseMessage

The core aim of a SynapseMessage is to capture the semantics of a SOAP message plus the context required to mediate it. The SynapseMessage is a simple rendition of a SOAP message plus context. The aim is that the message is injected into Synapse by the underlying framework, mediated by the mediators, and then sent on by the framework.

SynapseEnvironment

A given instance of Synapse is represented by a SynapseEnvironment (see org.apache.synapse.SynapseEnvironment). This provides the interface from the mediators into the underlying environment and thus the separation from – for example – Axis2.

The SynapseEnvironment “in-use” for any given message is kept through a pointer in the message. Thus, if the environment is reloaded or rebuilt (for example if the configuration is changed), then any messages currently flowing through the system retain their flow through the existing environment, while other messages could concurrently be flowing through the rebuilt environment.

Registry interface

The SynapseEnvironment offers mediators access to configuration and the overall SOA “fabric” through the concept of one or more abstract “registries”. The registry is abstractly something that offers access to Strings, Properties, XMLs (including WSDLs, Policies, Schemas), URIs and EndpointReferences. Each “registry” that Synapse has access to has a name, and in addition there is a default registry.

Metrics

In order to manage services, mediators need access to metrics about those services. For example, Synapse can collect metrics about the underlying performance of endpoints that it is calling, and then use that information to load-balance requests across those endpoints.

In general there are three types of metrics:

The actual metrics associated with external endpoints (which may or may not be visible to Synapse)

The metrics for outbound services that Synapse invokes

The metrics for the actual service invocations that Synapse itself makes.

Because of the inherent separation of concerns in the Synapse design, Synapse may be implemented on other systems than Axis2, and so the metrics available from that underlying system are abstracted through the SynapseEnvironment interface:

Metrics getMetrics(String URI);

This method returns an object providing the usual metrics (average response time, hit rate, failure rate, min response time, max response time, etc. Those metrics include metrics for both the time spent inside the local Synapse environment as well as time spent on onbound invocation) for any requests made to the given URI.

The SynapseEnvironment allows multiple “metric” providers to be used. For example, a simple internal system may be used, or a more extensive JMX or WSDM based system may be plugged in via this model. The metric provider is plugged in through the MetricFactory interface.

Events (work in progress)

Another important aspect of an ESB/Mediation fabric is the concept of an event. For example, a typical model is that a mediation engine may generate events – for example – if a failure occurs, or a large transaction goes through.

In order to support a simple event model in Synapse we support a publish capability which is available to a mediator.