weed master add peers=none option for faster startup (#7419)
* weed master -peers=none * single master mode only when peers is none * refactoring * revert duplicated code * revert * Update weed/command/master.go Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * preventing "none" passed to other components if master is not started --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
@@ -38,6 +38,10 @@ var (
|
|||||||
m MasterOptions
|
m MasterOptions
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
raftJoinCheckDelay = 1500 * time.Millisecond // delay before checking if we should join a raft cluster
|
||||||
|
)
|
||||||
|
|
||||||
type MasterOptions struct {
|
type MasterOptions struct {
|
||||||
port *int
|
port *int
|
||||||
portGrpc *int
|
portGrpc *int
|
||||||
@@ -74,7 +78,7 @@ func init() {
|
|||||||
m.ip = cmdMaster.Flag.String("ip", util.DetectedHostAddress(), "master <ip>|<server> address, also used as identifier")
|
m.ip = cmdMaster.Flag.String("ip", util.DetectedHostAddress(), "master <ip>|<server> address, also used as identifier")
|
||||||
m.ipBind = cmdMaster.Flag.String("ip.bind", "", "ip address to bind to. If empty, default to same as -ip option.")
|
m.ipBind = cmdMaster.Flag.String("ip.bind", "", "ip address to bind to. If empty, default to same as -ip option.")
|
||||||
m.metaFolder = cmdMaster.Flag.String("mdir", os.TempDir(), "data directory to store meta data")
|
m.metaFolder = cmdMaster.Flag.String("mdir", os.TempDir(), "data directory to store meta data")
|
||||||
m.peers = cmdMaster.Flag.String("peers", "", "all master nodes in comma separated ip:port list, example: 127.0.0.1:9093,127.0.0.1:9094,127.0.0.1:9095")
|
m.peers = cmdMaster.Flag.String("peers", "", "all master nodes in comma separated ip:port list, example: 127.0.0.1:9093,127.0.0.1:9094,127.0.0.1:9095; use 'none' for single-master mode")
|
||||||
m.volumeSizeLimitMB = cmdMaster.Flag.Uint("volumeSizeLimitMB", 30*1000, "Master stops directing writes to oversized volumes.")
|
m.volumeSizeLimitMB = cmdMaster.Flag.Uint("volumeSizeLimitMB", 30*1000, "Master stops directing writes to oversized volumes.")
|
||||||
m.volumePreallocate = cmdMaster.Flag.Bool("volumePreallocate", false, "Preallocate disk space for volumes.")
|
m.volumePreallocate = cmdMaster.Flag.Bool("volumePreallocate", false, "Preallocate disk space for volumes.")
|
||||||
m.maxParallelVacuumPerServer = cmdMaster.Flag.Int("maxParallelVacuumPerServer", 1, "maximum number of volumes to vacuum in parallel per volume server")
|
m.maxParallelVacuumPerServer = cmdMaster.Flag.Int("maxParallelVacuumPerServer", 1, "maximum number of volumes to vacuum in parallel per volume server")
|
||||||
@@ -105,6 +109,9 @@ var cmdMaster = &Command{
|
|||||||
|
|
||||||
The example security.toml configuration file can be generated by "weed scaffold -config=security"
|
The example security.toml configuration file can be generated by "weed scaffold -config=security"
|
||||||
|
|
||||||
|
For single-master setups, use -peers=none to skip Raft quorum wait and enable instant startup.
|
||||||
|
This is ideal for development or standalone deployments.
|
||||||
|
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,6 +188,9 @@ func startMaster(masterOption MasterOptions, masterWhiteList []string) {
|
|||||||
|
|
||||||
// start raftServer
|
// start raftServer
|
||||||
metaDir := path.Join(*masterOption.metaFolder, fmt.Sprintf("m%d", *masterOption.port))
|
metaDir := path.Join(*masterOption.metaFolder, fmt.Sprintf("m%d", *masterOption.port))
|
||||||
|
|
||||||
|
isSingleMaster := isSingleMasterMode(*masterOption.peers)
|
||||||
|
|
||||||
raftServerOption := &weed_server.RaftServerOption{
|
raftServerOption := &weed_server.RaftServerOption{
|
||||||
GrpcDialOption: security.LoadClientTLS(util.GetViper(), "grpc.master"),
|
GrpcDialOption: security.LoadClientTLS(util.GetViper(), "grpc.master"),
|
||||||
Peers: masterPeers,
|
Peers: masterPeers,
|
||||||
@@ -203,6 +213,11 @@ func startMaster(masterOption MasterOptions, masterWhiteList []string) {
|
|||||||
if raftServer == nil {
|
if raftServer == nil {
|
||||||
glog.Fatalf("please verify %s is writable, see https://github.com/seaweedfs/seaweedfs/issues/717: %s", *masterOption.metaFolder, err)
|
glog.Fatalf("please verify %s is writable, see https://github.com/seaweedfs/seaweedfs/issues/717: %s", *masterOption.metaFolder, err)
|
||||||
}
|
}
|
||||||
|
// For single-master mode, initialize cluster immediately without waiting
|
||||||
|
if isSingleMaster {
|
||||||
|
glog.V(0).Infof("Single-master mode: initializing cluster immediately")
|
||||||
|
raftServer.DoJoinCommand()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ms.SetRaftServer(raftServer)
|
ms.SetRaftServer(raftServer)
|
||||||
r.HandleFunc("/cluster/status", raftServer.StatusHandler).Methods(http.MethodGet, http.MethodHead)
|
r.HandleFunc("/cluster/status", raftServer.StatusHandler).Methods(http.MethodGet, http.MethodHead)
|
||||||
@@ -230,10 +245,10 @@ func startMaster(masterOption MasterOptions, masterWhiteList []string) {
|
|||||||
}
|
}
|
||||||
go grpcS.Serve(grpcL)
|
go grpcS.Serve(grpcL)
|
||||||
|
|
||||||
timeSleep := 1500 * time.Millisecond
|
// For multi-master mode with non-Hashicorp raft, wait and check if we should join
|
||||||
if !*masterOption.raftHashicorp {
|
if !*masterOption.raftHashicorp && !isSingleMaster {
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(timeSleep)
|
time.Sleep(raftJoinCheckDelay)
|
||||||
|
|
||||||
ms.Topo.RaftServerAccessLock.RLock()
|
ms.Topo.RaftServerAccessLock.RLock()
|
||||||
isEmptyMaster := ms.Topo.RaftServer.Leader() == "" && ms.Topo.RaftServer.IsLogEmpty()
|
isEmptyMaster := ms.Topo.RaftServer.Leader() == "" && ms.Topo.RaftServer.IsLogEmpty()
|
||||||
@@ -292,9 +307,24 @@ func startMaster(masterOption MasterOptions, masterWhiteList []string) {
|
|||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isSingleMasterMode(peers string) bool {
|
||||||
|
p := strings.ToLower(strings.TrimSpace(peers))
|
||||||
|
return p == "none"
|
||||||
|
}
|
||||||
|
|
||||||
func checkPeers(masterIp string, masterPort int, masterGrpcPort int, peers string) (masterAddress pb.ServerAddress, cleanedPeers []pb.ServerAddress) {
|
func checkPeers(masterIp string, masterPort int, masterGrpcPort int, peers string) (masterAddress pb.ServerAddress, cleanedPeers []pb.ServerAddress) {
|
||||||
glog.V(0).Infof("current: %s:%d peers:%s", masterIp, masterPort, peers)
|
glog.V(0).Infof("current: %s:%d peers:%s", masterIp, masterPort, peers)
|
||||||
masterAddress = pb.NewServerAddress(masterIp, masterPort, masterGrpcPort)
|
masterAddress = pb.NewServerAddress(masterIp, masterPort, masterGrpcPort)
|
||||||
|
|
||||||
|
// Handle special case: -peers=none for single-master setup
|
||||||
|
if isSingleMasterMode(peers) {
|
||||||
|
glog.V(0).Infof("Running in single-master mode (peers=none), no quorum required")
|
||||||
|
cleanedPeers = []pb.ServerAddress{masterAddress}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
peers = strings.TrimSpace(peers)
|
||||||
|
|
||||||
cleanedPeers = pb.ServerAddresses(peers).ToAddresses()
|
cleanedPeers = pb.ServerAddresses(peers).ToAddresses()
|
||||||
|
|
||||||
hasSelf := false
|
hasSelf := false
|
||||||
|
|||||||
@@ -232,10 +232,17 @@ func runServer(cmd *Command, args []string) bool {
|
|||||||
*isStartingFiler = true
|
*isStartingFiler = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var actualPeersForComponents string
|
||||||
if *isStartingMasterServer {
|
if *isStartingMasterServer {
|
||||||
|
// If we are starting a master, validate and complete the peer list
|
||||||
_, peerList := checkPeers(*serverIp, *masterOptions.port, *masterOptions.portGrpc, *masterOptions.peers)
|
_, peerList := checkPeers(*serverIp, *masterOptions.port, *masterOptions.portGrpc, *masterOptions.peers)
|
||||||
peers := strings.Join(pb.ToAddressStrings(peerList), ",")
|
actualPeersForComponents = strings.Join(pb.ToAddressStrings(peerList), ",")
|
||||||
masterOptions.peers = &peers
|
} else if *masterOptions.peers != "" {
|
||||||
|
if isSingleMasterMode(*masterOptions.peers) {
|
||||||
|
glog.Fatalf("'-master.peers=none' is only valid when starting a master server, but master is not starting.")
|
||||||
|
}
|
||||||
|
// If not starting a master, just use the provided peers
|
||||||
|
actualPeersForComponents = *masterOptions.peers
|
||||||
}
|
}
|
||||||
|
|
||||||
if *serverBindIp == "" {
|
if *serverBindIp == "" {
|
||||||
@@ -249,7 +256,8 @@ func runServer(cmd *Command, args []string) bool {
|
|||||||
// ip address
|
// ip address
|
||||||
masterOptions.ip = serverIp
|
masterOptions.ip = serverIp
|
||||||
masterOptions.ipBind = serverBindIp
|
masterOptions.ipBind = serverBindIp
|
||||||
filerOptions.masters = pb.ServerAddresses(*masterOptions.peers).ToServiceDiscovery()
|
// Use actualPeersForComponents for volume/filer, not masterOptions.peers which might be "none"
|
||||||
|
filerOptions.masters = pb.ServerAddresses(actualPeersForComponents).ToServiceDiscovery()
|
||||||
filerOptions.ip = serverIp
|
filerOptions.ip = serverIp
|
||||||
filerOptions.bindIp = serverBindIp
|
filerOptions.bindIp = serverBindIp
|
||||||
if *s3Options.bindIp == "" {
|
if *s3Options.bindIp == "" {
|
||||||
@@ -259,11 +267,11 @@ func runServer(cmd *Command, args []string) bool {
|
|||||||
sftpOptions.bindIp = serverBindIp
|
sftpOptions.bindIp = serverBindIp
|
||||||
}
|
}
|
||||||
iamOptions.ip = serverBindIp
|
iamOptions.ip = serverBindIp
|
||||||
iamOptions.masters = masterOptions.peers
|
iamOptions.masters = &actualPeersForComponents
|
||||||
webdavOptions.ipBind = serverBindIp
|
webdavOptions.ipBind = serverBindIp
|
||||||
serverOptions.v.ip = serverIp
|
serverOptions.v.ip = serverIp
|
||||||
serverOptions.v.bindIp = serverBindIp
|
serverOptions.v.bindIp = serverBindIp
|
||||||
serverOptions.v.masters = pb.ServerAddresses(*masterOptions.peers).ToAddresses()
|
serverOptions.v.masters = pb.ServerAddresses(actualPeersForComponents).ToAddresses()
|
||||||
serverOptions.v.idleConnectionTimeout = serverTimeout
|
serverOptions.v.idleConnectionTimeout = serverTimeout
|
||||||
serverOptions.v.dataCenter = serverDataCenter
|
serverOptions.v.dataCenter = serverDataCenter
|
||||||
serverOptions.v.rack = serverRack
|
serverOptions.v.rack = serverRack
|
||||||
|
|||||||
Reference in New Issue
Block a user