在使用
github.com/kardianos/service
开发的Windows服务中,有时会遇到”The requested control is not valid for this service”的错误信息,一般情况下,这可能是由于服务在Stop方法中的处理存在问题。
具体来说,我们需要注意以下几点:
- 服务的Stop方法需要正确的实现且适应服务的生命周期的所有阶段。无论服务处于何种状态,无论何时调用,Stop方法都应安全地返回,且不产生错误。
- 如果Stop方法已经正确实现,可能的问题时在处理Stop请求时发生错误,这往往会出现在服务停止时抛出异常或者失败。根据Windows的系统日志或者程序的输出可以进一步确认。
- 我们需要保证在程序的main函数中将服务正确的hook到service的Run函数,以保证Stop方法能被正确的调用。
需要特别注意的是,关闭http服务的方式。在Golang的http.Server
中,提供了Close
和Shutdown
两个方法来关闭服务。其中,Close
方法只会立即关闭监听器,对于已经运行的连接不会等待其处理完成。因此,我们最好使用Shutdown
方法来优雅地关闭服务器。
示例代码:
func (p *Program) Stop(s service.Service) error {
close(p.backupMsgChan)
if p.server != nil {
// 创建一个超时上下文,如果 Shutdown 操作在5秒内未完结,那么将强制取消所有连接并返回错误。
ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second)
defer cancel() // 在函数执行完毕后取消该上下文
if err := p.server.Shutdown(ctx); err != nil {
p.logger.Error("shutdown server error", slog.String("error", err.Error()))
return err
}
}
return nil
}
在以上代码中,我们使用了http.Server
的Shutdown
方法来关闭服务器,并且设置了超时,若在5秒内无法关闭全部连接,那么将强制关闭并返回错误。否则,只有在所有连接全部关闭后,Shutdown
函数才会返回,保证了服务的正确关闭,避免了”The requested control is not valid for this service”的错误。