Hé les gophers ?!
Avez-vous déjà pensé aux meilleurs moyens d'assurer un service plus rapide des fichiers statiques à l'aide de TCP dans Go ? Bien qu'il existe des fonctions intégrées telles que http.ServeFile qui font le travail dans des tâches simples de service de fichiers, ces fonctions deviennent un obstacle lorsqu'il s'agit de fichiers extrêmement volumineux ou lorsqu'elles sont exécutées sous une charge importante. Dans cet article, nous souhaitons aborder les problèmes avancés de ce processus afin que les personnes souhaitant aller au-delà du niveau typique de développement Go soient satisfaites.
Une attention particulière doit être portée à la vitesse de diffusion des fichiers car elle est particulièrement importante en cas de trafic intense. Lors de la diffusion de contenu statique via des solutions telles que http.ServeFile, les problèmes suivants doivent être résolus :
Mémoire tampon en une seule couche : les données sont d'abord chargées en mémoire, puis ensuite envoyées sur le réseau, créant ainsi une empreinte mémoire et des retards inutiles.
Blocage des E/S : effectuer des opérations de blocage sur des fichiers peut affecter négativement la vitesse, surtout si les fichiers font plusieurs mégaoctets.
Mauvais équilibre de charge : Il n'existe aucune disposition permettant d'effectuer des transferts de fichiers de manière plus simultanée, ce qui signifie une perte de vitesse.
Voici comment contourner ces contraintes et améliorer les performances :
Réduisez la consommation de mémoire et augmentez la vitesse des transferts en utilisant l'appel système sendfile du package syscall pour réaliser un transfert de fichier sans copie. La mémoire dans l'espace utilisateur n'est pas impliquée et les données sont « envoyées » directement du descripteur de fichier au socket.
import ( "syscall" "net" "os" ) func serveFile(conn net.Conn, filePath string) error { file, err := os.Open(filePath) if err != nil { return err } defer file.Close() fileStat, err := file.Stat() if err != nil { return err } // Directly transfer file content to the connection socket _, err = syscall.Sendfile(int(conn.(*net.TCPConn).File().Fd()), int(file.Fd()), nil, int(fileStat.Size())) return err }
Utilisez le cadre de concurrence dans Go en divisant un transfert de fichiers en morceaux asynchrones. Déchargez ces éléments en parallèle à l'aide de goroutines pour réduire le temps perdu à attendre la fin de l'appel d'E/S.
func asyncServeFile(conn net.Conn, filePath string) error { file, err := os.Open(filePath) if err != nil { return err } defer file.Close() buf := make([]byte, 32*1024) // 32KB buffer var wg sync.WaitGroup for { n, err := file.Read(buf) if n > 0 { wg.Add(1) go func(data []byte) { defer wg.Done() conn.Write(data) }(buf[:n]) } if err != nil { if err == io.EOF { break } return err } } wg.Wait() return nil }
Toutes les sections du dossier peuvent ne pas avoir la même valeur. À titre d'illustration, les fichiers vidéo dont la lecture peut commencer peuvent nécessiter des métadonnées vidéo. Concentrez-vous sur ces sections afin d'améliorer la vitesse perçue au sein de l'interface utilisateur.
func serveCriticalSections(conn net.Conn, filePath string, criticalSections []fileRange) error { file, err := os.Open(filePath) if err != nil { return err } defer file.Close() for _, section := range criticalSections { buf := make([]byte, section.length) _, err := file.ReadAt(buf, section.offset) if err != nil { return err } conn.Write(buf) } return nil }
L'optimisation de la gestion des transferts de fichiers statiques via TCP dans Go ne se résume pas à la simple utilisation des fonctionnalités intégrées. Des performances améliorées de l'application peuvent être obtenues grâce à l'utilisation du transfert de fichiers sans copie, des E/S de fichiers asynchrones et de la gestion des segments critiques de fichiers. Ces méthodes permettent un trafic élevé et la gestion de fichiers volumineux sans perdre la satisfaction des utilisateurs.
Cela dit, bon codage et j'espère que vous n'aurez aucun problème à transférer vos fichiers la prochaine fois. et n'oubliez jamais de le battre
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!