如何在Windows上将Redis作为服务运行

在CodeProject上,使用Redis作为分布式缓存,存储大量的信息,比如文章、论坛消息,并且从缓存而不是数据库中检索这些项目。Redis允许存储和检索完整的文档,而不是为每个请求查询SQL以获取各个部分并组合格式化文档。在网站上这是可能的,因为大多数信息被读取的频率远高于被写入的频率,而且一些信息,比如浏览次数,可以稍微过时一些。

虽然在生产环境中在Linux服务器上运行Redis,但在开发环境中,在Windows 7桌面上运行Microsoft版本的Redis。问题是Redis不是设计为作为Windows服务运行的。这意味着必须有人登录并运行Redis可执行文件。当Chris是唯一登录服务器的人时,这没问题,但上周不得不连接以安装搜索服务器的副本用于开发目的。不用说,这使Chris注销了,并且杀死了Redis服务器。在会话下重新启动了它。

在机器上,正在修复一个微妙的缓存错误,当开始测试时,代码表现得像是与Redis服务器的连接失败。由于正在更改的代码与检测与Redis连接问题有关,在意识到Chris已经远程登录到服务器,杀死了会话和Redis服务器之前,大约转了半个小时的轮子。

Chris和尝试了许多推荐的方法来将Redis作为Windows服务运行,但没有成功。由于编写了几个Windows服务来支持各种CodeProject进程,决定编写一个实用程序,允许将exe作为Windows服务安装和运行。这个实用程序叫做Exe2Srvc。

使用Exe2Srvc

Exe2Srv是一个可以作为控制台应用程序运行或作为Windows服务安装的程序。这个应用程序读取来自它的.config文件的可执行文件的路径和命令行参数,然后在新进程中启动可执行文件。

使用可执行文件的最简单方法是将binfiles下载的文件或从编译源的bin/Release复制到包含希望作为服务运行的可执行文件的目录中。

编辑Exe2Srvc.exe.config中的"Cmd"和"CmdArgs"值,以包含可执行文件的完整路径和所需的命令行参数。

从'以管理员身份运行'命令shell运行Install.bat文件。

使用服务管理器:

  • 将启动模式设置为Automatic
  • 设置恢复选项。通常将它们设置为"Restart Service"。
  • 启动服务。

对于测试,从Nuget下载了Redis,并将文件从解决方案目录下的/packages/Redis-64.2.6.12.1/tools复制到C:/Redis。然后将Exe2Srvc\bin\Release中的文件复制到同一个目录。

Exe2Srvc.exe.config文件包含:

<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" /> </startup> <appSettings> <!-- set Cmd to the executable file name. --> <!-- set CmdArg to any command arguments required. --> <add key="Cmd" value="c:\Redis\redis-server.exe" /> <add key="CmdArgs" value="c:\Redis\redis.conf --port 6379" /> </appSettings> </configuration>

如果可执行文件的路径包含空格,则需要用引号括起来。这可以通过将双引号字符串用单引号括起来来实现,如下所示。

<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" /> </startup> <appSettings> <!-- set Cmd to the executable file name. --> <!-- set CmdArg to any command arguments required. --> <add key="Cmd" value='"c:Program Files\Redis\redis-server.exe"' /> <add key="CmdArgs" value="c:\Redis\redis.conf --port 6379" /> </appSettings> </configuration>

Install.bat文件,必须以管理员身份运行,使用SC命令安装服务。

sc create Redis binpath= "c:\Redis\Exe2Srvc.exe"

然后使用服务管理器配置服务并启动它。

双击Redis服务以打开属性编辑器并选择恢复选项卡。将选项设置为在错误时重新启动服务,如下所示。

选择常规选项卡。

  • 将启动类型设置为Automatic,
  • 点击启动按钮,
  • 点击确定按钮。

Redis现在已安装并作为Windows服务运行。使用redis-cli.exe测试连接。

Exe2Srvc的工作原理

创建一个可以作为Windows服务运行的控制台应用程序,使用了Steve Smith向展示的技术,并基于Einar Egilsson的文章"Run Windows Service as a console program"。基本上,创建一个控制台应用程序,并将Program类更改为派生自ServiceBase。在Main中,使用Environment.UserInteractive属性来确定程序是从命令行运行,还是作为服务运行。

所需的命令和命令行参数从LoadConfiguration方法中读取。

/// <summary> /// Loads the configuration parameters from the application config file /// </summary> private void LoadConfiguration { // Load the executable filename and command arguements from config file. _cmd = ConfigurationManager.AppSettings["Cmd"]; _cmdArgs = ConfigurationManager.AppSettings["CmdArgs"]; if (string.IsNullOrWhiteSpace(_cmd)) throw new Exception("The appsetting 'Cmd' was not defined in the config file."); }

这从Main调用,当作为控制台应用程序启动时,或由服务基础结构作为服务运行时调用。OnStart在下面显示的方式中运行可执行文件。

/// <summary> /// When implemented in a derived class, executes when a Start command is sent to the /// service by the Service Control Manager (SCM) or when the operating system starts /// (for a service that starts automatically). /// Specifies actions to take when the service starts. /// </summary> /// <param name="args"> /// Data passed by the start command. /// </param> protected override void OnStart(string[] args) { if (Environment.UserInteractive) { string message = String.Format("Starting {0} at {1}.", _serviceName, DateTime.Now); Console.WriteLine(message); } // loading the configuration file info here allows the service to be stopped, // the configuration modified, and the service restarted. LoadConfiguration(); // Start the executable. ProcessStartInfo procInfo = new ProcessStartInfo(_cmd); procInfo.UseShellExecute = false; if (!string.IsNullOrWhiteSpace(_cmdArgs)) procInfo.Arguments = _cmdArgs; _process = Process.Start(procInfo); }

当服务停止时,调用OnStop方法。这会杀死进程,等待它终止,并处理进程。确保等待进程终止,否则将导致服务不正确地停止,难以移除和修复。

/// <summary> /// When implemented in a derived class, executes when a Stop command is sent to the service /// by the Service Control Manager (SCM). Specifies actions to take when a service stops running. /// </summary> /// <remarks> /// Stops the background tasks. /// </remarks> protected override void OnStop() { if (Environment.UserInteractive) { string message = String.Format("Stopping {0} at {1}.", _serviceName, DateTime.Now); Console.WriteLine(message); } // Kill the process if if (_process != null) { _process.Kill(); _process.WaitForExit(); _process.Dispose(); _process = null; } }

注意事项

已尽力使这个尽可能简单和灵活,但它只满足了最初的要求,即能够将Windows版本的Redis作为Windows服务器运行。如果有额外的要求,请随时修改代码以满足需求。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485