Skip to content

Commit f330572

Browse files
committed
forgot to add file
Signed-off-by: Hannah Hunter <hannahhunter@microsoft.com>
1 parent 866d235 commit f330572

File tree

1 file changed

+257
-0
lines changed

1 file changed

+257
-0
lines changed
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
---
2+
type: docs
3+
title: "How to: Use the gRPC interface in your Dapr application"
4+
linkTitle: "gRPC interface"
5+
weight: 400
6+
description: "Use the Dapr gRPC API in your application"
7+
---
8+
9+
Dapr implements both an HTTP and a gRPC API for local calls. [gRPC](https://grpc.io/) is useful for low-latency, high performance scenarios and has language integration using the proto clients.
10+
11+
[Find a list of auto-generated clients in the Dapr SDK documentation]({{< ref sdks >}}).
12+
13+
The Dapr runtime implements a [proto service](https://github.com/dapr/dapr/blob/master/dapr/proto/runtime/v1/dapr.proto) that apps can communicate with via gRPC.
14+
15+
In addition to calling Dapr via gRPC, Dapr supports service-to-service calls with gRPC by acting as a proxy. [Learn more in the gRPC service invocation how-to guide]({{< ref howto-invoke-services-grpc.md >}}).
16+
17+
This guide demonstrates configuring and invoking Dapr with gRPC using a Go SDK application.
18+
19+
## Configure Dapr to communicate with an app via gRPC
20+
21+
{{< tabs "Self-hosted" "Kubernetes">}}
22+
<!--selfhosted-->
23+
{{% codetab %}}
24+
25+
When running in self-hosted mode, use the `--app-protocol` flag to tell Dapr to use gRPC to talk to the app.
26+
27+
```bash
28+
dapr run --app-protocol grpc --app-port 5005 node app.js
29+
```
30+
31+
This tells Dapr to communicate with your app via gRPC over port `5005`.
32+
33+
{{% /codetab %}}
34+
35+
<!--k8s-->
36+
{{% codetab %}}
37+
38+
On Kubernetes, set the following annotations in your deployment YAML:
39+
40+
```yaml
41+
apiVersion: apps/v1
42+
kind: Deployment
43+
metadata:
44+
name: myapp
45+
namespace: default
46+
labels:
47+
app: myapp
48+
spec:
49+
replicas: 1
50+
selector:
51+
matchLabels:
52+
app: myapp
53+
template:
54+
metadata:
55+
labels:
56+
app: myapp
57+
annotations:
58+
dapr.io/enabled: "true"
59+
dapr.io/app-id: "myapp"
60+
dapr.io/app-protocol: "grpc"
61+
dapr.io/app-port: "5005"
62+
...
63+
```
64+
65+
{{% /codetab %}}
66+
67+
{{< /tabs >}}
68+
69+
## Invoke Dapr with gRPC
70+
71+
The following steps show how to create a Dapr client and call the `SaveStateData` operation on it.
72+
73+
1. Import the package:
74+
75+
```go
76+
package main
77+
78+
import (
79+
"context"
80+
"log"
81+
"os"
82+
83+
dapr "github.com/dapr/go-sdk/client"
84+
)
85+
```
86+
87+
1. Create the client:
88+
89+
```go
90+
// just for this demo
91+
ctx := context.Background()
92+
data := []byte("ping")
93+
94+
// create the client
95+
client, err := dapr.NewClient()
96+
if err != nil {
97+
log.Panic(err)
98+
}
99+
defer client.Close()
100+
```
101+
102+
3. Invoke the `SaveState` method:
103+
104+
```go
105+
// save state with the key key1
106+
err = client.SaveState(ctx, "statestore", "key1", data)
107+
if err != nil {
108+
log.Panic(err)
109+
}
110+
log.Println("data saved")
111+
```
112+
113+
Now you can explore all the different methods on the Dapr client.
114+
115+
## Create a gRPC app with Dapr
116+
117+
The following steps will show how to create an app that exposes a server for with which Dapr can communicate.
118+
119+
1. Import the package:
120+
121+
```go
122+
package main
123+
124+
import (
125+
"context"
126+
"fmt"
127+
"log"
128+
"net"
129+
130+
"github.com/golang/protobuf/ptypes/any"
131+
"github.com/golang/protobuf/ptypes/empty"
132+
133+
commonv1pb "github.com/dapr/dapr/pkg/proto/common/v1"
134+
pb "github.com/dapr/dapr/pkg/proto/runtime/v1"
135+
"google.golang.org/grpc"
136+
)
137+
```
138+
139+
1. Implement the interface:
140+
141+
```go
142+
// server is our user app
143+
type server struct {
144+
pb.UnimplementedAppCallbackServer
145+
}
146+
147+
// EchoMethod is a simple demo method to invoke
148+
func (s *server) EchoMethod() string {
149+
return "pong"
150+
}
151+
152+
// This method gets invoked when a remote service has called the app through Dapr
153+
// The payload carries a Method to identify the method, a set of metadata properties and an optional payload
154+
func (s *server) OnInvoke(ctx context.Context, in *commonv1pb.InvokeRequest) (*commonv1pb.InvokeResponse, error) {
155+
var response string
156+
157+
switch in.Method {
158+
case "EchoMethod":
159+
response = s.EchoMethod()
160+
}
161+
162+
return &commonv1pb.InvokeResponse{
163+
ContentType: "text/plain; charset=UTF-8",
164+
Data: &any.Any{Value: []byte(response)},
165+
}, nil
166+
}
167+
168+
// Dapr will call this method to get the list of topics the app wants to subscribe to. In this example, we are telling Dapr
169+
// To subscribe to a topic named TopicA
170+
func (s *server) ListTopicSubscriptions(ctx context.Context, in *empty.Empty) (*pb.ListTopicSubscriptionsResponse, error) {
171+
return &pb.ListTopicSubscriptionsResponse{
172+
Subscriptions: []*pb.TopicSubscription{
173+
{Topic: "TopicA"},
174+
},
175+
}, nil
176+
}
177+
178+
// Dapr will call this method to get the list of bindings the app will get invoked by. In this example, we are telling Dapr
179+
// To invoke our app with a binding named storage
180+
func (s *server) ListInputBindings(ctx context.Context, in *empty.Empty) (*pb.ListInputBindingsResponse, error) {
181+
return &pb.ListInputBindingsResponse{
182+
Bindings: []string{"storage"},
183+
}, nil
184+
}
185+
186+
// This method gets invoked every time a new event is fired from a registered binding. The message carries the binding name, a payload and optional metadata
187+
func (s *server) OnBindingEvent(ctx context.Context, in *pb.BindingEventRequest) (*pb.BindingEventResponse, error) {
188+
fmt.Println("Invoked from binding")
189+
return &pb.BindingEventResponse{}, nil
190+
}
191+
192+
// This method is fired whenever a message has been published to a topic that has been subscribed. Dapr sends published messages in a CloudEvents 0.3 envelope.
193+
func (s *server) OnTopicEvent(ctx context.Context, in *pb.TopicEventRequest) (*pb.TopicEventResponse, error) {
194+
fmt.Println("Topic message arrived")
195+
return &pb.TopicEventResponse{}, nil
196+
}
197+
198+
```
199+
200+
1. Create the server:
201+
202+
```go
203+
func main() {
204+
// create listener
205+
lis, err := net.Listen("tcp", ":50001")
206+
if err != nil {
207+
log.Fatalf("failed to listen: %v", err)
208+
}
209+
210+
// create grpc server
211+
s := grpc.NewServer()
212+
pb.RegisterAppCallbackServer(s, &server{})
213+
214+
fmt.Println("Client starting...")
215+
216+
// and start...
217+
if err := s.Serve(lis); err != nil {
218+
log.Fatalf("failed to serve: %v", err)
219+
}
220+
}
221+
```
222+
223+
This creates a gRPC server for your app on port 50001.
224+
225+
## Run the application
226+
227+
{{< tabs "Self-hosted" "Kubernetes">}}
228+
<!--selfhosted-->
229+
{{% codetab %}}
230+
231+
To run locally, use the Dapr CLI:
232+
233+
```bash
234+
dapr run --app-id goapp --app-port 50001 --app-protocol grpc go run main.go
235+
```
236+
237+
{{% /codetab %}}
238+
239+
<!--k8s-->
240+
{{% codetab %}}
241+
242+
On Kubernetes, set the required `dapr.io/app-protocol: "grpc"` and `dapr.io/app-port: "50001` annotations in your pod spec template, as mentioned above.
243+
244+
{{% /codetab %}}
245+
246+
{{< /tabs >}}
247+
248+
249+
## Other languages
250+
251+
You can use Dapr with any language supported by Protobuf, and not just with the currently available generated SDKs.
252+
253+
Using the [protoc](https://developers.google.com/protocol-buffers/docs/downloads) tool, you can generate the Dapr clients for other languages like Ruby, C++, Rust, and others.
254+
255+
## Related Topics
256+
- [Service invocation building block]({{< ref service-invocation >}})
257+
- [Service invocation API specification]({{< ref service_invocation_api.md >}})

0 commit comments

Comments
 (0)