Как выглядит готовая к работе облачная функция Google?
Я только начинаю с этой бессерверной штуки, используя Google Cloud Functions, и все примеры в основном "Helloworld".
package function
import (
"net/http"
)
func F(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!\n"))
}
Как выглядит функция готовности к производству?
1 ответ
Учитывая, что провайдер заботится о таких вещах, как масштабирование, первое, что я хотел бы сделать, - это сосредоточиться на наблюдаемости. Вы не знаете, чего не знаете. Мне нравится добавлять свою собственную трассировку и структурированное ведение журнала; ведение журнала на стандартный вывод не выполняется во многих отношениях.
package function
import (
"context"
"fmt"
"net/http"
"os"
"sync"
"cloud.google.com/go/logging"
"contrib.go.opencensus.io/exporter/stackdriver"
"contrib.go.opencensus.io/exporter/stackdriver/propagation"
"go.opencensus.io/trace"
"google.golang.org/genproto/googleapis/api/monitoredres"
)
var (
logger *logging.Logger
once sync.Once
)
// configFunc sets the global configuration; it's overridden in tests.
var configFunc = defaultConfigFunc
func F(w http.ResponseWriter, r *http.Request) {
once.Do(func() {
if err := configFunc(); err != nil {
panic(err)
}
})
defer logger.Flush()
ctx := r.Context()
var span *trace.Span
httpFormat := &propagation.HTTPFormat{}
sc, ok := httpFormat.SpanContextFromRequest(r)
if ok {
ctx, span = trace.StartSpanWithRemoteParent(ctx, "helloworld", sc,
trace.WithSampler(trace.AlwaysSample()),
trace.WithSpanKind(trace.SpanKindServer),
)
defer span.End()
}
logger.Log(logging.Entry{
Payload: "Handling new HTTP request",
Severity: logging.Info,
})
w.Write([]byte("Hello, World!\n"))
}
func defaultConfigFunc() error {
var err error
projectId := os.Getenv("GCP_PROJECT")
if projectId == "" {
return fmt.Errorf("GCP_PROJECT environment variable unset or missing")
}
functionName := os.Getenv("FUNCTION_NAME")
if functionName == "" {
return fmt.Errorf("FUNCTION_NAME environment variable unset or missing")
}
region := os.Getenv("FUNCTION_REGION")
if region == "" {
return fmt.Errorf("FUNCTION_REGION environment variable unset or missing")
}
stackdriverExporter, err := stackdriver.NewExporter(stackdriver.Options{ProjectID: projectId})
if err != nil {
return err
}
trace.RegisterExporter(stackdriverExporter)
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
client, err := logging.NewClient(context.Background(), projectId)
if err != nil {
return err
}
monitoredResource := monitoredres.MonitoredResource{
Type: "cloud_function",
Labels: map[string]string{
"function_name": functionName,
"region": region,
},
}
commonResource := logging.CommonResource(&monitoredResource)
logger = client.Logger(functionName, commonResource)
return nil
}
Кроме того, убедитесь, что вы продаете все свои зависимости, вы действительно хотите, чтобы ваша сборка была воспроизводимой. В эти дни я использую Go 1.11, и у меня работает следующее:
$ mkdir helloworld
$ cd helloworld
$ vim function.go
$ echo "module github.com/kelseyhightower/helloworld" > go.mod
$ go mod vendor