8

わかりました、ここで少し背景を説明します。私はあらゆる種類の重要でないことを行う大規模な Web アプリケーション (MVC3) を持っています。この Web アプリケーションには、Oracle データベースでアドホック Quartz.NET ジョブをスケジュールする機能が必要です。次に、後でWindows サービスを介してジョブを実行したいと考えています。理想的には、それらを等間隔で実行するようにスケジュールしたいと思いますが、Web アプリを介してジョブを追加するオプションがあります。

基本的に、望ましいアーキテクチャはこれのいくつかのバリエーションです。

Web アプリ <--> Quartz.NET <--> データベース <--> Quartz.NET <--> Windows サービス

これまでにコード化したもの:

  • (今のところ) ジョブをスケジュールして実行する Windows サービス。これは明らかに長期的には当てはまりませんが、これだけを保持して、基本的に上の図の両方の「Quartz.NET」を表すように変更できるかどうか疑問に思っています.
  • Web アプリ (詳細はここではあまり重要ではないと思います)
  • ジョブ (実際には別のWindows サービスです)

そして、いくつかの重要な注意事項:

  • Windows サービスから実行する必要があり、Web アプリを介してスケジュールする必要があります (IIS の負荷を軽減するため)。
  • 上記の箇条書きがまだ適用されると仮定すると、上記のアーキテクチャは少し再配置できます。

さて、いくつか質問があります:

  1. これは可能ですか?
  2. (1) がパスすると仮定すると、これに最適なアーキテクチャは何だと思いますか? 私がコード化した内容の最初の箇条書きを参照してください。
  3. ジョブがすでにスケジュールされている場合に DB にクエリを実行してジョブを実行するのに役立ついくつかの Quartz メソッドを誰かが教えてくれませんか?

この質問には、資格があり次第報奨金があります。それまでに質問に満足のいく回答があった場合でも、回答の投稿者に報奨金を授与します。ですから、いずれにせよ、ここで良い答えを出せば報奨金がもらえます。

4

1 に答える 1

27

ご質問いただいた順にお答えしていきます。

  1. はい、可能です。実際には、Quartz.Net を操作する一般的な方法です。実際、Quartz.Net スケジューラを管理する ASP.Net MVC アプリケーションを作成することもできます。

  2. 建築。理想的には、高レベルでは、MVC アプリケーションは Quartz.Net API を使用して、Windows サービスとしてどこかにインストールされている Quartz.Net サーバーと通信します。Quartz.Net はリモーティングを使用してリモートで通信するため、リモーティングの使用に関する制限が適用されます (Silverlight ではサポートされていないなど)。Quartz.Net は、箱から出してすぐに Windows サービスとしてインストールする方法を提供します。そのため、(あなたの場合) AdoJobStore を使用するようにサービス自体を構成し、有効にする以外に、ここで行う作業はあまりありません。リモーティング。サービスを適切にインストールする方法については注意が必要です。まだインストールしていない場合は、この投稿をご覧ください。

内部的には、MVC アプリケーションでスケジューラへの参照を取得し、それをシングルトンとして保存する必要があります。次に、コードでジョブをスケジュールし、この一意のインスタンスを介してスケジューラに関する情報を取得します。次のようなものを使用できます。

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

        try
        {
            _scheduler = _schedulerFactory.GetScheduler();
        }
        catch (SchedulerException)
        {
            MessageBox.Show("Unable to connect to the specified server", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }
    }
    public string Address { get; private set; }
    private NameValueCollection getProperties(string address)
    {
        NameValueCollection properties = new NameValueCollection();
        properties["quartz.scheduler.instanceName"] = "RemoteClient";
        properties["quartz.scheduler.proxy"] = "true";
        properties["quartz.threadPool.threadCount"] = "0";
        properties["quartz.scheduler.proxy.address"] = address;
        return properties;
    }
    public IScheduler GetScheduler()
    {
        return _scheduler;
    }
}

このコードは、Quart.Net クライアントをセットアップします。次に、リモートスケジューラにアクセスするには、単に呼び出します

GetScheduler()
  1. クエリ スケジューラからすべてのジョブを取得するためのサンプル コードを次に示します。

    public DataTable GetJobs()
    {
        DataTable table = new DataTable();
        table.Columns.Add("GroupName");
        table.Columns.Add("JobName");
        table.Columns.Add("JobDescription");
        table.Columns.Add("TriggerName");
        table.Columns.Add("TriggerGroupName");
        table.Columns.Add("TriggerType");
        table.Columns.Add("TriggerState");
        table.Columns.Add("NextFireTime");
        table.Columns.Add("PreviousFireTime");
        var jobGroups = GetScheduler().GetJobGroupNames();
        foreach (string group in jobGroups)
        {
            var groupMatcher = GroupMatcher<JobKey>.GroupContains(group);
            var jobKeys = GetScheduler().GetJobKeys(groupMatcher);
            foreach (var jobKey in jobKeys)
            {
                var detail = GetScheduler().GetJobDetail(jobKey);
                var triggers = GetScheduler().GetTriggersOfJob(jobKey);
                foreach (ITrigger trigger in triggers)
                {
                    DataRow row = table.NewRow();
                    row["GroupName"] = group;
                    row["JobName"] = jobKey.Name;
                    row["JobDescription"] = detail.Description;
                    row["TriggerName"] = trigger.Key.Name;
                    row["TriggerGroupName"] = trigger.Key.Group;
                    row["TriggerType"] = trigger.GetType().Name;
                    row["TriggerState"] = GetScheduler().GetTriggerState(trigger.Key);
                    DateTimeOffset? nextFireTime = trigger.GetNextFireTimeUtc();
                    if (nextFireTime.HasValue)
                    {
                        row["NextFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime(nextFireTime.Value.DateTime);
                    }
    
                    DateTimeOffset? previousFireTime = trigger.GetPreviousFireTimeUtc();
                    if (previousFireTime.HasValue)
                    {
                        row["PreviousFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime(previousFireTime.Value.DateTime);
                    }
    
                    table.Rows.Add(row);
                }
            }
        }
        return table;
    }
    

このコードはGithubで表示できます

于 2012-05-31T21:10:54.650 に答える