Correct grammar, spelling and verbiage in the Multi-Site Caching Guide.

Resolves gh-80.
This commit is contained in:
John Blum
2020-04-19 20:46:00 -07:00
parent 01e0f2f5f0
commit ff9594e26d

View File

@@ -39,6 +39,7 @@ link:../index.html[Index]
link:../index.html#geode-samples[Back to Samples]
[[geode-samples-caching-multisite-background]]
== Background
@@ -198,7 +199,7 @@ by using the _Multi-Site Caching_ pattern along with giving you the configuratio
== Example
For our example, we are going to build on the Spring code snippet above, using the `CustomerService` class with
the _Look-Aside Caching_ pattern applied, then enhance the caching solution with an _Active-Active_, Multi-Site,
the _Look-Aside Caching_ pattern applied, then enhance the caching solution with an _Active-Active_, Multi-Site
WAN topology.
However, instead of looking up `Customers` by `Account` number, we are simply going to lookup `Customers` by "name".
@@ -216,7 +217,7 @@ include::{samples-dir}/caching/multi-site/src/main/java/example/app/caching/mult
NOTE: The `Customer` class uses https://projectlombok.org/[Project Lombok] to simplify the implementation.
The `Customer` class is mapped to the "Customers" `Region` using the SDG `@Region` mapping annotation. The `@Region`
annotation is very similar in purpose to the JPA `@Entity` and `@Table` annotation. A `Customer` is very simply defined
annotation is very similar in purpose to the JPA `@Entity` and `@Table` annotations. A `Customer` is very simply defined
in terms of an `id` and `name`, which will be used to lookup a `Customer`.
[[geode-samples-caching-multisite-example-customerservice]]
@@ -244,24 +245,24 @@ cache the results of the `findBy(..)` method. Since a `Customer's` "name" is not
candidate for caching.
`@Cacheable` works by first searching for the `Customer` by "name" in the "CustomerByName" cache. If an entry is found,
then the cached value (i.e. `Customer`) is returned. Otherwise, the `findBy(..)` method is invoked to lookup the
`Customer` by "name". When the `findBy(..)` method returns, assuming it does not return a `null` value, then `@Cacheable`
will store the `Customer` in the cache keyed by the `Customer's` "name" (i.e. the "name" argument passed to
the `findBy(..)` method).
then the cached value (i.e. `Customer`) is returned immediately, without invoking the `findBy(..)` method. Otherwise,
the `findBy(..)` method is invoked to lookup the `Customer` by "name". When the `findBy(..)` method returns, assuming
it does not return a `null` value, then `@Cacheable` logic will store the `Customer` in the cache keyed by the
`Customer's` "name" (i.e. the "name" argument passed to the `findBy(..)` method).
To make the `findBy(..)` operation appear to be expensive (either time or resource consuming), we add a safe Thread
sleep call. Otherwise, the `findBy(..)` method simply constructs a new `Customer` with the given "name" and returns it.
The `CustomerService` class contains a `isCacheMiss()` method to determine whether the `Customer` was found in the cache
mapped to the givne "name", or if the `findBy(..)` method had to be invoked (i.e. a _cache miss_).
mapped to the given "name", or if the `findBy(..)` method had to be invoked (i.e. a _cache miss_).
What is not apparent from looking at the `findBy(..)` service method is how the _Look-Aside Cache_ pattern is decorated,
or enhanced with _Multi-Site (WAN) Caching_. It turns out to be all in the configuration as we will see further below.
or enhanced by _Multi-Site (WAN) Caching_. It turns out to be all in the configuration as we will see further below.
[[geode-samples-caching-multisite-example-customercontroller]]
=== `CustomerController` class
Finally, we add `CustomerController` class exposing a simple REST interface for our application:
Finally, we add `CustomerController` class exposing a simple REST interface to the Web application:
.CustomerController class
[source,java]
@@ -270,7 +271,7 @@ include::{samples-dir}/caching/multi-site/src/main/java/example/app/caching/mult
----
The `CustomerController` is a Spring Web MVC `@RestController`, which uses the `CustomerService` class, and allows users
to search for `Customers` using a Web browser.
to search for `Customers` by "name" using a Web browser.
[[geode-samples-caching-multisite-example-client-app]]
=== Spring Boot, {geode-name} `ClientCache` application
@@ -411,12 +412,12 @@ Compare and contrast this with the Spring Boot `application.properties` for clus
[[geode-samples-caching-multisite-example-server-configuration]]
=== Cluster/Server Configuration
Let's break down the `BootGeodeMultiSiteCachingServerApplication` class configuration a bit further.
Let's break down the `BootGeodeMultiSiteCachingServerApplication` class configuration in more detail.
[[geode-samples-caching-multisite-example-server-configuration-cacheserver-region]]
==== `CacheServer` and "_CustomersByName_" `Region` Configuration
First, we have the configuration for the peer `Cache`, `CacheServer` and "CustomersByName" REPLICATE `Region`:
This first bit of configuration creates a peer `Cache`, a `CacheServer` and the "CustomersByName" REPLICATE `Region`:
.CacheServer & Region
[source,java]
@@ -425,24 +426,24 @@ include::{samples-dir}/caching/multi-site/src/main/java/example/app/caching/mult
----
The `CacheServer` port is set to the ephemeral port (i.e. `0`) to let the system allocate a port. Since the client is
connecting to the cluster via a Locator, the Locator sends meta-data about the cluster to the client thereby informing
connecting to the cluster via a Locator, the Locator sends meta-data about the cluster to the client informing
the client of the available `CacheServers`, which server is hosting what data, the port(s) the `CacheServer(s)`
are listening on, and so on.
The name of the client and server-side Region backing the cache named in the `@Cacheable` annotation declared on
The name of the client and server-side `Region` backing the cache named in the `@Cacheable` annotation declared on
the `CustomerService.findBy(..)` method must match. The client-side "CustomersByName" `Region` is a PROXY, and
therefore forwards all data access operations to the matching server-side REPLICATE Region by the same name
therefore forwards all data access operations to the matching server-side REPLICATE `Region` by the same name
(i.e. "CustomersByName").
TIP: The `DataPolicy` of the server-side, "CustomersByName" `Region` could have been PARTITION, sharding the data across
the servers in the cluster that host the "CustomersByName" `Region`. However, it is common for "reference" data, such as
"cached" data, to be stored in a REPLICATE `Region`. However, if the data is transactional in anyway, then it is
recommended that you use a PARTITION `Region`.
TIP: The `DataPolicy` of the server-side, "CustomersByName" `Region` could have been PARTITION, thereby sharding the
data across the servers in the cluster that host the "CustomersByName" `Region`. However, it is common for "reference"
data, such as "cached" data, to be stored in a REPLICATE `Region`. Although, if the data is transactional in nature,
then it is recommended that you use a PARTITION `Region`.
[[geode-samples-caching-multisite-example-server-configuration-locator-manager]]
==== `Locator` and `Manager` Configuration
The next bit of configuration involves enabling the embedded Locator and starting a Manager service inside the server:
The next bit of configuration enables an embedded Locator and starts a Manager service inside the server:
.Locator & Manager
[source,java]
@@ -450,8 +451,8 @@ The next bit of configuration involves enabling the embedded Locator and startin
include::{samples-dir}/caching/multi-site/src/main/java/example/app/caching/multisite/server/BootGeodeMultiSiteCachingServerApplication.java[tags=locator-manager-configuration]
----
If you are starting up a multi-node cluster, then you can choose whether to start an embedded Locator & Manager
on a node-by-node basis. If you do, you must vary the port numbers or configure the Locator & Manager using
If you are starting up a multi-node cluster, then you can choose whether to start an embedded Locator and Manager
on a node-by-node basis. If you do, you must vary the port numbers or configure the Locator and Manager using
the ephemeral port.
We'll see below how configuring a Manager can be useful for inspecting the cluster using _Gfsh_. But first, let's
@@ -460,9 +461,9 @@ talk about the final bit of configuration that enables _Multi-Site Caching_ with
[[geode-samples-caching-multisite-example-server-configuration-gateway-sender-receiver]]
==== `GatewaySender` and `GatewayReceiver` Configuration
The final bit of configuration configures a `GatewaySender` for sending `Region` operations from this cluster
(e.g. cluster #1) to a remote cluster (e.g. cluster #2). Gateways are an essential component for enabling
_Multi-Site Caching_ using a WAN topology:
The final bit of configuration configures a `GatewaySender` for sending `Region` events from this cluster
(i.e. cluster #1) to a remote cluster (e.g. cluster #2). {geode-name} (or {gemfire-name}) Gateways are the essential
component for enabling _Multi-Site Caching_ using a WAN topology:
.Gateway Sender & Receiver
[source,java]
@@ -474,35 +475,37 @@ Just as the Locator communicates cluster meta-data to the clients allowing clien
servers, and specifically `CacheServers` in the cluster, the remote Locator endpoint communicates cluster meta-data
between sites.
While a `GatewaySender` is configured per `Region`, a `GatewayReceiver` is setup for the entire cluster, and the Gateway
events are then routed to the right cluster objects, typically `Regions`. `GatewaySenders` are `Region` specific since
you might have different {apache-geode-javadoc}/org/apache/geode/cache/wan/GatewayEventFilter.html[event filters]
combined with {apache-geode-javadoc}/org/apache/geode/cache/wan/GatewayEventSubstitutionFilter.html[event substitution filtering]
or different {apache-geode-javadoc}/org/apache/geode/cache/wan/GatewayTransportFilter.html[transports], etc.
While a `GatewaySender` is configured per `Region`, a `GatewayReceiver` is setup per server, and the Gateway events
are routed to the appropriate server objects, such as `Regions`. `GatewaySenders` are `Region` specific since you might
have different {apache-geode-javadoc}/org/apache/geode/cache/wan/GatewayEventFilter.html[event filters] coupled with
{apache-geode-javadoc}/org/apache/geode/cache/wan/GatewayEventSubstitutionFilter.html[event substitution filtering],
or be using different {apache-geode-javadoc}/org/apache/geode/cache/wan/GatewayTransportFilter.html[transports], etc.
You can even control the _concurrency-level_ along with the {apache-geode-javadoc}/org/apache/geode/cache/wan/GatewaySender.OrderPolicy.html[order of events]
passing through the Gateway(s). In fact, there are many aspects of Gateways you can control, different configurations to
use, conflict resolution policies, etc, setup to properly address the unique requirements (or SLAs) of your application
use case(s), that are quite frankly, well beyond the scope of this guide. Therefore, you are encouraged to follow the
{apache-geode-docs}/topologies_and_comm/multi_site_configuration/chapter_overview.html[User Guide] for further guidance.
passing through the Gateway(s). In fact, there are many aspects of Gateways you can control, different configurations
you can use, conflict resolution policies, etc, in order to properly address the unique requirements (or SLAs) of your
application use case(s), that are quite frankly, well beyond the scope of this guide. Therefore, you are encouraged to
follow the {geode-name} {apache-geode-docs}/topologies_and_comm/multi_site_configuration/chapter_overview.html[User Guide]
for further guidance.
Although, there is 1 aspect of the configuration we want to address here, and that is _Active-Active_
Although, there is 1 aspect of the Gateway configuration we want to address here, and that is _Active-Active_
vs. _Active-Passive_.
Currently, the example is setup to use _Active-Active_ replication, where all clusters are actors in the overall
system architecture. However, it is a simple matter to setup our system architecture using the _Active-Passive_ pattern.
system architecture. However, it is a simple matter to setup the system architecture using an _Active-Passive_
WAN Gateway pattern.
You can do this by limiting the `GatewaySender` configuration to, for example, cluster/site #1. That is, you do not
You do this by limiting the `GatewaySender` configuration to cluster/site #1, for example. That is, you do not
configure a `GatewaySender` on the "CustomersByName" `Region` in cluster/site #2. Cluster #2 still requires a
`GatewayReceiver` so events sent from cluster #1 are received by and replicated in cluster #2. This arrangement is used
in cases where no clients can actively connect directly to cluster #2 thereby positioning cluster #2 for standby in the
event the cluster #1 goes down.
`GatewayReceiver` so Gateway events sent from cluster #1 are received by and replicated in cluster #2. This arrangement
is commonly used to position cluster #2 for standby in the event that cluster #1 goes down. As such, no clients can
connect directly to cluster #2.
Therefore, we have declared Spring Profiles for each side of the Gateway, the receiving side (`GatewayReceiver`) along
The configuration declares Spring Profiles for each side of the Gateway, the receiving side (`GatewayReceiver`) along
with the sending side (`GatewaySender`). The sending side clearly does not require a `GatewayReceiver` when it is the
"_Active_" cluster in the _Active-Passive_ architecture. _Active-Passive_ replication is 1-way.
Now that we have talked about the configuration in detail, let's run the example and have a look at the cluster
Now that we have talked about the configuration in more detail, let's run the example and have a look at the cluster
using _Gfsh_.
[[geode-samples-caching-multisite-example-run]]
@@ -540,10 +543,11 @@ configuration. The configuration for each cluster has been neatly encapsulated i
file denoted by a Spring Profile, i.e. `server-site1` for cluster #1 and `server-site2` for cluster #2.
Therefore, to start a cluster, simply run the `BootGeodeMultiSiteCachingServerApplication` class from your IDE
and enable the Spring Profile for the cluster you want start, e.g. cluster #1 using:
and enable the Spring Profile for the cluster you want start, e.g. to start cluster #1 use:
`-Dspring.profiles.active=server-site1`.
To run cluster #2, simply create another run configuration with the Spring Profile set to `server-site2`.
To start cluster #2, simply create another run configuration in your IDE with the
`BootGeodeMultiSiteCachingServerApplication` class with the Spring Profile set to `server-site2`.
When the cluster starts up, you should see log output similar to (log output formatted to fit this guide):
@@ -860,7 +864,7 @@ Region | data-policy | REPLICATE
----
Even though the `GatewaySender` and `GatewayReceiver` were configured correctly, _Gfsh_ apparently is not aware of it,
at least not by `list gateways`:
at least not by `list gateways` command, anyway:
[source,text]
----
@@ -870,7 +874,7 @@ GatewaySenders or GatewayReceivers are not available in cluster
----
Interestingly, the `describe region` command for the "CustomersByName" `Region` does appropriately show the `Region`
has a `GatewaySender` identified as "customersByNameGatewaySender".
has a `GatewaySender` identified as "customersByNameGatewaySender", as we expect!
[[geode-samples-caching-multisite-example-run-clients]]
=== Start the Clients
@@ -1068,12 +1072,12 @@ After the client has successfully started, you can see that the client has conne
.Client connected to cluster
[source,text]
----
Cluster-10 gfsh>list clients
list clients
Client List
Client Name / ID | Server Name / ID
------------------------------------------------------------------------------------------------------------------------
10.99.199.24(BootGeodeMultiSiteCachingClientApplication-Site1:47756:loner):... | member=BootGeodeMultiSiteCachingServerApplication-Site1,port=51682
Client Name / ID | Server Name / ID
------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------
10.99.199.24(BootGeodeMultiSiteCachingClientApplication-Site1:47756:loner):52447:333e0094:BootGeodeMultiSiteCachingClientApplication-Site1 | member=BootGeodeMultiSiteCachingServerApplication-Site1,port=51682
----
@@ -1096,17 +1100,16 @@ effects of a resource expensive operation, we add a 5 second delay, which if you
include::{samples-dir}/caching/multi-site/src/main/java/example/app/caching/multisite/client/service/CustomerService.java[tags=find-by-name]
----
On subsequent access, the operation results in a cache hit given the same argument (e.g. "JonDoe"), and we again witness
the effects that caching now has on our application (i.e. no 5 second delay; the result is returned immediately).
On subsequent access, the operation results in a cache hit when given the same argument (e.g. "JonDoe"), and we again
witness the effects that caching now has on our application (i.e. no 5 second delay; the result is returned immediately).
Simply hit refresh in your Web browser to resubmit the HTTP request and receive a response:
image::{images-dir}/Multi-Site-Caching-Client-Application-1-Customer-JonDoe-CacheHit.png[]
Of course, this only half of the equation. What happens when we access "JonDoe" from site #2 using client #2?
Well, "JonDoe" has already been replicated from cluster #1 to cluster #2 and therefore, the operation results in
a cache hit:
This time, the access was a cache hit! Of course, this is only half of the equation. What happens when we access
"JonDoe" from site #2 using client #2? Well, "JonDoe" has already been replicated from cluster #1 to cluster #2
and therefore, the operation results in a cache hit:
image::{images-dir}/Multi-Site-Caching-Client-Application-2-Customer-JonDoe-CacheHit.png[]
@@ -1117,14 +1120,13 @@ image::{images-dir}/Multi-Site-Caching-Client-Application-2-Customer-JaneDoe-Cac
Of course, if we hit refresh in our Web browser, then the subsequent access of "JaneDoe" from client #2 should result
in a cache hit. However, without hitting refresh, let's immediately go back to client #1 and try to access "JaneDoe".
The result is already a cache hit since the "JaneDoe" has already been replicated between the 2 sites over the WAN
Gateways:
The result is a cache hit since the "JaneDoe" has already been replicated between the 2 sites over the WAN Gateways:
image::{images-dir}/Multi-Site-Caching-Client-Application-1-Customer-JaneDoe-CacheHit.png[]
After our testing, we can query the data in _Gfsh_:
In addition to testing in a Web browser, you can also query the data using _Gfsh_:
.Querying the Customers from Gfsh
.Querying "CustomersByName" from Gfsh
[source,text]
----
Cluster-10 gfsh>describe region --name=CustomersByName
@@ -1162,10 +1164,11 @@ configured, SBDG will configure {geode-name}'s PDX Serialization framework.
PDX allows you to query objects in serialized form, without causing a deserialization, as long as you know the structure
of your application domain model types. Using PDX can be helpful in situations where your application domain model types
refer to 3rd party library types you cannot control, and that may not be `java.io.Serializable`.
refer to 3rd party library types you cannot control, and that may not implement `java.io.Serializable`.
You should refer to the {geode-name} User Guide on more details on
{apache-geode-docs}/developing/data_serialization/gemfire_pdx_serialization.html[PDX].
TIP: You should refer to the {geode-name} User Guide on more details on
{apache-geode-docs}/developing/data_serialization/gemfire_pdx_serialization.html[PDX]. You can also refer to SBDG's
support of link:../index.html#geode-data-serialization[PDX Serialization].
You can try other experiments, too. For example, you can rerun this example with the _Active-Passive_ pattern, which we
leave as an exercise for the curious reader.
@@ -1175,7 +1178,7 @@ leave as an exercise for the curious reader.
You have now just learned and witnessed first-hand the power of _Look-Aside Caching_ enhanced with _Multi-Site Caching_,
implemented with {geode-name} (or {gemfire-name}) WAN Gateway functionality. This is but a simple example. WAN Gateway
functionality can accommodate a wide-range of different use cases.
functionality can accommodate a wide-range of different use cases and complex configuration.
Imagine if timely and accurate (i.e. "consistent") information is a major concern for your application use case
and your application is backed by an RDBMS for its _System of Record_ (SOR). How do you keep the remote database
@@ -1186,11 +1189,11 @@ between the clusters, like so:
image::{images-dir}/Look-Aside--Near--Inline--Multi-Site-Caching.png[]
In this image, we also depicted the use of _Near Caching_ to reduce network traffic. The system architecture could
optionally use the _Active-Active_ WAN Gateway pattern and the cluster on the right, could optionally serve application
clients, or not, which might be the case in an _Active-Passive_ configuration. The choice is yours and you are only
limited by your imagination and constrained by your application requirements. Whatever the case, you have extreme power
and flexibility at your fingertips.
In this image, we also depicted the use of _Near Caching_ to reduce network traffic between the client(s)
and the servers in the cluster. The system architecture could optionally use the _Active-Active_ WAN Gateway pattern
and the cluster on the right could optionally serve application clients, or not, which might be the case in an
_Active-Passive_ configuration. The choice is yours and you are only limited by your imagination and constrained by
your application requirements. Whatever the case, you have extreme power and flexibility at your fingertips.
Indeed, when you combine and apply multiple patterns of caching (_Look-Aside_, _Near_, _Inline_ and now,
_Multi-Site Caching_) to your applications, you can greatly enhance your end-users experience.