Лучшие практики для Развертывания заданий Таймера в Средах Фермы Сервера с несколькими WFE

у меня есть задание таймера, которое я хочу выполнить только однажды в день для всей фермы. Как делают меня

  1. Развернуть его в нескольких среда WFE? Я выполняю stsadm-o deploysolution команда в каждом WFE или просто та, где я хочу выполнить его?
  2. Где я должен активировать опцию? Это должно быть активировано только от конкретного WFE?
  3. Каково должно быть значение SPJobLockType.
7
задан ashwnacharya 1 June 2010 в 21:45
поделиться

1 ответ

Похоже, вам нужна функция уровня фермы, которая устанавливает службу, выполняющую это задание. Вот как я это сделал (если честно, используя код, написанный коллегой, но он не в SO).

Создайте файл feature.xml с приемником событий функции.

<Feature
  Id="..."
  Title="..."
  Description="..."
  Scope="Farm"
  Version="1.0.0.0"
  Hidden="FALSE"
  ReceiverAssembly="XXX.FarmService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxx"
  ReceiverClass="XXX.FarmService.XXXFarmFeatureEventReceiver"
  xmlns="http://schemas.microsoft.com/sharepoint/">
</Feature>

Внутри приемника событий:

public override void OnFeatureActivated(SPFeatureReceiverProperties properties)
    {
        try
        {
            SPFarm farm = SPFarm.Local;

            // Get Service, if it already exists
            JobService myService = null; // JobService is a subclass of SPService
            foreach (SPService service in farm.Services)
            {
                if (String.Compare(service.Name, JobService.XXXServiceName, true) == 0)
                {
                    myService = (service as JobService);
                    break;
                    }
                }

                if (cegService == null)
                {
                    // Create service
                    myService = new JobService(farm);
                    myService.Update();

                    // Create service instances
                    JobServiceInstance myServiceInstance; // JobServiceInstance is a subclas of SPServiceInstance
                    foreach (SPServer server in farm.Servers)
                    {
                        myServiceInstance = new JobServiceInstance(server, myService);
                        myServiceInstance.Update();
                    }
                }

                // Dayly schedule 
                SPDailySchedule schedule = new SPDailySchedule();
                schedule.BeginHour = 1;
                schedule.EndHour = 1;
                schedule.BeginMinute = 0;
                schedule.EndMinute = 59;

                // Our own job; JobCheckDocDates is a subclass of SPJobDefinition
                JobCheckDocDates newJob = new JobCheckDocDates(cegService, null, SPJobLockType.Job);
                newJob.Schedule = schedule;
                newJob.Update();
                myService.JobDefinitions.Add(newJob);
                myService.Update();
            }
            catch (Exception e)
            {
                Logger.Error("[" + properties.Feature.Definition.DisplayName + "] Error during feature activation", e);
            }
        }        

Это создает службу, доступную на каждом сервере фермы.

Еще немного подробностей о подклассах:

public class JobCheckDocDates: Common.BaseJob
{
    /// <summary>
    /// The job name
    /// </summary>
    public static string JobName = "XXX job";

    /// <summary>
    /// Constructor
    /// </summary>
    public JobCheckDocDates() : base() { }

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="service"></param>
    /// <param name="server"></param>
    /// <param name="lockType"></param>
    public JobCheckDocDates(SPService service, SPServer server, SPJobLockType lockType)
            : base(JobName, service, server, lockType) { }

...

и, конечно, метод Execute.

public class JobService : SPService 
{
    public static string XXXServiceName = "XXX Service";

    public override string DisplayName
    {
        get
        {
            return XXXServiceName;
        }
    }

    public override string TypeName
    {
        get
        {
            return "XXX Service Type";
        }
    }

    /* An empty public constructor required for serialization. */
    public JobService() { }

    public JobService(SPFarm farm)
          : base(XXXServiceName, farm)
    {         
    }
}


    public class JobServiceInstance : SPServiceInstance
    {
        /// <summary>
        /// Eos Service Instance Name
        /// </summary>
        public static string XXXServiceInstanceName = "XXXServiceInstance";

        /// <summary>
        /// Manage Link
        /// </summary>
        private SPActionLink _manageLink;

        /// <summary>
        /// Provision Link
        /// </summary>
        private SPActionLink _provisionLink;

        /// <summary>
        /// Unprovision Link
        /// </summary>
        private SPActionLink _unprovisionLink;

        /// <summary>
        /// Roles
        /// </summary>
        private ICollection<string> _roles;

        /// <summary>
        /// Manage Link
        /// </summary>
        public override SPActionLink ManageLink
        {
            get
            {
                if (_manageLink == null)
                {
                    _manageLink = new SPActionLink(SPActionLinkType.None);
                }
                return _manageLink;
            }
        }

        /// <summary>
        /// Provision Link
        /// </summary>
        public override SPActionLink ProvisionLink
        {
            get
            {
                if (_provisionLink == null)
                {
                    _provisionLink = new SPActionLink(SPActionLinkType.ObjectModel);
                }
                return _provisionLink;
            }
        }

        /// <summary>
        /// Unprovision Link
        /// </summary>
        public override SPActionLink UnprovisionLink
        {
            get
            {
                if (_unprovisionLink == null)
                {
                    _unprovisionLink = new SPActionLink(SPActionLinkType.ObjectModel);
                }
                return _unprovisionLink;
            }
        }

        /// <summary>
        /// Roles
        /// </summary>
        public override ICollection<string> Roles
        {
            get
            {
                if (_roles == null)
                {
                    _roles = new string[1] { "Custom" };
                }
                return _roles;
            }
        }

        /// <summary>
        /// Empty constructor
        /// </summary>
        public JobServiceInstance() : base() { }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="server">The server</param>
        /// <param name="service">The Eos service</param>
        public JobServiceInstance(SPServer server, JobService service)
            : base(XXXServiceInstanceName, server, service)
        {
        }

Теперь в Central Admin перейдите в Операции / Службы на сервере. Выберите желаемый сервер и запустите службу.

Чтобы ответить на ваш список вопросов: 1. Разверните решение только один раз, независимо от WFE. 2. Поскольку функция относится к области фермы, ее следует активировать в Central Admin. 3. SPJobLockType - это SPJobLockType.Job

. Это не совсем то, что вы себе представляли, но у него есть то преимущество, что вы можете легко выбрать, где будет выполняться задание, даже спустя долгое время после установки функции (например, если сервер становится перегруженным из-за другие вещи).

Метод OnFeatureActivated может быть умнее и проверять для каждого сервера, существует ли служба, и добавлять ее при необходимости. Но проще удалить службу из каждой службы в OnFeatureDeactivated. Итак, если вы добавляете новые серверы, отключите, а затем снова активируйте эту функцию.

7
ответ дан 7 December 2019 в 07:40
поделиться