Skip to content

Commit

Permalink
ISPN-6635 ISPN-6636 ISPN-6637 Multi-tenancy for REST and Hotrod
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Laskawiec authored and tristantarrant committed Jan 20, 2017
1 parent 9630ca1 commit 7d500e7
Show file tree
Hide file tree
Showing 143 changed files with 4,154 additions and 190 deletions.
5 changes: 5 additions & 0 deletions bom/pom.xml
Expand Up @@ -280,6 +280,11 @@
<artifactId>infinispan-server-websocket</artifactId> <artifactId>infinispan-server-websocket</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>infinispan-server-router</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>infinispan-spring4-common</artifactId> <artifactId>infinispan-spring4-common</artifactId>
Expand Down
@@ -0,0 +1,20 @@
package org.infinispan.checkstyle.filters;

import java.io.File;

import com.puppycrawl.tools.checkstyle.api.AuditEvent;
import com.puppycrawl.tools.checkstyle.api.Filter;

/**
* Excludes generated packages.
*/
public class ExcludeGeneratedTestPackages implements Filter {

private static final String SUB_PATH = File.separator + "target" + File.separator + "generated-test-sources";

@Override
public boolean accept(AuditEvent aEvent) {
final String fileName = aEvent.getFileName();
return !fileName.contains(SUB_PATH);
}
}
1 change: 1 addition & 0 deletions checkstyle/src/main/resources/checkstyle.xml
Expand Up @@ -127,6 +127,7 @@


<!-- Allow for some code sanity rules to be violated by test code --> <!-- Allow for some code sanity rules to be violated by test code -->
<module name="org.infinispan.checkstyle.filters.ExcludeTestPackages" /> <module name="org.infinispan.checkstyle.filters.ExcludeTestPackages" />
<module name="org.infinispan.checkstyle.filters.ExcludeGeneratedTestPackages" />


<!--&lt;!&ndash; Check that the copyright header is correct (empty) &ndash;&gt;--> <!--&lt;!&ndash; Check that the copyright header is correct (empty) &ndash;&gt;-->
<!--<module name="org.infinispan.checkstyle.filters.HeadersNoCopyrightCheck" />--> <!--<module name="org.infinispan.checkstyle.filters.HeadersNoCopyrightCheck" />-->
Expand Down
@@ -0,0 +1,7 @@
package org.infinispan.commons.test.annotations;

/**
* JUnit category for profiling tests.
*/
public interface Profiling {
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 75 additions & 0 deletions documentation/src/main/asciidoc/server_guide/server_guide.asciidoc
Expand Up @@ -107,3 +107,78 @@ Date: Wed, 10 Aug 2016 10:39:15 GMT
---- ----


Note that the result is exactly the same as the one obtained by CLI interface. Note that the result is exactly the same as the one obtained by CLI interface.

== Multi-tenancy

Multi-tenancy allows accessing multiple containers as shown below:

image::images/multi-tenancy.png[]

Currently there are two supported protocols for accessing the data - using Hot Rod client and using REST interface.

=== Using REST interface

Multi-tenancy router uses URL prefixes to separate containers using the following template: `https://<server_ip>:<server_port>/rest/<rest_connector_name>/<cache_name>/<key>`. All HTTP operations remain exactly the same as using standard `rest-connector`.

=== Using Hot Rod client

Multi-tenant routing for binary protocols requires using a standard, transport layer mechanism such as link:$$https://en.wikipedia.org/wiki/Server_Name_Indication$$[SSL/TLS Server Name Indication]. The server needs to be configured to support encryption and additional SNI routing needs to be added to the `router-connector`.

In order to connect to a secured Hot Rod server, the client needs to use configuration similar to this:

[source,java]
----
ConfigurationBuilder clientBuilder = new ConfigurationBuilder();
clientBuilder
.addServer()
.host("127.0.0.1")
.port(hotrodServer.getPort())
.security()
.ssl()
.enabled(sslClient)
.sniHostName("hotrod-1") // SNI Host Name
.trustStoreFileName("truststore.jks")
.trustStorePassword("secret".toCharArray());
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
----

==== Multi-tenant router

The Multi-tenant router endpoint works as a facade for one or more REST/Hot Rod connectors. Its main purpose is to forward client requests into proper container.

In order to properly configure the routing, `socket-binding` attributes of other connectors must be disabled and additional attribute `name` must be used as shown below:

[source,xml]
----
<rest-connector name="rest-1" cache-container="local"/>
<rest-connector name="rest-2" cache-container="local"/>
<hotrod-connector name="hotrod-1" cache-container="local" />
<hotrod-connector name="hotrod-1" cache-container="local" />
----

The next step is to add a new `router-connector` endpoint and configure how other containers will be accessed. Note that Hot Rod connectors require using TLS/SNI and REST connectors require using prefix in the URL:

[source,xml]
----
<router-connector hotrod-socket-binding="hotrod" rest-socket-binding="rest" keep-alive="true" tcp-nodelay="false" receive-buffer-size="1024" send-buffer-size="1024">
<hotrod name="hotrod-1" >
<sni host-name="hotrod-1" security-realm="SSLRealm1"/>
</hotrod>
<hotrod name="hotrod-2" >
<sni host-name="hotrod-2" security-realm="SSLRealm2"/>
</hotrod>
<rest name="rest-1">
<prefix path="rest-1" />
</rest>
<rest name="rest-2">
<prefix path="rest-2" />
</rest>
</router-connector>
----

With the following configuration, Hot Rod clients will access `hotrod-1` connector when using SNI Host Name "hotrod-1".
REST clients will need to use the following URL to access "rest-1" connector - `https://<server_ip>:<server_port>/rest/rest-1`.
12 changes: 8 additions & 4 deletions object-filter/pom.xml
Expand Up @@ -31,14 +31,18 @@
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>


<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-commons-test</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.antlr</groupId> <groupId>org.antlr</groupId>
<artifactId>antlr-runtime</artifactId> <artifactId>antlr-runtime</artifactId>
</dependency> </dependency>

<dependency> <dependency>
<groupId>org.easytesting</groupId> <groupId>org.assertj</groupId>
<artifactId>fest-assert</artifactId> <artifactId>assertj-core</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>


Expand All @@ -50,7 +54,7 @@
</dependencies> </dependencies>


<properties> <properties>
<suite.exclude.groups>org.infinispan.objectfilter.test.perf.Profiling</suite.exclude.groups> <suite.exclude.groups>org.infinispan.commons.test.annotations.Profiling</suite.exclude.groups>
<intermediary_jar_name>intermediary-${project.build.finalName}</intermediary_jar_name> <intermediary_jar_name>intermediary-${project.build.finalName}</intermediary_jar_name>
<intermediary_jar_path>${project.build.directory}/${intermediary_jar_name}.jar</intermediary_jar_path> <intermediary_jar_path>${project.build.directory}/${intermediary_jar_name}.jar</intermediary_jar_path>
</properties> </properties>
Expand Down
Expand Up @@ -5,6 +5,7 @@


import java.util.Arrays; import java.util.Arrays;


import org.infinispan.commons.test.annotations.Profiling;
import org.infinispan.objectfilter.Matcher; import org.infinispan.objectfilter.Matcher;
import org.infinispan.objectfilter.ObjectFilter; import org.infinispan.objectfilter.ObjectFilter;
import org.infinispan.objectfilter.impl.ReflectionMatcher; import org.infinispan.objectfilter.impl.ReflectionMatcher;
Expand Down

This file was deleted.

@@ -1,5 +1,6 @@
package org.infinispan.objectfilter.test.perf; package org.infinispan.objectfilter.test.perf;


import org.infinispan.commons.test.annotations.Profiling;
import org.infinispan.objectfilter.Matcher; import org.infinispan.objectfilter.Matcher;
import org.infinispan.objectfilter.impl.ProtobufMatcher; import org.infinispan.objectfilter.impl.ProtobufMatcher;
import org.infinispan.objectfilter.test.model.MarshallerRegistration; import org.infinispan.objectfilter.test.model.MarshallerRegistration;
Expand Down
20 changes: 15 additions & 5 deletions parent/pom.xml
Expand Up @@ -146,7 +146,7 @@
<version.jsap>2.1</version.jsap> <version.jsap>2.1</version.jsap>
<version.jstl>1.2</version.jstl> <version.jstl>1.2</version.jstl>
<version.junit>4.11</version.junit> <version.junit>4.11</version.junit>
<version.fest.assertions>1.4</version.fest.assertions> <version.assertj>3.4.1</version.assertj>
<version.log4j>2.5</version.log4j> <version.log4j>2.5</version.log4j>
<version.lucene>5.5.2</version.lucene> <version.lucene>5.5.2</version.lucene>
<version.mc4j>1.2.6</version.mc4j> <version.mc4j>1.2.6</version.mc4j>
Expand All @@ -172,6 +172,7 @@
<version.weld>2.3.4.Final</version.weld> <version.weld>2.3.4.Final</version.weld>
<version.weld-se>2.3.4.Final</version.weld-se> <version.weld-se>2.3.4.Final</version.weld-se>
<version.jgroups.kubernetes>0.9.1</version.jgroups.kubernetes> <version.jgroups.kubernetes>0.9.1</version.jgroups.kubernetes>
<version.jmh>1.12</version.jmh>
<version.oauth.core>20090531</version.oauth.core> <version.oauth.core>20090531</version.oauth.core>


<version.org.wildfly>10.1.0.Final</version.org.wildfly> <version.org.wildfly>10.1.0.Final</version.org.wildfly>
Expand Down Expand Up @@ -429,10 +430,9 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.easytesting</groupId> <groupId>org.assertj</groupId>
<artifactId>fest-assert</artifactId> <artifactId>assertj-core</artifactId>
<version>${version.fest.assertions}</version> <version>${version.assertj}</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.sf.webdav-servlet</groupId> <groupId>net.sf.webdav-servlet</groupId>
Expand Down Expand Up @@ -977,6 +977,16 @@
<scope>import</scope> <scope>import</scope>
<type>pom</type> <type>pom</type>
</dependency> </dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${version.jmh}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${version.jmh}</version>
</dependency>
<dependency> <dependency>
<groupId>org.jgroups.kubernetes</groupId> <groupId>org.jgroups.kubernetes</groupId>
<artifactId>kubernetes</artifactId> <artifactId>kubernetes</artifactId>
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Expand Up @@ -50,6 +50,7 @@
<module>server/hotrod</module> <module>server/hotrod</module>
<module>server/websocket</module> <module>server/websocket</module>
<module>server/rest</module> <module>server/rest</module>
<module>server/router</module>
<module>client/hotrod-client</module> <module>client/hotrod-client</module>
<module>atomic-factory</module> <module>atomic-factory</module>
<module>all</module> <module>all</module>
Expand Down
7 changes: 5 additions & 2 deletions query/pom.xml
Expand Up @@ -102,16 +102,19 @@
<dependency> <dependency>
<groupId>org.testng</groupId> <groupId>org.testng</groupId>
<artifactId>testng</artifactId> <artifactId>testng</artifactId>
<scope>test</scope>
</dependency> </dependency>


<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope>
</dependency> </dependency>


<dependency> <dependency>
<groupId>org.easytesting</groupId> <groupId>org.assertj</groupId>
<artifactId>fest-assert</artifactId> <artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency> </dependency>


<dependency> <dependency>
Expand Down
@@ -1,7 +1,7 @@
package org.infinispan.query.dsl.embedded.impl; package org.infinispan.query.dsl.embedded.impl;




import static org.fest.assertions.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;


import org.hibernate.search.annotations.Analyze; import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.DocumentId; import org.hibernate.search.annotations.DocumentId;
Expand Down
@@ -1,6 +1,6 @@
package org.infinispan.query.dsl.embedded.impl; package org.infinispan.query.dsl.embedded.impl;


import static org.fest.assertions.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;


import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
Expand Down
Expand Up @@ -7,7 +7,7 @@
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;


import org.fest.util.Collections; import org.assertj.core.util.Sets;
import org.infinispan.Cache; import org.infinispan.Cache;
import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.cache.Index; import org.infinispan.configuration.cache.Index;
Expand Down Expand Up @@ -85,7 +85,7 @@ public void testQueryCache() throws Exception {
// ensure the query cache has it now: one FilterParsingResult and one LuceneQueryParsingResult // ensure the query cache has it now: one FilterParsingResult and one LuceneQueryParsingResult
assertEquals(2, internalCache.size()); assertEquals(2, internalCache.size());
Set<Class<?>> cacheValueClasses = internalCache.entrySet().stream().map(e -> e.getValue().getClass()).collect(Collectors.toSet()); Set<Class<?>> cacheValueClasses = internalCache.entrySet().stream().map(e -> e.getValue().getClass()).collect(Collectors.toSet());
Set<Class<?>> expectedCachedValueClasses = Collections.set(FilterParsingResult.class, LuceneQueryParsingResult.class); Set<Class<?>> expectedCachedValueClasses = Sets.newLinkedHashSet(FilterParsingResult.class, LuceneQueryParsingResult.class);
assertEquals(expectedCachedValueClasses, cacheValueClasses); assertEquals(expectedCachedValueClasses, cacheValueClasses);


// ensure the QueryCreator does not get invoked now // ensure the QueryCreator does not get invoked now
Expand Down
Expand Up @@ -69,7 +69,8 @@ protected void startInternal(A configuration, EmbeddedCacheManager cacheManager)
// Start default cache // Start default cache
startDefaultCache(); startDefaultCache();


startTransport(); if(configuration.startTransport())
startTransport();
} }


@Override @Override
Expand Down Expand Up @@ -122,7 +123,7 @@ protected void unregisterTransportMBean() throws Exception {
} }
} }


protected String getQualifiedName() { public String getQualifiedName() {
return protocolName + (configuration.name().length() > 0 ? "-" : "") + configuration.name(); return protocolName + (configuration.name().length() > 0 ? "-" : "") + configuration.name();
} }


Expand Down Expand Up @@ -165,4 +166,12 @@ public A getConfiguration() {
protected void startDefaultCache() { protected void startDefaultCache() {
cacheManager.getCache(configuration.defaultCacheName()); cacheManager.getCache(configuration.defaultCacheName());
} }

public boolean isTransportEnabled() {
return transport != null;
}

public NettyTransport getTransport() {
return transport;
}
} }
Expand Up @@ -20,8 +20,9 @@ public abstract class ProtocolServerConfiguration {
private final boolean tcpNoDelay; private final boolean tcpNoDelay;
private final int workerThreads; private final int workerThreads;
private final Set<String> ignoredCaches; private final Set<String> ignoredCaches;
private final boolean startTransport;


protected ProtocolServerConfiguration(String defaultCacheName, String name, String host, int port, int idleTimeout, int recvBufSize, int sendBufSize, SslConfiguration ssl, boolean tcpNoDelay, int workerThreads, Set<String> ignoredCaches) { protected ProtocolServerConfiguration(String defaultCacheName, String name, String host, int port, int idleTimeout, int recvBufSize, int sendBufSize, SslConfiguration ssl, boolean tcpNoDelay, int workerThreads, Set<String> ignoredCaches, boolean startTransport) {
this.defaultCacheName = defaultCacheName; this.defaultCacheName = defaultCacheName;
this.name = name; this.name = name;
this.host = host; this.host = host;
Expand All @@ -33,6 +34,7 @@ protected ProtocolServerConfiguration(String defaultCacheName, String name, Stri
this.tcpNoDelay = tcpNoDelay; this.tcpNoDelay = tcpNoDelay;
this.workerThreads = workerThreads; this.workerThreads = workerThreads;
this.ignoredCaches = ignoredCaches; this.ignoredCaches = ignoredCaches;
this.startTransport = startTransport;
} }


public String defaultCacheName() { public String defaultCacheName() {
Expand Down Expand Up @@ -79,6 +81,10 @@ public Set<String> ignoredCaches() {
return ignoredCaches; return ignoredCaches;
} }


public boolean startTransport() {
return startTransport;
}

@Override @Override
public String toString() { public String toString() {
return "ProtocolServerConfiguration [defaultCacheName=" + defaultCacheName +", name=" + name + ", host=" + host + ", port=" + port + ", idleTimeout=" + idleTimeout + ", recvBufSize=" + recvBufSize + ", sendBufSize=" return "ProtocolServerConfiguration [defaultCacheName=" + defaultCacheName +", name=" + name + ", host=" + host + ", port=" + port + ", idleTimeout=" + idleTimeout + ", recvBufSize=" + recvBufSize + ", sendBufSize="
Expand Down
Expand Up @@ -22,6 +22,7 @@ public abstract class ProtocolServerConfigurationBuilder<T extends ProtocolServe
protected boolean tcpNoDelay = true; protected boolean tcpNoDelay = true;
protected int workerThreads = 2 * Runtime.getRuntime().availableProcessors(); protected int workerThreads = 2 * Runtime.getRuntime().availableProcessors();
protected Set<String> ignoredCaches = Collections.EMPTY_SET; protected Set<String> ignoredCaches = Collections.EMPTY_SET;
protected boolean startTransport = true;


protected ProtocolServerConfigurationBuilder(int port) { protected ProtocolServerConfigurationBuilder(int port) {
this.port = port; this.port = port;
Expand Down Expand Up @@ -110,6 +111,12 @@ public void validate() {
} }
} }


@Override
public S startTransport(boolean startTransport) {
this.startTransport = startTransport;
return this.self();
}

@Override @Override
public Builder<?> read(T template) { public Builder<?> read(T template) {
this.defaultCacheName = template.defaultCacheName(); this.defaultCacheName = template.defaultCacheName();
Expand Down
Expand Up @@ -65,6 +65,11 @@ public interface ProtocolServerConfigurationChildBuilder<T extends ProtocolServe
*/ */
S ignoredCaches(Set<String> ignoredCaches); S ignoredCaches(Set<String> ignoredCaches);


/**
* Indicates whether transport implementation should or should not be started.
*/
S startTransport(boolean startTransport);

/** /**
* Builds a configuration object * Builds a configuration object
*/ */
Expand Down

0 comments on commit 7d500e7

Please sign in to comment.