mirror of https://github.com/dapr/docs.git
Merge pull request #1965 from amulyavarote/feature/service_invocation
Provide consistent examples of service invocation for all SDKs
This commit is contained in:
commit
59fc6f8068
|
@ -8,29 +8,136 @@ weight: 2000
|
||||||
|
|
||||||
This article describe how to deploy services each with an unique application ID, so that other services can discover and call endpoints on them using service invocation API.
|
This article describe how to deploy services each with an unique application ID, so that other services can discover and call endpoints on them using service invocation API.
|
||||||
|
|
||||||
|
## Example:
|
||||||
|
|
||||||
|
The below code examples loosely describe an application that processes orders. In the examples, there are two services - an order processing service and a checkout service. Both services have Dapr sidecars and the order processing service uses Dapr to invoke the checkout method in the checkout service.
|
||||||
|
|
||||||
|
<img src="/images/service_invocation_eg.png" width=1000 height=500 alt="Diagram showing service invocation of example service">
|
||||||
|
|
||||||
## Step 1: Choose an ID for your service
|
## Step 1: Choose an ID for your service
|
||||||
|
|
||||||
Dapr allows you to assign a global, unique ID for your app. This ID encapsulates the state for your application, regardless of the number of instances it may have.
|
Dapr allows you to assign a global, unique ID for your app. This ID encapsulates the state for your application, regardless of the number of instances it may have.
|
||||||
|
|
||||||
{{< tabs "Self-Hosted (CLI)" Kubernetes >}}
|
|
||||||
|
{{< tabs Dotnet Java Python Go Javascript Kubernetes>}}
|
||||||
|
|
||||||
|
|
||||||
{{% codetab %}}
|
{{% codetab %}}
|
||||||
In self hosted mode, set the `--app-id` flag:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dapr run --app-id cart --dapr-http-port 3500 --app-port 5000 python app.py
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 dotnet run
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 dotnet run
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If your app uses an SSL connection, you can tell Dapr to invoke your app over an insecure SSL connection:
|
If your app uses an SSL connection, you can tell Dapr to invoke your app over an insecure SSL connection:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dapr run --app-id cart --dapr-http-port 3500 --app-port 5000 --app-ssl python app.py
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 --app-ssl dotnet run
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 --app-ssl dotnet run
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
{{% /codetab %}}
|
{{% /codetab %}}
|
||||||
|
|
||||||
{{% codetab %}}
|
{{% codetab %}}
|
||||||
|
|
||||||
### Setup an ID using Kubernetes
|
```bash
|
||||||
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 mvn spring-boot:run
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 mvn spring-boot:run
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If your app uses an SSL connection, you can tell Dapr to invoke your app over an insecure SSL connection:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 --app-ssl mvn spring-boot:run
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 --app-ssl mvn spring-boot:run
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
{{% /codetab %}}
|
||||||
|
|
||||||
|
{{% codetab %}}
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 -- python3 CheckoutService.py
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 -- python3 OrderProcessingService.py
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If your app uses an SSL connection, you can tell Dapr to invoke your app over an insecure SSL connection:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 --app-ssl -- python3 CheckoutService.py
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 --app-ssl -- python3 OrderProcessingService.py
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
{{% /codetab %}}
|
||||||
|
|
||||||
|
|
||||||
|
{{% codetab %}}
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 go run CheckoutService.go
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 go run OrderProcessingService.go
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If your app uses an SSL connection, you can tell Dapr to invoke your app over an insecure SSL connection:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 --app-ssl go run CheckoutService.go
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 --app-ssl go run OrderProcessingService.go
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
{{% /codetab %}}
|
||||||
|
|
||||||
|
|
||||||
|
{{% codetab %}}
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 npm start
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 npm start
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If your app uses an SSL connection, you can tell Dapr to invoke your app over an insecure SSL connection:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
dapr run --app-id checkout --app-port 6002 --dapr-http-port 3602 --dapr-grpc-port 60002 --app-ssl npm start
|
||||||
|
|
||||||
|
dapr run --app-id orderprocessing --app-port 6001 --dapr-http-port 3601 --dapr-grpc-port 60001 --app-ssl npm start
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
{{% /codetab %}}
|
||||||
|
|
||||||
|
|
||||||
|
{{% codetab %}}
|
||||||
|
|
||||||
|
### Set an app-id when deploying to Kubernetes
|
||||||
|
|
||||||
In Kubernetes, set the `dapr.io/app-id` annotation on your pod:
|
In Kubernetes, set the `dapr.io/app-id` annotation on your pod:
|
||||||
|
|
||||||
|
@ -38,23 +145,23 @@ In Kubernetes, set the `dapr.io/app-id` annotation on your pod:
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: python-app
|
name: <language>-app
|
||||||
namespace: default
|
namespace: default
|
||||||
labels:
|
labels:
|
||||||
app: python-app
|
app: <language>-app
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: python-app
|
app: <language>-app
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: python-app
|
app: <language>-app
|
||||||
annotations:
|
annotations:
|
||||||
dapr.io/enabled: "true"
|
dapr.io/enabled: "true"
|
||||||
dapr.io/app-id: "cart"
|
dapr.io/app-id: "orderprocessingservice"
|
||||||
dapr.io/app-port: "5000"
|
dapr.io/app-port: "6001"
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
*If your app uses an SSL connection, you can tell Dapr to invoke your app over an insecure SSL connection with the `app-ssl: "true"` annotation (full list [here]({{< ref arguments-annotations-overview.md >}}))*
|
*If your app uses an SSL connection, you can tell Dapr to invoke your app over an insecure SSL connection with the `app-ssl: "true"` annotation (full list [here]({{< ref arguments-annotations-overview.md >}}))*
|
||||||
|
@ -63,103 +170,169 @@ spec:
|
||||||
|
|
||||||
{{< /tabs >}}
|
{{< /tabs >}}
|
||||||
|
|
||||||
|
## Step 2: Invoke the service
|
||||||
|
|
||||||
## Step 2: Setup a service
|
To invoke an application using Dapr, you can use the `invoke` API on any Dapr instance.
|
||||||
|
|
||||||
The following is a Python example of a cart app. It can be written in any programming language.
|
The sidecar programming model encourages each application to interact with its own instance of Dapr. The Dapr sidecars discover and communicate with one another.
|
||||||
|
|
||||||
```python
|
Below are code examples that leverage Dapr SDKs for service invocation.
|
||||||
from flask import Flask
|
|
||||||
app = Flask(__name__)
|
|
||||||
|
|
||||||
@app.route('/add', methods=['POST'])
|
{{< tabs Dotnet Java Python Go Javascript>}}
|
||||||
def add():
|
|
||||||
return "Added!"
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app.run()
|
|
||||||
```
|
|
||||||
|
|
||||||
This Python app exposes an `add()` method via the `/add` endpoint.
|
|
||||||
|
|
||||||
## Step 3: Invoke the service
|
|
||||||
|
|
||||||
Dapr uses a sidecar, decentralized architecture. To invoke an application using Dapr, you can use the `invoke` API on any Dapr instance.
|
|
||||||
|
|
||||||
The sidecar programming model encourages each applications to talk to its own instance of Dapr. The Dapr instances discover and communicate with one another.
|
|
||||||
|
|
||||||
{{< tabs curl CLI >}}
|
|
||||||
|
|
||||||
{{% codetab %}}
|
{{% codetab %}}
|
||||||
From a terminal or command prompt run:
|
```csharp
|
||||||
```bash
|
|
||||||
curl http://localhost:3500/v1.0/invoke/cart/method/add -X POST
|
//headers
|
||||||
|
|
||||||
|
using Dapr.Client;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
//code
|
||||||
|
|
||||||
|
CancellationTokenSource source = new CancellationTokenSource();
|
||||||
|
CancellationToken cancellationToken = source.Token;
|
||||||
|
using var client = new DaprClientBuilder().Build();
|
||||||
|
var result = client.CreateInvokeMethodRequest(HttpMethod.Get, "checkout", "checkout/" + orderId, cancellationToken);
|
||||||
|
await client.InvokeMethodAsync(result);
|
||||||
|
|
||||||
```
|
```
|
||||||
|
{{% /codetab %}}
|
||||||
|
|
||||||
Since the add endpoint is a 'POST' method, we used `-X POST` in the curl command.
|
|
||||||
|
|
||||||
To invoke a 'GET' endpoint:
|
{{% codetab %}}
|
||||||
|
```java
|
||||||
|
|
||||||
|
//headers
|
||||||
|
|
||||||
|
import io.dapr.client.DaprClient;
|
||||||
|
import io.dapr.client.DaprClientBuilder;
|
||||||
|
import io.dapr.client.domain.HttpExtension;
|
||||||
|
|
||||||
|
//code
|
||||||
|
|
||||||
|
DaprClient daprClient = new DaprClientBuilder().build();
|
||||||
|
var result = daprClient.invokeMethod(
|
||||||
|
"checkout",
|
||||||
|
"checkout/" + orderId,
|
||||||
|
null,
|
||||||
|
HttpExtension.GET,
|
||||||
|
String.class
|
||||||
|
);
|
||||||
|
|
||||||
```bash
|
|
||||||
curl http://localhost:3500/v1.0/invoke/cart/method/add
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To invoke a 'DELETE' endpoint:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl http://localhost:3500/v1.0/invoke/cart/method/add -X DELETE
|
|
||||||
```
|
|
||||||
|
|
||||||
Dapr puts any payload returned by the called service in the HTTP response's body.
|
|
||||||
|
|
||||||
### Additional URL formats
|
|
||||||
|
|
||||||
In order to avoid changing URL paths as much as possible, Dapr provides the following ways to call the service invocation API:
|
|
||||||
|
|
||||||
|
|
||||||
1. Change the address in the URL to `localhost:<dapr-http-port>`.
|
|
||||||
2. Add a `dapr-app-id` header to specify the ID of the target service, or alternatively pass the ID via HTTP Basic Auth: `http://dapr-app-id:<service-id>@localhost:3500/path`.
|
|
||||||
|
|
||||||
For example, the following command
|
|
||||||
```bash
|
|
||||||
curl http://localhost:3500/v1.0/invoke/cart/method/add
|
|
||||||
```
|
|
||||||
|
|
||||||
is equivalent to:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -H 'dapr-app-id: cart' 'http://localhost:3500/add' -X POST
|
|
||||||
```
|
|
||||||
|
|
||||||
or:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl 'http://dapr-app-id:cart@localhost:3500/add' -X POST
|
|
||||||
```
|
|
||||||
|
|
||||||
{{% /codetab %}}
|
{{% /codetab %}}
|
||||||
|
|
||||||
{{% codetab %}}
|
{{% codetab %}}
|
||||||
```bash
|
```python
|
||||||
dapr invoke --app-id cart --method add
|
|
||||||
|
//headers
|
||||||
|
|
||||||
|
from dapr.clients import DaprClient
|
||||||
|
|
||||||
|
//code
|
||||||
|
|
||||||
|
with DaprClient() as daprClient:
|
||||||
|
result = daprClient.invoke_method(
|
||||||
|
"checkout",
|
||||||
|
f"checkout/{orderId}",
|
||||||
|
data=b'',
|
||||||
|
http_verb="GET"
|
||||||
|
)
|
||||||
|
|
||||||
|
```
|
||||||
|
{{% /codetab %}}
|
||||||
|
|
||||||
|
{{% codetab %}}
|
||||||
|
```go
|
||||||
|
|
||||||
|
//headers
|
||||||
|
import (
|
||||||
|
dapr "github.com/dapr/go-sdk/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
//code
|
||||||
|
|
||||||
|
client, err := dapr.NewClient()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
result, err := client.InvokeMethod(ctx, "checkout", "checkout/" + strconv.Itoa(orderId), "get")
|
||||||
|
|
||||||
|
```
|
||||||
|
{{% /codetab %}}
|
||||||
|
|
||||||
|
{{% codetab %}}
|
||||||
|
```javascript
|
||||||
|
|
||||||
|
//headers
|
||||||
|
|
||||||
|
import { DaprClient, HttpMethod, CommunicationProtocolEnum } from 'dapr-client';
|
||||||
|
|
||||||
|
//code
|
||||||
|
|
||||||
|
const daprHost = "127.0.0.1";
|
||||||
|
const client = new DaprClient(daprHost, process.env.DAPR_HTTP_PORT, CommunicationProtocolEnum.HTTP);
|
||||||
|
const result = await client.invoker.invoke('checkout' , "checkout/" + orderId , HttpMethod.GET);
|
||||||
|
|
||||||
```
|
```
|
||||||
{{% /codetab %}}
|
{{% /codetab %}}
|
||||||
|
|
||||||
{{< /tabs >}}
|
{{< /tabs >}}
|
||||||
|
|
||||||
### Namespaces
|
### Additional URL formats
|
||||||
|
|
||||||
When running on [namespace supported platforms]({{< ref "service_invocation_api.md#namespace-supported-platforms" >}}), you include the namespace of the target app in the app ID: `myApp.production`
|
To invoke a 'GET' endpoint:
|
||||||
|
```bash
|
||||||
|
curl http://localhost:3602/v1.0/invoke/checkout/method/checkout/100
|
||||||
|
```
|
||||||
|
|
||||||
For example, invoking the example python service with a namespace would be:
|
In order to avoid changing URL paths as much as possible, Dapr provides the following ways to call the service invocation API:
|
||||||
|
|
||||||
|
|
||||||
|
1. Change the address in the URL to `localhost:<dapr-http-port>`.
|
||||||
|
2. Add a `dapr-app-id` header to specify the ID of the target service, or alternatively pass the ID via HTTP Basic Auth: `http://dapr-app-id:<service-id>@localhost:3602/path`.
|
||||||
|
|
||||||
|
For example, the following command
|
||||||
|
```bash
|
||||||
|
curl http://localhost:3602/v1.0/invoke/checkout/method/checkout/100
|
||||||
|
```
|
||||||
|
|
||||||
|
is equivalent to:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl http://localhost:3500/v1.0/invoke/cart.production/method/add -X POST
|
curl -H 'dapr-app-id: checkout' 'http://localhost:3602/checkout/100' -X POST
|
||||||
|
```
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl 'http://dapr-app-id:checkout@localhost:3602/checkout/100' -X POST
|
||||||
|
```
|
||||||
|
|
||||||
|
Using CLI:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dapr invoke --app-id checkout --method checkout/100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Namespaces
|
||||||
|
|
||||||
|
When running on [namespace supported platforms]({{< ref "service_invocation_api.md#namespace-supported-platforms" >}}), you include the namespace of the target app in the app ID: `checkout.production`
|
||||||
|
|
||||||
|
For example, invoking the example service with a namespace would be:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:3602/v1.0/invoke/checkout.production/method/checkout/100 -X POST
|
||||||
```
|
```
|
||||||
|
|
||||||
See the [Cross namespace API spec]({{< ref "service_invocation_api.md#cross-namespace-invocation" >}}) for more information on namespaces.
|
See the [Cross namespace API spec]({{< ref "service_invocation_api.md#cross-namespace-invocation" >}}) for more information on namespaces.
|
||||||
|
|
||||||
## Step 4: View traces and logs
|
## Step 3: View traces and logs
|
||||||
|
|
||||||
The example above showed you how to directly invoke a different service running locally or in Kubernetes. Dapr outputs metrics, tracing and logging information allowing you to visualize a call graph between services, log errors and optionally log the payload body.
|
The example above showed you how to directly invoke a different service running locally or in Kubernetes. Dapr outputs metrics, tracing and logging information allowing you to visualize a call graph between services, log errors and optionally log the payload body.
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 181 KiB |
Loading…
Reference in New Issue