Example of using nginx-ingress with gRPC
This commit is contained in:
parent
87d1b8bbf2
commit
e98e3f3b9d
15 changed files with 697 additions and 0 deletions
69
images/grpc-fortune-teller/app/BUILD.bazel
Normal file
69
images/grpc-fortune-teller/app/BUILD.bazel
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_embed_data")
|
||||
load("@io_bazel_rules_docker//go:image.bzl", "go_image")
|
||||
load("@io_bazel_rules_docker//container:push.bzl", "container_push")
|
||||
|
||||
# Concatenates the fortune databases to a single bundle.
|
||||
# May need to adjust paths for your system (built on ubuntu 16.04).
|
||||
# $ apt-get install fortune
|
||||
genrule(
|
||||
name = "tar",
|
||||
outs = ["fortune.tar"],
|
||||
cmd = " && ".join([
|
||||
"OUT=$$(pwd)/$@",
|
||||
"tar -cvf $$OUT /usr/share/games/fortunes",
|
||||
]),
|
||||
)
|
||||
|
||||
# Generates a .go source file with the tarball content in
|
||||
# the fortuneFiles variable.
|
||||
go_embed_data(
|
||||
name = "fortune_assets",
|
||||
srcs = [
|
||||
":tar",
|
||||
],
|
||||
package = "main",
|
||||
unpack = True,
|
||||
var = "fortuneFiles",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"main.go",
|
||||
":fortune_assets", # keep
|
||||
],
|
||||
importpath = "github.com/kubernetes/ingress-nginx/images/grpc-fortune-teller/app",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//proto/fortune:go_default_library",
|
||||
"@com_github_vromero_gofortune//lib/fortune:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_grpc//codes:go_default_library",
|
||||
"@org_golang_google_grpc//reflection:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "fortune",
|
||||
embed = [":go_default_library"],
|
||||
goarch = "amd64",
|
||||
goos = "linux",
|
||||
pure = "on",
|
||||
static = "on",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_image(
|
||||
name = "image",
|
||||
binary = ":fortune",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
container_push(
|
||||
name = "push",
|
||||
format = "Docker",
|
||||
image = ":image",
|
||||
registry = "quay.io",
|
||||
repository = "kubernetes-ingress-controller/grpc-fortune-teller",
|
||||
tag = "0.1",
|
||||
)
|
||||
137
images/grpc-fortune-teller/app/main.go
Normal file
137
images/grpc-fortune-teller/app/main.go
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes 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
|
||||
|
||||
http://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.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
proto "github.com/kubernetes/ingress-nginx/images/grpc-fortune-teller/proto/fortune"
|
||||
"github.com/vromero/gofortune/lib/fortune"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/reflection"
|
||||
)
|
||||
|
||||
const (
|
||||
grpcPort = 50051
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
baseDir := "/tmp/fortune-teller"
|
||||
mustMkdirAll(baseDir)
|
||||
|
||||
opts := []grpc.ServerOption{
|
||||
grpc.MaxConcurrentStreams(200),
|
||||
}
|
||||
|
||||
grpcServer := grpc.NewServer(opts...)
|
||||
|
||||
fortuneTeller := &FortuneTeller{
|
||||
fs: createFortuneFilesystemNodeDescriptor(baseDir),
|
||||
}
|
||||
proto.RegisterFortuneTellerServer(grpcServer, fortuneTeller)
|
||||
|
||||
reflection.Register(grpcServer)
|
||||
|
||||
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", grpcPort))
|
||||
if err != nil {
|
||||
log.Fatalf("Error while starting grpc server: %v\n", err)
|
||||
}
|
||||
|
||||
log.Printf("Listening for gRPC requests at %d\n", grpcPort)
|
||||
grpcServer.Serve(lis)
|
||||
}
|
||||
|
||||
// FortuneTeller - struct that will implement the grpc service interface.
|
||||
type FortuneTeller struct {
|
||||
fs *fortune.FileSystemNodeDescriptor
|
||||
}
|
||||
|
||||
// Predict - implementation for the grpc unary request method.
|
||||
func (f *FortuneTeller) Predict(ctx context.Context, r *proto.PredictionRequest) (*proto.PredictionResponse, error) {
|
||||
_, data, err := fortune.GetRandomFortune(*f.fs)
|
||||
if err != nil {
|
||||
return nil, grpc.Errorf(codes.Internal, "Unable to render fortune: %v", err)
|
||||
}
|
||||
return &proto.PredictionResponse{
|
||||
Message: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createFortuneFilesystemNodeDescriptor(baseDir string) *fortune.FileSystemNodeDescriptor {
|
||||
|
||||
// Restore the packed fortune data
|
||||
fortuneDir := path.Join(baseDir, "usr/share/games/fortunes")
|
||||
|
||||
mustRestore(baseDir, fortuneFiles, nil)
|
||||
|
||||
// init gofortune fs
|
||||
fs, err := fortune.LoadPaths([]fortune.ProbabilityPath{
|
||||
{Path: fortuneDir},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to load fortune paths: %v", err)
|
||||
}
|
||||
|
||||
fortune.SetProbabilities(&fs, true) // consider all equal probabilities
|
||||
return &fs
|
||||
}
|
||||
|
||||
// mustRestore - Restore assets.
|
||||
func mustRestore(baseDir string, assets map[string][]byte, mappings map[string]string) {
|
||||
// unpack variable is provided by the go_embed data and is a
|
||||
// map[string][]byte such as {"/usr/share/games/fortune/literature.dat":
|
||||
// bytes... }
|
||||
for basename, bytes := range assets {
|
||||
if mappings != nil {
|
||||
replacement := mappings[basename]
|
||||
if replacement != "" {
|
||||
basename = replacement
|
||||
}
|
||||
}
|
||||
filename := path.Join(baseDir, basename)
|
||||
dirname := path.Dir(filename)
|
||||
//log.Printf("file %s, dir %s, rel %d, abs %s, absdir: %s", file, dir, rel, abs, absdir)
|
||||
if err := os.MkdirAll(dirname, os.ModePerm); err != nil {
|
||||
log.Fatalf("Failed to create asset dir %s: %v", dirname, err)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filename, bytes, os.ModePerm); err != nil {
|
||||
log.Fatalf("Failed to write asset %s: %v", filename, err)
|
||||
}
|
||||
log.Printf("Restored %s", filename)
|
||||
}
|
||||
|
||||
log.Printf("Assets restored to %s", baseDir)
|
||||
}
|
||||
|
||||
// mustMkdirAll - make all dirs and panic if fail
|
||||
func mustMkdirAll(dirs ...string) {
|
||||
for _, dir := range dirs {
|
||||
err := os.MkdirAll(dir, os.ModePerm)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed mkdir %s: %v", dir, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue