Skip to content

是否可以通过增大监听的backlog解决并发连接unix domain socket失败问题 #994

Open
@yuexiaocai

Description

@yuexiaocai

问题描述

在使用dpvs-agent批量下发配置(例如并发设置几十条转发路由,并发量并不大)时经常出现Get conn from pool failed: Error="dial unix /var/run/dpvs.ipc: connect: resource temporarily unavailable"的报错。

dpvs-agent的解决方法(未奏效)

注意到dpvs-agent的代码中也有提到相关问题,解决方法是进行10次重试(但在我的测试中并未奏效,重试10次后仍有很多路由下发失败):

func unixDialer(ctx context.Context) (net.Conn, error) {
	retry := 0
	d := net.Dialer{Timeout: 10 * time.Second}
	raddr := net.UnixAddr{Name: IpcSocket, Net: "unix"}
	for {
		conn, err := d.DialContext(ctx, "unix", raddr.String())
		if err == nil {
			return conn, nil
		}
		// FIXME: A weird fact was observed in tests of large concurrency that the previous
		// "DailContext" returned the error "resource temporarily unavailable" occasionally.
		// No solution to it has found yet, thus just retry as a compromise.
		if strings.Contains(err.Error(), "resource temporarily unavailable") != true {
			return nil, err
		}
		retry++
		if retry > 10 {
			return nil, err
		}
	}
	return nil, errors.New("unknown error")
}

疑点

连接池参数

此时我尝试输出中有多少连接可以复用,结果调试发现代码中的ConnPool似乎并未起到作用:我在route.go执行conn, err := cp.Get(ctx)之后打印了cp.Stats(),发现在每次查找连接时都是Miss,从未Hit连接,TotalConns的数量也是0。

我发现dpvs-agent代码中,初始化时未设置MinIdleConns字段,因而缺省为0,进而连接池中并无idle连接可以复用,每次与数据面交互似乎都需要重新创建连接

cp := pool.NewConnPool(&pool.Options{
		Dialer:   unixDialer,
		PoolSize: 1024,
		// PoolTimeout:        -1,
		// IdleTimeout:        -1,
		// IdleCheckFrequency: -1,
	})

然而设置了MinIdleConns字段后,所有访问dpvs-agent的curl请求都block住了,无法正常运行。

socket监听参数

同时,数据面的ctrl.c中 Server socket 监听的 backlog 设置成了1,这样的做法似乎并不常见:

if (-1 == listen(srv_fd, 1)) {
        RTE_LOG(ERR, MSGMGR, "%s: Server socket listen failed\n", __func__);
        close(srv_fd);
        unlink(ipc_unix_domain);
        return EDPVS_IO;
    }

当我把 backlog 调大后,connect: resource temporarily unavailable 的问题解决了,所有路由都可以批量下发成功。

问题

想请教一下 DPVS 的开发者们:

  1. listen(srv_fd, 1)backlog设置为1 有什么其他方面的特殊考虑吗?这会不会是导致下发配置并发问题的根因?
  2. 是我的配置出了问题,导致在dpvs-agent中连接池没有生效吗?如果连接池中没有可以复用的连接,为什么要设置ConnPool机制?

Metadata

Metadata

Labels

issue/to-solveissues await answers tobe solved

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions