2010-06-01 8 views
7

Tengo un trabajo temporizador que quiero ejecutar sólo una vez por día, durante toda la granja. ¿Cómo puedomejores prácticas para la implementación de temporizador puestos de trabajo en entornos de servidor de granja con múltiples WFE

  1. ¿Implementarlo en un entorno WFE múltiple? ¿Ejecutaré el comando stsadm -o deploysolution en cada WFE, o solo en el que quiero ejecutarlo?
  2. dónde debería activar la función? ¿Debería activarse solo desde un WFE particular?
  3. cuál debe ser el valor de la SPJobLockType.

Respuesta

7

Parece que necesita una función de ámbito de granja, que instala un servicio que ejecuta este trabajo. Así es como lo hice (usando el código escrito por un colega, para ser honesto, pero él no está en SO).

Crear un archivo feature.xml con un receptor de evento de estas características.

<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> 

Dentro del receptor de eventos:

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); 
      } 
     }   

Esto crea un servicio disponible en todos los servidores de la comunidad.

Algunos detalles más sobre las subclases:

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) { } 

...

y por supuesto el método 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) 
     { 
     } 

Ahora, en Central Admin, vaya a Operaciones/Servicios en el servidor. Elija el servidor deseado e inicie el servicio.

para responder a su lista de preguntas: 1. Implementar la solución de una sola vez, independientemente de un WFE. 2. Como la función tiene un alcance de granja, debe activarse en Central Admin. 3. SPJobLockType es SPJobLockType.Job

Esto no es exactamente lo que imaginaba, pero tiene la ventaja de permitirle elegir fácilmente dónde se ejecuta el trabajo, incluso mucho después de instalar la característica (por ejemplo, si un servidor se convierte sobrecargado con otras cosas).

El método OnFeatureActivated podría ser más inteligentes y comprobar para cada servidor si existe el servicio y añadir si es necesario. Pero es más sencillo eliminar el servicio de todos los servicios en OnFeatureDeactivated. Entonces, si agrega servidores nuevos, desactívelos y luego reactive la función.

Cuestiones relacionadas