Add a sample of Golang gRPC client/server programs

This commit is contained in:
James Dong 2020-08-27 17:22:40 +00:00 committed by Tate, Hongliang Tian
parent 027e1569e0
commit 124acba6db
13 changed files with 243 additions and 0 deletions

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/

@ -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.

@ -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
)

@ -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())
}

@ -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) {}
}

@ -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)
}
}

@ -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

@ -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

@ -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