diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 689d5a8..65f04b8 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -5,4 +5,5 @@ RUN sudo apt-get update
## Install Redis client toolings
RUN su vscode -c "umask 0002 && sudo apt-get install redis-tools -y 2>&1"
+## Install the curl client
RUN su vscode -c "sudo apt-get install curl"
\ No newline at end of file
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index eda311a..97b49d7 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -10,6 +10,11 @@
"version":"latest"
},
+ "ghcr.io/devcontainers/features/docker-in-docker":{
+ "version":"latest",
+ "moby":"false"
+ },
+
// //Azure Function Core tools + Visual Studio Extension install
"ghcr.io/jlaundry/devcontainer-features/azure-functions-core-tools:1":{},
@@ -26,9 +31,10 @@
//PORT Forward config :
//5076 : Asp Net Core HTTP Debug port
//7062 : Asp Net Core HTTPS Debug port
- //7071 : Azure Function Debug port
- //1000[0,1,2] : Azurite storage emulator
- "forwardPorts": [5076, 7071, 10000, 10001, 10002],
+ //7071 : Azure Function Cache-Refresh-Func Debug port
+ //7072 : Azure Function History-Func Debug port
+ //1000[0,1,2] : Azurite storage emulator used with Azure Function
+ "forwardPorts": [5076, 7062, 7071, 7072, 10000, 10001, 10002],
//Static Web App Cli Install
"updateContentCommand": "bash .devcontainer/setup.sh",
@@ -41,7 +47,8 @@
"ms-dotnettools.csharp",
"ms-vscode.vscode-node-azure-pack",
"humao.rest-client",
- "azurite.azurite"
+ "azurite.azurite",
+ "ms-azurecache.vscode-azurecache"
]
}
},
diff --git a/docs/assets/devcontainer-reopen.png b/docs/assets/devcontainer-reopen.png
index 3b017cf..dfe49ee 100644
Binary files a/docs/assets/devcontainer-reopen.png and b/docs/assets/devcontainer-reopen.png differ
diff --git a/docs/assets/monitor-alert-action-group-select.png b/docs/assets/monitor-alert-action-group-select.png
new file mode 100644
index 0000000..0452bb5
Binary files /dev/null and b/docs/assets/monitor-alert-action-group-select.png differ
diff --git a/docs/assets/monitor-alert-action-group.png b/docs/assets/monitor-alert-action-group.png
new file mode 100644
index 0000000..bdd5a33
Binary files /dev/null and b/docs/assets/monitor-alert-action-group.png differ
diff --git a/docs/assets/monitor-alert-condition.png b/docs/assets/monitor-alert-condition.png
new file mode 100644
index 0000000..5cd64d9
Binary files /dev/null and b/docs/assets/monitor-alert-condition.png differ
diff --git a/docs/assets/monitor-alert-details.png b/docs/assets/monitor-alert-details.png
new file mode 100644
index 0000000..b0fee41
Binary files /dev/null and b/docs/assets/monitor-alert-details.png differ
diff --git a/docs/assets/monitor-alert-email.png b/docs/assets/monitor-alert-email.png
new file mode 100644
index 0000000..bdef0f7
Binary files /dev/null and b/docs/assets/monitor-alert-email.png differ
diff --git a/docs/assets/monitor-alert-history.png b/docs/assets/monitor-alert-history.png
new file mode 100644
index 0000000..c7946d4
Binary files /dev/null and b/docs/assets/monitor-alert-history.png differ
diff --git a/docs/assets/monitor-alert-new.png b/docs/assets/monitor-alert-new.png
new file mode 100644
index 0000000..9d22eee
Binary files /dev/null and b/docs/assets/monitor-alert-new.png differ
diff --git a/docs/assets/monitor-alert-notification.png b/docs/assets/monitor-alert-notification.png
new file mode 100644
index 0000000..896fe6c
Binary files /dev/null and b/docs/assets/monitor-alert-notification.png differ
diff --git a/docs/assets/monitor-alert-rules.png b/docs/assets/monitor-alert-rules.png
new file mode 100644
index 0000000..0635c86
Binary files /dev/null and b/docs/assets/monitor-alert-rules.png differ
diff --git a/docs/assets/monitor-alerts-select.png b/docs/assets/monitor-alerts-select.png
new file mode 100644
index 0000000..c8405b6
Binary files /dev/null and b/docs/assets/monitor-alerts-select.png differ
diff --git a/docs/workshop.md b/docs/workshop.md
index 78ba8b9..e216404 100644
--- a/docs/workshop.md
+++ b/docs/workshop.md
@@ -18,7 +18,7 @@ tags: azure, azure cache for redis, database, serverless, apim, cache, csu
navigation_levels: 3
---
-# Azure Cache for Redis Workshop
+# Azure Cache for Redis in the Azure World
Welcome to this Azure Cache for Redis Workshop. You will be experimenting with Azure Cache for Redis in multiple labs to discover how it's integrated to other Azure services by running a real world scenarios. Don't worry, even if the challenges will increase in difficulty, this is a step by step lab, you will be guided through the whole process.
@@ -58,8 +58,8 @@ If you are not prompted by Visual Studio Code, you can open the command palette
### Using a pre-configured GitHub Codespace
-Github Codespace offers the ability to run a complete dev environment (Visual Studio Code, extensions, third party tools, secure port forwarding etc.) on a dedicated virtual machine accessed via a web browser directly.
-The configuration for the environment is defined in the `.devcontainer` folder, making sure everyone gets to develop and practice on identical environments : No more dependency conflict or missing tools !
+Github Codespace offers the ability to run a complete dev environment (Visual Studio Code, Extensions, Tools, Secure port forwarding etc.) on a dedicated virtual machine.
+The configuration for the environment is defined in the `.devcontainer` folder, making sure everyone gets to develop and practice on identical environments : No more conflict on dependencies or missing tools !
Every Github account (even the free ones) grants access to 120 vcpu hours per month, _**for free**_. A 2 vcpu dedicated environment is enough for the purpose of the lab, meaning you could run such environment for 60 hours a month at no cost!
@@ -343,16 +343,22 @@ In this lab, you will see how to use Azure Cache for Redis in your API to improv
Open the `src/catalog-api` folder in Visual Studio Code in your active devcontainer or GitHub Codespace.
-
+
For the purpose of this lab you will have to add a delay for the response of the API to be able to see the difference between the response time with and without the cache. This is because a database like Cosmos Db is able to return the data in a few milliseconds after a few calls so you won't be able to see the difference between the response time with and without the cache after a few retry.
-To do this, copy the entire content of the `appsettings.json.template` into a new file called `appsettings.Development.json` in `src/catalog-api` and set the `SIMULATED_DB_LATENCY_IN_SECONDS` value to `2`.
+
+
+For the moment, the API is only connecting to Azure CosmosDB to retrieve the products list persisted in the `products` container. To have this interaction with CosmosDb work, you will need to configure your catalog-api.
+
+The configuration file format is provided in `src/catalog-api/appsettings.json.template` and will need to be duplicated in a new file called `src/catalog-api/appsettings.Development.json`.
+Once duplicated, you will need to fill in the missing values in this new file to configure the app.
> - Set the Cosmos Db connection string in the `appsettings.Development.json` file
-> - Set the Redis connection string in the `appsettings.Development.json` file
+> - Set the Redis connection string in the `appsettings.Development.json` file (in preparation for the next lab)
+> - Set `SIMULATED_DB_LATENCY_IN_SECONDS` to `"1"`
> - Run the API in your devcontainer or using the provided GitHub Codespace.
> - Call the GET `/products` endpoint to confirm that the API is working
@@ -377,6 +383,9 @@ Then inside the Azure Portal, go to your resource group, search the Azure Cache

+
+You can set `SIMULATED_DB_LATENCY_IN_SECONDS` to `"1"` to artificially represent a larger CosmosDB size
+
You can now run debug for the catalog-api by selecting **Run and Debug** in the left menu, select `.Net Core Launch (web)` and click the green arrow :

@@ -391,17 +400,16 @@ Depending on the environment you are using :
-## Add Azure Cache for Redis to your API
+## Add caching to your API
-If you look at the `Catalog.Api.csproj` you will see that the `StackExchange.Redis` NuGet package is already referenced in the project. This is the package that will allow you to use Azure Cache for Redis in your .NET API.
-
-The goal of this part is to set up the interactions with Azure Cache for Redis in your API and to use it to improve the performance of the `/products` endpoint. To do this, you will use the `ProductCacheService.cs` class which is pre-configured for you.
+The goal of this part is to set up the logic to interact with Azure Cache for Redis to store and retrieve the products list, and improve the overall latency of the `/products` endpoint.
+Most of the bricks you will need for the lab are provided in the `ProductCacheService.cs` class preconfigured for you. You will need to implement the caching logic using these bricks to complete the lab.
If you open it you will see two methods:
- `GetProductsAsync`: This method is used to get the products from the cache
- `SetProductsAsync`: This method is used to set the products in the cache
-They both use the `IRedisService` interface to interact with the cache and use the mechanism of serialization/deserialization to store and retrieve data.
+They both use the `IRedisService` interface to interact with the cache and use the mechanism of serialization/deserialization to store and retrieve data. This interface and the standard interaction methods to any Redis Cache come from the `StackExchange.Redis` Nuget Package already referenced in `src/catalog-api/Catalog.Api.csproj`
@@ -417,20 +425,21 @@ They both use the `IRedisService` interface to interact with the cache and use t
Now it is time to work with Azure Cache for Redis to retrieve and return the list of products provided by the persistence tier played by CosmosDb in this lab's scenario.
+
If no product exists in your Azure Cache for Redis Instance, then you will need to retrieve a fresh list of products from your persisting database (CosmosDb) and rehydrate the cache with this fresh data.
This way, the next call will extract the list of products directly from the cache, improving the overall request performance, as well as freeing up resources for the database to focus on actual data persistence activities.
> - Open the `ProductEndpoints.cs` file
-> - Use the `IProductCacheService` to setup the caching system in the `/products` endpoint
+> - Use the `IProductCacheService` to setup the caching logic for the `/products` endpoint
Toggle solution
-Inside the `ProductEndpoints.cs` file and in the `/products` endpoint use the `IProductCacheService` to retrieve the products from the cache. If some products are found in the cache, return them directly:
+Inside the `ProductEndpoints.cs` file and in the `/products` endpoint use `IProductCacheService` to retrieve the products from the cache. If some products are found in the cache, return them directly:
```csharp
IEnumerable? cachedProducts = await productCacheService.GetProductsAsync();
@@ -476,14 +485,17 @@ app.MapGet("/products", async (ICosmosService cosmosService, IProductCacheServic
});
```
-Now, if you run your API again and call the `/products` endpoint, you should see the response time of your API reduced to a few milliseconds!
+Now, if you run your API again and call the `/products` endpoint, you should see the response time of your API reduced to a few milliseconds!
+
+Thanks Redis! ;)
+
## Deploy the API to Azure
-Now that you have your API working locally, you will deploy it to Azure. To do this, you will use the Azure App Service. This service allows you to host your API in the cloud.
+Now that you have your API working locally, you will deploy it to Azure. To do this, you will use the Azure App Service provided by the Terraform infrastructure as code applied earlier. This service allows you to host your API in the cloud.
-To deploy your API directly from Visual Studio Code, you will use the Azure extension.
+To deploy your API directly from Visual Studio Code, you will use the Visual Studio Code Azure extension.
Search your App Service in the Visual Studio Code Azure extension and click on the **Deploy to Web App...** button:
@@ -1132,7 +1144,7 @@ You have confirmed that your code is working fine locally, so now you can procee
-> Deploy the `history-func` app to Azure on the Azure Function that start with `func-hist`
+> Deploy the `history-func` app to Azure on the Azure Function that start with `func-hist`
@@ -1218,10 +1230,10 @@ To authenticate to your Azure Cache for Redis resource you will need an access k
Next, to generate some load on the Azure Cache for Redis resource use the following command :
```bash
-redis-benchmark -h
.redis.cache.windows.net -p 6379 -a -t GET -n 1000000 -d 1024 -c 300 --threads 2
+redis-benchmark -h .redis.cache.windows.net -p 6379 -a -t GET -n 10000000 -d 1024 -c 300 --threads 2
```
-Redis Benchmark will send 1 million `SET` queries of 1KB each from 300 parallel connections. In this lab's use case, the duration of the operation will mainly be influenced by the codespace/dev environment CPU, RAM and network bandwidth resources.
+Redis Benchmark will send 10 million `SET` queries of 1KB each from 300 parallel connections. In this lab's use case, the duration of the operation will mainly be influenced by the codespace/dev environment CPU, RAM and network bandwidth resources.
When the benchmark is done, you should see this kind of results :
@@ -1235,51 +1247,97 @@ And then inside the **Performance** tab you can check how the resource performed

-These metrics are available out of the box, with any Azure Cache for Redis SKU and are precious insights to take informed decisions concerning the sizing of the your caching resource.
+These metrics are available out of the box, with any Azure Cache for Redis SKU and are precious insights to take informed decisions concerning the sizing of your caching resource.
The Azure Cache for Redis Enterprise SKU also comes with `autoscaling` capabilities to guarantee necessary caching resources at all times.
-Currently, only the Enterprise SKU support the `autoscaling` feature. However, you can do it manually using the `Premium` SKY with the cluster option and take advantage of Azure Monitor Alerts to respond to increasing usage trends and trigger additional node and shard provisionning.
+Currently, only the Enterprise SKU support the `autoscaling` feature. However, you can do it manually using the `Premium` SKU, enabling the `cluster` option and taking advantage of Azure Monitor Alerts to respond to increasing usage trends and trigger additional node and shard provisionning.
+
+## Usage Trend monitoring
+
+Let's create an [alert rule][alert-rule-creation] with Azure Monitor to send an email notification when the CPU average usage of the Azure Cache for Redis resource is above `30%` for more than `1` minute. When the alert is triggered, you will send an email to notify the Ops team that the usage trend on Redis increased.
+
+In a real world scenario this alert could be coupled with a request to increase the number of nodes in the cluster to help you respond to usage increase, as well as scale down rule to reduce the number of nodes when demand drops. For simplicity and to avoid scaling delay for the lab, we'll limit to a simple email notification here.
+
+
+
+> - Create a `static alert rule` to trigger when CPU reaches `30%` on `average` during `1` minute
+> - Create an [`action group`][action-group-creation] that will be executed by this alert rule
+> - The `action group` must send an `email` notification to your email address
+> - Execute a new benchmark of `10 Million` requests to load the Azure Cache for Redis CPU and trigger the alert
+
+
+
+
+
+Toggle solution
+
+To do so, open the Azure Portal on your Azure Cache for Redis resource and open the **Metrics** panel.
+
+In the **Metric** dropdown, select `CPU` and set **Aggregation** to `Avg` and click on **New alert rule** :
+
+
+
+In the **Condition** panel you just opened, make sure to fill in the trigger conditions as follows and click **Next: Actions >** :
-## Alert scaling
+
-Let's create an alert within Azure Monitor to trigger an action when the CPU usage of the Azure Cache for Redis resource is above 40% for more than 1 minute. When the alert is triggered, you will scale your Azure Cache for Redis resource to add one more node to the cluster.
+Now you have the rules set to trigger the notification, it's time to set the actual action that will send the notification.
+To do so, click **Create action group**, set the action group to your `resource group`, give it a `name` and `Display name` and click **Next: Notifications >**:
-In a real world scenario you will also add an alert to scale down the resource when the CPU usage is below a given percentage.
+
-Open the Azure Portal on your Azure Cache for Redis resource and open the **Alerts** panel.
+Select the **Notification Type** `Email/SMS message/Push/Voice`, tick **Email** in the panel that just opened and fill in your `email address`, then save by clicking **OK**. Once done, you'll have to give a **Name** to the notification type you just set and click **Review + Create** :
-Then click on the **Create alert rule** button, in the condition tab select `CPU` and fill the form with the following information:
+
-*Details*
+Check the action group you just created is added in the Action Group list and click **Next: Details >**:
-Once the alert is created, you can test it by generating some load on the Azure Cache for Redis resource using the [Redis-Benchmark][redis-benchmark] tool like you did before.
+
-Run the following command:
+Now is time to finalize the configuration of the alert rule: Giving it a `resource group` save location, define the **Severity** to `2 - Warning`, set an `Alert rule name` and check `Enable upon creation`. When done, hit **Review + Create** :
+
+
+
+Now the alert is created, you can test it by generating some load on the Azure Cache for Redis resource using the [Redis-Benchmark][redis-benchmark] tool like you did before.
+
+Run the same **redis-benchmark** command from your devcontainer/copdespace terminal as earlier :
```bash
-redis-benchmark
+redis-benchmark -h .redis.cache.windows.net -p 6379 -a -t GET -n 10000000 -d 1024 -c 300 --threads 2
```
-*Details*
+After a few minutes, a notification like the following should be sent to your email address :
-Take the time to dig in the toolbox offered by the Azure Portal to help you quickly **diagnose and solve problems** with the configuration of the resource or the connected clients :
+
-
+After the benchmark ended, you will be able to check the trigger history by clicking **Alerts** and then **Alert Rules** in the Azure Cache for Redis resource and select the Alert Rule you built in this lab, and open the **history** panel where you should see the alert trigger details :
-## Security (RBAC + Private Endpoint ?)
+
+
+
-
-
+As a side note, we really encourage you to take the time to dig in the toolbox offered by the Azure Portal to help you quickly **diagnose and solve problems** with the configuration of the resource or the connected clients :
-
+
-> [`Microsoft.Azure.StackExchangeRedis`][redis-dev-wrapper] is a wrapper to StackExchange.Redis client library, built to extend its capabilities and offer Azure Active Directory (secret-less) authentication.
+
-
+[alert-rule-creation]: https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/alerts-create-new-alert-rule?tabs=metric
+[action-group-creation]: https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/action-groups#create-an-action-group-in-the-azure-portal
+[redis-benchmark]: (https://redis.io/docs/management/optimization/benchmarks/)
+[redis-dev-wrapper]: https://github.com/Azure/Microsoft.Azure.StackExchangeRedis/
+
+---
# Closing the workshop
+The **Product Hands on Lab : Azure Cache for Redis in Azure World** comes to an end : We hope you liked practicing with Azure solutions and that this lab will help you kick start your journey to caching in Azure.
+Most of the solution that were quickly presented as a cloud native application integrated with Azure Cache for Redis have their dedicated lab to help you practice in depth way with these products.
+You can find dedicated labs here :
+- [Product Hands-on lab : Azure Serverless Architecture][hol-serverless]
+- [Product Hands-on lab : API Management][hol-apim]
+
Once you're done with this lab you can delete the resource group you created at the beginning.
To do so, click on `delete resource group` in the Azure Portal to delete all the resources and audio content at once.
@@ -1290,5 +1348,5 @@ The following Az-Cli command can also be used to delete the resource group :
az group delete --name
```
-[redis-benchmark]: (https://redis.io/docs/management/optimization/benchmarks/)
-[redis-dev-wrapper]: https://github.com/Azure/Microsoft.Azure.StackExchangeRedis/
\ No newline at end of file
+[hol-serverless]: https://moaw.dev/workshop/gh:microsoft/hands-on-lab-serverless/main/docs/
+[hol-apim]: https://azure.github.io/apim-lab/
\ No newline at end of file