Edit Sample Guide on Near Caching.

Fix grammatical and spelling errors.

Make the prose more concise.
This commit is contained in:
John Blum
2019-08-13 01:05:38 -07:00
parent 114dae5df3
commit 4c505e7568

View File

@@ -32,7 +32,7 @@ link:../index.html#geode-samples[Back]
In the first sample on link:caching-look-aside.html[_Look-Aside Caching_], we paved the foundation for using caching in
your Spring Boot applications. _Look-Aside Caching_ makes efficient use of resources (e.g. by reducing contention on
the database, or by reducing the number of network calls between Microservices in a distributed system) simply by
keeping frequently (read) accessed data in-memory for quick retrieval, which can improve throughput and reduce latency.
keeping frequently accessed data in-memory for quick retrieval (reads), which can improve throughput and reduce latency.
In the second sample, we expanded on _Look-Aside Caching_ with link:caching-inline.html[_Inline Caching_] and extended
the _Look-Aside Caching_ pattern to "_read/write-through_" to a backend data source (e.g. database). The backend data
@@ -45,13 +45,12 @@ or the _Inline Caching_ pattern to your Spring Boot application(s). This is esp
multiple instances of the same application in a Microservices architecture.
Multiple, Microservice, application instances will need a consistent view of the data, especially in a load-balanced,
cloud environment where separate client requests, that are part of the same session, could be routed to different
cloud-native environment where separate client requests, that are part of the same session, could be routed to different
application instances. Therefore, application state needs to be maintained independent of the application instances.
NOTE: _Sticky Sessions_ could be used to keep the conversational state associated with a user's Session tied to a single
application instance. However, using _Sticky Sessions_ is not resilient to failures and as such, are essentially an
anti-pattern in a cloud context. You should avoid the use of _Stick Sessions_, particularly in a cloud environment,
whenever possible.
NOTE: _Sticky Sessions_ can be used to keep conversational state associated with a user's Session tied to a single
application instance. However, use of _Sticky Sessions_ is not resilient to failures, and as such, essentially become
an anti-pattern in a cloud context. You should avoid using _Stick Sessions_ in a cloud environment whenever possible.
To keep up with demand and not overload backend systems, like a database, you would have to scale-up with more Memory,
more CPU, more Disk, more Network bandwidth, basically, more of everything, which can be a very costly endeavor as you
@@ -59,40 +58,40 @@ try to keep up with the every growing demand (which is a good problem to have, b
image::../images/Small-Database-To-Big-Database.png[]
Rather than scaling-up, you could scale-out by using a sophisticated caching technology that uniformly partitions data
across a cluster of data nodes thereby enabling data access operations to be evenly distributed and intelligently routed
across the cluster. In addition, data can be replicated for both redundancy and high-availability (HA) purposes making
the cluster more resilient to failure. Such a data management technology is ideal in a cloud environment. The cluster
acts as a single, logical unit of pooled resources (Memory, CPU, Disk, and Network) but uses a shared-nothing
architecture.
Rather than scale-up, you could scale-out by using a sophisticated caching technology that uniformly partitions data
across a cluster of data nodes thereby enabling data access operations to be intelligently routed and evenly distributed
across the cluster. In addition, data can be replicated for redundancy and high-availability (HA) purposes making the
cluster more resilient to failure. Such a data management technology is ideal in a cloud environment. The cluster acts
as a single, logical unit of pooled resources (Memory, CPU, Disk, and Network) but uses a shared-nothing architecture.
That is, no node in the cluster can be a single point of failure.
image::../images/Cluster.png[]
From a Spring Boot application's point-of-view, it is a client in this architecture, and multiple application instances
can access and share the same data. Indeed, in a Microservices architecture, another application instance must be
prepared to take over in a moments notice if any application instance goes down in order to avoid any perceived
disruption in the users' service.
From a Spring Boot application's point-of-view, it is the client in this application architecture, and multiple
application instances can access and share the same data. Indeed, in a Microservices architecture, another application
instance must be prepared to take over in a moments notice if any application instance goes down in order to avoid any
perceived disruption in the users' service.
However, even in a sophisticated, scale-out, client/server architecture such as the one we described above, it still
involves network access, even if only a "single-hop".
involves network access, even if only a "_single-hop_".
So, how might we use caching, to yet again, further reduce resource consumption (e.g. Network) even further?
So, how might we use caching to further reduce resource consumption (e.g. Network) in our application architecture?
The key lies in keeping data closer to the point of access, i.e. on the client, in our Spring Boot application.
In essence, we put more responsibility on our Spring Boot applications by increasing the participation of our
applications in this slightly modified architecture in a "_pro-active_" way.
In essence, we put more responsibility on our Spring Boot application by increasing the participation of our application
in this slightly modified architecture, in a "_pro-active_" way.
Enter *_Near Caching_*.
Basically, in addition to our server-side, peer node, cache topology, the client additionally caches data, but only
the data it is most "_interested_" in.
the data it is "_interested_" in.
Additionally, rather than the client having to pull for data changes, the data can be pushed to the client when the data
changes, based on its "_registered interests_". Therefore, the client only receives the data it is interested in,
changes, based on its "_registered interests_". Therefore, the client only receives the data it subscribed to,
in the first place.
Furthermore, the data change events can be conflated so our client application only sees the latest updates, not every
single change that may have occurred due to other application instances accessing the same data.
single change that may have occurred due to other application instances modifying the same data, possibly concurrently.
These 3 things in conjunction with each other should have a net effect of reducing noise and network saturation.
@@ -106,22 +105,22 @@ It is now time to see the _Near Caching_ pattern in action.
[[geode-samples-caching-near-example]]
== Example
For our example, we will develop a Yellow Pages application with the ability to lookup a person by name to retrieve
their contact information, such as an email address and phone number.
For our example, we develop a _Yellow Pages_ application with the ability to lookup a person by name and retrieve
the person's contact information, such as an email address and phone number.
[[geode-samples-caching-near-example-server-side]]
=== Server-side
=== Server-side Configuration
First, we will configure and bootstrap an Apache Geode, peer `CacheServer` node using Spring Boot:
.SpringBootApplication for a Geode `CacheServer`
.SpringBootApplication for an Apache Geode `CacheServer`
[source,java]
----
include::{samples-dir}/caching/near/src/main/java/example/app/caching/near/server/BootGeodeNearCachingCacheServerApplication.java[tags=class]
----
This class consists of Spring `@Configuration` class to configure the necessary server-side Region (i.e "_YellowPages_")
used to store a person's contact information:
This class consists of a Spring `@Configuration` class to configure the necessary server-side Region
(i.e "_YellowPages_") used to store a person's contact information:
.Server-side Configuration
@@ -131,9 +130,9 @@ include::{samples-dir}/caching/near/src/main/java/example/app/caching/near/serve
----
The pertinent bit of this configuration is the subscription conflation on the "_YellowPages_" Region. This setting
ensures that only the latest information (i.e. person contact information) is sent to the clients. It is possible
that multiple clients maybe accessing and updating a person's contact information. Therefore, we want to make sure
all the clients have, and are only sent, the latest information, which therefore reduces load on our network.
ensures that only the latest information is sent to the clients. It is possible that multiple clients maybe accessing
and updating a person's contact information. Therefore, we want to make sure all the clients have, and are only sent,
the latest information, which therefore reduces traffic across our network.
We include a Spring Boot `ApplicationRunner` with a few assertions to make sure the server is configured properly
on startup:
@@ -144,10 +143,9 @@ on startup:
include::{samples-dir}/caching/near/src/main/java/example/app/caching/near/server/BootGeodeNearCachingCacheServerApplication.java[tags=application-runner]
----
And finally, we include a Spring `@Profile` to enable an embedded Apache Geode Locator and Manager, allowing us to connect
to our Spring Boot, Apache Geode `CacheServer` application using _Gfsh_ (Geode Shell). Enabling the embedded Locator
and Manager are not necessary when starting the server and running our application. We will see an example
of this later:
And finally, we include a Spring `@Profile` to enable an embedded Locator and Manager, allowing us to connect to our
Spring Boot, Apache Geode `CacheServer` application using _Gfsh_ (Geode Shell). Enabling the embedded Locator
and Manager are not necessary when starting the server or to run our application, but can be useful when debugging.
.Embedded Locator & Manager Configuration
[source,java]
@@ -155,11 +153,14 @@ of this later:
include::{samples-dir}/caching/near/src/main/java/example/app/caching/near/server/BootGeodeNearCachingCacheServerApplication.java[tags=locator-manager]
----
[[geode-samples-caching-near-example-client-side]]
=== Client-side Application
TIP: For more information on configurating and bootstrapping a small cluster of Apache Geode servers using Spring Boot,
see link:../appendix.html#geode-cluster-configuration-bootstrapping[Running an Apache Geode or Pivotal GemFire Cluster using Spring Boot].
Next, we will create and start 2 instances of our Spring Boot, Apache Geode, `ClientCache` application, which will use
the _Look-Aside Caching_ pattern with _Near Caching_ enabled.
[[geode-samples-caching-near-example-client-side]]
=== Client-side Configuration
Next, we will create and start 2 instances of our Spring Boot, Apache Geode `ClientCache` application, which will use
the _Look-Aside Caching_ pattern enhanced with_Near Caching_.
We start with the `@SpringBootApplication` main class:
@@ -170,7 +171,7 @@ include::{samples-dir}/caching/near/src/main/java/example/app/caching/near/clien
----
Essentially, the main class just serves to bootstrap our application configuration and components. Additionally, we
include some assertions in the Spring Boot `ApplicationRunner` bean to ensure our client configuration is correct.
include some assertions in a Spring Boot `ApplicationRunner` bean to ensure our client configuration is correct.
Our configuration appears as follows:
@@ -182,7 +183,7 @@ include::{samples-dir}/caching/near/src/main/java/example/app/caching/near/clien
First, we note the "_YellowPages_" client Region, which must match the server-side Region by name:
."YellowPages" Region
.The "YellowPages" client `CACHING_PROXY` Region
[source,java]
----
include::{samples-dir}/caching/near/src/main/java/example/app/caching/near/client/config/GeodeConfiguration.java[tags=region]
@@ -196,49 +197,53 @@ Most importantly, the client Region's data policy is set to `ClientRegionShortcu
clientRegion.setShortcut(ClientRegionShortcut.CACHING_PROXY);
----
This enables a _local cache_ (a.k.a. "*_Near Cache_*") maintained by Apache Geode on the client,
in our Spring Boot application JVM.
This enables a _local cache_ (a.k.a. "*_Near Cache_*") on the client in our Spring Boot application.
NOTE: The default `ClientRegionShortcut` is `PROXY`, which means there is not local cache. That is all cache operations
are forwarded to the server.
NOTE: The default `ClientRegionShortcut` is `PROXY`, which means there is no local cache. With a client `PROXY` Region,
all cache operations are forwarded to the server.
Equally important is the "interest registration" for all KEYS:
Equally important is the "_interest registration_" for all KEYS:
.Register Interest
[source,java]
----
include::{samples-dir}/caching/near/src/main/java/example/app/caching/near/client/config/GeodeConfiguration.java[tags=interest-registration]
----
The first parameter is a _Regular Expression_ (i.e. `.*`) matching the KEYS this client is interested in
receiving updates for.
receiving updates for, which in this case, is all KEYS.
The other parameters to the `RegexInterest` constructor includes the `InterestResultPolicy`, which determines whether
the client should get an initial push of the data (keys/values) matching the Regex when the client registers interest.
the client should get an initial push of the data (KEYS/VALUES) matching the regex when the client registers interest.
The `durable` boolean parameter sets whether the client subscription queue on the server should be "durable",
i.e. maintained when the client is not present. If the client goes down for whatever reason, the server will continue
to maintain the client's subscription queue created by the interest registration with events matching the regex up to
a specified timeout (configurable on the server). If the client comes back online before the queue times out,
the events in the queue will be replayed to the client. If the client does not reconnect before the (server-side)
configured timeout, the queue is discarded.
i.e. maintained when the client is not present. If the client goes down, for whatever reason, the server will continue
to maintain the client's subscription queue with events matching the regex up to a specified timeout (configurable on
the server). If the client comes back online before the configured timeout, the events in the queue will be replayed
back to the client. If the client does not reconnect before the configured timeout, the queue is discarded.
Durability can be useful for clients that need to receive events for data it missed while the client was away
in the order the events occurred. Of course, keep in mind that durable client does use up system resources
on the server (e.g. memory).
Durability can be useful for clients that need to receive events for data it missed while the client was offline in the
order the events occurred. Of course, keep in mind that durable clients use up system resources on the server
(e.g. memory).
TIP: To learn more about durable subscriptions, see the Apache Geode
{apache-geode-docs}/developing/events/implementing_durable_client_server_messaging.html[documentation]
The final boolean parameter, `receiveValues` determines whether the client will receive both keys & values when an
event matching the regex occurs, or will only receive the key for the value that changed.
The `receiveValues` boolean parameter determines whether the client will receive both KEYS and VALUES when an event
matching the regex occurs, or whether the client will only receive the KEYS for the VALUES that changed.
Receiving only the key 1) minimizes the amount of data sent over the network 2) when the client only wants to
"invalidate" the keyed entry, e.g. by using {apache-geode-javadoc}/org/apache/geode/cache/Region.html#localInvalidate-java.lang.Object-[`Region.localInvalidate(:Object)`].
Configuring the client to only receive KEYS minimizes the amount of data sent over the network when the client only
wants to (perhaps) "invalidate" the keyed entriess, e.g. by using
{apache-geode-javadoc}/org/apache/geode/cache/Region.html#localInvalidate-java.lang.Object-[`Region.localInvalidate(key:Object)`].
In that way, the memory footprint of the clients can also be maintained and the client will only lazily fetch the value
when needed again.
TIP: The `RegexInterest` constructor corresponds to
{apache-geode-javadocs}/org/apache/geode/cache/Region.html#registerInterestRegex-java.lang.String-org.apache.geode.cache.InterestResultPolicy-boolean-boolean-[Region.registerInterest(:String, :InterestResultPolicy, :boolean, :boolean)]
{apache-geode-javadoc}/org/apache/geode/cache/Region.html#registerInterestRegex-java.lang.String-org.apache.geode.cache.InterestResultPolicy-boolean-boolean-[Region.registerInterestRegex(:String, :InterestResultPolicy, :boolean, :boolean)]
There is 1 final bit of configuration on the client-side that we need, and that is to enable subscriptions.
We do so by setting the appropriate Spring Data for Apache Geode (SDG) property
There is one final bit of configuration on the client-side that we need, and that is to enable subscriptions. We do so
by setting the appropriate Spring Data for Apache Geode (SDG) property
(e.g. `spring.data.gemfire.pool.subscriptions-enabled`) in `application.properties`, like so:
.Common Client `application.properties`
@@ -256,15 +261,15 @@ client specific `application.properties`, for example:
include::{samples-dir}/caching/near/src/main/resources/application-client-one.properties[]
----
We set the `spring.application.name` to help identify the client and additionally set the `server.port` to a unique
value since our Spring Boot application is a Web application.
We set the `spring.application.name` property to help identify the client and additionally set the `server.port`
property to a unique value since our Spring Boot application is a Web application.
Now we can discuss the components of the application.
[[geode-samples-caching-near-example-client-side-app-model]]
==== Client-side Application Model
[[geode-samples-caching-near-example-app-model]]
=== Application Model
We start by modeling our `Person` and his/her contact information, an email address and phone number:
We start by modeling our `Person` and a person's contact information, an email address and phone number:
.`Person` class
[source,java]
@@ -275,10 +280,10 @@ include::{samples-dir}/caching/near/src/main/java/example/app/caching/near/clien
The class uses https://projectlombok.org/[Project Lombok] to simplify the implementation. Otherwise, the `Person` class
is pretty self-explanatory and there is nothing else special about the class.
[[geode-samples-caching-near-example-client-side-app-service]]
==== Client-side Application Service
[[geode-samples-caching-near-example-app-service]]
=== Application Service
Next, we have our `YellowPagesService` class that implements our Yellow Pages application logic. This class also uses
Next, we have our `YellowPagesService` class that implements our _Yellow Pages_ application logic. This class also uses
Spring's Caching annotations to demarcate service methods that will apply "_Look-Aside_" with "_Near Caching_"
semantics:
@@ -292,16 +297,17 @@ Essentially, we have a `@Cacheable`, `find(:String)` service method that tries t
from the cache. If a `Person` by name is found, then the `Person` is simply returned, otherwise, the `find(:String)`
service method is invoked and a `Person` with the given name and generated contact information is created and cached.
Technically, our `find(:String)` method should "_idempotent_", but for example purposes, we combine READ with CREATE.
Technically, our `find(:String)` service method should "_idempotent_", but for example purposes,
we combine READ with CREATE.
Our service class additionally contains operations to update (i.e. `@CachePut`) a `Person's` contact information
as well as evict (i.e. `@CacheEvict`) the `Person's` contact information from the cache.
[[geode-samples-caching-near-example-client-side-app-controller]]
==== Client-side Application Controller
[[geode-samples-caching-near-example-app-controller]]
=== Application Controller
To make the operations of our Yellow Pages application accessible, we expose a REST-ful API using a Spring Web MVC
`@RestController` class:
To make the operations of our _Yellow Pages_ application accessible, we expose REST-ful Web service endpoints using a
Spring Web MVC `@RestController` class:
.`YellowPagesController` class
[source,java]
@@ -321,16 +327,16 @@ Now we are ready to run our example application and observe the effects of *_Nea
== Run the Example
[[geode-samples-caching-near-example-run-server]]
== Run the Server
=== Run the Server
First, we must start our Spring Boot application that configures and bootstraps the Apache Geode `CacheServer`.
TIP: If you want to connect to the server with _Gfsh_, you must have a distribution of Apache Geode installed on your
system and you must enable the "_locator-manager_" profile using `-Dspring.profiles.active=server,locator-manager`.
Additionally, we have enabled the "_server_" profile as well.
system and you must enable the "_locator-manager_" profile. The "_locator-manager_" profile can be enabled using the
`-Dspring.profiles.active=server,locator-manager` Java System property. Additionally, the `server` profile has been
enabled as well.
If you setup a run profile in your IDE (of choice) and ran the `BootGeodeNearCachingCacheServerApplication` class,
then you should see output similar to the following:
When running the `BootGeodeNearCachingCacheServerApplication` class, you should see output similar to the following:
.Server output
[source,txt]
@@ -351,6 +357,8 @@ then you should see output similar to the following:
// Then you should see a bunch of Apache Geode log output, ending with something like...
...
[info 2019/08/12 13:02:20.975 PDT <main> tid=0x1] CacheServer Configuration: port=40404 max-connections=800 max-threads=0 notify-by-subscription=true socket-buffer-size=32768 maximum-time-between-pings=60000 maximum-message-count=230000 message-time-to-live=180 eviction-policy=none capacity=1 overflow directory=. groups=[] loadProbe=ConnectionCountProbe loadPollInterval=5000 tcpNoDelay=true
[info 2019/08/12 13:02:20.996 PDT <main> tid=0x1] Started BootGeodeNearCachingCacheServerApplication in 4.216 seconds (JVM running for 5.49)
@@ -359,13 +367,13 @@ then you should see output similar to the following:
NOTE: The Spring Boot Gradle plugin has been configured to run the `BootGeodeNearCachingClientCacheApplication` class,
not the server.
Now that the server is running, if you installed Apache Geode locally and set a path to `$GEODE/bin` (where the value of
the `$GEODE` environment variable has been set to the location of your Apache Geode installation), then you can:
Now that the server is running, if you installed Apache Geode on your system and set the `$PATH` to include `$GEODE/bin`,
then you can run _Gfsh_ and connect to the server:
.Connect to the Server with Gfsh
[source,txt]
----
$ echo $GEMFIRE
$ echo $GEODE
/Users/jblum/pivdev/apache-geode-1.6.0
$ gfsh
@@ -434,49 +442,48 @@ gfsh>
----
[[geode-samples-caching-near-example-run-client-app]]
== Run the Client Application
=== Run the Client Application
Now it is time to start 2 instances of the Spring Boot, Apache Geode, `ClientCache` application hosting our Yellow Pages
service.
Now it is time to start 2 instances of the Spring Boot, Apache Geode `ClientCache` application hosting
our _Yellow Pages_ service.
TIP: Make sure to enable the "_client_" generic profile in addition to 1 of the client-specific profiles,
e.g. "_client-one_", like so: `-Dspring.profiles.active=client,client-one`. To run a second instance, change
"_client-one_" to "_client-two_".
NOTE: Make sure to enable the `client` generic profile in addition to 1 of the client-specific profiles,
e.g. "_client-one_", like so: `-Dspring.profiles.active=client,client-one`. To run a second application instance,
change the profile from `client-one` to `client-two`.
TIP: Alternatively, rather than using a client instance specific `application.properties` file, you could set the
TIP: Alternatively, rather than using client instance specific `application.properties`, you could set the
`spring.application.name` and `server.port` properties using JVM System properties on the command-line, or in your IDE
run configuration profile as so: `-Dspring.application.name=ClientApplicationTwo -Dserver.port=8282`. Furthermore,
you could set the `server.port` property to the ephemeral port and let the system determine an available port for
the embedded Web Server (i.e. Jetty). You must need to make note of the port number when the application starts up
so that you can access the Webapp from the browser. Look for a line containing:
`[info 2019/08/12 13:14:19.755 PDT <main> tid=0x1] Tomcat initialized with port(s): 8181 (http)`.
run profile as so: `-Dspring.application.name=ClientApplicationTwo -Dserver.port=8282`. Furthermore, you could set the
`server.port` property to the ephemeral port and let the system determine an available port for the embedded Web Server
(i.e. Jetty). You must make note of the port number when the application starts up so that you can access the Webapp
from your Web browser. Look for a line containing: `[info 2019/08/12 13:14:19.755 PDT <main> tid=0x1] Tomcat initialized with port(s): 8181 (http)`.
Once you get both application instances running, you can access the Webapp from your Web browser at the following URL,
`http::/localhost:8181/`:
Once both application instances are running, you can access the Webapp from your Web browser at the following URL:
`http::/localhost:8181/`.
image::../images/Near-Caching-Example-Webapp.png[]
TIP: To switch between the 2 client app instances, it is useful to have 2 Web browser tabs open
TIP: To switch between the 2 client app instances, it is useful to have 2 Web browser tabs or windows open
accessing each Web Server port (e.g. `8181` and `8282`).
Next, let's create some data using client app instance by accessing the following URL
Next, let's create some data using client app instance one.
image::../images/Near-Caching-Example-Webapp-Create-JonDoe.png[]
This operation takes a bit of (simulated) time (`2167` milliseconds (ms), or `~2` seconds (s)) since "_Jon Doe_"
This operation takes a bit of (simulated) time (`2167 milliseconds (ms)`, or `~2 seconds (s)`) since "_Jon Doe_"
did not previously exist in the cache, which can be noted by the `cacheMiss` value of *true*. "_JonDoe's_"
email address and phone number were randomly generated.
If you hit the refresh button in our Web browser, then the latency significantly drops (~`0-1|2 ms`) because the value
is being pulled from the "local" cache (i.e. "_Near Cache_), stored on the client.
If you hit the refresh button in your Web browser, the latency significantly drops (~`0-1|2 ms`) because the value
is being pulled from the "_local_" cache (i.e. "_Near Cache_) on the client.
Now, in our second client app instance, if we access the same person, "_JonDoe_", then we see the following:
image::../images/Near-Caching-Example-Webapp-Read-JonDoe.png[]
Notice that `cacheMiss` is *false* and the `latency` is only `1 ms`. That is because, the 2nd client app instance
Notice that `cacheMiss` is *false* and the `latency` is only `1 ms`. That is because the 2nd client app instance
was already pushed the data from the server based on the client's interest registration. This is also apparent
in the log output the for client application instances:
in the log output for the client application instances:
.Client Application Instance 2 Log Output On Create
[source,txt]
@@ -484,10 +491,10 @@ in the log output the for client application instances:
[CREATE] EntryEvent for [JonDoe] with value [Person(name=JonDoe, email=jondoe@microsoft.com, phoneNumber=319-468-4802)]
----
To see the effects of updating an entry from a client app instance, let's update "_JonDoe_" from the 2nd client app
To see the effects of updating a cache entry from a client app instance, let's update "_JonDoe_" from the 2nd client app
instance by changing his email address and phone number:
image::../images/Near-Caching-Example-Webapp-Read-JonDoe.png[]
image::../images/Near-Caching-Example-Webapp-Update-JonDoe.png[]
Before we refresh the Web browser tab or window pointing to our 1st client app instance, if you look at the log output
for the 1st client app instance, you will see:
@@ -499,7 +506,7 @@ for the 1st client app instance, you will see:
----
Then, switch back to the 1st client app instance Web browser tab or window and hit the refresh button, or navigate
to the URL, `http://localhost:8181/yellow-pages/JonDoe`, and you should see the updated information:
to the URL, `http://localhost:8181/yellow-pages/JonDoe`, and you should see the updated contact information:
image::../images/Near-Caching-Example-Webapp-Reload-JonDoe.png[]
@@ -542,27 +549,27 @@ JonDoe | jondoe@google.com | 206-555-1234
PieDoe | piedoe@comcast.net | 406-413-6170
----
Presto! You know have just created and experienced a Spring Boot application that is using the _Look-Aside Caching_
pattern enhanced with _Near Caching_.
Presto! You have now just created a Spring Boot application using the _Look-Aside Caching_ pattern enhanced with
_Near Caching_.
[[geode-samples-caching-near-summary]]
== Summary
In this guide, we learned how to create a Spring Boot application using Spring's Cache Abstraction backed by
Apache Geode to enable the _Look-Aside Caching_ pattern in our application service methods. We further enhanced
Apache Geode using the _Look-Aside Caching_ pattern in our application service methods. We further enhanced
the caching ability of our application with *_Near Caching_*.
With *_Near Caching_*, we have the ability to further improve on the throughput and latency in our application
as well as make even more efficient use of system resources, since _Near Caching_ gives us:
With *_Near Caching_*, we have the added ability to further improve on the throughput and latency of our application
as well as make even more efficient use of system resources. _Near Caching_ gives us:
* A local, client-side cache for quick lookup, transforming our client into efficient, light-weight data containers
* A local, client-side cache for quick lookup, transforming our client into an efficient, light-weight data container
for data that is relevant to the client, thereby reducing the load on our servers.
* By _enabling subscriptions_ and _registering interest_, we can have data intelligently pushed to us (rather than
simply pulled when needed) based on only the data the client is specifically interested in, or "subscribed" to.
* By _enabling subscriptions_ and _registering interests_, we can have data intelligently pushed to us (rather than
simply pulled when needed) based on the data the client is specifically interested in, or "subscribed" to.
* Then, we saw that we can conflate subscription events on the server-side so clients only receive the latest updates
to the data that will be sent to the client based on the registered interests.
* With 1 more step, it is simple to make the subscription queue on the servers maintained for each client "durable"
so the client goes down, it does not miss any events, if necessary.
* With 1 more step, it is simple to make the subscription queues maintained on the servers for each client "durable"
so if the client is offline, it does not miss any events, if necessary.
* Furthermore, the client subscriptions queues on the servers can be made both redundant and persistent for
high-availability (HA) and resiliency purposes.