mirror of
https://github.com/DeBrosOfficial/network.git
synced 2026-01-30 06:53:03 +00:00
Fixed dns failover middleware
This commit is contained in:
parent
82963c960e
commit
7b12dde469
@ -366,6 +366,22 @@ func (s *DeploymentService) setupDynamicReplica(ctx context.Context, deployment
|
|||||||
zap.String("deployment_id", deployment.ID),
|
zap.String("deployment_id", deployment.ID),
|
||||||
zap.String("node_id", nodeID),
|
zap.String("node_id", nodeID),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Create DNS record for the replica node (after successful setup)
|
||||||
|
dnsName := deployment.Subdomain
|
||||||
|
if dnsName == "" {
|
||||||
|
dnsName = deployment.Name
|
||||||
|
}
|
||||||
|
fqdn := fmt.Sprintf("%s.%s.", dnsName, s.BaseDomain())
|
||||||
|
if err := s.createDNSRecord(ctx, fqdn, "A", nodeIP, deployment.Namespace, deployment.ID); err != nil {
|
||||||
|
s.logger.Error("Failed to create DNS record for replica", zap.String("node_id", nodeID), zap.Error(err))
|
||||||
|
} else {
|
||||||
|
s.logger.Info("Created DNS record for replica",
|
||||||
|
zap.String("fqdn", fqdn),
|
||||||
|
zap.String("ip", nodeIP),
|
||||||
|
zap.String("node_id", nodeID),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// callInternalAPI makes an HTTP POST to a node's internal API.
|
// callInternalAPI makes an HTTP POST to a node's internal API.
|
||||||
@ -559,34 +575,45 @@ func (s *DeploymentService) UpdateDeploymentStatus(ctx context.Context, deployme
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDNSRecords creates DNS records for a deployment
|
// CreateDNSRecords creates DNS records for a deployment.
|
||||||
|
// Creates A records for the home node and all replica nodes for round-robin DNS.
|
||||||
func (s *DeploymentService) CreateDNSRecords(ctx context.Context, deployment *deployments.Deployment) error {
|
func (s *DeploymentService) CreateDNSRecords(ctx context.Context, deployment *deployments.Deployment) error {
|
||||||
// Get node IP using the full node ID
|
|
||||||
nodeIP, err := s.getNodeIP(ctx, deployment.HomeNodeID)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Error("Failed to get node IP", zap.Error(err))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use subdomain if set, otherwise fall back to name
|
// Use subdomain if set, otherwise fall back to name
|
||||||
// New format: {name}-{random}.{baseDomain} (e.g., myapp-f3o4if.dbrs.space)
|
|
||||||
dnsName := deployment.Subdomain
|
dnsName := deployment.Subdomain
|
||||||
if dnsName == "" {
|
if dnsName == "" {
|
||||||
dnsName = deployment.Name
|
dnsName = deployment.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create deployment record: {subdomain}.{baseDomain}
|
|
||||||
// Any node can receive the request and proxy to the home node if needed
|
|
||||||
fqdn := fmt.Sprintf("%s.%s.", dnsName, s.BaseDomain())
|
fqdn := fmt.Sprintf("%s.%s.", dnsName, s.BaseDomain())
|
||||||
|
|
||||||
|
// Collect all node IDs that should have DNS records (home node + replicas)
|
||||||
|
nodeIDs := []string{deployment.HomeNodeID}
|
||||||
|
if s.replicaManager != nil {
|
||||||
|
replicaNodes, err := s.replicaManager.GetActiveReplicaNodes(ctx, deployment.ID)
|
||||||
|
if err == nil {
|
||||||
|
for _, nodeID := range replicaNodes {
|
||||||
|
if nodeID != deployment.HomeNodeID {
|
||||||
|
nodeIDs = append(nodeIDs, nodeID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, nodeID := range nodeIDs {
|
||||||
|
nodeIP, err := s.getNodeIP(ctx, nodeID)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to get node IP for DNS record", zap.String("node_id", nodeID), zap.Error(err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
if err := s.createDNSRecord(ctx, fqdn, "A", nodeIP, deployment.Namespace, deployment.ID); err != nil {
|
if err := s.createDNSRecord(ctx, fqdn, "A", nodeIP, deployment.Namespace, deployment.ID); err != nil {
|
||||||
s.logger.Error("Failed to create DNS record", zap.Error(err))
|
s.logger.Error("Failed to create DNS record", zap.String("node_id", nodeID), zap.Error(err))
|
||||||
} else {
|
} else {
|
||||||
s.logger.Info("Created DNS record",
|
s.logger.Info("Created DNS record",
|
||||||
zap.String("fqdn", fqdn),
|
zap.String("fqdn", fqdn),
|
||||||
zap.String("ip", nodeIP),
|
zap.String("ip", nodeIP),
|
||||||
zap.String("subdomain", dnsName),
|
zap.String("node_id", nodeID),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -874,10 +874,18 @@ serveLocal:
|
|||||||
httpClient := &http.Client{Timeout: 30 * time.Second}
|
httpClient := &http.Client{Timeout: 30 * time.Second}
|
||||||
resp, err := httpClient.Do(proxyReq)
|
resp, err := httpClient.Do(proxyReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.ComponentError(logging.ComponentGeneral, "proxy request failed",
|
g.logger.ComponentError(logging.ComponentGeneral, "local proxy request failed",
|
||||||
zap.String("target", target),
|
zap.String("target", target),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Local process is down — try other replica nodes before giving up
|
||||||
|
if g.replicaManager != nil {
|
||||||
|
if g.proxyCrossNodeWithReplicas(w, r, deployment) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
http.Error(w, "Service unavailable", http.StatusServiceUnavailable)
|
http.Error(w, "Service unavailable", http.StatusServiceUnavailable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1049,7 +1057,7 @@ func (g *Gateway) proxyCrossNodeToIP(w http.ResponseWriter, r *http.Request, dep
|
|||||||
proxyReq.Header.Set("X-Forwarded-For", getClientIP(r))
|
proxyReq.Header.Set("X-Forwarded-For", getClientIP(r))
|
||||||
proxyReq.Header.Set("X-Orama-Proxy-Node", g.nodePeerID)
|
proxyReq.Header.Set("X-Orama-Proxy-Node", g.nodePeerID)
|
||||||
|
|
||||||
httpClient := &http.Client{Timeout: 120 * time.Second}
|
httpClient := &http.Client{Timeout: 5 * time.Second}
|
||||||
resp, err := httpClient.Do(proxyReq)
|
resp, err := httpClient.Do(proxyReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.logger.Warn("Replica proxy request failed",
|
g.logger.Warn("Replica proxy request failed",
|
||||||
@ -1060,6 +1068,15 @@ func (g *Gateway) proxyCrossNodeToIP(w http.ResponseWriter, r *http.Request, dep
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// If the remote node returned a gateway error, try the next replica
|
||||||
|
if resp.StatusCode == http.StatusBadGateway || resp.StatusCode == http.StatusServiceUnavailable || resp.StatusCode == http.StatusGatewayTimeout {
|
||||||
|
g.logger.Warn("Replica returned gateway error, trying next",
|
||||||
|
zap.String("target_ip", nodeIP),
|
||||||
|
zap.Int("status", resp.StatusCode),
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
for key, values := range resp.Header {
|
for key, values := range resp.Header {
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
w.Header().Add(key, value)
|
w.Header().Add(key, value)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user