This chapter provides instructions for configuring the Oracle Coherence memcached adapter. The memcached adapter allows Coherence to be used as a distributed cache for memcached-based clients. The instructions in this chapter assume that an existing memcached client is being used to connect to Coherence. A simple hello world client that is written using the spymemcached API is provided for demonstration purposes.
This chapter contains the following sections:
The memcached adapter provides access to Coherence caches over the memcached binary protocol and allows Coherence to be used as a drop-in replacement for a memcached server. The adapter supports any memcached client API that supports the memcached binary protocol. This allows memcached clients that are written in many different programming languages to use Coherence.
The memcached adapter is located on a Coherence proxy server and is implemented as a Coherence*Extend-styled acceptor. Memcached clients connect to the acceptor, which manages the distributed cache operations on the cluster. The cache operations are performed as entry processor operations. The acceptor must first be enabled within a proxy service in order to interact with Coherence cached data. Additional features for securing memcached client communication and for sharing data with native Coherence clients are provided and can be configured as required.
Figure 8-1 shows a conceptual view of a memcached client connecting to the memcached acceptor located on a Coherence proxy server in order to use a distributed cache.
Figure 8-1 Conceptual View of a Memcached Client Connection
Memcached adapters are configured within a proxy service using a specific memcached acceptor. The acceptor configuration defines the socket address and the distributed cache for use by memcached clients.
The memcached adapter uses a socket address (IP, or DNS name, and port) for clients to connect to. The socket address is configured in an operational override configuration file using the <address-provider>
element. The address is then referenced from a proxy service definition using the configured id
attribute. For details on the <address-provider>
element, see Oracle Fusion Middleware Developing Applications with Oracle Coherence.
The following example configures a socket address and uses 198.168.1.5
for the IP address, 9099
for the port, and memcached
for the ID.
... <cluster-config> <address-providers> <address-provider id="memcached"> <socket-address> <address>198.168.1.5</address> <port>9099</port> </socket-address> </address-provider> </address-providers> </cluster-config> ...
A proxy service allows remote clients to interact with the caching services of a Coherence cluster without becoming cluster members. A proxy service for the memcached adapter includes a specific memcached acceptor that accepts memcached client requests on a defined socket address and then delegates the requests to a distributed cache.
Note:
The memcached adapter can only use a distributed cache.
To create a proxy service for memcached clients, edit the cache configuration file and add a <proxy-scheme>
element and include the <memcached-acceptor>
element within the <acceptor-config>
element. The <memcached-acceptor>
element must include the name of the cache to use and a reference to an address provider definition that defines the socket address to listen to for memcached client communication. For a detailed reference of the <memcached-acceptor>
element, see Oracle Fusion Middleware Developing Applications with Oracle Coherence.
The following example creates a proxy service and defines a memcached acceptor. The example references the address provider that was defined in Section 8.2.1.
... <caching-schemes> <proxy-scheme> <service-name>MemcachedProxyService</service-name> <acceptor-config> <memcached-acceptor> <cache-name>hello-example</cache-name> <address-provider>memcached</address-provider> </memcached-acceptor> </acceptor-config> <autostart>true</autostart> </proxy-scheme> </caching-schemes> ...
The cache name refers to the hello-example
cache. The cache name must resolve to a distributed cache. The following example shows the definition of the hello-example
cache and the distributed scheme to which it maps.
<?xml version="1.0"?> <cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config" xsi:schemaLocation= "http://xmlns.oracle.com/coherence/coherence-cache-config coherence-cache-config.xsd"> <caching-scheme-mapping> <cache-mapping> <cache-name>hello-example</cache-name> <scheme-name>distributed</scheme-name> </cache-mapping> </caching-scheme-mapping> <caching-schemes> <distributed-scheme> <scheme-name>distributed</scheme-name> <service-name>MemcachedTest</service-name> <backing-map-scheme> <local-scheme/> </backing-map-scheme> <autostart>true</autostart> </distributed-scheme> <proxy-scheme> <service-name>MemcachedProxyService</service-name> <acceptor-config> <memcached-acceptor> <cache-name>hello-example</cache-name> <address-provider>memcached</address-provider> </memcached-acceptor> </acceptor-config> <autostart>true</autostart> </proxy-scheme> </caching-schemes> </cache-config>
Memcached clients must specify the address and port of a proxy service for the memcached adapter. The proxy service address is used in place of the memcached server address. Refer to your memcached client documentation for details on how to specify the address of a memcached server.
The following example shows a simple hello world client that uses the spymemcached client API to connect to the proxy service for the memcached adapter that was defined in Section 8.2.
import net.spy.memcached.AddrUtil; import net.spy.memcached.BinaryConnectionFactory; import net.spy.memcached.MemcachedClient; public class MemcachedExample { public static void main(String[] args) throws Exception { String key = "k1"; String value = "Hello World!"; MemcachedClient c = new MemcachedClient( new BinaryConnectionFactory(), AddrUtil.getAddresses("198.168.1.5:9099")); c.add(key, 0, value); System.out.println((String)c.get(key)); c.shutdown(); } }
The memcached adapter can use both authentication and authorization to restrict access to cluster resources. Authentication support is provided for the SASL (Simple Authentication and Security Layer) plain authentication. Authorization is implemented using Oracle Coherence*Extend-styled authorization, which relies on interceptor classes that provide fine-grained access for cache service operations. The memcached adapter authentication and authorization features reuses much of the existing security capabilities of Oracle Coherence: references are provided to existing content where applicable.
Memcached clients can use SASL plain authentication to provide a username and password when connecting to the memcached adapter. To use SASL plain authentication, you must create an IdentityAsserter
implementation on the proxy. The memcached adapter calls the IdentityAsserter
implementation and passes the com.tangosol.net.security.UsernameAndPassword
object as a token. For details on creating and enabling an IdentityAsserter
implementation, see Oracle Fusion Middleware Securing Oracle Coherence. Refer to your memcached client documentation for details on establishing a SASL plain connection.
In addition to an IdentityAsserter
implementation, authentication must be enabled on a memcached adapter to use SASL plain authentication. To enable authentication, edit the proxy service definition in the cache configuration file and add a <memcached-auth-method>
element, within the <memcached-acceptor>
element, and set it to plain
.
... <caching-schemes> <proxy-scheme> <service-name>MemcachedProxyService</service-name> <acceptor-config> <memcached-acceptor> <cache-name>hello-example</cache-name> <memcached-auth-method>plain</memcached-auth-method> <address-provider>memcached</address-provider> </memcached-acceptor> </acceptor-config> <autostart>true</autostart> </proxy-scheme> </caching-schemes> ...
The memcached adapter relies on the Oracle Coherence*Extend authorization framework to restrict which operations a memcached client performs on a cluster. For detailed instructions about implementing Oracle Coherence*Extend-style authorization, see Oracle Fusion Middleware Securing Oracle Coherence.
The memcached adapter stores entries in a cache using a binary format. If you intend to share the data with Coherence clients, then memcached clients must use a serialization format that Coherence clients also support. Coherence clients typically use Portable Object Format (POF), which is highlighted in this section. For details about POF, see Oracle Fusion Middleware Developing Applications with Oracle Coherence.
To share data between memcached and coherence clients:
Edit the proxy service definition in the cache configuration file and add an <interop-enabled>
element, within the <memcached-acceptor>
element, and set it to true
.
... <proxy-scheme> <service-name>MemcachedProxyService</service-name> <acceptor-config> <memcached-acceptor> <cache-name>hello-example</cache-name> <interop-enabled>true</interop-enabled> <address-provider>memcached</address-provider> </memcached-acceptor> </acceptor-config> <autostart>true</autostart> </proxy-scheme> ...
Enable POF on the distributed cache that is used by the memcached acceptor.
... <distributed-scheme> <scheme-name>distributed</scheme-name> <service-name>MemcachedTest</service-name> <serializer> <instance> <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name> <init-params> <init-param> <param-type>String</param-type> <param-value>memcached-pof-config.xml</param-value> </init-param> </init-params> </instance> </serializer> <backing-map-scheme> <local-scheme/> </backing-map-scheme> <autostart>true</autostart> </distributed-scheme>
Register POF types in the defined POF configuration file. For the above example, the POF configuration file is named memcached-pof-config.xml
. The file must be found on the classpath before the coherence.jar
file. The following example defines a POF user type for the PofUser
object:
<?xml version='1.0'?> <pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config" xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config coherence-pof-config.xsd"> <user-type-list> <include>coherence-pof-config.xml</include> <!-- User types must be above 1000 --> <user-type> <type-id>1001</type-id> <class-name>memcached.PofUser</class-name> </user-type> </user-type-list> </pof-config>
Create a Memcached Client that Uses POF
Many memcached client libraries include the ability to plug in custom serializers. Refer to your memcached client documentation for details on how to plug in custom serializers. The following excerpt shows a spymemcached client that adds the PofUser
object that was registered in step 3 and uses a spymemcached transcoder to plug in the POF serializer.
MemcachedClient client = m_client; String key = "pofKey"; PofUser user = new PofUser("memcached", 1); PofTranscoder<PofUser> tc = new PofTranscoder("memcached-pof-config.xml"); if (!client.set(key, 0, user, tc).get()) { throw new Exception("failed to set value"); }
The POF transcoder plug-in is defined as follows:
import com.tangosol.io.pof.ConfigurablePofContext; import com.tangosol.util.Binary; import com.tangosol.util.ExternalizableHelper; import net.spy.memcached.CachedData; import net.spy.memcached.compat.SpyObject; import net.spy.memcached.transcoders.Transcoder; public class PofTranscoder<T> extends SpyObject implements Transcoder<T> { public PofTranscoder(String sLocator) { m_ctx = new ConfigurablePofContext(sLocator); } @Override public boolean asyncDecode(CachedData arg0) { return Boolean.FALSE; } @Override public T decode(CachedData cachedData) { int nFlag = cachedData.getFlags(); Binary bin = new Binary(cachedData.getData()); return (T) ExternalizableHelper.fromBinary(bin, m_ctx); } @Override public CachedData encode(Object obj) { byte[] oValue = ExternalizableHelper.toByteArray(obj, m_ctx); return new CachedData(FLAG, oValue, CachedData.MAX_SIZE); } @Override public int getMaxSize() { return CachedData.MAX_SIZE; } protected ConfigurablePofContext m_ctx; protected static final int FLAG = 4;