Redis-Redis 绑定套接字用unix socket还是tcp socket比较好
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis-Redis 绑定套接字用unix socket还是tcp socket比较好相关的知识,希望对你有一定的参考价值。
参考技术A 套接字就相当于一个数据进出的通道吧,套接字里面的数据按照一定的格式传输,这个格式就是TCP协议。。。这个是我的通俗理解,希望对你有帮助。Go Unix Domain Socket:绑定地址已在使用中
【中文标题】Go Unix Domain Socket:绑定地址已在使用中【英文标题】:Go Unix Domain Socket: bind address already in use 【发布时间】:2017-05-14 10:24:34 【问题描述】:我有以下服务器代码,它通过 unix 域套接字进行侦听
package main
import (
"log"
"net"
"os"
"os/signal"
"syscall"
)
func echoServer(c net.Conn)
for
buf := make([]byte, 512)
nr, err := c.Read(buf)
if err != nil
return
data := buf[0:nr]
println("Server got:", string(data))
_, err = c.Write(data)
if err != nil
log.Fatal("Writing client error: ", err)
func main()
log.Println("Starting echo server")
ln, err := net.Listen("unix", "/tmp/go.sock")
if err != nil
log.Fatal("Listen error: ", err)
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, os.Interrupt, syscall.SIGTERM)
go func(ln net.Listener, c chan os.Signal)
sig := <-c
log.Printf("Caught signal %s: shutting down.", sig)
ln.Close()
os.Exit(0)
(ln, sigc)
for
fd, err := ln.Accept()
if err != nil
log.Fatal("Accept error: ", err)
go echoServer(fd)
当我使用 Ctrl+C 关闭它时,会捕获信号并关闭套接字。当我重新运行程序时,一切正常。
但是,如果正在运行的进程被突然杀死,并且如果程序重新启动,则侦听失败并出现错误Listen error: listen unix /tmp/go.sock: bind: address already in use
如何优雅地处理这个?
我问这个的原因是:我知道突然杀死不是正常的方法,但是我的程序会作为守护进程自动启动,如果我的守护进程重新启动,我希望能够再次监听套接字没有这个错误。
这也可能是因为先前的实例正在运行,我理解。这里的问题是如何在 Go 中以编程方式识别并处理这种情况。正如答案here 中所指出的,可以在C 程序中使用SO_REUSEADDR。 Go中有这样的可能性吗?另外,C 程序如何处理这种多实例问题。
【问题讨论】:
服务器无法连接。客户端连接。服务器侦听并接受连接。如果绑定时得到 'address already in use,则该地址已在使用中,可能是由您的程序的先前实例使用的,可能是因为“突然杀死”不是终止它的方法。 @EJP Wow.. -1 是一个错字,我写的是connect
而不是listen
。你说突然杀戮不是终止它的方法,这很有趣。我知道。但是,当使用我的程序的客户以某种方式杀死它时,我想考虑如何优雅地处理它!在 C 中,我可以使用重用套接字,但是如何在 Go 中的问题中做到这一点。在给问题打负分之前三思!
SO_REUSEADDR 与此处无关(请参阅***.com/questions/15716302/so-reuseaddr-and-af-unix)。如果您不需要该文件并想再次绑定到该地址,请删除该文件。
见related question。总之,还要处理signal.Notify
中的os.Kill
和syscall.SIGTERM
信号。
这个答案解释了如何检测一个工作实例是否正在监听,它的问题有更多关于为什么要删除 unix 域套接字的详细信息:***.com/a/13719866/7496656
【参考方案1】:
您需要捕捉信号并进行清理;一些示例代码:
func HandleSIGINTKILL() chan os.Signal
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
return sig
...
go func()
<-HandleSIGINTKILL()
log.Info("Received termination signal")
// Cleanup code here
os.Exit(0)
()
如果你kill -9
进程,这当然行不通;您将需要手动移除套接字(或让您的 init 系统为您完成)。
【讨论】:
以上是关于Redis-Redis 绑定套接字用unix socket还是tcp socket比较好的主要内容,如果未能解决你的问题,请参考以下文章