65.9K
CodeProject 正在变化。 阅读更多。
Home

Quartz.Net Windows 服务在服务器上的重要配置步骤

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2013 年 1 月 23 日

CPOL

3分钟阅读

viewsIcon

26443

如果你正在远程服务器上以 Windows 服务的形式运行 Quartz.Net,并且尝试从客户端连接到它来调度作业,请阅读这篇文章。

你是否正在远程服务器上以 Windows 服务的形式运行 Quartz.Net,并且尝试从客户端连接到它来调度作业? 那么,我强烈建议阅读下面列出的配置步骤,以避免花费无休止的调试时间。

  • 01 – 如何确保 Quartz.NET 服务在服务器上执行作业,而不是本地执行?
  • 02 – 修复“名称为 xxx 的调度程序已存在”问题

01 - 如何确保 Quartz.NET 服务在服务器上执行作业,而不是本地执行?

为了确保 Quartz.Net 在*远程服务器*上调度作业,而不是在本地实例上,你需要在实例化调度程序服务的新实例时,将线程数设置为0,并设置下面显示的其他属性。

// address = string.Format("tcp://{0}:{1}/{2}", server, port, scheduler)
private static NameValueCollection GetProperties(string address) 
{
     var properties = new NameValueCollection();
     properties["quartz.scheduler.instanceName"] = "ServerScheduler";
     properties["quartz.scheduler.proxy"] = "true";
     properties["quartz.threadPool.threadCount"] = "0";
     properties["quartz.scheduler.proxy.address"] = address;
     return properties;
}

SNAGHTML3a6dd4be

图 1 – Quartz.Net 配置,包含有用的详细信息,不需要更改

实例化 Quartz 服务的新实例时需要传递的属性值。

地址:地址需要以以下格式传递:tcp://NameOfSeverWhereQuartzIsInstalled:555/QuartzScheduler

实例名称:你可以在服务器上的 Quartz.Net 配置文件中找到实例名称。 参见上面的配置,实例名称是 ‘ServerScheduler’。

代理:将代理设置为 true

线程数:如果你没有将threadcount指定为0,quartz.net 将启动服务的本地实例来调度你的作业。 也就是说,你的作业将被调度,但不会在你希望调度的服务器上。 缺点是,一旦本地进程终止,调度程序将会丢失。

在实例化 Quartz 调度程序之前,你为属性指定的值将优先于 config 文件中的值。

如何验证 Quartz.Net 调度程序服务正在远程调度,而不是本地调度?

你可以在 Scheduler 实例上使用 GetMetaData() 方法来获取信息,例如 quartz.net 的版本、线程池大小、jobStoreTypejobStorePersistanceType 等。 这个重要的方法还会返回属性 ‘IsRemote’。 如果你正确配置了调度程序并正确实例化了它,则此属性的值应为 ‘True

image

02 – 修复“名称为 xxx 的调度程序已存在”问题

如果你尝试在进程中已经加载一个活动实例时实例化调度程序的新实例,通常会发生这种情况。 避免此问题的最简单方法是使用单例模式实现 Scheduler 实例化。 请参阅使用单例模式实例化 Quartz.Net 的示例代码。

调度程序是一个单例实现。 仅当传递服务器名称、端口号和调度程序名称输入参数时,才实例化该类。 使用此方法,你可以调用 StdSchedulerFactory 方法,并搜索是否已经使用这些属性实例化了调度程序的实例。 如果是,则返回该实例,否则,创建一个新实例并记住它。

public class Scheduler
{
    public readonly IScheduler Instance;
    public string Address { get; private set; }
    public string JobName { get; set; }
    public string JobGroup { get; set; }
    public int Priority { get; set; }
    public string CronExpression { get; set; }

    private readonly ISchedulerFactory _schedulerFactory;

    public Scheduler(string server, int port, string scheduler)
    {
        Address = string.Format("tcp://{0}:{1}/{2}", server, port, scheduler);
        _schedulerFactory = new StdSchedulerFactory(GetProperties(Address));

        try
        {
            Instance = _schedulerFactory.GetScheduler();

            if (!Instance.IsStarted)
                Instance.Start();
        }
        catch (SchedulerException ex)
        {
            throw new Exception(string.Format("Failed: {0}", ex.Message));
        }
    }

    private static NameValueCollection GetProperties(string address) 
    {
        var properties = new NameValueCollection();
        properties["quartz.scheduler.instanceName"] = "ServerScheduler";
        properties["quartz.scheduler.proxy"] = "true";
        properties["quartz.threadPool.threadCount"] = "0";
        properties["quartz.scheduler.proxy.address"] = address;
        return properties;
    }

    public IScheduler GetScheduler()
    {
        return Instance;
    }
}

如果你想调用 Scheduler,那么你应该使用类似下面的代码示例…

只需使用安装了 Quartz 的服务器的名称、quartz 服务正在侦听的端口以及调度程序的名称调用 Scheduler 类。

public SchedulerMetaData GetMetaData()
{
        var scheduler = new Scheduler("ServerName", Convert.ToInt32("PortNumber"), "Scheduler"));
        return scheduler.GetMetaData();
}

希望这有帮助!

这是关于使用 Quartz.net 进行企业调度的系列文章中的第五篇。 在下一篇文章中,我将介绍如何通过 WebService 暴露 Quartz.Net 调度程序服务的功能。 所有 Quartz.Net 相关的博客文章都列在这里。 感谢你抽出时间阅读这篇博文。 如果你喜欢这篇文章,请记住订阅 http://feeds.feedburner.com/TarunArora。 敬请关注!

© . All rights reserved.