blob: a261e74b7b1350ddd0629a238f99d0845c538c62 [file]
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you 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 cmdsetup
import (
"context"
"github.com/spf13/cobra"
"github.com/apache/skywalking-banyandb/api/common"
"github.com/apache/skywalking-banyandb/api/data"
databasev1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v1"
"github.com/apache/skywalking-banyandb/banyand/dquery"
"github.com/apache/skywalking-banyandb/banyand/liaison/grpc"
"github.com/apache/skywalking-banyandb/banyand/liaison/grpc/route"
"github.com/apache/skywalking-banyandb/banyand/liaison/http"
"github.com/apache/skywalking-banyandb/banyand/measure"
"github.com/apache/skywalking-banyandb/banyand/metadata"
"github.com/apache/skywalking-banyandb/banyand/observability"
"github.com/apache/skywalking-banyandb/banyand/observability/services"
"github.com/apache/skywalking-banyandb/banyand/protector"
"github.com/apache/skywalking-banyandb/banyand/queue"
"github.com/apache/skywalking-banyandb/banyand/queue/pub"
"github.com/apache/skywalking-banyandb/banyand/queue/sub"
"github.com/apache/skywalking-banyandb/banyand/stream"
"github.com/apache/skywalking-banyandb/banyand/trace"
"github.com/apache/skywalking-banyandb/pkg/logger"
"github.com/apache/skywalking-banyandb/pkg/node"
"github.com/apache/skywalking-banyandb/pkg/run"
"github.com/apache/skywalking-banyandb/pkg/version"
)
func newLiaisonCmd(runners ...run.Unit) *cobra.Command {
l := logger.GetLogger("bootstrap")
ctx := context.Background()
metaSvc, err := metadata.NewClient()
if err != nil {
l.Fatal().Err(err).Msg("failed to initiate metadata service")
}
tire1Client := pub.New(metaSvc, databasev1.Role_ROLE_LIAISON)
tire2Client := pub.New(metaSvc, databasev1.Role_ROLE_DATA)
metaSvc.SetDataBroadcaster(tire2Client)
metaSvc.SetLiaisonBroadcaster(tire1Client)
localPipeline := queue.Local()
measureLiaisonNodeSel := node.NewRoundRobinSelector(data.TopicMeasureWrite.String(), metaSvc)
measureLiaisonNodeRegistry := grpc.NewClusterNodeRegistry(data.TopicMeasureWrite, tire1Client, measureLiaisonNodeSel)
measureDataNodeSel := node.NewRoundRobinSelector(data.TopicMeasureWrite.String(), metaSvc)
metricSvc := services.NewMetricService(metaSvc, tire1Client, "liaison", measureLiaisonNodeRegistry)
metaSvc.SetMetricsRegistry(metricSvc)
pm := protector.NewMemory(metricSvc)
internalPipeline := sub.NewServerWithPorts(metricSvc, "liaison-server", 18912, 18913)
measureSVC, err := measure.NewLiaison(metaSvc, internalPipeline, metricSvc, pm, measureDataNodeSel, tire2Client)
if err != nil {
l.Fatal().Err(err).Msg("failed to initiate measure liaison service")
}
streamLiaisonNodeSel := node.NewRoundRobinSelector(data.TopicStreamWrite.String(), metaSvc)
streamDataNodeSel := node.NewRoundRobinSelector(data.TopicStreamPartSync.String(), metaSvc)
streamSVC, err := stream.NewLiaison(metaSvc, internalPipeline, metricSvc, pm, streamDataNodeSel, tire2Client)
if err != nil {
l.Fatal().Err(err).Msg("failed to initiate stream liaison service")
}
traceLiaisonNodeSel := node.NewRoundRobinSelector(data.TopicTraceWrite.String(), metaSvc)
traceDataNodeSel := node.NewRoundRobinSelector(data.TopicTracePartSync.String(), metaSvc)
traceSVC, err := trace.NewLiaison(metaSvc, internalPipeline, metricSvc, pm, traceDataNodeSel, tire2Client)
if err != nil {
l.Fatal().Err(err).Msg("failed to initiate trace liaison service")
}
propertyNodeSel := node.NewRoundRobinSelector(data.TopicPropertyUpdate.String(), metaSvc)
dQuery, err := dquery.NewService(metaSvc, localPipeline, tire2Client, metricSvc, streamSVC, measureSVC, traceSVC)
if err != nil {
l.Fatal().Err(err).Msg("failed to initiate distributed query service")
}
routeProviders := map[string]route.TableProvider{
"tire1": tire1Client,
"tire2": tire2Client,
}
grpcServer := grpc.NewServer(ctx, tire1Client, tire2Client, localPipeline, metaSvc, grpc.NodeRegistries{
MeasureLiaisonNodeRegistry: measureLiaisonNodeRegistry,
StreamLiaisonNodeRegistry: grpc.NewClusterNodeRegistry(data.TopicStreamWrite, tire1Client, streamLiaisonNodeSel),
PropertyNodeRegistry: grpc.NewClusterNodeRegistry(data.TopicPropertyUpdate, tire2Client, propertyNodeSel),
TraceLiaisonNodeRegistry: grpc.NewClusterNodeRegistry(data.TopicTraceWrite, tire1Client, traceLiaisonNodeSel),
}, metricSvc, pm, routeProviders)
internalPipeline.SetMetadataRepo(metaSvc)
internalPipeline.SetNodeSchemaStatusRepo(metaSvc)
profSvc := observability.NewProfService()
httpServer := http.NewServer(grpcServer.GetAuthReloader())
var units []run.Unit
units = append(units, runners...)
units = append(units,
metricSvc,
metaSvc,
localPipeline,
internalPipeline,
tire1Client,
tire2Client,
measureLiaisonNodeSel,
measureDataNodeSel,
streamLiaisonNodeSel,
streamDataNodeSel,
traceLiaisonNodeSel,
traceDataNodeSel,
propertyNodeSel,
streamSVC,
measureSVC,
traceSVC,
dQuery,
grpcServer,
httpServer,
profSvc,
)
liaisonGroup := run.NewGroup("liaison")
liaisonGroup.Register(units...)
var nodeSelector string
liaisonCmd := &cobra.Command{
Use: "liaison",
Version: version.Build(),
Short: "Run as the liaison server",
RunE: func(_ *cobra.Command, _ []string) (err error) {
// See standalone.go for the rationale: Cobra short-circuits
// PersistentPostRunE on a non-nil RunE error, so we must
// drain the artifact sink here.
defer ShutdownSupervisor()
// Derive from SupervisorContext so that a panic recovered anywhere
// in the process, including goroutines spawned via run.Go, fires
// cancellation here.
runCtx := SupervisorContext()
if nodeSelector != "" {
runCtx = context.WithValue(runCtx, common.ContextNodeSelectorKey, nodeSelector)
var ls *pub.LabelSelector
ls, err = pub.ParseLabelSelector(nodeSelector)
if err != nil {
return err
}
for _, sel := range []node.Selector{measureDataNodeSel, streamDataNodeSel, propertyNodeSel, traceDataNodeSel} {
sel.SetNodeSelector(ls)
}
}
node, err := common.GenerateNode(internalPipeline.GetPort(), httpServer.GetPort(), nil, nil, nil)
if err != nil {
return err
}
// Stamp the liaison's own identity onto the cluster publishers so the
// receiving data nodes can label queue metrics by sender (remote_node/
// role/tier), enabling the liaison<->data topology to be drawn.
liaisonTier := node.Labels["type"]
for _, c := range []queue.Client{tire1Client, tire2Client} {
if setter, ok := c.(interface{ SetSelfNode(string, string, string) }); ok {
setter.SetSelfNode(node.NodeID, "liaison", liaisonTier)
}
}
logger.GetLogger().Info().Msg("starting as a liaison server")
runCtx = context.WithValue(runCtx, common.ContextNodeKey, node)
// Spawn our go routines and wait for shutdown.
if err := liaisonGroup.Run(runCtx); err != nil {
logger.GetLogger().Error().Err(err).Stack().Str("name", liaisonGroup.Name()).Msg("Exit")
return err
}
return nil
},
}
liaisonCmd.Flags().AddFlagSet(liaisonGroup.RegisterFlags().FlagSet)
liaisonCmd.PersistentFlags().StringVar(&nodeSelector, "data-node-selector", "",
"the data node selector. e.g. key1=value1,key2=value2. If not set, all nodes are selected")
return liaisonCmd
}