我有一個計時器作業,我只想每天只運行一次整個農場。我如何在具有多個WFE的服務器場環境中部署計時器作業的最佳實踐
- 將其部署到多個WFE環境中?我是否在每個WFE中運行stsadm -o deploysolution命令,或者只是運行它的那個命令?
- 我應該在哪裏激活該功能?是否只能從特定的WFE激活?
- SPJobLockType的值應該是什麼。
我有一個計時器作業,我只想每天只運行一次整個農場。我如何在具有多個WFE的服務器場環境中部署計時器作業的最佳實踐
看起來您需要一個農場範圍的功能,它安裝運行此作業的服務。我是這麼做的(使用由同事編寫的代碼,說實話,但他不在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) { }
...
過程和執行方法。
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中,轉到服務器上的Operations/Services。選擇所需的服務器並啓動服務。
回答您的問題列表: 1.僅部署一次解決方案,而不依賴於WFE。 2.由於該功能是服務器場範圍,因此應在中央管理中激活。 3. SPJobLockType是SPJobLockType.Job
這不正是你想象的東西,但它有讓您輕鬆選擇作業在哪裏運行,即使長時間在安裝功能後(例如,如果一臺服務器變成優勢與其他東西超載)。
OnFeatureActivated方法可能更智能,並檢查每個服務器是否存在服務,並在需要時添加它。但是從OnFeatureDeactivated中的每個服務中刪除服務會更簡單。所以,如果您添加新的服務器,請取消激活然後重新激活該功能。