acl-dev / acl

C/C++ server and network library, including coroutine,redis client,http/https/websocket,mqtt, mysql/postgresql/sqlite client with C/C++ for Linux, Android, iOS, MacOS, Windows, etc..
https://acl-dev.cn
GNU Lesser General Public License v3.0
2.83k stars 937 forks source link

linux环境下run_alone调试运行有问题 #332

Closed dragon-dan closed 3 months ago

dragon-dan commented 3 months ago

在模板项目代码基础上增加了一个接口,然后调试运行 使用run_alone方式运行调试,windows下表现正常。

然后编译了linux版本在测试环境运行。 ./httpserver 命令启动正常,调用接口正常。 5分钟之后再尝试调用,接口不通,一直转圈圈。 新开启终端检查进程和端口占用,httpserver依然存活并占用着端口,但不能提供服务。 (反复尝试发现,不停发送请求,服务就一直可以用,连续点击十几分钟都很正常,不请求接口静置几分钟就不能再用了)

怀疑是自己写的代码有问题,尝试把新增代码全部注释,重新编译运行情况一样。

猜测后台运行可能会正常,nohup ./httpserver 1>/dev/null 2>&1 & 命令启动,无法启动成功。 (反复尝试nohup方式都不能启动。增加日志打印观察,走到run_alone 进程就没了。)

总结问题两个: 1)./ 方式启动刚开始功能正常, 过一会就接口不通

// 反复调整日志发现 貌似是线程全部推出后 没有在初始化线程 无法提供服务
void master_service::thread_on_exit(void)
{
    s_info(">>>thread_on_exit acl::thread_self:{}, tid:{}<<<", acl::thread::thread_self(), tid);
    // linux下下面会出问题, 然后导致不能再初始化线程, 无法再提供服务, windows能正常使用
    //acl_pthread_pool_t* p_pool = this->threads_pool();
    //if (NULL == p_pool) {
    //    s_info("after thread_on_exit pool is NULL");
    //}
    //else 
    //{
    //    s_info("after thread_on_exit 线程池当前线程数: {}", acl_pthread_pool_size(this->threads_pool()));
    //}
   s_info(">>>thread_on_exit over<<<");
}

2)nohup方式无法启动

src/stdlib/iostuff/acl_non_blocking.c(66), acl_non_blocking: fcntl(6, F_GETFL) error: Bad file descriptor
fatal:fcntl: get flags: Bad file descriptor

配置如下:


service httpserver
{
#   进程是否禁止运行
    master_disable = no
#   服务地址及端口号
#   for master_type = inet
#   master_service = 127.0.0.1|5001
#   for master_type = unix
#   master_service = echo.sock
#   for master_type = sock
#   master_service = 127.0.0.1|5001, 5002, |5003, echo.sock@unix, echo2.sock@unix
    master_service = |8288

#   服务监听为域套接口
#   master_service = aio_echo.sock
#   服务类型
#   master_type = inet
#   master_type = unix
    master_type = sock

#   停止子进程时是否采用强行停止的方式(即给子进程发送 SIGTERM 信号)
    master_stop_kill = false
#   当 master_stop_kill 为 true 时,该配置决定是否要等待子进程退出
    master_stop_wait = false

#   当系统支持 SO_REUSEPORT 时,是否启用该功能
    master_reuseport = no
#   当启用 SO_REUSEPORT 时(即 master_reuseport=yes 时), 是否需要 acl_master
#   也监听该地址, 对于使用旧版 acl(< 3.5.3-17) 编写的服务, 必须将此项设为
#   yes, 即: master_reuseport_listen = yes; 对于使用 acl 版本 >= 3.5.3-17
#   编写的服务需设置为 no; 当 master_reuseport=no时,该项设置将被忽略; 当未
#   设置此项时内部缺省值为 yes. 以便使 acl_master 保持对于旧版服务的兼容性.
    master_reuseport_listen = no
#   是否针对监听套接口设定为非阻塞方式
    master_nonblock = yes
#   当系统支持 TCP_FASTOPEN 时,是否启用该功能
    master_fastopen = no

#   当子进程异常退出时,如果该值非空,则将子进程异常退出的消息通知该服务
#   master_notify_addr = 127.0.0.1:5801
#   邮件通知接收者
#   master_notify_recipients = zhengshuxin@hotmail.com

#   是否允许延迟接受客户端连接,如果为0则表示关闭该功能,如果大于0则表示打开此功能
#   并且此值代表延迟接受连接的超时值,超过此值时如果客户端依然没有发来数据,则操作
#   系统会在系统层直接关闭该连接
#   master_defer_accept = 0
#   是否只允许私有访问, 如果为 y, 则域套接口创建在 {install_path}/var/log/private/ 目录下,
#   如果为 n, 则域套接口创建在 {install_path}/var/log/public/ 目录下,
    master_private = n
    master_unpriv = n
#   是否需要 chroot: n -- no, y -- yes
    master_chroot = n
#   每隔多长时间触发一次,单位为秒(仅对 trigger 模式有效)
    master_wakeup = -
#   最大进程数
    master_maxproc = 1
#   预启动进程数,该值不得大于 master_maxproc
    master_prefork = 1
#   进程程序名
    master_command = {install_path}/sbin/zhserver
#   进程日志记录文件
    master_log = logs/acl_zhserver.log
#   调试日志方式,格式:tag:level; tag:level; tab:level, 如:all:1; 101:2
#   master_debug =
#   进程启动参数,只能为: -u [是否允许以某普通用户的身份运行]
#   master_args =
#   传递给服务子进程的环境变量, 可以通过 getenv("SERVICE_ENV") 获得此值
#   master_env = mempool_limit:512000000
#   master_env = logme:FALSE, priority:E_LOG_INFO, action:E_LOG_PER_DAY, flush:sync_flush, imit_size:512,\
#           sync_action:E_LOG_SEM, sem_name:/tmp/ioctl_echo.sem

#   当启动多个子进程实例时,该开关控制多个子进程在接收连接时是否向 acl_master 发送消息报告自己的状态
#   master_status_notify = 1
#   程序标准输出重定向至指定文件中
#   master_stdout = {install_path}/var/log/stdout.log
#   程序错误输出重定向至指定文件中
#   master_stderr = {install_path}/var/log/stderr.log

#   是否允许产生 core 文件
#   ioctl_enable_core = 1
#   core 文件大小限制,-1 表示不限制 core 文件大小,0 表示禁止产生 core,> 0 表示 core 文件最大大小
#   ioctl_core_limit = -1
#   进程退出时是否禁止产生 core 文件
#   ioctl_disable_core_onexit = 1
#   每个进程实例处理连接数的最大次数,超过此值后进程实例主动退出
    ioctl_use_limit = 0
#   每个进程实例的空闲超时时间,超过此值后进程实例主动退出
    ioctl_idle_limit = 0
#   记录进程PID的位置(对于多进程实例来说没有意义)
    ioctl_pid_dir =  {install_path}/var/pid
#   进程运行时所在的路径
    ioctl_queue_dir = {install_path}/var
#   读写超时时间, 单位为秒
    ioctl_rw_timeout = 120
#   读缓冲区的缓冲区大小
    ioctl_buf_size = 8192
#   每次 accept 时的循环接收的最大次数
    ioctl_max_accept = 25
#   在并发访问量非常低的情况下,如访问量在 10 次/秒 以下时,可以找开此值(即赋为1),
#   以加速事件循环过程, 从而防止服务进程阻塞在 select 上的时间过长而影响访问速度
#   ioctl_enable_dog = 1
#   进程运行时的用户身份
    ioctl_owner = root

#   用 select 进行循环时的时间间隔
#   单位为秒
    ioctl_delay_sec = 1
#   单位为微秒
    ioctl_delay_usec = 500

#       采用事件循环的方式: select(default), poll, kernel(epoll/devpoll/kqueue)
    ioctl_event_mode = epoll
#   事件引擎检查所有空闲描述符的时间间隔(毫秒)
#   ioctl_check_inter = 100
#   当启用 master_dispatch 连接分开服务后,该配置指定 master_dispatch 所监听的
#   域套接口的全路径,这样本子进程就可以从 master_dispatch 获得客户端连接
#   ioctl_dispatch_addr = {install_path}/var/private/dispatch.sock
#   当 ioctl_dispatch_addr 开启后,下面参数控制本服务进程发给前端 master_dispatch 的服务标识信息
#   ioctl_dispatch_type = default

#   线程池的最大线程数
    ioctl_max_threads = 250
#   线程池中工作线程等待任务时间间隔(毫秒)
#   ioctl_schedule_wait = 50
#   线程任务调度的时间间隔大于此值(毫秒)后记警告日志
    ioctl_schedule_warn = 100
#   线程处理任务拥堵数超过此阀值后记警告日志,设为 0 则内部只有当拥堵任务数超过总线程数的 10 倍时才报警
#   ioctl_qlen_warn = 0
#   线程的堆栈空间大小,单位为字节,0表示使用系统缺省值
    ioctl_stacksize = 0
#   允许访问 udserver 的客户端IP地址范围
#   ioctl_access_allow = 127.0.0.1:255.255.255.255, 127.0.0.1:127.0.0.1
    ioctl_access_allow = all

#   当 acl_master 退出时,如果该值置1则该程序不等所有连接处理完毕便立即退出
    ioctl_quick_abort = 1

############################################################################
#   应用自己的配置选项

}

正式环境后续可以逐步搭建acl_master 管理运行,测试环境使用者众多资源有限,希望能简单点一直运行

zhengshuxin commented 3 months ago

alone 模式运行应该没有问题的,我测试时一直这么用的。

dragon-dan commented 3 months ago

代码全回退干净确实可以 ./ 运行, 我想在线程退出的时候this->threads_pool(); 输出下线程池的信息, 结果linux上执行有问题。 测试环境我想后台运行便于开发调试 nohup直接就崩了,正在尝试tmux或者screen能不能后台挂起来。

试了下tmux能挂起来,那就先不用nohup了。

dragon-dan commented 3 months ago

thread_on_exit 不能打印线程池信息,那就换个地方打印,先绕过去了,先能用起来就行