Add a sample of Golang gRPC client/server programs
This commit is contained in:
parent
027e1569e0
commit
124acba6db
6
demos/golang/grpc_pingpong/.gitignore
vendored
Normal file
6
demos/golang/grpc_pingpong/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
occlum_ping
|
||||||
|
occlum_pong
|
||||||
|
occlum_ping_instance/
|
||||||
|
occlum_pong_instance/
|
||||||
|
go.sum
|
||||||
|
github.com/
|
20
demos/golang/grpc_pingpong/README.md
Normal file
20
demos/golang/grpc_pingpong/README.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Use Golang and gRPC with Occlum
|
||||||
|
|
||||||
|
This project demonstrates how Occlum enables [Golang](https://golang.org) programs with [gRPC](google.golang.org/grpc) calls running in SGX enclaves. The client program invokes a gRPC call with a ping message, and receives a pong message sent by the server program.
|
||||||
|
|
||||||
|
Step 1: Build the Golang gRPC application using the Occlum Golang toolchain via
|
||||||
|
```
|
||||||
|
./prepare_ping_pong.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Step 2: Run the gRPC server demo on Occlum via
|
||||||
|
```
|
||||||
|
./run_pong_on_occlum.sh
|
||||||
|
```
|
||||||
|
The gRPC server should now start to listen on port 8888 and serve incoming requests.
|
||||||
|
|
||||||
|
Step 3: Run the gRPC client demo on Occlum via
|
||||||
|
```
|
||||||
|
./run_ping_on_occlum.sh
|
||||||
|
```
|
||||||
|
After the reply message is received, the latency incurred during a gRPC call will be printed out.
|
9
demos/golang/grpc_pingpong/go.mod
Normal file
9
demos/golang/grpc_pingpong/go.mod
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module grpc_pingpong
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/golang/protobuf v1.4.1
|
||||||
|
google.golang.org/grpc v1.33.0-dev
|
||||||
|
google.golang.org/protobuf v1.25.0
|
||||||
|
)
|
31
demos/golang/grpc_pingpong/ping.go
Normal file
31
demos/golang/grpc_pingpong/ping.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
|
"grpc_pingpong/github.com/occlum/demos/grpc_pingpong/pingpong"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
conn, err := grpc.Dial("localhost:8888", grpc.WithInsecure())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to connect: %s\n", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
previousTime := time.Now()
|
||||||
|
fmt.Printf("Ping: at %s\n", previousTime.Format("2006-01-02T15:04:05.999999999Z07:00"))
|
||||||
|
client := pingpong.NewPingPongServiceClient(conn)
|
||||||
|
response, err := client.PingPong(context.Background(), &pingpong.PingPongMesg{Ping: "Hello"})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error when calling PingPongHandler: %s\n", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Pong from server: %s (at %s)\n", response.Pong, response.Timestamp)
|
||||||
|
currentTime := time.Now()
|
||||||
|
fmt.Printf("End-to-End latency is: %f Seconds\n", currentTime.Sub(previousTime).Seconds())
|
||||||
|
}
|
||||||
|
|
13
demos/golang/grpc_pingpong/pingpong/pingpong.proto
Normal file
13
demos/golang/grpc_pingpong/pingpong/pingpong.proto
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package pingpong;
|
||||||
|
option go_package = "github.com/occlum/demos/grpc_pingpong/pingpong";
|
||||||
|
|
||||||
|
message PingPongMesg {
|
||||||
|
string ping = 1;
|
||||||
|
string pong = 2;
|
||||||
|
string timestamp = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
service PingPongService {
|
||||||
|
rpc PingPong(PingPongMesg) returns (PingPongMesg) {}
|
||||||
|
}
|
38
demos/golang/grpc_pingpong/pong.go
Normal file
38
demos/golang/grpc_pingpong/pong.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
|
"grpc_pingpong/github.com/occlum/demos/grpc_pingpong/pingpong"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PingPong(ctx context.Context, in *pingpong.PingPongMesg) (*pingpong.PingPongMesg, error) {
|
||||||
|
currentTime := time.Now()
|
||||||
|
fmt.Printf("Receiving Ping: %s (at %s)\n", in.Ping, currentTime.Format("2006-01-02T15:04:05.999999999Z07:00"))
|
||||||
|
return &pingpong.PingPongMesg{Ping: in.Ping,
|
||||||
|
Pong: fmt.Sprintf("Greetings from Pong! Ping Echoed: %s", in.Ping),
|
||||||
|
Timestamp: currentTime.Format("2006-01-02T15:04:05.999999999Z07:00")}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("grpc_pingpong server is waiting for service requests ...")
|
||||||
|
|
||||||
|
conn, err := net.Listen("tcp", "localhost:8888")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to listen: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
grpcServer := grpc.NewServer()
|
||||||
|
|
||||||
|
pingpong.RegisterPingPongServiceService(grpcServer, &pingpong.PingPongServiceService{PingPong: PingPong})
|
||||||
|
|
||||||
|
if err := grpcServer.Serve(conn); err != nil {
|
||||||
|
fmt.Printf("Failed to serve: %s\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
56
demos/golang/grpc_pingpong/prepare_ping_pong.sh
Executable file
56
demos/golang/grpc_pingpong/prepare_ping_pong.sh
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BLUE='\033[1;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# sanity check
|
||||||
|
FILE_SET="
|
||||||
|
occlum_ping
|
||||||
|
occlum_pong
|
||||||
|
go.sum"
|
||||||
|
for CURR_FILE in $FILE_SET
|
||||||
|
do
|
||||||
|
if [ -f "$CURR_FILE" ]; then
|
||||||
|
rm $CURR_FILE
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
DIR_SET="
|
||||||
|
github.com
|
||||||
|
occlum_ping_instance
|
||||||
|
occlum_pong_instance"
|
||||||
|
for CURR_DIR in $DIR_SET
|
||||||
|
do
|
||||||
|
if [ -d "$CURR_DIR" ]; then
|
||||||
|
rm -fr $CURR_DIR
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# enable Go modules for package management
|
||||||
|
export GO111MODULE=on
|
||||||
|
|
||||||
|
# update PATH so that the protoc compiler can find the plugin:
|
||||||
|
export PATH="$PATH:$(go env GOPATH)/bin"
|
||||||
|
|
||||||
|
# assume that protoc is installed
|
||||||
|
if ! type "protoc" > /dev/null 2>&1; then
|
||||||
|
echo "Please install protoc"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# install protoc-gen-go and protoc-gen-go-grpc plugin
|
||||||
|
if ! type "protoc-gen-go" > /dev/null 2>&1; then
|
||||||
|
go get google.golang.org/protobuf/cmd/protoc-gen-go
|
||||||
|
fi
|
||||||
|
if ! type "protoc-gen-go-grpc" > /dev/null 2>&1; then
|
||||||
|
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc
|
||||||
|
fi
|
||||||
|
|
||||||
|
# compiling pingpong gRPC .proto file
|
||||||
|
export GOPRIVATE=github.com/occlum/demos/\*
|
||||||
|
protoc --proto_path=pingpong --go-grpc_out=. --go_out=. pingpong/pingpong.proto
|
||||||
|
|
||||||
|
# prepare occlum images
|
||||||
|
occlum-go build -o occlum_pong pong.go
|
||||||
|
occlum-go build -o occlum_ping ping.go
|
35
demos/golang/grpc_pingpong/run_ping_on_occlum.sh
Executable file
35
demos/golang/grpc_pingpong/run_ping_on_occlum.sh
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BLUE='\033[1;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
occlum_ping="./occlum_ping"
|
||||||
|
|
||||||
|
if [ ! -f $occlum_ping ];then
|
||||||
|
echo "Error: cannot stat file '$occlum_ping'"
|
||||||
|
echo "Please see README and build it using prepare_ping_pong.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Init Occlum Workspace
|
||||||
|
rm -rf occlum_ping_instance && mkdir occlum_ping_instance
|
||||||
|
cd occlum_ping_instance
|
||||||
|
occlum init
|
||||||
|
new_json="$(jq '.resource_limits.user_space_size = "2560MB" |
|
||||||
|
.resource_limits.kernel_space_heap_size="320MB" |
|
||||||
|
.resource_limits.kernel_space_stack_size="10MB" |
|
||||||
|
.process.default_stack_size = "40MB" |
|
||||||
|
.process.default_heap_size = "320MB" |
|
||||||
|
.process.default_mmap_size = "960MB" ' Occlum.json)" && \
|
||||||
|
echo "${new_json}" > Occlum.json
|
||||||
|
|
||||||
|
# 2. Copy program into Occlum Workspace and build
|
||||||
|
cp ../occlum_ping image/bin
|
||||||
|
mkdir image/etc/
|
||||||
|
cp /etc/hosts image/etc/
|
||||||
|
occlum build
|
||||||
|
|
||||||
|
# 3. Run the hello world sample
|
||||||
|
echo -e "${BLUE}occlum run /bin/occlum_ping${NC}"
|
||||||
|
time occlum run /bin/occlum_ping
|
35
demos/golang/grpc_pingpong/run_pong_on_occlum.sh
Executable file
35
demos/golang/grpc_pingpong/run_pong_on_occlum.sh
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BLUE='\033[1;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
occlum_pong="./occlum_pong"
|
||||||
|
|
||||||
|
if [ ! -f $occlum_pong ];then
|
||||||
|
echo "Error: cannot stat file '$occlum_pong'"
|
||||||
|
echo "Please see README and build it using prepare_pong_pong.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Init Occlum Workspace
|
||||||
|
rm -rf occlum_pong_instance && mkdir occlum_pong_instance
|
||||||
|
cd occlum_pong_instance
|
||||||
|
occlum init
|
||||||
|
new_json="$(jq '.resource_limits.user_space_size = "2560MB" |
|
||||||
|
.resource_limits.kernel_space_heap_size="320MB" |
|
||||||
|
.resource_limits.kernel_space_stack_size="10MB" |
|
||||||
|
.process.default_stack_size = "40MB" |
|
||||||
|
.process.default_heap_size = "320MB" |
|
||||||
|
.process.default_mmap_size = "960MB" ' Occlum.json)" && \
|
||||||
|
echo "${new_json}" > Occlum.json
|
||||||
|
|
||||||
|
# 2. Copy program into Occlum Workspace and build
|
||||||
|
cp ../occlum_pong image/bin
|
||||||
|
mkdir image/etc/
|
||||||
|
cp /etc/hosts image/etc/
|
||||||
|
occlum build
|
||||||
|
|
||||||
|
# 3. Run the hello world sample
|
||||||
|
echo -e "${BLUE}occlum run /bin/occlum_pong${NC}"
|
||||||
|
time occlum run /bin/occlum_pong
|
Loading…
Reference in New Issue
Block a user