Adding time-preservation changes, feedback from test participants

This commit is contained in:
Yev Bronshteyn 2020-01-26 21:39:32 -05:00
Родитель c76ca016af
Коммит 84266b0abe
70 изменённых файлов: 2070 добавлений и 307 удалений

8
.gitignore поставляемый
Просмотреть файл

@ -21,3 +21,11 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Eclipse
**/.project
**/.classpath
**/.settings
# VS Code
**/.vscode/

3
.vscode/settings.json поставляемый
Просмотреть файл

@ -1,3 +0,0 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
}

Просмотреть файл

@ -0,0 +1,46 @@
FROM ubuntu:18.04
RUN apt update -y && apt upgrade -y \
&& apt install apt-utils -y \
&& apt install wget -y \
&& apt install git -y \
&& apt install nano -y \
&& apt install inetutils-ping \
&& apt install jq -y
# Install JAVA
RUN wget https://repos.azul.com/azure-only/zulu/packages/zulu-8/8u232/zulu-8-azure-jdk_8.42.0.23-8.0.232-linux_amd64.deb -O zulu.deb \
&& apt install ./zulu.deb -y \
&& rm zulu.deb \
&& rm -fR /usr/lib/jvm/zulu-8-amd64/sample \
&& rm -fR /usr/lib/jvm/zulu-8-amd64/man \
&& rm -fR /usr/lib/jvm/zulu-8-amd64/demo
# Install Maven
RUN cd /opt \
&& wget https://www-us.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz -O maven.tar.gz \
&& tar xzf maven.tar.gz \
&& rm maven.tar.gz \
&& mkdir /m2 \
&& cd /usr/local/bin \
&& ln -s $(ls /opt/*maven*/bin/mvn)
# Install Azure CLI
RUN apt-get install ca-certificates curl apt-transport-https lsb-release gnupg -y \
&& curl -sL https://packages.microsoft.com/keys/microsoft.asc | \
gpg --dearmor | \
tee /etc/apt/trusted.gpg.d/microsoft.asc.gpg > /dev/null \
&& AZ_REPO=$(lsb_release -cs) \
&& echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | \
tee /etc/apt/sources.list.d/azure-cli.list \
&& apt-get update -y \
&& apt-get install azure-cli -y \
&& apt autoremove -y
# Install MySQL CLI
RUN apt-get install mysql-client -y
ENV JAVA_HOME /usr/lib/jvm/zulu-8-azure-amd64
ENV M2_HOME /m2
ENTRYPOINT [ "bash", "-c", "tail -f /dev/null" ]

Просмотреть файл

@ -0,0 +1,115 @@
# 00 - Setup your environment
__This guide is part of the [Azure Spring Cloud training](../README.md)__
Setting up all the necessary prerequisites in order to complete the lab in time.
---
## Setting up your local environment
To complete the lab in the time allotted, you should have all the pre-requisites ready. The easiest way to get all the pre-requisites is to use the provided docker image (see ["Using Docker"](#using-docker) below). Alternatively, you can install all the pre-requisites on your own machine (see ["Local System Prerequisites"](#local-system-prerequisites) below).
> 💡 All commands in this lab are formatted for the Bash shell. While Azure CLI should behave identically on all environments, some semantics may need to be modifed if you use other shells.
> 💡 In sections 9 and 10, you will access the UI of the Microservice application in a web browser. This UI does not render correctly in Internet Explorer and the pre-Chromium version of Edge. Use the [new Edge](https://microsoft.com/edge), Google Chrome, or Firefox for these sections.
### Using Docker (Recommended)
A docker image conaining all of the pre-requisites is available. You'll need:
* Docker Desktop.
> If you need to install Docker...
> - [Click here](https://download.docker.com/win/stable/Docker%20Desktop%20Installer.exe) for Windows
> - [Click here](https://download.docker.com/mac/stable/Docker.dmg) for Mac
* Visual Studio Code ([Download here](https://code.visualstudio.com))
* ["Remote - Containers" extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) for Visual Studio Code
* [Java Extension Pack](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack) for Visual Studio Code (optional)
With Docker installed, run (in bash or PowerShell with administrator privileges)
```bash
docker run -d azurejavalab.azurecr.io/azurejavalab:2020.01
```
#### Preparing Visual Studio Code
Visual Studio code makes it easy to edit files and run commands inside a container all in one single, fluid interface. If you don't have VS Code installed, [install it now](https://code.visualstudio.com).
With Visual Studio Code installed, open the page for the [Remote - Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension, and click "Install". If prompted to allow the browser to open Visual Studio Code, allow it.
Visual Studio Code will open, showing the description of the Remote Containers extension. Click on the green install button on that page to install the extension:
![Visual Studio Code extension page](media/01-remote-containers-extension-install-page.png)
If an "uninstall" button appears in place of the "Install" button, then the extension is already installed and you can continue.
> Consider installing the [Java Extension Pack](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack) for Visual Studio Code, using similar steps as above. While it is not strictly necessary to complete this lab, it will provide syntax highlighting and flag potential mistakes.
#### Connecting to the Container
With the container running on your machine, click on the "Remote Explorer" button on the left toolbar in Visual Studio Code:
![Remote explorer button](media/02-remote-explorer-button.png)
The Remote Explorer pane will appear, and you should see the lab container in it. Right-click on the container and click "Connect to Container".
![Remote explorer pane](media/03-remote-explorer-pane.png)
A new window will open. Press CTRL+SHIFT+P (Mac: ⇧⌘P) to open the command bar and Enter "Open Folder". In the subsequent dialog, enter `/lab`:
![Open Folder](media/04-open-folder.png)
![Select the remote folder](media/05-selecting-folder.png)
Click Ok.
You should now see the contents of the `lab` folder on the left side pane. There isn't much to see (yet), as the folder is empty.
Last, press CTRL+SHIFT+\` (Mac: ⌃⇧`) or choose "Terminal: Create New Integrated Terminal" from the command pallete.
Your Visual Studio Code window should now look like this:
![Visual Studio Code - Remote](media/06-container-vscode.png)
You can use the integrated shell on the bottom right for any command you need to run as part of this lab. Any files you need to edit, you can open from the panel on the left or by pressing CTRL+P.
### Local System Prerequisites (Only if you can't use Docker)
This training lab requires the following to be installed on your machine:
* [JDK 1.8](https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk)
* A text editor or an IDE. If you do not already have an IDE for Java development, we recommend using [Visual Studio Code](https://code.visualstudio.com/) with the [Java Extension Pack](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack).
* [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) version 2.0.80 or later. You can check the version of your current Azure CLI installation by running:
```bash
az --version
```
* 🚧 The `spring-cloud` extension for Azure CLI. You can install this extension after installing Azure CLI by running `az extension add -n spring-cloud -y`.
* [MySQL CLI](https://dev.mysql.com/downloads/)
The environment variable `JAVA_HOME` should be set to the path of `javac` in the JDK installation.
You can then use Visual Studio Code or an IDE of your choice.
## Creating Azure Resources
To save time, we provide an ARM template for creating all the Azure resources you will need for this lab other than the Azure Spring Cloud instance itself.
>🛑Be sure to substitute or assign a valid resource group name for `$RESOURCE_GROUP_NAME`.
```bash
az login # Log into your Azure account if necessary
az group create -g $RESOURCE_GROUP_NAME --location westus2 # Create a new resource group for this lab
az group deployment create -g $RESOURCE_GROUP_NAME --template-file azuredeploy.json --no-wait --parameters 'mysql_admin_password=super$ecr3t' # Substitute something else for the password parameter
```
>💡 The resource provisioning will take some time. Once you have run the Docker image or installed all the pre-requisites, proceed to the next section.
---
➡️ Next guide: [01 - Create an Azure Spring Cloud instance](../01-create-a-cluster/README.md)

Просмотреть файл

@ -0,0 +1,174 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location" : {
"type" : "string",
"defaultValue" : "[resourceGroup().location]"
},
"db_for_mysql_name": {
"defaultValue": "[concat('sclabm-', uniqueString(resourceGroup().id))]",
"type": "string"
},
"cosmosdb_account_name": {
"defaultValue": "[concat('sclabc-', uniqueString(resourceGroup().id))]",
"type": "string"
},
"app_insights_workspace_name": {
"defaultValue": "[concat('sclab-ai-', uniqueString(resourceGroup().id))]",
"type": "string"
},
"log_analytics_workspace_name": {
"defaultValue": "[concat('sclab-la-', uniqueString(resourceGroup().id))]",
"type": "string"
},
"mysql_admin_password": {
"type" :"securestring",
"metadata" :{
"description" : "The administrator password for the MySQL instance"
}
}
},
"resources": [
{
"type": "Microsoft.DBforMySQL/servers",
"apiVersion": "2017-12-01",
"name": "[parameters('db_for_mysql_name')]",
"location": "[parameters('location')]",
"sku": {
"name": "B_Gen5_1",
"tier": "Basic",
"family": "Gen5",
"capacity": 1
},
"properties": {
"administratorLogin" : "sqlAdmin",
"administratorLoginPassword" : "[parameters('mysql_admin_password')]",
"createMode" : "Default",
"storageProfile": {
"storageMB": 5120,
"backupRetentionDays": 7,
"geoRedundantBackup": "Disabled",
"storageAutoGrow": "Enabled"
},
"version": "5.7",
"sslEnforcement": "Enabled"
}
},
{
"type": "Microsoft.DocumentDB/databaseAccounts",
"apiVersion": "2019-08-01",
"name": "[parameters('cosmosdb_account_name')]",
"location": "[parameters('location')]",
"tags": {
"defaultExperience": "Core (SQL)",
"hidden-cosmos-mmspecial": ""
},
"kind": "GlobalDocumentDB",
"properties": {
"enableAutomaticFailover": false,
"enableMultipleWriteLocations": false,
"isVirtualNetworkFilterEnabled": false,
"virtualNetworkRules": [
],
"disableKeyBasedMetadataWriteAccess": false,
"databaseAccountOfferType": "Standard",
"consistencyPolicy": {
"defaultConsistencyLevel": "Session",
"maxIntervalInSeconds": 5,
"maxStalenessPrefix": 100
},
"locations": [
{
"locationName": "[parameters('location')]",
"provisioningState": "Succeeded",
"failoverPriority": 0,
"isZoneRedundant": false
}
],
"capabilities": [
]
}
},
{
"type": "Microsoft.OperationalInsights/workspaces",
"apiVersion": "2015-11-01-preview",
"name": "[parameters('log_analytics_workspace_name')]",
"location": "[parameters('location')]",
"properties": {
"sku": {
"name": "PerGB2018"
},
"retentionInDays": 30
}
},
{
"type": "Microsoft.Insights/components",
"apiVersion": "2015-05-01",
"name": "[parameters('app_insights_workspace_name')]",
"location": "[parameters('location')]",
"kind": "web",
"properties": {
"Application_Type": "web",
"Flow_Type": "Bluefield",
"Request_Source": "rest"
}
},
{
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases",
"apiVersion": "2019-08-01",
"name": "[concat(parameters('cosmosdb_account_name'), '/azure-spring-cloud-cosmosdb')]",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('cosmosdb_account_name'))]"
],
"properties": {
"resource": {
"id": "azure-spring-cloud-cosmosdb"
},
"options": {
"throughput" : "400"
}
}
},
{
"type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers",
"apiVersion": "2019-08-01",
"name": "[concat(parameters('cosmosdb_account_name'), '/azure-spring-cloud-cosmosdb/City')]",
"dependsOn": [
"[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('cosmosdb_account_name'), 'azure-spring-cloud-cosmosdb')]",
"[resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('cosmosdb_account_name'))]"
],
"properties": {
"resource": {
"id": "City",
"indexingPolicy": {
"indexingMode": "Consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*"
}
],
"excludedPaths": [
{
"path": "/\"_etag\"/?"
}
]
},
"partitionKey": {
"paths": [
"/name"
],
"kind": "Hash"
},
"conflictResolutionPolicy": {
"mode": "LastWriterWins",
"conflictResolutionPath": "/_ts"
}
},
"options": {
}
}
}
]
}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 77 KiB

Двоичные данные
00-setup-your-environment/media/02-remote-explorer-button.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 842 B

Двоичные данные
00-setup-your-environment/media/03-remote-explorer-pane.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 25 KiB

Двоичные данные
00-setup-your-environment/media/04-open-folder.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 11 KiB

Двоичные данные
00-setup-your-environment/media/05-selecting-folder.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.0 KiB

Двоичные данные
00-setup-your-environment/media/06-container-vscode.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 47 KiB

Просмотреть файл

@ -1,68 +1,60 @@
# 01 - Create a cluster
# 01 - Create an Azure Spring Cloud instance
__This guide is part of the [Azure Spring Cloud training](../README.md)__
Basics on creating a cluster and configuring the CLI to work efficiently.
Basics on creating an instance and configuring the CLI to work efficiently.
---
## Install the CLI and authenticate
## Verify Azure Subscription
Install the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli/?WT.mc_id=azurespringcloud-github-judubois) and log in to your account:
Ensure your Azure CLI is logged into your Azure subscription.
>💡If you intend to use the Docker container as recommended, do this inside the container bash session.
```bash
az login
az login # Sign into an azure account
az account show # See the currently signed-in account.
```
Configure the CLI to use Azure subscription you want to use for this training:
```bash
# List all subscriptions
az account list -o table
# Set active subscription
az account set --subscription <target subscription ID>
```
## Install the Azure Spring Cloud CLI extension
To install the Azure Spring Cloud CLI extension, type the following command:
```bash
az extension add --name spring-cloud
```
Ensure your default subscription is the one you intend to use for this lab, and if not - set the subscription via
```az account set --subscription <SUBSCRIPTION_ID>```
## Create an Azure Spring Cloud instance
- [Click here](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois&microsoft_azure_marketplace_ItemHideKey=AppPlatformExtension#blade/Microsoft_Azure_Marketplace/MarketplaceOffersBlade/selectedMenuItemId/home/searchQuery/spring%20cloud) to access the cluster creation page.
In this section, we will create our Azure Spring Cloud Instance using Azure CLI.
![Cluster creation](media/01-create-azure-spring-cloud.png)
First, you will need to come up with a name for your Azure Spring Cloud instance.
- Click on "Azure Spring Cloud" and then on "Create".
- Select your subscription, resource group name, name of the service and location.
- The name must be unique among all Azure Spring Cloud Instances across all of Azure. Consider using your username as part of the name.
- The name can contain only lowercase letters, numbers and hyphens. The first character must be a letter. The last character must be a letter or number. The value must be between 4 and 32 characters long.
![Cluster configuration](media/02-creation-details.png)
To save minimize, set the variable `RESOURCE_GROUP_NAME` to the name of the resource group created in the previous section. Set the variable `SPRING_CLOUD_NAME` to the name of the Azure Spring Cloud instance to be created:
- Click on "Next : Diagnostic Setting" to go to the next screen.
- Here you can either select an existing "Log Analytics workspace" or create a new one. Create a new one, and we will configure it later in [03 - Configure application logs](../03-configure-application-logs/README.md).
![Configure Log Analytics](media/03-creation-log-analytics.png)
![Create new Log Analytics](media/04-create-new-log-analytics.png)
- Once everything is validated, the cluster can be created.
Creating the cluster will take a few minutes.
## Configure the CLI to use that cluster
Using the cluster's resource group and name by default will save you a lot of typing later:
>🛑Be sure to substitute your own values in the example below.
```bash
az configure --defaults group=<resource group name>
az configure --defaults spring-cloud=<service instance name>
RESOURCE_GROUP_NAME=spring-cloud-lab
SPRING_CLOUD_NAME=azure-spring-cloud-lab
```
With these variables set, we can now create the Azure Spring Cloud Instance:
```bash
az spring-cloud create \
-g "$RESOURCE_GROUP_NAME" \
-n "$SPRING_CLOUD_NAME"
```
For the remainder of this workshop, we will be running Azure CLI commands referencing the same resource group and Azure Spring Cloud instance. So let's set them as defaults, so we don't have to specify them again:
```bash
az configure --defaults group=${RESOURCE_GROUP_NAME}
az configure --defaults spring-cloud=${SPRING_CLOUD_NAME}
```
---
⬅️ Previous guide: [00 - Set Up Your Environment](../00-setup-your-environment/README.md)
➡️ Next guide: [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md)

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 197 KiB

После

Ширина:  |  Высота:  |  Размер: 201 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 149 KiB

После

Ширина:  |  Высота:  |  Размер: 139 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 148 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 158 KiB

Просмотреть файл

@ -10,23 +10,20 @@ Build the simplest possible Spring Boot microservice, made with [https://start.s
The microservice that we create in this guide is [available here](simple-microservice/).
To create our microservice, we will use [https://start.spring.io/](https://start.spring.io/) with the command line:
To create our microservice, we will use [https://start.spring.io/](https://start.spring.io/) via the command line.
>💡__Note:__ All subsequent commands in this workshop should be run from the same directory, except where otherwise indicated via `cd` commands. If you are using the provided Docker container, this directory should be `/lab`.
```bash
curl https://start.spring.io/starter.tgz -d dependencies=web -d baseDir=simple-microservice -d bootVersion=2.1.9.RELEASE | tar -xzvf -
```
> We force the Spring Boot version to be 2.1.9
Go into the `simple-microservice` directory to view what has been generated:
```bash
cd simple-microservice
```
## Add a new Spring MVC Controller
Open the project with your favorite IDE, and next to the `DemoApplication` class, create a new class called `HelloController` with the following content:
Create a new class called `HelloController` in `src/main/java/com/example/demo`, next to `DemoApplication` with the following content:
```java
package com.example.demo;
@ -39,7 +36,7 @@ public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello from Azure Spring Cloud";
return "Hello from Azure Spring Cloud\n";
}
}
```
@ -51,7 +48,9 @@ The final project is available in the ["simple-microservice" folder](simple-micr
Run the project:
```bash
./mvnw spring-boot:run
cd simple-microservice
./mvnw spring-boot:run &
cd ..
```
Requesting the `/hello` endpoint should return the "Hello from Azure Spring Cloud" message.
@ -60,6 +59,12 @@ Requesting the `/hello` endpoint should return the "Hello from Azure Spring Clou
curl http://127.0.0.1:8080/hello
```
Finally, kill running app:
```bash
kill %1
```
## Create and deploy the application on Azure Spring Cloud
This section shows how to create an app instance, and then deploy your
@ -67,7 +72,7 @@ code to it.
In order to create the app instance graphically, you can use [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois):
- Look for your Azure Spring Cloud cluster in your resource group
- Look for your Azure Spring Cloud instance in your resource group
- Click on the "Overview" link at the top of the navigation sidebar.
- Click on the link "Create App". You may have to scroll to reveal the "Create App" blade.
@ -77,7 +82,7 @@ In order to create the app instance graphically, you can use [the Azure portal](
![Create application](media/01-create-application.png)
- Click on "Review and Create", then "Create"
- Click on "Create".
You can also use the command line to create the app instance, which is easier:
@ -88,8 +93,10 @@ az spring-cloud app create -n simple-microservice
You can now build your "simple-microservice" project and send it to Azure Spring Cloud:
```bash
cd simple-microservice
./mvnw clean package
az spring-cloud app deploy -n simple-microservice --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
This creates a jar file on your local disk and uploads it to the app instance you created in the preceding step. The `az` command will output a result in JSON. You don't need to pay attention to this output right now, but in the future, you will find it useful for diagnostic and testing purposes.
@ -98,7 +105,7 @@ This creates a jar file on your local disk and uploads it to the app instance yo
Go to [the Azure portal](https://portal.azure.com/):
- Look for your Azure Spring Cloud cluster in your resource group
- Look for your Azure Spring Cloud instance in your resource group
- Click "Apps" in the "Settings" section of the navigation pane and select "simple-microservice"
- Mouse over the URL labeled as "Test Endpoint" and click the clipboard icon that appears. This will give you something like:
`https://primary:BBQM6nsYnmmdQREXQINityNx63kWUbjsP7SIvqKhOcWDfP6HJTqg27klMLaSfpTB@rwo1106f.test.azuremicroservices.io/simple-microservice/default/`
@ -110,8 +117,7 @@ You can now use cURL again to test the `/hello` endpoint, this time served by Az
curl https://primary:BBQM6nsYnmmdQREXQINityNx63kWUbjsP7SIvqKhOcWDfP6HJTqg27klMLaSfpTB@rwo1106f.test.azuremicroservices.io/simple-microservice/default/hello/
```
Note that we have appended `hello/` to the URL. Failure to do this will result in a "404 not found".
>💡Note that we have appended `hello/` to the URL. Failure to do this will result in a "404 not found".
## Conclusion
@ -147,6 +153,6 @@ az spring-cloud app deploy -n simple-microservice --jar-path target/demo-0.0.1-S
---
⬅️ Previous guide: [01 - Create a cluster](../01-create-a-cluster/README.md)
⬅️ Previous guide: [01 - Create an Azure Spring Cloud instance](../01-create-a-cluster/README.md)
➡️ Next guide: [03 - Configure application logs](../03-configure-application-logs/README.md)
➡️ Next guide: [03 - Configure monitoring](../03-configure-monitoring/README.md)

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 96 KiB

После

Ширина:  |  Высота:  |  Размер: 39 KiB

Просмотреть файл

@ -14,6 +14,6 @@ public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello from Azure Spring Cloud";
return "Hello from Azure Spring Cloud\n";
}
}

Просмотреть файл

@ -1,61 +0,0 @@
# 03 - Configure application logs
__This guide is part of the [Azure Spring Cloud training](../README.md)__
Access Spring Boot applications logs to understand common issues.
---
## About log aggregation
There are actually three ways to access your application's logs: [Azure Storage](https://docs.microsoft.com/en-us/azure/storage/common/storage-introduction/?WT.mc_id=azurespringcloud-github-judubois), [Azure Events Hub](https://docs.microsoft.com/en-us/azure/event-hubs/?WT.mc_id=azurespringcloud-github-judubois), and [Log Analytics](https://docs.microsoft.com/en-us/azure/azure-monitor/log-query/get-started-portal/?WT.mc_id=azurespringcloud-github-judubois). We will focus here on Log Analytics as it's the default solution configured with Azure Spring Cloud.
## Configure Log Analytics
[Log Analytics](https://docs.microsoft.com/en-us/azure/azure-monitor/log-query/get-started-portal/?WT.mc_id=azurespringcloud-github-judubois) is part of [Azure Monitor](https://azure.microsoft.com/en-us/services/monitor/?WT.mc_id=azurespringcloud-github-judubois), which is well-integrated into Azure Spring Cloud, and which we will also use for metrics monitoring.
In [01 - Create a cluster](../01-create-a-cluster/README.md), when the Azure Spring Cloud cluster was created, you should have also created a new "Log Analytics workspace" and linked it to your Azure Spring Cloud cluster.
<details>
<summary>If you did not configure it during the cluster creation, here's how to set up the "Log Analytics workspace" manually</summary>
- Go to the [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois).
- Search for "Log Analytics workspaces" in the search box.
- Create a new workspace in your Azure Spring Cloud resource group.
![Create Log analytics workspace](media/01-create-logs-analytics-workspace.png)
- Now that the Log analytics workspace has been created, we must configure our Azure Spring Cloud cluster instance to send its data to this workspace.
- Go to the "Overview" page of your Azure Spring Cloud cluster, and select "Diagnostic settings" in the "Monitoring" section of the navigation pane.
- Click on "Add diagnostic setting" and configure your cluster to send all its logs to the Log analytics workspace that we just created.
- Fill in the values as shown here and click "Save".
![Send logs to the log analytics workspace](media/02-send-logs-to-log-analytics-workspace.png)
</details>
## Query application logs
Logs are available in the "Logs" link in the "Monitoring" section in the navigation pane for your Azure Spring Cloud cluster. Click on "Logs" and, optionally, go through any tutorial content provided. Feel free to skip that content for now.
This is a shortcut to the Logs Analytics workspace that was created earlier, so you can access that workspace through both menus.
This workspace allows to do queries on the aggregated logs, the most common one being to get the latest log from a specific application:
__Important:__ Spring Boot applications logs have a dedicated `AppPlatformLogsforSpring` type.
As we called the application in the [previous guide](../02-build-a-simple-spring-boot-microservice/README.md) "simple-microservice", here is how to get its 50 most recent logs of the `AppPlatformLogsforSpring` type for this application. Insert this text in the text area that states "Type your queries here or click on of the example queries to start". Click the text of the query, then click "Run".
```
AppPlatformLogsforSpring
| where AppName == "simple-microservice"
| limit 50
```
![Query logs](media/03-logs-query.png)
---
⬅️ Previous guide: [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md)
➡️ Next guide: [04 - Configure a Spring Cloud Config server](../04-configure-a-spring-cloud-config-server/README.md)

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 44 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 59 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 306 KiB

Просмотреть файл

@ -0,0 +1,37 @@
# 03 - Configure application logs
__This guide is part of the [Azure Spring Cloud training](../README.md)__
Access Spring Boot applications logs and distributed tracing to understand common issues.
---
## Configure log aggregation
There are actually three ways to access your application's logs: [Azure Storage](https://docs.microsoft.com/en-us/azure/storage/common/storage-introduction/), [Azure Events Hub](https://docs.microsoft.com/en-us/azure/event-hubs/), and [Log Analytics](https://docs.microsoft.com/en-us/azure/azure-monitor/log-query/get-started-portal). We will focus here on Log Analytics as it's the most common one, and as it's integrated into Azure Spring Cloud.
[Log Analytics](https://docs.microsoft.com/en-us/azure/azure-monitor/log-query/get-started-portal/) is part of [Azure Monitor](https://azure.microsoft.com/en-us/services/monitor/), which is well-integrated into Azure Spring Cloud, and which we will also use for metrics monitoring.
Having completed the setup in Section 00, you should have a Log Analytics workspace named `sclab-la-<unique string>`. We must now configure our Azure Spring Cloud instance to send its data to this workspace.
- Go to the "Overview" page of your Azure Spring Cloud instance, and select "Diagnostic settings" in the "Monitoring" section of the navigation pane.
- Delete any diagnostic settings you may see there.
- Click on "Add diagnostic setting" and configure your instance to send all its logs to the Log analytics workspace that we just created.
- Fill in the values as shown here and click "Save".
![Send logs to the log analytics workspace](media/02-send-logs-to-log-analytics-workspace.png)
## Configure Distributed Tracing
Distributed tracing allows you to observe interaction among microservices and diagnose issues. We will see this feature in action in Section 9, but because its configuration requires some time to be applied, let's enable it now:
- Go to the [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois).
- Go to the Azure Spring Cloud instance and click on "Distributed Tracing" (under Monitoring).
- Click on "Edit Settings" and select the App Insights workspace created in Section 00 (named `sclab-ai-<unique string>`).
- Once the Application Insights configuration is saved, click "Enable" at the top of the "Distributed Tracing" pane if it is enabled.
---
⬅️ Previous guide: [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md)
➡️ Next guide: [04 - Configure a Spring Cloud Config server](../04-configure-a-spring-cloud-config-server/README.md)

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 24 KiB

Просмотреть файл

@ -6,8 +6,7 @@ Configure a [Spring Cloud Config Server](https://cloud.spring.io/spring-cloud-co
---
> If you want to skip this section, you can use the following public Git repository by entering this URI in the URI textbox of the default repository, under the Config Server menu.
[https://github.com/jdubois/spring-cloud-config-public.git](https://github.com/jdubois/spring-cloud-config-public.git)
> If you want to skip this section, you can use the following public Git repository [https://github.com/jdubois/spring-cloud-config-public.git](https://github.com/jdubois/spring-cloud-config-public.git)
## Create a Git repository for storing the application configuration
@ -15,34 +14,51 @@ On your [GitHub account](https://github.com), create a new **private** repositor
> We will store configuration information, which should not be shared in public, so we recommend creating a private repository
In this repository, add a new `application.yml` file which will store configuration data for all our microservices. For the moment, it will just store a message to check if the configuration is successful:
In this repository, add a new `application.yml` file which will store configuration data for all our microservices.
> Typically, each Spring Boot application includes such a file with the application binaries to contain application settings. A Spring Cloud configuration server allow such settings to be stored at a single location and served from a single source.
For the moment, our `application.yml` will just store a message to check if the configuration is successful:
```yaml
application:
message: Configured by Azure Spring Cloud
```
Commit and push the new file.
## Create a GitHub personal token
Azure Spring Cloud can access Git repositories that are public, secured by SSH, or secured using HTTP basic authentication. We will use that last option, as it is easier to create and manage with GitHub.
Follow the [GitHub guide to create a personal token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) and save your token, as we will use it in the next section.
Follow the [GitHub guide to create a personal token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) and save your token. When asked to select scopes, check off the entire "repo" section (as shown below) and nothing else.
![GitHub personnal access token](media/01-github-personal-access-token.png)
When a token is generated, leave that tab open until the end of this section.
## Configure Azure Spring Cloud to access the Git repository
- Go to the [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois).
- Go to the overview page of your Azure Spring Cloud server, and select "Config server" in the menu
- Configure the repository we previously created:
- Add the repository URL, for example `https://github.com/jdubois/azure-spring-cloud-config.git`
- Add the repository URL, for example `https://github.com/jdubois/azure-spring-cloud-config.git`.
>💡 Make you include the `.git` ending in the URL.
- Click on `Authentication` and select `HTTP Basic`
- The username is your GitHub login name
- The password is the personal token we created in the previous section
- The __username__ is your GitHub login name
- The __password__ is the personal token we created in the previous section
- Click on "Apply" and wait for the operation to succeeed
![Spring Cloud config server](media/02-config-server.png)
## Review
We have now created a private configuration repository. We have enabled Azure Spring Cloud to create a configuration server with the configuration files from this repository.
In the next section, we will create an application that consumes this configuration, specifically the custom message we defined in `application.yml`.
---
⬅️ Previous guide: [03 - Configure application logs](../03-configure-application-logs/README.md)

Просмотреть файл

@ -11,6 +11,7 @@ Build a Spring Boot microservice that is cloud-enabled: it uses a Spring Cloud S
This guide builds upon the previous guides: we are going to build again a simple Spring Boot microservice like in [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md), but this time it will use two major Spring Cloud features:
- It will be connected to a Spring Cloud Service Registry so it can discover other microservices, as well as being discovered itself!
- It will get its configuration from the Spring Cloud Config server that we configured in the previous guide, [04 - Configure a Spring Cloud Config server](../04-configure-a-spring-cloud-config-server/README.md)
For both features, it will just be a matter of adding an official Spring Boot starter, and Azure Spring Cloud will take care of everything else.
@ -37,11 +38,20 @@ At the end of the application's `pom.xml` file (just before the closing `</proje
<profiles>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.2.0</version>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
@ -50,7 +60,7 @@ At the end of the application's `pom.xml` file (just before the closing `</proje
## Add a new Spring MVC Controller
Open the project with your favorite IDE, and next to the `DemoApplication` class, create a new class called `HelloController` with the following content:
Next to the DemoApplication class, create a new class called `HelloController` with the following content:
```java
package com.example.demo;
@ -77,18 +87,28 @@ public class HelloController {
Run the project:
```bash
./mvnw spring-boot:run
cd spring-cloud-microservice
./mvnw spring-boot:run &
cd ..
```
Do not be alarmed when you see exception stack traces. Spring Cloud is attempting to contact a local configuration server, which we have not provided. The application will still start using any available local settings and defaults.
Requesting the `/hello` endpoint should return the "Not configured by a Spring Cloud Server" message.
```bash
curl http://127.0.0.1:8080/hello
```
Kill the locally running microservice:
```bash
kill %1
```
## Create and deploy the application on Azure Spring Cloud
As in [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md), create a specific `spring-cloud-microservice` application in your Azure Spring Cloud cluster:
As in [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md), create a specific `spring-cloud-microservice` application in your Azure Spring Cloud instance:
```bash
az spring-cloud app create -n spring-cloud-microservice
@ -97,16 +117,18 @@ az spring-cloud app create -n spring-cloud-microservice
You can now build your "spring-cloud-microservice" project and send it to Azure Spring Cloud:
```bash
cd spring-cloud-microservice
./mvnw clean package -DskipTests -Pcloud
az spring-cloud app deploy -n spring-cloud-microservice --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
## Test the project in the cloud
Go to [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois):
- Look for your Azure Spring Cloud cluster in your resource group
- Go to "App Management"
- Look for your Azure Spring Cloud instance in your resource group
- Go to "Apps"
- Verify that `spring-cloud-microservice` has a `Discovery status` which says `UP(1),DOWN(0)`. This shows that it is correctly registered in Spring Cloud Service Registry.
- Select `spring-cloud-microservice` to have more information on the microservice.
- Copy/paste the "Test Endpoint" that is provided.
@ -119,6 +141,32 @@ As a result, requesting the `/hello` endpoint should return the message that we
Configured by Azure Spring Cloud
```
## Query application logs
In section 3, we enabled log aggergation in Azure Log Analytics. Such settings changes can take 1-2 minutes to apply, so by now, you should be able to query Azure Log Analytics.
[Open Azure Portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois) and navigate to your Azure Spring Cloud Instance. Click on "Logs". This is a shortcut to the Log Analytics workspace that was created earlier. If a tutorial appears, feel free to skip it for now.
This workspace allows you to run queries on the aggregated logs. The most common query is to get the latest log from a specific application:
__Important:__ Spring Boot applications logs have a dedicated `AppPlatformLogsforSpring` type.
Here is how to get its 50 most recent logs of the `AppPlatformLogsforSpring` type for the microservice we just deployed:
Insert this text in the text area that states "Type your queries here or click on of the example queries to start". Click the text of the query, then click "Run".
```sql
AppPlatformLogsforSpring
| where AppName == "spring-cloud-microservice"
| project TimeGenerated, Log
| order by TimeGenerated desc
| limit 50
```
![Query logs](media/03-logs-query.png)
>💡 It can also take 1-2 minutes for the console output of an Azure Spring Cloud microservice to be read into Log Analytics.
## Conclusion
Congratulations, you have deployed a complete Spring Cloud microservice, using Spring Cloud Service Registry and Spring Cloud Config Server!

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 148 KiB

Просмотреть файл

@ -62,16 +62,25 @@
</build>
<profiles>
<profile>
<id>cloud</id>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

Просмотреть файл

@ -18,6 +18,6 @@ public class HelloController {
@GetMapping("/hello")
public String hello() {
return message;
return message+'\n';
}
}

Просмотреть файл

@ -2,44 +2,32 @@
__This guide is part of the [Azure Spring Cloud training](../README.md)__
Build a reactive Spring Boot microservice, that uses the [Spring reactive stack](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) and is binded to a [Cosmos DB database](https://docs.microsoft.com/en-us/azure/cosmos-db/?WT.mc_id=azurespringcloud-github-judubois) in order to access a globally-distributed database with optimum performance.
Build a reactive Spring Boot microservice, that uses the [Spring reactive stack](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) and is binded to a [Cosmos DB database](https://docs.microsoft.com/en-us/azure/cosmos-db/) in order to access a globally-distributed database with optimum performance.
---
## Create a Cosmos DB database
## Prepare the Cosmos DB database
- Go to the [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois) and look for "Cosmos DB" in the search box.
- Create a new Cosmos DB account
- Keep the default "Core (SQL)" API
- Select the same location as your Azure Spring Cloud cluster
From Section 00, you should already have a CosmosDB account named `sclabc-<unique string>`.
![Create Cosmos DB account](media/01-create-cosmos-db.png)
> We are going to use the Web interface to add some data, but an easiest way to do it is to use
> [Microsoft Azure Storage Explorer](https://azure.microsoft.com/en-us/features/storage-explorer/?WT.mc_id=azurespringcloud-github-judubois)
> It's a free application that runs on Windows, Mac OS X and Linux!
- Once this Cosmo DB account is created, select it and click on the "Keys" menu item, and copy the account's primary key for later usage.
- Click on the "Data Explorer" menu item
- Create a new database called `azure-spring-cloud-training`
- In that container, create a new container called `City`
- Input `/name` as partition key
- Expand the container named `azure-spring-cloud-cosmosdb`.
- In that container, expand the container named `City`.
- Click on "Items" and use the "New Item" button to create some sample items:
In that container, insert some sample items:
```json
{
"name": "Paris, France"
}
```
```json
{
"name": "Paris, France"
}
```
```json
{
"name": "London, UK"
}
```
```json
{
"name": "London, UK"
}
```
![Azure storage explorer](media/02-azure-storage-explorer.png)
![Data explorer](media/02-data-explorer.png)
## Create a Spring Webflux microservice
@ -75,11 +63,20 @@ At the end of the application's `pom.xml` file (just before the closing `</proje
<profiles>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.2.0</version>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
@ -107,10 +104,9 @@ class City {
}
```
Then, create a new `CityController` class that will be used to query the database.
Then, in the same location, create a new `CityController` class that will be used to query the database.
> This class will get its Cosmos DB configuration from the Azure Spring Cloud service binding that we will configure later.
> If you want to test locally, you can create a specific `application-dev.yml` configuration file that would only be triggered with a specific `dev` Spring profile. Of course, we don't recommend storing this configuration data in your Git repository.
```java
package com.example.demo;
@ -171,7 +167,7 @@ public class CityController {
## Create the application on Azure Spring Cloud
As in [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md), create a specific `city-service` application in your Azure Spring Cloud cluster:
As in [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md), create a specific `city-service` application in your Azure Spring Cloud instance:
```bash
az spring-cloud app create -n city-service
@ -181,7 +177,7 @@ az spring-cloud app create -n city-service
Azure Spring Cloud can automatically bind the Cosmos DB database we created to our microservice.
- Go to "App Management" in your Azure Spring Cloud cluster.
- Go to "Apps" in your Azure Spring Cloud instance.
- Select the `city-service` application
- Go to `Service bindings`
- Click on `Create service binding``
@ -197,13 +193,15 @@ Azure Spring Cloud can automatically bind the Cosmos DB database we created to o
You can now build your "city-service" project and send it to Azure Spring Cloud:
```bash
cd city-service
./mvnw clean package -DskipTests -Pcloud
az spring-cloud app deploy -n city-service --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
## Test the project in the cloud
- Go to "App Management" in your Azure Spring Cloud cluster.
- Go to "Apps" in your Azure Spring Cloud instance.
- Verify that `city-service` has a `Discovery status` which says `UP(1),DOWN(0)`. This shows that it is correctly registered in Spring Cloud Service Registry.
- Select `city-service` to have more information on the microservice.
- Copy/paste the "Test Endpoint" that is provided.

Просмотреть файл

@ -76,16 +76,25 @@
</build>
<profiles>
<profile>
<id>cloud</id>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 114 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 133 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 29 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 50 KiB

После

Ширина:  |  Высота:  |  Размер: 57 KiB

Просмотреть файл

@ -6,31 +6,97 @@ Build a classical Spring Boot application that uses JPA to acess a [MySQL databa
---
## Create a MySQL Server instance
## Configure the MySQL Server instance
- Go to the [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois) and look for "Azure Database for MySQL servers" in the search box.
- Create a new database
- Write down the password in a safe place
- You can choose a low-budget "Basic" database
After following the steps in Section 00, you should have an Azure Database for MySQL instance named `sclabm-<unique string>` in your resource group.
![Create MySQL database](media/01-create-mysql.png)
Before we can use it however, we will need to perform several tasks:
- Once the database is created, select it and go to "Connection security"
- Enable "Allow access to Azure services"
- Add your current IP to the firewall rules, so you can access it from your machine
1. Create a MySQL firewall rule to allow connections from our local environment.
1. Create a MySQL firewall rule to allow connections from Azure Services. This will enable connections from Azure Spring Cloud.
1. Connect to the MySQL server via MySQL CLI and initialize the database
> If you need to know your current external IP, you can use [https://www.whatismyip.com/](https://www.whatismyip.com/)
- Connect to your database using [MySQL CLI](https://dev.mysql.com/downloads/):
![Configure firewall](media/02-firewall.png)
> 💡When prompted for a password, enter the MySQL password you specified when deploying the ARM template in [Section 00](../00-setup-your-environment/README.md).
- Connect to your database using your favorite database explorer tool
- For example [MySQL Workbench](https://www.mysql.com/fr/products/workbench/)
- The admin login name is available in the "overview" section of your database, it is in the form of `username@database`
- Create a new schema named `azure-spring-cloud-training`
```bash
# Obtain the info on the MYSQL server in our resource group:
MYSQL_INFO=$(az mysql server list --query '[0]')
MYSQL_SERVERNAME=$(echo $MYSQL_INFO | jq -r .name)
MYSQL_USERNAME="$(echo $MYSQL_INFO | jq -r .administratorLogin)@${MYSQL_SERVERNAME}"
MYSQL_HOST="$(echo $MYSQL_INFO | jq -r .fullyQualifiedDomainName)"
read -p "Enter your MySQL password: " -s MYSQL_PASSWORD
# Create a firewall rule to allow connections from your machine:
MY_IP=$(curl whatismyip.akamai.com 2>/dev/null)
az mysql server firewall-rule create \
--server-name $MYSQL_SERVERNAME \
--name "connect-from-lab" \
--start-ip-address "$MY_IP" \
--end-ip-address "$MY_IP"
# Create a firewall rule to allow connections from Azure services:
az mysql server firewall-rule create \
--server-name $MYSQL_SERVERNAME \
--name "connect-from-azure" \
--start-ip-address "0.0.0.0" \
--end-ip-address "0.0.0.0"
# Connect through MySQL CLI
mysql --ssl -h "$MYSQL_HOST" -u "$MYSQL_USERNAME" --password="$MYSQL_PASSWORD"
```
- Once you are connected to MySQL, create a new schema named `azure-spring-cloud-training`:
```sql
mysql> CREATE DATABASE `azure-spring-cloud-training`;
Query OK, 1 row affected (0.22 sec)
```
- Press CTRL+D to exit the MySQL CLI.
## Create the application on Azure Spring Cloud
As in [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md), create a specific `weather-service` application in your Azure Spring Cloud instance:
```bash
az spring-cloud app create -n weather-service
```
## Bind the MySQL database to the application
In [Section 6](../06-build-a-reactive-spring-boot-microservice-using-cosmosdb/README.md), we created a service binding to inject CosmosDB configuration into an Azure Spring Cloud microservice.
Now, let's do the same thing to inject connectino information for our MySQL database into the new `weather-service` microservice. This time, we'll do it from the command line:
> 💡Make sure you use the same shell session that you've been using for the previous steps in this section.
```bash
MYSQL_ARM_RESOURCE_ID=$(echo $MYSQL_INFO | jq -r .id)
az spring-cloud app binding mysql add \
--app weather-service \
--name mysql-weather \
--resource-id "$MYSQL_ARM_RESOURCE_ID" \
--database-name 'azure-spring-cloud-training' \
--username "$MYSQL_USERNAME" \
--key "$MYSQL_PASSWORD"
```
You can, if you wish, view the newly-created service binding in [Azure Portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois):
- Navigate to your Azure Spring Cloud Instance
- Click on Apps
- Click on `weather-service`.
- Click on Service Bindings.
You should see the newly-created weather binding listed: `mysql-weather`. If you click on it, you can see the MySQL connection information:
![MySQL Service Binding](media/03-bind-service-mysql.png)
## Create a Spring Boot microservice
The microservice that we create in this guide is [available here](weather-service/).
Now that we've provisioned and Azure Spring Cloud app and prepared the service binding, let's get the code for `weather-service` ready. The microservice that we create in this guide is [available here](weather-service/).
To create our microservice, we will use [https://start.spring.io/](https://start.spring.io/) with the command line:
@ -50,11 +116,20 @@ At the end of the application's `pom.xml` file (just before the closing `</proje
<profiles>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.2.0</version>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
@ -158,43 +233,22 @@ INSERT INTO `azure-spring-cloud-training`.`weather` (`city`, `description`, `ico
INSERT INTO `azure-spring-cloud-training`.`weather` (`city`, `description`, `icon`) VALUES ('London, UK', 'Quite cloudy', 'weather-pouring');
```
> The icons we are using are the ones from [https://materialdesignicons.com/](https://materialdesignicons.com/) - you can pick there other weather icons if you wish.
## Create the application on Azure Spring Cloud
As in [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md), create a specific `weather-service` application in your Azure Spring Cloud cluster:
```bash
az spring-cloud app create -n weather-service
```
## Bind the MySQL database to the application
Azure Spring Cloud can automatically bind the MySQL database we created to our microservice.
- Go to "App Management" in your Azure Spring Cloud cluster.
- Select the `weather-service` application
- Go to `Service bindings`
- Click on `Create service binding``
- Give your binding a name, for example `mysql-weather`
- For `Binding type`, select `Azure database for MySQL``
- Select your database, and input your admin login and password
- Click on `Create` to create the database binding
![Bind MySQL database](media/03-bind-service-mysql.png)
> The icons we are using are the ones from [https://materialdesignicons.com/](https://materialdesignicons.com/) - you can pick their other weather icons if you wish.
## Deploy the application
You can now build your "weather-service" project and send it to Azure Spring Cloud:
```bash
cd weather-service
./mvnw clean package -DskipTests -Pcloud
az spring-cloud app deploy -n weather-service --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
## Test the project in the cloud
- Go to "App Management" in your Azure Spring Cloud cluster.
- Go to "Apps" in your Azure Spring Cloud instance.
- Verify that `weather-service` has a `Discovery status` which says `UP(1),DOWN(0)`. This shows that it is correctly registered in the Spring Cloud Service Registry.
- Select `weather-service` to have more information on the microservice.
- Copy/paste the "Test Endpoint" that is provided.

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 101 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 56 KiB

После

Ширина:  |  Высота:  |  Размер: 5.6 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 45 KiB

После

Ширина:  |  Высота:  |  Размер: 71 KiB

Просмотреть файл

@ -74,15 +74,24 @@
</build>
<profiles>
<profile>
<id>cloud</id>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

Просмотреть файл

@ -6,6 +6,7 @@
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@RestController

Просмотреть файл

@ -28,11 +28,20 @@ At the end of the application's `pom.xml` file (just before the closing `</proje
<profiles>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.2.0</version>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
@ -64,7 +73,7 @@ spring:
## Create the application on Azure Spring Cloud
As in [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md), create a specific `gateway` application in your Azure Spring Cloud cluster. As this application is a gateway, we add the `--is-public true` flag so it is exposed publicly.
As in [02 - Build a simple Spring Boot microservice](../02-build-a-simple-spring-boot-microservice/README.md), create a specific `gateway` application in your Azure Spring Cloud instance. As this application is a gateway, we add the `--is-public true` flag so it is exposed publicly.
```bash
az spring-cloud app create -n gateway --is-public true
@ -75,22 +84,25 @@ az spring-cloud app create -n gateway --is-public true
You can now build your "gateway" project and send it to Azure Spring Cloud:
```bash
cd gateway
./mvnw clean package -DskipTests -Pcloud
az spring-cloud app deploy -n gateway --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
## Test the project in the cloud
- Go to "App Management" in your Azure Spring Cloud cluster.
- Go to "Apps" in your Azure Spring Cloud instance.
- Verify that `gateway` has a `Discovery status` which says `UP(1),DOWN(0)`. This shows that it is correctly registered in the Spring Cloud Service Registry.
- Select `gateway` to have more information on the microservice.
- Copy/paste the public URL that is provided (there is a "Test Endpoint" like for microservices, but the gateway is directly exposed on the Internet, so let's use this).
- Copy/paste the public URL that is provided (there is a "Test Endpoint" like for microservices, but the gateway is directly exposed on the Internet, so let's use the public URL). Keep this URL handy for subsequent sections.
As the gateway is connected to the Spring Cloud Service Registry, it should have automatically opened routes to the available microservices, with URL paths in the form of `/MICROSERVICE-ID/**`:
[The MICROSERVICE-ID must be in capital]
[The MICROSERVICE-ID must be in capital letters]
- Test the `city-service` microservice endpoint by doing: `curl https://XXXXXXXX.azureapps.io/CITY-SERVICE/cities` (replacing XXXXXXXX by the name of your gateway)
- Test the `weather-service` microservice endpoint by doing: `curl 'https://XXXXXXXX.azureapps.io/WEATHER-SERVICE/weather/city?name=Paris%2C%20France'` (replacing XXXXXXXX by the name of your gateway)
- Test the `city-service` microservice endpoint by doing: `curl https://XXXXXXXX-gateway.azuremicroservices.io/CITY-SERVICE/cities` (replacing XXXXXXXX with the name of your Azure Spring Cloud instance)
- Test the `weather-service` microservice endpoint by doing: `curl 'https://XXXXXXXX-gateway.azuremicroservices.io/WEATHER-SERVICE/weather/city?name=Paris%2C%20France'` (replacing XXXXXXXX by the name of your gateway)
If you need to check your code, the final project is available in the ["gateway" folder](gateway/).

Просмотреть файл

@ -68,11 +68,20 @@
<profiles>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.2.0</version>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>

Просмотреть файл

@ -20,7 +20,7 @@ In order to finish this architecture, we need to add a front-end to it:
- This front-end could be hosted in Azure Spring Cloud, using the same domain name (this won't be the case in this guide, and that's why we enabled CORS in our gateway earlier).
- If you are familiar with NodeJS and Vue CLI, you can run this application locally by typing `npm install && vue ui`.
In order to simplify this part, which has little value to understand Azure Spring Cloud, we already built a running front-end:
In order to simplify this part, which is not relevant to understanding Spring Cloud, we have already built a running front-end:
__[https://spring-training.azureedge.net/](https://spring-training.azureedge.net/)__
@ -30,7 +30,7 @@ Go to [https://spring-training.azureedge.net/](https://spring-training.azureedge
![VueJS front-end](media/01-vuejs-frontend.png)
## Add distributed tracing to better understand the architecture
## Enable distributed tracing to better understand the architecture
In each application (`city-service`, `weather-service`, `gateway`), open up the `pom.xml` file and add the following Maven dependencies:
@ -48,35 +48,44 @@ Now you need to update those applications on Azure Spring Cloud.
Re-deploy the `city-service` microservice:
```bash
cd city-service
./mvnw clean package -DskipTests -Pcloud
az spring-cloud app deploy -n city-service --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
Re-deploy the `weather-service` microservice:
```bash
cd weather-service
./mvnw clean package -DskipTests -Pcloud
az spring-cloud app deploy -n weather-service --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
Re-deploy the `gateway` gateway:
```bash
cd gateway
./mvnw clean package -DskipTests -Pcloud
az spring-cloud app deploy -n gateway --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
Once everything is deployed:
### Once everything is deployed
- Go to the [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois).
- Go to the overview page of your Azure Spring Cloud server, and select "Distributed tracing" in the menu.
- Click on "enable" and create a new Application Insights instance to store distributed tracing data.
- Use the VueJS application on [https://spring-training.azureedge.net/](https://spring-training.azureedge.net/) to generate some traffic on our microservices stack. Tracing data can take a couple of minutes to be ingested by the system, so use this time to generate some load.
We have already enabled distributed tracing on our Azure Spring Cloud instance in Section 3. Now, you can use the VueJS application on [https://spring-training.azureedge.net/](https://spring-training.azureedge.net/) to generate some traffic on the microservices stack.
In the "Distributed tracing" menu, you should now have access to a full application map, as well as a search engine that allows to find performance bottlenecks:
>💡 Tracing data can take a couple of minutes to be ingested by the system, so use this time to generate some load.
In the "Distributed tracing" menu in Azure Portal, you should now have access to a full application map, as well as a search engine that allows to find performance bottlenecks.
![Distributed tracing](media/02-distributed-tracing.png)
> 💡 If your application map looks different from the one above, select the hierarchical view from the layout switch in the top-right corner:
>
> ![layout switch](media/05-layout-switch.png)
![Trace detail](media/03-trace-detail.png)
## Scale applications
@ -84,7 +93,7 @@ In the "Distributed tracing" menu, you should now have access to a full applicat
Now that distributed tracing is enabled, we can scale applications depending on our needs.
- Go to the [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois).
- Go to the overview page of your Azure Spring Cloud server, and select "App management" in the menu.
- Go to the overview page of your Azure Spring Cloud server, and select "Apps" in the menu.
- Select one service, and click on "Scale"
- Modify the number of instances, or change the CPU/RAM of the instance

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.1 KiB

Просмотреть файл

@ -43,17 +43,36 @@ public class WeatherController {
}
```
## Deploy the new application to a new "green" deployment set
## Deploy the new application to a new "green" deployment
Build a new version of the application and deploy it to a new `deployment set` called `green`:
Build a new version of the application and deploy it to a new `deployment` called `green`:
```bash
cd weather-service
./mvnw clean package -DskipTests -Pcloud
az spring-cloud app deployment create --name green --app weather-service --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
Once the application is deployed, if you go to [https://spring-training.azureedge.net/](https://spring-training.azureedge.net/) you will still have the same data, as the new version of the microservice is now in a staging area, and not in production yet.
Navigate to the Azure Spring Cloud Instance in [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois) and click on "Deployments" (under Settings). You should now see the "green" deployment in the "Staging Deployment" column:
![Deployment Pane](media/02-deployment-pane.png)
You can test the `green` deployment by invoking the same URL as in section 7, but replacing the deployment name `default` with `green`:
```bash
curl https://***.test.azuremicroservices.io/weather-service/green/weather/city?name=Paris%2C%20France
```
And you should see the result of the recent modification:
```json
{"city":"Paris, France","description":"It's always sunny on Azure Spring Cloud","icon":"weather-sunny"}
```
Note: we're not testing the green deployment through through the `gateway` application. The purpose of a green deployment is to test changes to a microservice before routing production traffic to it. Therefore, if you access `weather-service` through the public Gateway URL, as you did in section 8, you will be routed to the original version of the service.
To put this `green` deployment into production, you can use the command line:
```bash
@ -62,11 +81,11 @@ az spring-cloud app set-deployment -n weather-service --deployment green
Another solution is to use [the Azure portal](https://portal.azure.com/?WT.mc_id=azurespringcloud-github-judubois):
- Find your Azure Spring Cloud cluster
- Find your Azure Spring Cloud instance
- Click on the "deployement" menu
- Select the `weather-service` application and click on "Set deployment"
> If you want to reuse a deployment set, you need first to delete it, for instance:
> If you want to reuse a deployment name, you need first to delete the previous deployment under that name:
>
> ```bash
> az spring-cloud app deployment delete --name green --app weather-service

Двоичные данные
10-blue-green-deployment/media/02-deployment-pane.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 21 KiB

Просмотреть файл

@ -74,15 +74,24 @@
</build>
<profiles>
<profile>
<id>cloud</id>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

Просмотреть файл

@ -12,12 +12,21 @@ We are going to automate the deployment of the `weather-service` microservice th
## Configure GitHub
If it is not already done, [create a GitHub] repository and commit the code from the `weather-service` microservice into that repository.
[Create a new GitHub repository](https://github.com/new) and commit the code from the `weather-service` microservice into that repository.
You now need to allow access from your GitHub workflow to your Azure Spring Cloud cluster. Open up a terminal and type the following command, replacing `<azure-subscription-id>` by you Azure subscription ID, and `<resource-group-name>` by the name of the resource group in which your Azure Spring Cloud cluster is located:
>💡 Note: this should be a different repository than the one you used to store configuration in section 4.
You now need to allow access from your GitHub workflow to your Azure Spring Cloud instance. Open up a terminal and type the following command, replacing `$RESOURCE_GROUP_NAME` with the name of your resource group.
🛑Make sure you assign the name of your resource group to the variable `RESOURCE_GROUP_NAME` or substitute the value for it in the commands below.
```bash
az ad sp create-for-rbac --name spring-cloud-training --role contributor --scopes /subscriptions/<azure-subscription-id>/resourceGroups/<resource-group-name> --sdk-auth
# Get the ARM resource ID of the resource group
RESOURCE_ID=$(az group show --name "$RESOURCE_GROUP_NAME" --query id -o tsv)
# Create a service principal with a Contributor role to the resource group.
SPNAME="sp-$(az spring-cloud list --query '[].name' -o tsv)"
az ad sp create-for-rbac --name "${SPNAME}" --role contributor --scopes "$RESOURCE_ID" --sdk-auth
```
This should output a JSON text, that you need to copy.
@ -26,9 +35,11 @@ Then, in your GitHub project, select `Settings > Secrets` and add a new secret c
## Create a GitHub action
In your project, create a new directory called `.github/workflows` and add a file called `azure-spring-cloud.yml` in it. This file is a GitHub workflow, and will use the secret we just configured above, in order to deploy the application to your Azure Spring Cloud cluster.
Inside the `weather-service` directory, create a new directory called `.github/workflows` and add a file called `azure-spring-cloud.yml` in it. This file is a GitHub workflow, and will use the secret we just configured above, in order to deploy the application to your Azure Spring Cloud instance.
In that file, copy/paste the following content:
In that file, copy/paste the following content, performing the indicated substitutions:
>🛑 You must substitute the name of your Azure Spring Cloud Instance for `<SPRING_CLOUD_INSTANCE_NAME>` and the name of the resource group for `<RESOURCE_GROUP>` in the YAML below.
```yaml
name: Build and deploy on Azure Spring Cloud
@ -51,9 +62,9 @@ jobs:
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Install Azure Spring Cloud extension
run: az extension add --name spring-cloud
run: az extension add -y --name spring-cloud
- name: Deploy to Azure Spring Cloud
run: az spring-cloud app deploy --resource-group azure-spring-cloud --service azure-spring-cloud-training --name weather-service --jar-path target/demo-0.0.1-SNAPSHOT.jar
run: az spring-cloud app deploy --resource-group <RESOURCE_GROUP> --service <SPRING_CLOUD_INSTANCE_NAME> --name weather-service --jar-path target/demo-0.0.1-SNAPSHOT.jar
```
This workflow does the following:
@ -62,18 +73,16 @@ This workflow does the following:
- It compiles and packages the application using Maven
- It authenticates to Azure Spring Cloud using the credentials we just configured
- It adds the Azure Spring Cloud extensions to the Azure CLI (this step should disappear when the service is in final release)
- It deploys the application to your Azure Spring Cloud cluster
__Warning__ To deploy your application, you need to input your real Azure resource group and Azure Spring Cloud cluster name in that last command line.
- It deploys the application to your Azure Spring Cloud instance
This workflow is configured to be triggered whenever code is pushed to the repository.
There are many other [events that trigger GitHub actions](https://help.github.com/en/articles/events-that-trigger-workflows): you could for example deploy each time a new tag is created on the project.
There are many other [events that trigger GitHub actions](https://help.github.com/en/articles/events-that-trigger-workflows). You could, for example, deploy each time a new tag is created on the project.
## Test the GitHub action
You can now commit and push the `azure-spring-cloud.yml` file we just created.
Going to the `Actions` tab of your GitHub project, you should see that your project is automatically built and deployed to your Azure Spring Cloud cluster:
Going to the `Actions` tab of your GitHub project, you should see that your project is automatically built and deployed to your Azure Spring Cloud instance:
![GitHub workflow](media/01-github-workflow.png)
@ -82,3 +91,5 @@ Congratulations! Each time you `git push` your code, your microservice is now au
---
⬅️ Previous guide: [10 - Blue/Green deployment](../10-blue-green-deployment/README.md)
➡️ Next guide: [12 - Making Microservices Talk To Each Other](../12-making-microservices-talk-to-each-other/README.md)

Просмотреть файл

@ -0,0 +1,269 @@
# 12 - Making Microservices Talk to Each Other
__This guide is part of the [Azure Spring Cloud training](../README.md)__
Creating a microservice that talks to other microservices.
---
In [Section 6](../06-build-a-reactive-spring-boot-microservice-using-cosmos/README.md) we deployed a microservice that returns a list of cities. In [Section 7](../07-build-a-spring-boot-microservice-using-mysql/README.md), we deployed a microservice that, given a city, returns the weather for that city. And in [Section 9](../09-putting-it-all-together-a-complete-microservice-stack/README.md), we created a front-end application that queries these two microservices.
There is a glaring inefficiency in this design: the browser first calls `city-service`, waits for it to respond, and upon getting that response, calls `weather-service` for each of the cities returned. All these remote calls are made over public internet, whose speed is never guaranteed.
To resolve this inefficiency, we will create a single microservice that implements the [Transaction Script](https://www.martinfowler.com/eaaCatalog/transactionScript.html) pattern: it will orchestrate the calls to individual microservices and return the weather for all cities. To do this, we will use [Spring Cloud OpenFeign]. OpenFeign will automatically obtain the URLs of invoked microservices from Spring Cloud Registry, allowing us to build our `all-cities-weather-services` microservice without needing to resolve the locations of the constituent microservices.
## Create a Spring Boot Microservice
To create our microservice, we will use [https://start.spring.io/](https://start.spring.io/) with the command line:
```bash
curl https://start.spring.io/starter.tgz -d dependencies=cloud-feign,web,cloud-eureka,cloud-config-client -d baseDir=all-cities-weather-service -d bootVersion=2.1.9.RELEASE | tar -xzvf -
```
## Add a "cloud" Maven profile
*To deploy to Azure Spring Cloud, we add a "cloud" Maven profile like in the guide [05 - Build a Spring Boot microservice using Spring Cloud features](../05-build-a-spring-boot-microservice-using-spring-cloud-features/README.md)*
At the end of the application's `pom.xml` file (just before the closing `</project>` XML node), add the following code:
```xml
<profiles>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
```
## Add distributed tracing
As with previous services in Section 9, open up the `pom.xml` file and add the following Maven dependencies to enable distributed tracing:
```java
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
```
## Add Spring code to call other microservices
Next to the `DemoApplication` class, create a `Weather` class:
```java
package com.example.demo;
public class Weather {
private String city;
private String description;
private String icon;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
}
```
Note: this is the same `Weather` class that we created in Section 7 when we defined the original `weather-service` with one important difference: we no longer annotate the class as a JPA entity for data retrieval.
Next, in the same location create the `City` class. This is the same `City` class that we created in Section 6.
```java
package com.example.demo;
public class City {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
```
Then, in the same location, create an interface called `CityServiceClient` with the following contents. When we run our new service, OpenFeign will automatically provide an implementation for this interface.
```java
package com.example.demo;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient("city-service")
public interface CityServiceClient{
@GetMapping("/cities")
List<List<City>> getAllCities();
}
```
Create a similar OpenFeign client interface for the weather service, named `WeatherServiceClient`.
```java
package com.example.demo;
import com.example.demo.Weather;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient("weather-service")
@RequestMapping("/weather")
public interface WeatherServiceClient{
@GetMapping("/city")
Weather getWeatherForCity(@RequestParam("name") String cityName);
}
```
To enable Spring Cloud to discovery the underlying servies and to automatically generate OpenFeign clients, add the annotations @EnableDiscoveryClient and @EnableFeignClients to the `DemoApplication` class (as well as the corresponding `import` statements):
```java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
Everything is now in place to implement the `all-cities-weather-service`. Create the class `AllCitiesWeatherController` as follows:
```java
package com.example.demo;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.example.demo.City;
import com.example.demo.CityServiceClient;
import com.example.demo.Weather;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AllCitiesWeatherController {
@Autowired
private CityServiceClient cityServiceClient;
@Autowired
private WeatherServiceClient weatherServiceClient;
@GetMapping("/")
public List<Weather> getAllCitiesWeather(){
Stream<City> allCities = cityServiceClient.getAllCities().stream().flatMap(list -> list.stream());
//Obtain weather for all cities in parallel
List<Weather> allCitiesWeather = allCities.parallel()
.peek(city -> System.out.println("City: >>"+city.getName()+"<<"))
.map(city -> weatherServiceClient.getWeatherForCity(city.getName()))
.collect(Collectors.toList());
return allCitiesWeather;
}
}
```
## Create the application on Azure Spring Cloud
As before, create a specific `all-cities-weather-service` application in your Azure Spring Cloud instance:
```bash
az spring-cloud app create -n all-cities-weather-service
```
## Deploy the application
You can now build your "all-cities-weather-service" project and send it to Azure Spring Cloud:
```bash
cd all-cities-weather-service
./mvnw clean package -DskipTests -Pcloud
az spring-cloud app deploy -n all-cities-weather-service --jar-path target/demo-0.0.1-SNAPSHOT.jar
cd ..
```
## Test the project in the cloud
You can use the gateway created in Section 8 to access the all-cities-weather-service directly.
>💡__Note:__ the trailing slash (`/`) is not optional.
```bash
https://<Your gateway URL>/ALL-CITIES-WEATHER-SERVICE/
```
You should get the JSON output with the weather for all the cities:
```json
[{"city":"Paris, France","description":"It's always sunny on Azure Spring Cloud","icon":"weather-sunny"},
{"city":"London, UK","description":"It's always sunny on Azure Spring Cloud","icon":"weather-sunny"}]
```
---
⬅️ Previous guide: [11 - Configure CI/CD](../11-configure-ci-cd/README.md)
➡️ Next guide: [Conclusion](../99-conclusion/README.md)

Просмотреть файл

@ -0,0 +1,31 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/

Просмотреть файл

@ -0,0 +1,117 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.5";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Двоичные данные
12-making-microservices-talk-to-each-other/all-cities-weather-service/.mvn/wrapper/maven-wrapper.jar поставляемый Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar

Просмотреть файл

@ -0,0 +1,310 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

Просмотреть файл

@ -0,0 +1,182 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

Просмотреть файл

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>cloud</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-cloud-starter-azure-spring-cloud-client</artifactId>
<version>2.1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

Просмотреть файл

@ -0,0 +1,42 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.example.demo;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.example.demo.City;
import com.example.demo.CityServiceClient;
import com.example.demo.Weather;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AllCitiesWeatherController {
@Autowired
private CityServiceClient cityServiceClient;
@Autowired
private WeatherServiceClient weatherServiceClient;
@GetMapping("/")
public List<Weather> getAllCitiesWeather(){
Stream<City> allCities = cityServiceClient.getAllCities().stream().flatMap(list -> list.stream());
//Obtain weather for all cities in parallel
List<Weather> allCitiesWeather = allCities.parallel()
.peek(city -> System.out.println("City: >>"+city.getName()+"<<"))
.map(city -> weatherServiceClient.getWeatherForCity(city.getName()))
.collect(Collectors.toList());
return allCitiesWeather;
}
}

Просмотреть файл

@ -0,0 +1,20 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.example.demo;
public class City {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

Просмотреть файл

@ -0,0 +1,19 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.example.demo;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient("city-service")
public interface CityServiceClient{
@GetMapping("/cities")
List<List<City>> getAllCities();
}

Просмотреть файл

@ -0,0 +1,23 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

Просмотреть файл

@ -0,0 +1,40 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.example.demo;
public class Weather {
private String city;
private String description;
private String icon;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
}

Просмотреть файл

@ -0,0 +1,23 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.example.demo;
import com.example.demo.Weather;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient("weather-service")
@RequestMapping("/weather")
public interface WeatherServiceClient{
@GetMapping("/city")
Weather getWeatherForCity(@RequestParam("name") String cityName);
}

Просмотреть файл

@ -0,0 +1 @@

27
99-conclusion/README.md Normal file
Просмотреть файл

@ -0,0 +1,27 @@
# Conclusion
__This guide is part of the [Azure Spring Cloud training](../README.md)__
---
## Cleaning up
Unless you plan to perform additional tasks with the Azure resources from the workshop (such as tutorials referenced below), it is important to destroy the resources that we created for it to avoid the cost of keeping them provisioned.
The easiest way to do this is to delete the entire resource group.
>🛑Substitute the name of your resource group for `$RESOURCE_GROUP_NAME` below:
```bash
az group delete -g "$RESOURCE_GROUP_NAME" --yes --no-wait
```
## Additional Resources
As an addendum to this workshop, consider taking the [tutorial on using alerts and action groups with Azure Spring Cloud](https://docs.microsoft.com/azure/spring-cloud/spring-cloud-tutorial-alerts-action-groups) to detect and respond to abberant conditions.
Have a look through the [Azure Spring Cloud documentation](https://docs.microsoft.com/azure/spring-cloud) for more quickstarts, tutorials, and reference materials.
---
⬅️ Previous guide: [12 - Making Microservices Talk To Each Other](../12-making-microservices-talk-to-each-other/README.md)

Просмотреть файл

@ -1,9 +1,9 @@
# Microsoft Open Source Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/?WT.mc_id=azurespringcloud-github-judubois).
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
Resources:
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/?WT.mc_id=azurespringcloud-github-judubois)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/?WT.mc_id=azurespringcloud-github-judubois)
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns

21
LICENSE Normal file
Просмотреть файл

@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

Просмотреть файл

@ -1,8 +1,14 @@
---
page_type: sample
languages:
- java
---
# Azure Spring Cloud training
You will find here a full workshop on Azure Spring Cloud, including guides and demos.
This was created by [Julien Dubois](https://twitter.com/juliendubois) and available for free to everyone, under the [MIT license](LICENSE.txt).
This lab is based on a public workshop created by [Julien Dubois](https://twitter.com/juliendubois) and available for free to everyone, under the [MIT license](LICENSE.txt).
## What you should expect
@ -12,14 +18,19 @@ It is a hands-on training, and it will use the command line extensively. The ide
After completing all the guides, you should have a fairly good understanding of everything that Azure Spring Cloud offers.
## Prerequisites
## Symbols
- Java 8 or above
- The [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli/?WT.mc_id=azurespringcloud-github-judubois)
- A [GitHub account](https://github.com)
- An Azure account. [Get one for free](https://azure.microsoft.com/free/?WT.mc_id=azurespringcloud-github-judubois).
>🛑 - __Manual Modification Required__. When this symbol appears in front of one or more commands, you will need to modify the commands as indicated prior to running them.
## [01 - Create a cluster](01-create-a-cluster/README.md)
>🚧 - __Preview-specific__. This symbol indicates steps that are only necessary while Azure Spring Cloud is in preview.
>💡 - __Frustration Avoidance Tip__. These will help you avoid potential pitfalls.
## [00 - Prerequisites and Setup](00-setup-your-environment/README.md)
Prerequisites and environment setup.
## [01 - Create an Azure Spring Cloud cluster](01-create-a-cluster/README.md)
Basics on creating a cluster and configuring the CLI to work efficiently.
@ -63,6 +74,12 @@ Deploy new versions of applications in a staging environment, and switch between
Configure a Continuous Integration / Continuous Deployement platform using GitHub Actions, so our Spring Boot microservices are automatically deployed.
## [12 - Making Microservices Talk to Each Other](12-making-microservices-talk-to-each-other/README.md)
Creating a microservice that talks to other microservices.
## [Conclusion](99-conclusion/README.md)
---
## Legal Notices
@ -77,7 +94,8 @@ may be either trademarks or registered trademarks of Microsoft in the United Sta
The licenses for this project do not grant you rights to use any Microsoft names, logos, or trademarks.
Microsoft's general trademark guidelines can be found at http://go.microsoft.com/fwlink/?LinkID=254653.
Privacy information can be found at [https://privacy.microsoft.com/en-us/](https://privacy.microsoft.com/en-us/?WT.mc_id=azurespringcloud-github-judubois)
Privacy information can be found at https://privacy.microsoft.com/en-us/
Microsoft and any contributors reserve all other rights, whether under their respective copyrights, patents,
or trademarks, whether by implication, estoppel or otherwise.

Просмотреть файл

@ -1,20 +1,21 @@
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.2 BLOCK -->
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.3 BLOCK -->
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [many more](https://opensource.microsoft.com/?WT.mc_id=azurespringcloud-github-judubois).
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [definition](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report/?WT.mc_id=azurespringcloud-github-judubois).
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msr/?WT.mc_id=azurespringcloud-github-juduboisc).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc/?WT.mc_id=azurespringcloud-github-judubois).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
@ -36,6 +37,6 @@ We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd/?WT.mc_id=azurespringcloud-github-judubois).
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
<!-- END MICROSOFT SECURITY.MD BLOCK -->