mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-30 17:00:48 +01:00
The vectors gateway backs off discovery for 5s between resolutions, but the backoff also suppressed rediscovery after an empty lookup. A worker that landed its KeepConnected registration a moment after the first query stayed invisible for the whole window — longer than a client's retry budget — so the S3 Vectors e2e flaked: CreateIndex raced the registration, got InternalFailure, and every boto retry fell inside the same 5s fast-fail window. With no cached backend, recheck every 500ms instead; the 5s interval now only bounds membership refreshes against a live client, and an absent worker still cannot flood the master with lookups. The empty-membership error also becomes codes.Unavailable so the API answers 503 rather than InternalFailure. cluster.ps lists registered vector nodes like the other node types, and the e2e harness polls it for the engine's registration instead of only checking the gRPC port — a listening engine is not discoverable until the registration lands.
196 lines
5.8 KiB
Go
196 lines
5.8 KiB
Go
package shell
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/cluster"
|
|
"github.com/seaweedfs/seaweedfs/weed/filer"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/volume_server_pb"
|
|
"github.com/seaweedfs/seaweedfs/weed/util"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
|
|
)
|
|
|
|
func init() {
|
|
Commands = append(Commands, &commandClusterPs{})
|
|
}
|
|
|
|
type commandClusterPs struct {
|
|
}
|
|
|
|
func (c *commandClusterPs) Name() string {
|
|
return "cluster.ps"
|
|
}
|
|
|
|
func (c *commandClusterPs) Help() string {
|
|
return `check current cluster process status
|
|
|
|
cluster.ps
|
|
|
|
`
|
|
}
|
|
|
|
func (c *commandClusterPs) HasTag(CommandTag) bool {
|
|
return false
|
|
}
|
|
|
|
func (c *commandClusterPs) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {
|
|
|
|
clusterPsCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
|
if err = clusterPsCommand.Parse(args); err != nil {
|
|
return nil
|
|
}
|
|
|
|
listClusterNodes := func(clientType string) ([]*master_pb.ListClusterNodesResponse_ClusterNode, error) {
|
|
var nodes []*master_pb.ListClusterNodesResponse_ClusterNode
|
|
err := commandEnv.MasterClient.WithClient(context.Background(), false, func(client master_pb.SeaweedClient) error {
|
|
resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{
|
|
ClientType: clientType,
|
|
FilerGroup: *commandEnv.option.FilerGroup,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
nodes = resp.ClusterNodes
|
|
return nil
|
|
})
|
|
return nodes, err
|
|
}
|
|
|
|
filerNodes, err := listClusterNodes(cluster.FilerType)
|
|
if err != nil {
|
|
return
|
|
}
|
|
mqBrokerNodes, err := listClusterNodes(cluster.BrokerType)
|
|
if err != nil {
|
|
return
|
|
}
|
|
s3Nodes, err := listClusterNodes(cluster.S3Type)
|
|
if err != nil {
|
|
return
|
|
}
|
|
vectorNodes, err := listClusterNodes(cluster.VectorType)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if len(mqBrokerNodes) > 0 {
|
|
fmt.Fprintf(writer, "* message queue brokers %d\n", len(mqBrokerNodes))
|
|
for _, node := range mqBrokerNodes {
|
|
fmt.Fprintf(writer, " * %s (%v)\n", node.Address, node.Version)
|
|
if node.DataCenter != "" {
|
|
fmt.Fprintf(writer, " DataCenter: %v\n", node.DataCenter)
|
|
}
|
|
if node.Rack != "" {
|
|
fmt.Fprintf(writer, " Rack: %v\n", node.Rack)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(s3Nodes) > 0 {
|
|
fmt.Fprintf(writer, "* s3 servers %d\n", len(s3Nodes))
|
|
for _, node := range s3Nodes {
|
|
fmt.Fprintf(writer, " * %s (%v)\n", node.Address, node.Version)
|
|
if node.DataCenter != "" {
|
|
fmt.Fprintf(writer, " DataCenter: %v\n", node.DataCenter)
|
|
}
|
|
if node.Rack != "" {
|
|
fmt.Fprintf(writer, " Rack: %v\n", node.Rack)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(vectorNodes) > 0 {
|
|
fmt.Fprintf(writer, "* vector servers %d\n", len(vectorNodes))
|
|
for _, node := range vectorNodes {
|
|
fmt.Fprintf(writer, " * %s (%v)\n", node.Address, node.Version)
|
|
if node.DataCenter != "" {
|
|
fmt.Fprintf(writer, " DataCenter: %v\n", node.DataCenter)
|
|
}
|
|
if node.Rack != "" {
|
|
fmt.Fprintf(writer, " Rack: %v\n", node.Rack)
|
|
}
|
|
}
|
|
}
|
|
|
|
filerSignatures := make(map[*master_pb.ListClusterNodesResponse_ClusterNode]int32)
|
|
fmt.Fprintf(writer, "* filers %d\n", len(filerNodes))
|
|
for _, node := range filerNodes {
|
|
fmt.Fprintf(writer, " * %s (%v) %v\n", node.Address, node.Version, time.Unix(0, node.CreatedAtNs).UTC())
|
|
if node.DataCenter != "" {
|
|
fmt.Fprintf(writer, " DataCenter: %v\n", node.DataCenter)
|
|
}
|
|
if node.Rack != "" {
|
|
fmt.Fprintf(writer, " Rack: %v\n", node.Rack)
|
|
}
|
|
pb.WithFilerClient(false, 0, pb.ServerAddress(node.Address), commandEnv.option.GrpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
|
|
resp, err := client.GetFilerConfiguration(context.Background(), &filer_pb.GetFilerConfigurationRequest{})
|
|
if err == nil {
|
|
if resp.FilerGroup != "" {
|
|
fmt.Fprintf(writer, " filer group: %s\n", resp.FilerGroup)
|
|
}
|
|
fmt.Fprintf(writer, " signature: %d\n", resp.Signature)
|
|
filerSignatures[node] = resp.Signature
|
|
} else {
|
|
fmt.Fprintf(writer, " failed to connect: %v\n", err)
|
|
}
|
|
return err
|
|
})
|
|
}
|
|
for _, node := range filerNodes {
|
|
pb.WithFilerClient(false, 0, pb.ServerAddress(node.Address), commandEnv.option.GrpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
|
|
fmt.Fprintf(writer, "* filer %s metadata sync time\n", node.Address)
|
|
selfSignature := filerSignatures[node]
|
|
for peer, peerSignature := range filerSignatures {
|
|
if selfSignature == peerSignature {
|
|
continue
|
|
}
|
|
if resp, err := client.KvGet(context.Background(), &filer_pb.KvGetRequest{Key: filer.GetPeerMetaOffsetKey(peerSignature)}); err == nil && len(resp.Value) == 8 {
|
|
lastTsNs := int64(util.BytesToUint64(resp.Value))
|
|
fmt.Fprintf(writer, " %s: %v\n", peer.Address, time.Unix(0, lastTsNs).UTC())
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// collect volume servers
|
|
var volumeServers []pb.ServerAddress
|
|
t, _, err := collectTopologyInfo(commandEnv, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, dc := range t.DataCenterInfos {
|
|
for _, r := range dc.RackInfos {
|
|
for _, dn := range r.DataNodeInfos {
|
|
volumeServers = append(volumeServers, pb.NewServerAddressFromDataNode(dn))
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Fprintf(writer, "* volume servers %d\n", len(volumeServers))
|
|
for _, dc := range t.DataCenterInfos {
|
|
fmt.Fprintf(writer, " * data center: %s\n", dc.Id)
|
|
for _, r := range dc.RackInfos {
|
|
fmt.Fprintf(writer, " * rack: %s\n", r.Id)
|
|
for _, dn := range r.DataNodeInfos {
|
|
pb.WithVolumeServerClient(false, pb.NewServerAddressFromDataNode(dn), commandEnv.option.GrpcDialOption, func(client volume_server_pb.VolumeServerClient) error {
|
|
resp, err := client.VolumeServerStatus(context.Background(), &volume_server_pb.VolumeServerStatusRequest{})
|
|
if err == nil {
|
|
fmt.Fprintf(writer, " * %s (%v)\n", dn.Id, resp.Version)
|
|
}
|
|
return err
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|