この記事では、Azure WebJobs SDK を使用する方法について説明します。 WebJobs をすぐに使い始めたい場合は、「Azure WebJobs SDK の使用を開始する」をご覧ください。
WebJobs SDK のバージョン
WebJobs SDK のバージョン 3.x とバージョン 2.x の主な違いは以下のとおりです。
- バージョン 3.x では、.NET Core のサポートが追加されています。
- バージョン 3。x: WebJobs SDK で必要なストレージ バインディング拡張機能をインストールします。 バージョン 2.x では、ストレージ バインディングは SDK に含まれています。
- .NET Core (3.x) プロジェクト用の Visual Studio 2019 のツールは、.NET Framework (2.x) プロジェクト用のツールと異なります。 詳細については、「Visual Studio を使用して WebJobs の開発とデプロイを行う」をご覧ください。
この記事で扱う例の一部は、WebJobs バージョン 3.x と WebJobs バージョン 2.x の両方に対応しています。
Azure Functions は WebJobs SDK を基にして構築されています。
- Azure Functions バージョン 2.x は、WebJobs SDK バージョン 3.x を基にして構築されています。
- Azure Functions バージョン 1.x は、WebJobs SDK バージョン 2.x を基にして構築されています。
Azure Functions と WebJobs SDK の両方のソース コード リポジトリで、WebJobs SDK の番号付けが使用されています。 この記事のいくつかのセクションは、Azure Functions ドキュメントにリンクされています。
詳細については、「WebJobs SDK と Azure Functions の比較」をご覧ください。
WebJobs ホスト
WebJobs ホストは、関数のランタイム コンテナーです。 このホストは、トリガーをリッスンして関数を呼び出します。 バージョン 3.x では、ホストは IHost
の実装です。 バージョン 2.x では、JobHost
オブジェクトを使用します。 コードでホスト インスタンスを作成し、その動作をカスタマイズするコードを記述します。
このアーキテクチャの変更が、直接 WebJobs SDK を使用する場合と Azure Functions を介して間接的に使用する場合の重要な違いです。 Azure Functions では、サービスがホストを制御します。 コードを記述してホストをカスタマイズすることはできません。 Azure Functions では、host.json
ファイルの設定を使用してホストの動作をカスタマイズできます。 これらの設定はコードではなく文字列なので、これらの文字列の使用によって、実行できるカスタマイズの種類が制限されます。
ホスト接続
WebJobs SDK では、Azure Storage と Azure Service Bus の接続は、ローカルで実行するときは local.settings.json
ファイルで検索され、Azure で実行するときは WebJobs の環境で検索されます。 既定では、WebJobs SDK には AzureWebJobsStorage
という名前のストレージ接続が必要です。
接続名が 1 つの正確な値に解決されると、ランタイムは値を接続文字列として識別します。通常はシークレットが含まれます。 接続文字列の詳細は、接続先のサービスによって異なります。 ただし、接続名は、複数の構成項目のコレクションを参照することもできます。 この方法は、ID ベースの接続を構成する場合に役立ちます。 二重アンダースコア (__
) で終わる共有プレフィックスを使用して、環境変数をコレクションとして扱うことができます。 その後、接続名をこのプレフィックスに設定することで、グループを参照できます。
たとえば、Azure Blob Storage トリガー定義の connection
プロパティが Storage1
であるとします。
Storage1
という名前の環境変数で構成された単一の文字列値がない限り、Storage1__blobServiceUri
という名前の環境変数を使用して、接続の blobServiceUri
プロパティを通知できます。 接続のプロパティはサービスによって異なります。 接続を使用するコンポーネントのドキュメントをご覧ください。
ID ベースの接続
WebJobs SDK で ID ベースの接続を使用するには、プロジェクトで最新バージョンの WebJobs パッケージを使用していることを確認します。 また、Microsoft.Azure.WebJobs.Host.Storage への参照があることも確認します。
次の例は、これらの更新を行った後にプロジェクト ファイルがどのようになるかを示します。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net48</TargetFramework>
<IsWebJobProject>true</IsWebJobProject>
<WebJobName>$(AssemblyName)</WebJobName>
<WebJobType>Continuous</WebJobType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.42" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage.Queues" Version="5.3.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Host.Storage" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
HostBuilder インスタンスで Web ジョブを設定するときは、 AddAzureStorageCoreServices
の呼び出しが含まれていることを確認します。 これにより、AzureWebJobsStorage
やその他のストレージ トリガーとバインドがその ID を使用できるようになります。
次に例を示します。
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
// Other configurations...
});
次に、環境変数 (またはコードが Azure App Service でホストされている場合のアプリケーション設定) を設定して、 AzureWebJobsStorage
接続を構成できます。
環境変数 | 説明 | 値の例 |
---|---|---|
AzureWebJobsStorage__blobServiceUri |
ストレージ アカウントの BLOB サービスのデータ プレーン URI。 HTTPS スキームを使用します。 | https://<storage_account_name>.blob.core.windows.net |
AzureWebJobsStorage__queueServiceUri |
ストレージ アカウントのキュー サービスのデータ プレーン URI。 HTTPS スキームを使用します。 | https://<storage_account_name>.queue.core.windows.net |
appsettings.json
構成ファイルなど、環境変数以外の方法で構成を指定する場合は、代わりに接続とそのプロパティの構造化構成を指定する必要があります。
{
"AzureWebJobsStorage": {
"blobServiceUri": "https://<storage_account_name>.blob.core.windows.net",
"queueServiceUri": "https://<storage_account_name>.queue.core.windows.net"
}
}
BLOB トリガーを使用する予定がない場合は、queueServiceUri
プロパティを省略できます。
コードをローカルで実行する場合、DefaultAzureCredential
での記述に従って、既定では自分の開発者 ID を使用します。
コードが App Service でホストされている場合、前の例の構成は既定でリソースの システム割り当てマネージド ID になります。 代わりに、アプリ に割り当てられているユーザー割り当て ID を 使用するには、接続のプロパティを追加して、使用する ID を指定する必要があります。
credential
プロパティ (環境変数の AzureWebJobsStorage__credential
) は、文字列 managedidentity
に設定する必要があります。
clientId
プロパティ (環境変数としてAzureWebJobsStorage__clientId
) は、使用するユーザー割り当てマネージド ID のクライアント ID に設定する必要があります。
構造化された構成としては、完全なオブジェクトは次のようになります。
{
"AzureWebJobsStorage": {
"blobServiceUri": "https://<storage_account_name>.blob.core.windows.net",
"queueServiceUri": "https://<storage_account_name>.queue.core.windows.net",
"credential": "managedidentity",
"clientId": "<user-assigned-identity-client-id>"
}
}
AzureWebJobsStorage
に使用される ID には、ストレージ BLOB データ所有者、ストレージ キュー データ共同作成者、およびストレージ アカウント共同作成者のロールを付与するロール割り当てが必要です。 BLOB トリガーを使用する予定がない場合は、ストレージ キュー データ共同作成者とストレージ アカウント共同作成者のロールを省略できます。
次の表は、通常の操作でバインドでトリガーを使用する場合に推奨される、組み込みのロールを示します。 作成するコードによっては、アプリケーションにさらに多くのアクセス許可が必要になる場合があります。
バインド | 組み込みのロールの例 |
---|---|
BLOB トリガー |
ストレージ BLOB データ所有者およびストレージ キュー データ共同作成者 前述の AzureWebJobsStorage の要件もご覧ください。 |
BLOB (入力) | ストレージ BLOB データ閲覧者 |
BLOB (出力) | ストレージ BLOB データ所有者 |
キュー トリガー | ストレージ キュー データ閲覧者、ストレージ キュー データのメッセージ プロセッサ |
キュー (出力) | ストレージ キュー データ共同作成者、ストレージ キュー データ メッセージ送信者 |
Service Bus トリガー1 | Azure Service Bus データ受信者、Azure Service Bus データ所有者 |
Service Bus (出力) | Azure Service Bus データ送信者 |
1 Service Bus トピックからトリガーする場合、ロールの割り当てには、Service Bus サブスクリプション リソースに対する有効なスコープが必要です。 トピックのみが含まれている場合は、エラーが発生します。 Azure portal などの一部のクライアントは、ロール割り当てのスコープとして、Service Bus サブスクリプション リソースを公開しません。 このような場合、代わりに Azure CLI を使用できます。 詳細については、「Azure Service Bus 用の Azure 組み込みロール」をご覧ください。
バージョン 2 の接続文字列。x
バージョン 2。x の SDK では、接続文字列に特定の名前は必要ありません。 バージョン 2.x では、これらの接続文字列に独自の名前を使用でき、それらを他の場所に格納できます。 次の例に示すように、JobHostConfiguration
を使用してコードで名前を設定できます。
static void Main(string[] args)
{
var _storageConn = ConfigurationManager
.ConnectionStrings["MyStorageConnection"].ConnectionString;
//// Dashboard logging is deprecated; use Application Insights.
//var _dashboardConn = ConfigurationManager
// .ConnectionStrings["MyDashboardConnection"].ConnectionString;
JobHostConfiguration config = new JobHostConfiguration();
config.StorageConnectionString = _storageConn;
//config.DashboardConnectionString = _dashboardConn;
JobHost host = new JobHost(config);
host.RunAndBlock();
}
メモ
バージョン 3.x では、既定の .NET Core 構成 API が使用されるため、接続文字列の名前を変更するための API はありません。 詳細については、「Visual Studio を使用して WebJobs の開発とデプロイを行う」をご覧ください。
ホスト開発設定
ローカル開発をより効率的にするために、開発モードでホストを実行できます。 開発モードで実行しているときに自動的に変更されるいくつかの設定を以下に示します。
プロパティ | 開発設定 |
---|---|
Tracing.ConsoleLevel |
TraceLevel.Verbose でログ出力を最大化します。 |
Queues.MaxPollingInterval |
キューのメソッドがすぐにトリガーされるように、値は小さくしてあります。 |
Singleton.ListenerLockPeriod |
迅速な反復型の開発では 15 秒が有用です。 |
開発モードを有効にするプロセスは、SDK のバージョンによって異なります。
バージョン 3.x
バージョン 3。x では、標準の ASP.NET Core API を使用してホスト環境を変更します。
UseEnvironment
インスタンスで HostBuilder
メソッドを呼び出します。 次の例のように、development
という名前の文字列を渡します。
static async Task Main()
{
var builder = new HostBuilder();
builder.UseEnvironment("development");
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
バージョン 2.x
JobHostConfiguration
クラスには、開発モードを有効にする UseDevelopmentSettings
メソッドがあります。 次の例では、開発設定を使用する方法を示します。 ローカル環境で実行したときに config.IsDevelopment
が true
を返すようにするには、AzureWebJobsEnv
という名前のローカル環境変数を、値を Development
にして設定します。
static void Main()
{
config = new JobHostConfiguration();
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
var host = new JobHost(config);
host.RunAndBlock();
}
コンカレント接続の管理 (バージョン 2.x)
バージョン 3.x では、接続制限は既定で無限接続に設定されます。 何らかの理由でこの制限を変更する必要がある場合は、MaxConnectionsPerServer
クラス の WinHttpHandler
プロパティを使用できます。
バージョン 2。x では、 ServicePointManager.DefaultConnectionLimit
プロパティを使用して、ホストへの同時接続の数を制御します。 バージョン 2.x では、WebJobs ホストを開始する前に、この値を既定値の 2
から増やす必要があります。
HttpClient
を使用することで関数から送信するすべての HTTP 要求は、ServicePointManager
を通過します。
DefaultConnectionLimit
で設定されている値に達した後は、ServicePointManager
が要求を送信する前にキューに格納するようになります。 たとえば、DefaultConnectionLimit
が 2
に設定されている場合に、コードによって 1,000 回の HTTP 要求が実行されるとします。 最初は、OS への送信が許可される要求は 2 回だけです。 その他の 998 回は、処理が可能になるまでキューに配置されたままになります。 要求が送信されたように見えても、実際はその要求は OS によって宛先サーバーに送信されていないために、HttpClient
がタイムアウトする場合があります。 ローカルの HttpClient
では要求を完了するのに 10 秒間かかっているが、サービスではどの要求も 200 ミリ秒で返しているというような、理解に苦しむような動作に見えるかもしれません。
ASP.NET アプリケーションの既定値は Int32.MaxValue
であり、Basic 以上の App Service プランで実行されている WebJobs であれば問題なく動作する可能性があります。 通常、Web ジョブには Always On 設定が必要であり、Basic 以降の App Service プランでのみサポートされます。
Web ジョブが Free または Shared App Service プランで実行されている場合、アプリケーションは App Service サンドボックスによって制限されます。現在、 接続制限は 600 です。
ServicePointManager
にバインドされていない接続制限がある場合は、サンドボックス接続のしきい値に達し、サイトがシャットダウンされる可能性が高くなります。 その場合、 DefaultConnectionLimit
を 200 などの低い値に設定すると、このシナリオが発生するのを防ぎ、十分なスループットを確保できます。
この設定は、HTTP 要求が行われる前に構成する必要があります。 このため、WebJobs ホストでは設定を自動的に調整しないようにします。 ホストが開始する前に HTTP 要求が発生する可能性があり、予期しない動作を招くことがあります。 最善の方法としては、次の例で示すように、Main
を初期化する前に JobHost
メソッドですぐに値を設定します。
static void Main(string[] args)
{
// Set this immediately so that it's used by all requests.
ServicePointManager.DefaultConnectionLimit = Int32.MaxValue;
var host = new JobHost();
host.RunAndBlock();
}
トリガー
WebJobs SDK では、Azure Functions で使用されるのと同じトリガーとバインドのセットがサポートされます。 WebJobs SDK では、トリガーは関数固有であり、WebJob デプロイの種類とは関連していません。 SDK を使用して作成されたイベント トリガー関数を持つ WebJobs は、常に Always On が有効になっている継続的な WebJobs として発行する必要があります。
関数は、パブリック メソッドである必要があり、1 つのトリガー属性または NoAutomaticTrigger
属性を必要とします。
自動トリガー
自動トリガーは、イベントに応答して関数を呼び出します。 Azure Queue Storage に追加されたメッセージによってトリガーされる関数の例を次に示します。 この関数は、Blob Storage から BLOB を読み取ることで応答します。
public static void Run(
[QueueTrigger("myqueue-items")] string myQueueItem,
[Blob("samples-workitems/{queueTrigger}", FileAccess.Read)] Stream myBlob,
ILogger log)
{
log.LogInformation($"BlobInput processed blob\n Name:{myQueueItem} \n Size: {myBlob.Length} bytes");
}
QueueTrigger
属性は、キュー メッセージが myqueue-items
に出現するたびに関数を呼び出すようランタイムに通知します。
Blob
属性は、キュー メッセージを使用して sample-workitems
コンテナー内の BLOB を読み取るようにランタイムに通知します。
samples-workitems
コンテナー内の BLOB 項目の名前は、キュー トリガーからバインド式 ({queueTrigger}
) として直接取得されます。
メモ
Web アプリは非アクティブな状態が 20 分続くとタイムアウトになり、実際の Web アプリに対する要求だけがタイマーをリセットできます。 Azure portal でアプリの構成を表示したり、高度なツール サイトに要求を行ったりしても、タイマーはリセットされません。 ジョブをホストしている Web アプリを継続的に実行させるか、またはスケジュールに従って実行させるか、あるいはイベント ドリブン トリガーを使用するように設定する場合は、Web アプリの Azure の [構成]ウィンドウで [Always On] 設定を有効にします。 [Always On] 設定は、これらの種類の WebJobs が確実に実行されるようにするのに役立ちます。 この機能は、Basic、Standard、および Premium の価格レベルでのみ利用できます。
手動トリガー
関数を手動でトリガーするには、NoAutomaticTrigger
属性を使用します。
[NoAutomaticTrigger]
public static void CreateQueueMessage(
ILogger logger,
string value,
[Queue("outputqueue")] out string message)
{
message = value;
logger.LogInformation("Creating queue message: ", message);
}
関数を手動でトリガーするプロセスは、SDK のバージョンによって異なります。
バージョン 3.x
static async Task Main(string[] args)
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage();
});
var host = builder.Build();
using (host)
{
var jobHost = host.Services.GetService(typeof(IJobHost)) as JobHost;
var inputs = new Dictionary<string, object>
{
{ "value", "Hello world!" }
};
await host.StartAsync();
await jobHost.CallAsync("CreateQueueMessage", inputs);
await host.StopAsync();
}
}
バージョン 2.x
static void Main(string[] args)
{
JobHost host = new JobHost();
host.Call(typeof(Program).GetMethod("CreateQueueMessage"), new { value = "Hello world!" });
}
入出力バインド
入力バインドは、Azure やサード パーティ サービスからのデータをコードに使用できるようにする宣言方法を提供します。 出力バインドは、データを更新する方法を提供します。 使用の開始に関するページで、それぞれの例が示されています。
出力バインドに対してメソッドの戻り値を使用するには、属性をメソッドの戻り値に適用します。 Azure 関数の戻り値の使用の例をご覧ください。
バインドの種類
バインドの種類をインストールして管理するプロセスは、バージョン 3.x またはバージョン 2.x のどちらの SDK を使用しているかによって異なります。 特定のバインドの種類用にインストールするパッケージは、Azure Functions のそのバインドの種類の参照情報の記事にある「パッケージ」セクションで見つけることができます。 例外は (ローカル ファイル システム用の) Files トリガーとバインドで、Azure Functions ではサポートされていません。
バージョン 3.x
バージョン 3.x では、ストレージのバインドは Microsoft.Azure.WebJobs.Extensions.Storage
パッケージに含まれています。
AddAzureStorage
メソッドで ConfigureWebJobs
拡張メソッドを呼び出します。
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
他のトリガーやバインドの種類を使用するには、それらを含む NuGet パッケージをインストールして、拡張で実装されている Add<binding>
拡張メソッドを呼び出します。 たとえば、Azure Cosmos DB バインドを使用する場合は、Microsoft.Azure.WebJobs.Extensions.CosmosDB
をインストールして AddCosmosDB
を呼び出します。
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddCosmosDB();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
コア サービスの一部である Timer トリガーまたは Files バインドを使用するには、AddTimers
拡張メソッドまたは AddFiles
拡張メソッドを呼び出します。
バージョン 2.x
次のトリガーおよびバインドの種類は、 パッケージのバージョン 2.Microsoft.Azure.WebJobs
に含まれています。
- BLOB ストレージ
- キュー ストレージ
- テーブル ストレージ
その他の種類のトリガーやバインドを使用するには、それらを含む NuGet パッケージをインストールして、Use<binding>
オブジェクトの JobHostConfiguration
メソッドを呼び出します。 たとえば、タイマー トリガーを使用する場合は、Microsoft.Azure.WebJobs.Extensions
をインストールして、UseTimers
メソッドで Main
を呼び出します。
static void Main()
{
config = new JobHostConfiguration();
config.UseTimers();
var host = new JobHost(config);
host.RunAndBlock();
}
Files バインドを使用するには、Microsoft.Azure.WebJobs.Extensions
をインストールして UseFiles
を呼び出します。
実行コンテキスト
WebJobs では、ExecutionContext
インスタンスにバインドできます。 このバインディングを使用すると、関数シグネチャのパラメーターとして ExecutionContext
にアクセスできます。 たとえば、次のコードはコンテキスト オブジェクトを使用して呼び出し ID にアクセスします。その呼び出し ID を使用すると、特定の関数呼び出しによって生成されたすべてのログを関連付けることができます。
public class Functions
{
public static void ProcessQueueMessage([QueueTrigger("queue")] string message,
ExecutionContext executionContext,
ILogger logger)
{
logger.LogInformation($"{message}\n{executionContext.InvocationId}");
}
}
ExecutionContext
にバインドするプロセスは、SDK のバージョンによって異なります。
バージョン 3.x
AddExecutionContextBinding
メソッドで ConfigureWebJobs
拡張メソッドを呼び出します。
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddExecutionContextBinding();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
バージョン 2.x
前述の Microsoft.Azure.WebJobs.Extensions
パッケージは、UseCore
メソッドを呼び出すことによって登録できる特別なバインドの種類も提供しています。 このバインドを使用して、関数シグネチャで ExecutionContext
パラメーターを定義できます。
class Program
{
static void Main()
{
config = new JobHostConfiguration();
config.UseCore();
var host = new JobHost(config);
host.RunAndBlock();
}
}
バインド構成
一部のトリガーとバインドでは、動作を構成することができます。 それらを構成するプロセスは、SDK のバージョンによって異なります。
-
バージョン 3.x:
Add<Binding>
でConfigureWebJobs
メソッドが呼び出されたときに、構成を設定します。 -
バージョン 2.x:
JobHost
に渡す構成オブジェクトでプロパティを設定することによって、構成を設定します。
これらのバインド固有の設定は、Azure Functions の host.json
プロジェクト ファイルでの設定と同等です。
次のバインドを構成できます。
Azure Cosmos DB トリガーの構成 (バージョン 3.x)
次の例では、Azure Cosmos DB トリガーを構成する方法を示します。
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddCosmosDB(a =>
{
a.ConnectionMode = ConnectionMode.Gateway;
a.Protocol = Protocol.Https;
a.LeaseOptions.LeasePrefix = "prefix1";
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
詳細については、Azure Cosmos DB のバインドに関するページをご覧ください。
Azure Event Hubs トリガー構成 (バージョン 3.x)
次の例では、Event Hubs トリガーを構成する方法を示します。
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddEventHubs(a =>
{
a.BatchCheckpointFrequency = 5;
a.EventProcessorOptions.MaxBatchSize = 256;
a.EventProcessorOptions.PrefetchCount = 512;
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
詳細については、Event Hubs のバインドに関するページをご覧ください。
Queue Storage トリガーの構成
次の例では、Queue Storage トリガーを構成する方法を示します。
バージョン 3.x
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddAzureStorage(a => {
a.BatchSize = 8;
a.NewBatchThreshold = 4;
a.MaxDequeueCount = 4;
a.MaxPollingInterval = TimeSpan.FromSeconds(15);
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
詳しくは、Queue Storage バインドに関する記事をご覧ください。
バージョン 2.x
static void Main(string[] args)
{
JobHostConfiguration config = new JobHostConfiguration();
config.Queues.BatchSize = 8;
config.Queues.NewBatchThreshold = 4;
config.Queues.MaxDequeueCount = 4;
config.Queues.MaxPollingInterval = TimeSpan.FromSeconds(15);
JobHost host = new JobHost(config);
host.RunAndBlock();
}
詳細については、host.json
v1.x のリファレンスをご覧ください。
SendGrid バインドの構成 (バージョン 3.x)
次の例では、SendGrid 出力バインドを構成する方法を示します。
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddSendGrid(a =>
{
a.FromAddress.Email = "samples@functions.com";
a.FromAddress.Name = "Azure Functions";
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
詳細については、SendGrid
のバインドに関するページをご覧ください。
Service Bus トリガーの構成 (バージョン 3.x)
次の例では、Service Bus トリガーを構成する方法を示します。
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddServiceBus(sbOptions =>
{
sbOptions.MessageHandlerOptions.AutoComplete = true;
sbOptions.MessageHandlerOptions.MaxConcurrentCalls = 16;
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
詳細については、Service Bus のバインドに関するページをご覧ください。
その他のバインドの構成
一部のトリガーとバインドの種類では、独自のカスタム構成の種類が定義されています。 たとえば、次の例に示すように、File トリガーを使用して、監視するルート パスを指定できます。
バージョン 3.x
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
b.AddFiles(a => a.RootPath = @"c:\data\import");
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
バージョン 2.x
static void Main()
{
config = new JobHostConfiguration();
var filesConfig = new FilesConfiguration
{
RootPath = @"c:\data\import"
};
config.UseFiles(filesConfig);
var host = new JobHost(config);
host.RunAndBlock();
}
バインド式
属性コンストラクターのパラメーターでは、さまざまなソースからの値に解決する式を使用することができます。 たとえば、次のコードでは、BlobTrigger
属性のパスによって filename
という名前の式が作成されます。 これが出力バインドに使用されると、filename
はトリガーする BLOB の名前に解決されます。
public static void CreateThumbnail(
[BlobTrigger("sample-images/{filename}")] Stream image,
[Blob("sample-images-sm/{filename}", FileAccess.Write)] Stream imageSmall,
string filename,
ILogger logger)
{
logger.Info($"Blob trigger processing: {filename}");
// ...
}
バインド式の詳細については、Azure Functions ドキュメント内のバインド式とパターンをご覧ください。
カスタム バインド式
キュー名、BLOB 名、コンテナー、テーブル名を、ハードコーディングではなくコードに指定する場合もあります。 たとえば、構成ファイルや環境変数で QueueTrigger
属性のキュー名を指定するとします。
構成中にカスタムの名前リゾルバーを渡すことによって、属性にキュー名を割り当てることができます。 トリガーやバインド属性コンストラクターのパラメーターにプレースホルダーを組み込み、それらのプレースホルダーの代わりに使われる実際の値をリゾルバーのコードで提供します。 次に示すように、プレースホルダーはパーセント (%
) 記号で囲んで示します。
public static void WriteLog([QueueTrigger("%logqueue%")] string logMessage)
{
Console.WriteLine(logMessage);
}
このコードでは、logqueuetest
という名前のキューをテスト環境で使用し、logqueueprod
という名前のキューを実稼働環境で使用しています。 キュー名をハードコードする代わりに、appSettings
コレクションのエントリの名前を指定します。
カスタム リゾルバーを提供しない場合、既定のリゾルバーが使われます。 既定では、アプリの設定や環境変数から値を取得します。
.NET Core 3.1 以降では、使用する ConfigurationManager
インスタンスに System.Configuration.ConfigurationManager
NuGet パッケージが必要です。 このサンプルでは、次の using
ステートメントが必要です。
using System.Configuration;
NameResolver
クラスによってアプリの設定からキューの名前が取得されます。
public class CustomNameResolver : INameResolver
{
public string Resolve(string name)
{
return ConfigurationManager.AppSettings[name].ToString();
}
}
バージョン 3.x
リゾルバーは、依存関係インジェクションを使用して構成します。 これらのサンプルでは、次の using
ステートメントが必要です。
using Microsoft.Extensions.DependencyInjection;
次の例のように、ConfigureServices
で HostBuilder
拡張メソッドを呼び出してリゾルバーを追加します。
static async Task Main(string[] args)
{
var builder = new HostBuilder();
var resolver = new CustomNameResolver();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
});
builder.ConfigureServices(s => s.AddSingleton<INameResolver>(resolver));
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
バージョン 2.x
NameResolver
クラスを JobHost
オブジェクトに渡します。
static void Main(string[] args)
{
JobHostConfiguration config = new JobHostConfiguration();
config.NameResolver = new CustomNameResolver();
JobHost host = new JobHost(config);
host.RunAndBlock();
}
Azure Functions では、次の例に示すように、アプリの設定から値を取得するために INameResolver
が実装されます。 WebJobs SDK を直接使用する場合は、どのようなソースからでもプレースホルダーの置換値を取得するカスタム実装を記述できます。
実行時のバインド
Queue
、Blob
、Table
などのバインド属性を使用する前に関数で何らかの処理を行う必要がある場合は、IBinder
インターフェイスを使用できます。
次の例では、入力キュー メッセージを取得して、同じ内容の新しいメッセージを出力キューに作成します。 出力キュー名は、関数の本文のコードで設定されます。
public static void CreateQueueMessage(
[QueueTrigger("inputqueue")] string queueMessage,
IBinder binder)
{
string outputQueueName = "outputqueue" + DateTime.Now.Month.ToString();
QueueAttribute queueAttribute = new QueueAttribute(outputQueueName);
CloudQueue outputQueue = binder.Bind<CloudQueue>(queueAttribute);
outputQueue.AddMessageAsync(new CloudQueueMessage(queueMessage));
}
詳細については、Azure Functions ドキュメントの「実行時のバインド」をご覧ください。
バインド参照情報
Azure Functions のドキュメントでは、各バインドの種類に関する参照情報が提供されています。 各バインド参照記事には、以下の情報が記載されています。 (この例は、Storage キューに基づいています。)
- パッケージ。 WebJobs SDK プロジェクトにバインドのサポートを含めるためにインストールする必要のあるパッケージです。
-
例。 コード サンプルです。 C# クラス ライブラリの例は、WebJobs SDK に適用されます。
FunctionName
属性は単に省略します。 - 属性。 バインドの種類に使用する属性です。
- 構成。 属性のプロパティとコンストラクターのパラメーターの説明です。
- 使用方法。 どの種類にバインドできるかとバインドの動作方法に関する情報です。 例: ポーリング アルゴリズム、有害キュー処理。
メモ
HTTP、Webhook、Event Grid のバインドは、Azure Functions でのみサポートされており、WebJobs SDK ではサポートされていません。
Azure Functions ランタイムでサポートされるバインディングの完全な一覧については、「サポートされるバインディング」をご覧ください。
属性: Disable、Timeout、Singleton
これらの属性を使用して、関数のトリガーを制御し、関数を取り消し、関数のインスタンスが 1 つだけ実行されるようにすることができます。
Disable 属性
Disable
属性は、関数をトリガーできるかどうかを制御するために使用します。
次の例では、アプリ設定 Disable_TestJob
の値が 1
または True
(大文字小文字の区別なし) の場合、関数は実行されません。 その場合、ランタイムによって関数 'Functions.TestJob' が無効ですというログ メッセージが作成されます。
[Disable("Disable_TestJob")]
public static void TestJob([QueueTrigger("testqueue2")] string message)
{
Console.WriteLine("Function with Disable attribute executed!");
}
Azure portal でアプリ設定の値を変更すると、WebJobs が再起動され、新しい設定が取得されます。
属性は、パラメーター、メソッド、またはクラス レベルで宣言できます。 設定名には、バインド式を含めることもできます。
Timeout 属性
Timeout
属性を使用すると、指定された時間内に関数が完了しない場合に、その関数が取り消されます。 次の例では、Timeout
属性が使用されない場合、この関数は 1 日間にわたって実行される可能性があります。 Timeout があると、関数は 15 秒後に取り消されます。
Timeout
属性throwOnError
パラメーターが true
に設定されている場合、タイムアウト間隔を超えたときに WebJobs SDK によってスローされる例外が発生することによって、関数の呼び出しが終了します。
throwOnError
の既定値は false
です。
Timeout
属性を使用する場合、既定の動作では、キャンセル トークンを設定して関数の呼び出しを取り消し、関数コードが例外を返すかスローするまで呼び出しを無期限に実行できるようにします。
[Timeout("00:00:15")]
public static async Task TimeoutJob(
[QueueTrigger("testqueue2")] string message,
CancellationToken token,
TextWriter log)
{
await log.WriteLineAsync("Job starting");
await Task.Delay(TimeSpan.FromDays(1), token);
await log.WriteLineAsync("Job completed");
}
Timeout
属性はクラス レベルまたはメソッド レベルで適用でき、JobHostConfiguration.FunctionTimeout
を使用してグローバル タイムアウトを指定できます。 クラス レベルまたはメソッド レベルのタイムアウトは、グローバル タイムアウトをオーバーライドします。
Singleton 属性
Singleton
属性を使用すると、ホスト Web アプリの複数のインスタンスがある場合でも、関数の 1 つのインスタンスだけが実行されます。
Singleton
属性は、分散ロックを使用して、1 つのインスタンスだけが実行されるようにします。
次の例では、常に ProcessImage
関数の 1つのインスタンスだけが実行されます。
[Singleton]
public static async Task ProcessImage([BlobTrigger("images")] Stream image)
{
// Process the image.
}
SingletonMode.Listener
一部のトリガーには、コンカレンシー管理の組み込みサポートがあります。
-
QueueTrigger。
JobHostConfiguration.Queues.BatchSize
を1
に設定します。 -
ServiceBusTrigger。
ServiceBusConfiguration.MessageOptions.MaxConcurrentCalls
を1
に設定します。 -
FileTrigger。
FileProcessor.MaxDegreeOfParallelism
を1
に設定します。
これらの設定を使用すると、単一のインスタンスで、関数がシングルトンとして実行されるようになります。 Web アプリが複数のインスタンスにスケールアウトするとき、関数の単一のインスタンスのみが実行されるようにするには、関数にリスナー レベルのシングルトン ロック ([Singleton(Mode = SingletonMode.Listener)]
) を適用します。 リスナー ロックは、JobHost の起動時に取得されます。 3 つのスケール アウト インスタンスのすべてが同時に開始すると、1 つのインスタンスのみがロックを取得して、1 つのみがリスナーを開始します。
メモ
SingletonMode.Function
の仕組みの詳細については、SingletonMode の GitHub リポジトリをご覧ください。
スコープ値
シングルトンで "スコープ式/値" を指定することができます。 式/値を指定することでり、特定スコープでの関数のすべての実行が確実にシリアル化されます。 この方法で詳細なロックを実装すると、要件によって指示されたように他の呼び出しをシリアル化すると同時に、関数のある程度の並列処理が可能になります。 たとえば、次のコードでは、スコープ式は、受信メッセージの Region
値 にバインドしています。 キューに East、East、および West のリージョンの 3 つのメッセージが含まれている場合、リージョン East を持つメッセージは連続して実行されます。 リージョン West のメッセージは、リージョン East のメッセージと並行して実行されます。
[Singleton("{Region}")]
public static async Task ProcessWorkItem([QueueTrigger("workitems")] WorkItem workItem)
{
// Process the work item.
}
public class WorkItem
{
public int ID { get; set; }
public string Region { get; set; }
public int Category { get; set; }
public string Description { get; set; }
}
SingletonScope.Host
ロックの既定のスコープは SingletonScope.Function
です。 ロックのスコープ (BLOB リース パス) は、関数の完全修飾名に関連付けられます。 複数の関数にわたってロックするには、SingletonScope.Host
を指定して、同時に実行したくない関数すべてと同じスコープ ID 名を使用します。 次の例では、AddItem
または RemoveItem
のインスタンスが一度に 1 つだけ実行されます。
[Singleton("ItemsLock", SingletonScope.Host)]
public static void AddItem([QueueTrigger("add-item")] string message)
{
// Perform the add operation.
}
[Singleton("ItemsLock", SingletonScope.Host)]
public static void RemoveItem([QueueTrigger("remove-item")] string message)
{
// Perform the remove operation.
}
リース BLOB の表示
WebJobs SDK は、Azure BLOB リースを使用して、分散ロックを実装します。
Singleton
によって使用されるリース BLOB は、パス "locks" にある azure-webjobs-host
ストレージ アカウント内の AzureWebJobsStorage
コンテナーにあります。たとえば、前述した最初の ProcessImage
の例では、リース BLOB パスは locks/061851c758f04938a4426aa9ab3869c0/WebJobs.Functions.ProcessImage
である可能性があります。 どのパスにも JobHost ID が含まれています。この場合は、061851c758f04938a4426aa9ab3869c0 になります。
Async 関数
Async 関数のコードを記述する方法については、Azure Functions のドキュメントをご覧ください。
キャンセル トークン
キャンセル トークンを処理する方法については、Azure Functions ドキュメントでキャンセル トークンと正常なシャットダウンのページをご覧ください。
複数インスタンス
Web アプリが複数のインスタンス上で稼働している場合、継続的な WebJobs は各インスタンスで実行され、トリガーをリッスンして関数の呼び出しを行います。 各種のトリガー バインドは、インスタンス間で協調して作業を効率的に共有するよう設計されているため、より多くのインスタンスにスケール アウトすることで、より多くの負荷を処理できます。
一部のトリガーで二重の処理が発生する可能性がありますが、キューと BLOB ストレージ トリガーでは、関数がキュー メッセージや BLOB を 2 回以上処理することが自動的に防止されます。 詳細については、Azure Functions ドキュメントで同一入力のための設計に関するページをご覧ください。
タイマー トリガーは、指定された時刻に関数の複数のインスタンスが実行されないように、自動的にタイマーの1 つのインスタンスのみが実行されるようにします。
ホスト Web アプリの複数のインスタンスがある場合でも、関数の 1 つのインスタンスのみを実行するには Singleton
属性を使用できます。
フィルター
関数のフィルター (プレビュー) は、独自のロジックを使用して、WebJobs 実行パイプラインをカスタマイズする方法を提供します。 これらのフィルターは、 ASP.NET Core フィルターと似ています。 関数またはクラスに適用される宣言型の属性として実装することができます。 詳細については、関数フィルターをご覧ください。
ログ記録と監視
ASP.NET 用に開発されたログ記録フレームワークをお勧めします。 使用方法については、使用の開始に関する記事をご覧ください。
ログのフィルタリング
ILogger
インスタンスによって作成されるすべてのログには、Category
と Level
の値が関連付けられています。
LogLevel
は列挙型で、整数コードは次のような相対的な重要度を示します。
LogLevel | コード |
---|---|
トレース | 0 |
デバッグ | 1 |
情報 | 2 |
警告 | 3 |
エラー | 4 |
クリティカル | 5 |
なし | 6 |
特定の LogLevel
に合わせて各カテゴリを個別にフィルター処理できます。 たとえば、BLOB トリガー処理についてはすべてのログを表示するが、それ以外については Error
以上だけを表示することが可能です。
バージョン 3.x
バージョン 3。SDK の x は、.NET Core に組み込まれているフィルター処理に依存します。
LogCategories
クラスを使用して、特定の関数、トリガー、またはユーザーのカテゴリを定義することができます。
LogCategories
クラスでは、ログ出力を微調整できるように、特定のホスト状態 (Startup
や Results
) に応じてフィルターを定義することもできます。 定義されたカテゴリに一致するものが見つからない場合、フィルターはメッセージをフィルター処理するかどうかを決定するときに Default
値にフォールバックします。
LogCategories
には、次の using
ステートメントが必要です。
using Microsoft.Azure.WebJobs.Logging;
次の例では、既定で Warning
レベルのすべてのログをフィルター処理するフィルターを構築します。
Function
および results
カテゴリ (バージョン 2.Host.Results
の と同等) は、Error
レベルでフィルタリングされます。 フィルターは、現在のカテゴリを LogCategories
インスタンス内のすべての登録済みレベルと比較して、最も長い一致を選択します。 そのため、Debug
に登録されたHost.Triggers
レベルは、Host.Triggers.Queue
またはHost.Triggers.Blob
と一致します。 カテゴリを 1 つずつ追加しなくても、より幅広いカテゴリを制御できます。
static async Task Main(string[] args)
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
});
builder.ConfigureLogging(logging =>
{
logging.SetMinimumLevel(LogLevel.Warning);
logging.AddFilter("Function", LogLevel.Error);
logging.AddFilter(LogCategories.CreateFunctionCategory("MySpecificFunctionName"),
LogLevel.Debug);
logging.AddFilter(LogCategories.Results, LogLevel.Error);
logging.AddFilter("Host.Triggers", LogLevel.Debug);
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
バージョン 2.x
SDK のバージョン 2.x では、LogCategoryFilter
クラスを使用してフィルター処理を制御します。
LogCategoryFilter
には Default
プロパティがあり、初期値は Information
です。つまり、Information
、Warning
、Error
、Critical
レベルのメッセージはすべてログに記録されますが、Debug
または Trace
レベルのメッセージは除外されます。
バージョン 3.LogCategories
の と同様に、CategoryLevels
プロパティを使用すると特定のカテゴリのログ レベルを指定できるため、ロギング出力を微調整することができます。
CategoryLevels
ディクショナリ内で一致するものが見つからない場合、メッセージをフィルター処理するかどうかを決定するときに、フィルターはDefault
値にフォールバックします。
次の例は、既定値で Warning
レベルのすべてのログをフィルター処理するフィルターを構築します。
Function
および Host.Results
カテゴリは、Error
レベルでフィルター処理されます。
LogCategoryFilter
は、現在のカテゴリを、登録されているすべての CategoryLevels
と比較して、最も長い一致を選択します。 そのため、Debug
に登録されたHost.Triggers
レベルは、Host.Triggers.Queue
またはHost.Triggers.Blob
と一致します。 カテゴリを 1 つずつ追加しなくても、より幅広いカテゴリを制御できます。
var filter = new LogCategoryFilter();
filter.DefaultLevel = LogLevel.Warning;
filter.CategoryLevels[LogCategories.Function] = LogLevel.Error;
filter.CategoryLevels[LogCategories.Results] = LogLevel.Error;
filter.CategoryLevels["Host.Triggers"] = LogLevel.Debug;
config.LoggerFactory = new LoggerFactory()
.AddApplicationInsights(instrumentationKey, filter.Filter)
.AddConsole(filter.Filter);
Application Insights のカスタム テレメトリ
Application Insights 用のカスタム テレメトリを実装するプロセスは、SDK のバージョンによって異なります。 Application Insights の構成方法については、Application Insights ログの追加に関するページをご覧ください。
バージョン 3.x
WebJobs SDK のバージョン 3.x は、.NET Core 汎用ホストに依存しているため、カスタム テレメトリ ファクトリは提供されなくなりました。 ただし、依存関係インジェクションを使用してカスタム テレメトリをパイプラインに追加できます。 このセクションの例では、次の using
ステートメントが必要です。
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Channel;
次の ITelemetryInitializer
のカスタム実装を使用して、独自の ITelemetry
インスタンスを既定の TelemetryConfiguration
に追加できます。
internal class CustomTelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
// Do something with telemetry.
}
}
ビルダーで ConfigureServices
を呼び出して、カスタムの ITelemetryInitializer
インスタンスをパイプラインに追加します。
static async Task Main()
{
var builder = new HostBuilder();
builder.ConfigureWebJobs(b =>
{
b.AddAzureStorageCoreServices();
});
builder.ConfigureLogging((context, b) =>
{
// Add logging providers.
b.AddConsole();
// If this key exists in any config, use it to enable Application Insights.
string appInsightsKey = context.Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"];
if (!string.IsNullOrEmpty(appInsightsKey))
{
// This code uses the options callback to explicitly set the instrumentation key.
b.AddApplicationInsights(o => o.InstrumentationKey = appInsightsKey);
}
});
builder.ConfigureServices(services =>
{
services.AddSingleton<ITelemetryInitializer, CustomTelemetryInitializer>();
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
TelemetryConfiguration
が構築されるとき、すべての登録されている種類の ITelemetryInitializer
が組み込まれます。 詳細については、「カスタムのイベントとメトリックのための Application Insights API」をご覧ください。
バージョン 3.xでは、ホストが停止するときに TelemetryClient
をフラッシュする必要はありません。 .NET Core 依存関係インジェクション システムによって、登録されている ApplicationInsightsLoggerProvider
が自動的に破棄され、それにより TelemetryClient
がフラッシュされます。
バージョン 2.x
バージョン 2.x では、WebJobs SDK 用に Application Insights プロバイダーによって内部で作成された TelemetryClient
インスタンスで ServerTelemetryChannel
が使用されます。 Application Insights のエンドポイントが使用できない、または着信要求のスロットリングが行われている場合、このチャンネルが Web アプリのファイル システムで要求を保存して、後でこれらを再送信します。
TelemetryClient
は、ITelemetryClientFactory
を実装するクラスによって作成されます。 既定では、このクラスは DefaultTelemetryClientFactory
です。
Application Insights パイプラインの一部を変更する場合、独自の ITelemetryClientFactory
インスタンスを使用できます。 それにより、ホストは独自のクラスを使用して TelemetryClient
を構築します。 たとえば、次のコードでは DefaultTelemetryClientFactory
がオーバーライドされて、ServerTelemetryChannel
のプロパティが変更されます。
private class CustomTelemetryClientFactory : DefaultTelemetryClientFactory
{
public CustomTelemetryClientFactory(string instrumentationKey, Func<string, LogLevel, bool> filter)
: base(instrumentationKey, new SamplingPercentageEstimatorSettings(), filter)
{
}
protected override ITelemetryChannel CreateTelemetryChannel()
{
ServerTelemetryChannel channel = new ServerTelemetryChannel();
// Change the default from 30 seconds to 15 seconds.
channel.MaxTelemetryBufferDelay = TimeSpan.FromSeconds(15);
return channel;
}
}
SamplingPercentageEstimatorSettings
オブジェクトでは、アダプティブ サンプリングが構成されます。 この場合、特定の大規模なシナリオでは、Application Insights はテレメトリ データの選択されたサブセットをサーバーに送信します。
テレメトリ ファクトリを作成した後、Application Insights のログ プロバイダーにそれを渡します。
var clientFactory = new CustomTelemetryClientFactory(instrumentationKey, filter.Filter);
config.LoggerFactory = new LoggerFactory()
.AddApplicationInsights(clientFactory);
関連コンテンツ
この記事では、WebJobs SDK を操作するための一般的なシナリオを処理する方法を示すコード スニペットを提供します。 完全なサンプルについては、azure-webjobs-sdk-samples をご覧ください。