一、连接类型实现体系
valkey通过ConnectionType
结构体构建了灵活的网络连接抽象,支持多种连接类型的统一管理。每种连接类型都通过填充该结构体的函数指针来实现特定功能,形成了面向接口的设计模式。
1.1 socket连接
Socket连接提供了最基础的TCP/IP通信能力,实现了全部连接与IO操作接口,是valkey网络通信的基础实现。
src/socket.c
static ConnectionType CT_Socket = {/* connection type */.get_type = connSocketGetType,/* connection type initialize & finalize & configure */.init = NULL,.cleanup = NULL,.configure = NULL,/* ae & accept & listen & error & address handler */.ae_handler = connSocketEventHandler,.accept_handler = connSocketAcceptHandler,.addr = connSocketAddr,.is_local = connSocketIsLocal,.listen = connSocketListen,.closeListener = connSocketCloseListener,/* create/shutdown/close connection */.conn_create = connCreateSocket,.conn_create_accepted = connCreateAcceptedSocket,.shutdown = connSocketShutdown,.close = connSocketClose,/* connect & accept */.connect = connSocketConnect,.blocking_connect = connSocketBlockingConnect,.accept = connSocketAccept,/* IO */.write = connSocketWrite,.writev = connSocketWritev,.read = connSocketRead,.set_write_handler = connSocketSetWriteHandler,.set_read_handler = connSocketSetReadHandler,.get_last_error = connSocketGetLastError,.sync_write = connSocketSyncWrite,.sync_read = connSocketSyncRead,.sync_readline = connSocketSyncReadLine,/* pending data */.has_pending_data = NULL,.process_pending_data = NULL,.postpone_update_state = NULL,.update_state = NULL,/* Miscellaneous */.connIntegrityChecked = NULL,
};int RedisRegisterConnectionTypeSocket(void) {return connTypeRegister(&CT_Socket);
}
1.2 unix域套接字
Unix域套接字专注于本地进程间通信,省略了网络连接相关的接口,优化了本地通信的性能。
src/unix.c
static ConnectionType CT_Unix = {/* connection type */.get_type = connUnixGetType,/* connection type initialize & finalize & configure */.init = NULL,.cleanup = NULL,.configure = NULL,/* ae & accept & listen & error & address handler */.ae_handler = connUnixEventHandler,.accept_handler = connUnixAcceptHandler,.addr = connUnixAddr,.is_local = connUnixIsLocal,.listen = connUnixListen,.closeListener = connUnixCloseListener,/* create/shutdown/close connection */.conn_create = connCreateUnix,.conn_create_accepted = connCreateAcceptedUnix,.shutdown = connUnixShutdown,.close = connUnixClose,/* connect & accept */.connect = NULL,.blocking_connect = NULL,.accept = connUnixAccept,/* IO */.write = connUnixWrite,.writev = connUnixWritev,.read = connUnixRead,.set_write_handler = connUnixSetWriteHandler,.set_read_handler = connUnixSetReadHandler,.get_last_error = connUnixGetLastError,.sync_write = connUnixSyncWrite,.sync_read = connUnixSyncRead,.sync_readline = connUnixSyncReadLine,/* pending data */.has_pending_data = NULL,.process_pending_data = NULL,.postpone_update_state = NULL,.update_state = NULL,/* Miscellaneous */.connIntegrityChecked = NULL,
};int RedisRegisterConnectionTypeUnix(void) {return connTypeRegister(&CT_Unix);
}
1.3 tls加密连接
TLS连接增加了加密相关的初始化、清理和配置接口,提供了证书处理和加密数据传输能力,是安全通信的实现。
src/tls.c
static ConnectionType CT_TLS = {/* connection type */.get_type = connTLSGetType,/* connection type initialize & finalize & configure */.init = tlsInit,.cleanup = tlsCleanup,.configure = tlsConfigure,/* ae & accept & listen & error & address handler */.ae_handler = tlsEventHandler,.accept_handler = tlsAcceptHandler,.addr = connTLSAddr,.is_local = connTLSIsLocal,.listen = connTLSListen,.closeListener = connTLSCloseListener,/* create/shutdown/close connection */.conn_create = connCreateTLS,.conn_create_accepted = connCreateAcceptedTLS,.shutdown = connTLSShutdown,.close = connTLSClose,/* connect & accept */.connect = connTLSConnect,.blocking_connect = connTLSBlockingConnect,.accept = connTLSAccept,/* IO */.read = connTLSRead,.write = connTLSWrite,.writev = connTLSWritev,.set_write_handler = connTLSSetWriteHandler,.set_read_handler = connTLSSetReadHandler,.get_last_error = connTLSGetLastError,.sync_write = connTLSSyncWrite,.sync_read = connTLSSyncRead,.sync_readline = connTLSSyncReadLine,/* pending data */.has_pending_data = tlsHasPendingData,.process_pending_data = tlsProcessPendingData,.postpone_update_state = postPoneUpdateSSLState,.update_state = updateSSLState,/* TLS specified methods */.get_peer_cert = connTLSGetPeerCert,/* Miscellaneous */.connIntegrityChecked = connTLSIsIntegrityChecked,
};int RedisRegisterConnectionTypeTLS(void) {return connTypeRegister(&CT_TLS);
}
1.4 rdma高性能连接
RDMA连接针对高性能计算场景设计,提供了低延迟的数据传输能力,包含了特殊的状态管理接口。
src/rdma.c
static ConnectionType CT_RDMA = {/* connection type */.get_type = connRdmaGetType,/* connection type initialize & finalize & configure */.init = rdmaInit,.cleanup = NULL,/* ae & accept & listen & error & address handler */.ae_handler = connRdmaEventHandler,.accept_handler = connRdmaAcceptHandler,//.cluster_accept_handler = NULL,.is_local = connRdmaIsLocal,.listen = connRdmaListen,.closeListener = connRdmaCloseListener,.addr = connRdmaAddr,/* create/close connection */.conn_create = connCreateRdma,.conn_create_accepted = connCreateAcceptedRdma,.shutdown = connRdmaShutdown,.close = connRdmaClose,/* connect & accept */.connect = connRdmaConnect,.blocking_connect = connRdmaBlockingConnect,.accept = connRdmaAccept,/* IO */.write = connRdmaWrite,.writev = connRdmaWritev,.read = connRdmaRead,.set_write_handler = connRdmaSetWriteHandler,.set_read_handler = connRdmaSetReadHandler,.get_last_error = connRdmaGetLastError,.sync_write = connRdmaSyncWrite,.sync_read = connRdmaSyncRead,.sync_readline = connRdmaSyncReadLine,/* pending data */.has_pending_data = rdmaHasPendingData,.process_pending_data = rdmaProcessPendingData,.postpone_update_state = postPoneUpdateRdmaState,.update_state = updateRdmaState,/* Miscellaneous */.connIntegrityChecked = NULL,
};int RegisterConnectionTypeRdma(void) {return connTypeRegister(&CT_RDMA);
}
二、连接类型注册流程
2.1 注册调用链
src/server.c
main| src/connection.c|--> connTypeInitialize
2.2 注册实现
src/connection.c
int connTypeInitialize(void) {/* currently socket connection type is necessary */serverAssert(RedisRegisterConnectionTypeSocket() == C_OK);/* currently unix socket connection type is necessary */serverAssert(RedisRegisterConnectionTypeUnix() == C_OK);/* may fail if without BUILD_TLS=yes */RedisRegisterConnectionTypeTLS();/* may fail if without BUILD_RDMA=yes */RegisterConnectionTypeRdma();return C_OK;
}
这种注册机制实现了:
- 核心连接类型的强制注册(Socket和Unix)
- 可选连接类型的条件注册(TLS和RDMA)
- 编译时决定是否支持特定连接类型的灵活性
三、监听器初始化流程
监听器初始化是valkey网络服务启动的关键步骤,负责根据配置创建并激活各类连接的监听机制。
3.1 初始化调用链
src/server.c
main| src/config.c|--> loadServerConfig|| src/server.c|--> initListeners
3.2 初始化实现
根据不同的配置,初始化不同的监听器。
void initListeners(void) {/* Setup listeners from server config for TCP/TLS/Unix */int conn_index;connListener *listener;if (server.port != 0) {conn_index = connectionIndexByType(CONN_TYPE_SOCKET);if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_SOCKET);listener = &server.listeners[conn_index];listener->bindaddr = server.bindaddr;listener->bindaddr_count = server.bindaddr_count;listener->port = server.port;listener->ct = connectionByType(CONN_TYPE_SOCKET);}if (server.tls_port || server.tls_replication || server.tls_cluster) {ConnectionType *ct_tls = connectionTypeTls();if (!ct_tls) {serverLog(LL_WARNING, "Failed finding TLS support.");exit(1);}if (connTypeConfigure(ct_tls, &server.tls_ctx_config, 1) == C_ERR) {serverLog(LL_WARNING, "Failed to configure TLS. Check logs for more info.");exit(1);}}if (server.tls_port != 0) {conn_index = connectionIndexByType(CONN_TYPE_TLS);if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_TLS);listener = &server.listeners[conn_index];listener->bindaddr = server.bindaddr;listener->bindaddr_count = server.bindaddr_count;listener->port = server.tls_port;listener->ct = connectionByType(CONN_TYPE_TLS);}if (server.unixsocket != NULL) {conn_index = connectionIndexByType(CONN_TYPE_UNIX);if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_UNIX);listener = &server.listeners[conn_index];listener->bindaddr = &server.unixsocket;listener->bindaddr_count = 1;listener->ct = connectionByType(CONN_TYPE_UNIX);listener->priv = &server.unix_ctx_config; /* Unix socket specified */}if (server.rdma_ctx_config.port != 0) {conn_index = connectionIndexByType(CONN_TYPE_RDMA);if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_RDMA);listener = &server.listeners[conn_index];listener->bindaddr = server.rdma_ctx_config.bindaddr;listener->bindaddr_count = server.rdma_ctx_config.bindaddr_count;listener->port = server.rdma_ctx_config.port;listener->ct = connectionByType(CONN_TYPE_RDMA);listener->priv = &server.rdma_ctx_config;}/* create all the configured listener, and add handler to start to accept */int listen_fds = 0;for (int j = 0; j < CONN_TYPE_MAX; j++) {listener = &server.listeners[j];if (listener->ct == NULL) continue;if (connListen(listener) == C_ERR) {serverLog(LL_WARNING, "Failed listening on port %u (%s), aborting.", listener->port,listener->ct->get_type(NULL));exit(1);}if (createSocketAcceptHandler(listener, connAcceptHandler(listener->ct)) != C_OK)serverPanic("Unrecoverable error creating %s listener accept handler.", listener->ct->get_type(NULL));listen_fds += listener->count;}if (listen_fds == 0) {serverLog(LL_WARNING, "Configured to not listen anywhere, exiting.");exit(1);}
}
四、抽象连接层设计
valkey通过connection.h
头文件定义了抽象连接层的接口,实现了对各类连接的统一操作,体现了面向对象的多态特性。
4.1 统一接口设计
src/connection.h
...static inline int connWritev(connection *conn, const struct iovec *iov, int iovcnt) {return conn->type->writev(conn, iov, iovcnt);
}static inline int connRead(connection *conn, void *buf, size_t buf_len) {int ret = conn->type->read(conn, buf, buf_len);return ret;
}...
4.2 多态实现机制
抽象连接层通过函数指针实现了多态:
- 上层代码使用统一的
connRead
、connWritev
等接口 - 实际执行时根据
conn->type
指向的具体连接类型,调用对应的实现函数 - 新增连接类型时,只需实现
ConnectionType
结构体的函数,无需修改上层逻辑
这种设计带来的优势:
- 接口与实现分离,降低模块间耦合
- 便于扩展新的连接类型
- 保持上层代码的稳定性
- 统一的错误处理和状态管理
五、架构设计亮点
模块化设计: 每种连接类型作为独立模块实现,便于维护和扩展
条件编译支持: 通过编译选项控制TLS、RDMA等可选模块的编译和注册
统一抽象层: 通过函数指针实现多态,简化上层使用
渐进式初始化: 从连接注册到监听器启动,形成完整的初始化流程
灵活的配置体系: 支持多种连接类型的并行配置和启动
valkey的网络管理架构通过这种分层抽象和接口统一,既保证了底层实现的灵活性,又为上层提供了简单一致的使用方式,是高性能网络服务的典型设计模式。