Input Binding (入力バインディング)による連携
今まで、以下の流れで作業を行ってきました。今回はDaprに備わっているInput Binding (入力バインディング)の中でも、最もわかりやすいと思うスケジューラーによる定期実行に触れていきたいと思います。
今までの前提の上で入力バインディングの機能を追加しますので、このページから読まれている方は、前提として以下を読んできてください。
Input Bindingについて
Input Binding (入力バインディング)は、例えば5分毎(イベント)でサービスをコール(トリガ)してほしい、Azure Storage Queue / Amazon SQS / Apache Kafkaなど所謂キューに、enqueue(イベント)されたら、サービスをコール(トリガ)してほしいなどのケースで用いる事ができます。
イベントに対して、トリガされた処理を行う、Azure Functions や AWS Lambdaなどが、馴染み深いと思いますが、これらと同じような感じでイベントに対して処理を行う仕組みを構成する事ができます。
バインディングの一覧は、Input Binding (入力バインディング)、Output Binding (出力バインディング)共に以下に記載があります。
https://docs.dapr.io/reference/components-reference/supported-bindings/
Cron (Scheduler)バインディングを試す
これらのInput Binding (入力バインディング)で、最もシンプルなのはCron (Scheduler)だと思いますので、まずはCron (Scheduler)から試していきます。
プロジェクトを作成、追加
今まで作業してきた、ソリューションのルートフォルダに移動して新たにプロジェクトを追加して、そのプロジェクトのコントローラーを対象にバインディングを設定します。
dotnet new webapi -o WorkerService
dotnet sln add WorkerService
tye.yamlにプロジェクトを追加
忘れずにtye.yamlにもプロジェクトを追加して、daprをサイドカーとして起動するようにしておきましょう。ここでは、今までのYAMLにworker-serviceを追加している2行があります。
# tye application configuration file
# read all about it at https://github.com/dotnet/tye
#
# when you've given us a try, we'd love to know what you think:
# https://aka.ms/AA7q20u
#
name: dapr
extensions:
- name: dapr
# log-level configures the log level of the dapr sidecar
log-level: debug
# config allows you to pass additional configuration into the dapr sidecar
# config will be interpreted as a named k8s resource when deployed, and will be interpreted as
# a file on disk when running locally at `./components/myconfig.yaml`
#
# config: myconfig
# components-path configures the components path of the dapr sidecar
components-path: "./components/"
# If not using the default Dapr placement service or otherwise using a placement service on a nonstandard port,
# you can configure the Dapr sidecar to use an explicit port.
# placement-port: 6050
services:
- name: service-a
project: ServiceA/ServiceA.csproj
- name: service-b
project: ServiceB/ServiceB.csproj
- name: app
project: App/App.csproj
- name: stateservice
project: StateService/StateService.csproj
- name: worker-service
project: WorkerService/WorkerService.csproj
# This may conflict with the redis instance that dapr manages.
#
# Doing a `docker ps` can show if its already running. If that's the case
# then comment out out when running locally.
# - name: redis
# image: redis
# bindings:
# - port: 6379
componentフォルダにcron-binding.yamlファイルを追加
statestoreを扱った際に、statestore.yamlを追加したと思いますが、同じようにcron-binging.yamlを追加します。
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: Job # 呼び出されるコントローラーパス(JobController)
spec:
type: bindings.cron
version: v1
metadata:
- name: schedule
value: "@every 3s" # いわゆるCRON式です。* * *といったフォーマットも対応します。ここでは、3秒おきに実行しています。
scopes: # scopesでは、対象となるサービスを列挙して指定しています。
- worker-service
また、仕様を確認してみた所、POSTメソッドでの呼び出し固定となっています。
つまり、この場合/Job へPOSTの実装をJobControllerに行えばOKとなります。
プロジェクトの変更
プロジェクトを変更します。まず、このWorkerServiceでは WeatherForecast.cs と WeatherForecastController.csは使わないので削除してください。そして、新しくJobController.csとJobResponse.csを用意しました。
また、Program.csも忘れずに編集しましょう。
特に//app.UseHttpsRedirection();は必ずコメントアウトしてください。Dapr起動時にリダイレクトが走った結果、エラーが発生します。
using System.Diagnostics;
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
//app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
簡単ですが、レスポンス用のモデルを用意します。
namespace WorkerService;
public class JobResponse
{
public DateTime Date { get; set; }
}
JobController では、POSTされたら、簡単にDatetime.Nowを詰めてレスポンスをしています。
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace WorkerService.Controllers;
[ApiController]
[Route("[controller]")]
public class JobController : ControllerBase
{
private readonly ILogger<JobController> _logger;
public JobController(ILogger<JobController> logger)
{
_logger = logger;
}
[HttpPost(Name = "PostJob")]
public JobResponse Post()
{
JobResponse response = new JobResponse
{
Date = DateTime.Now
};
Console.WriteLine(response.ToString());
return response;
}
}
起動と確認
編集を終えたら、tye runで起動しましょう。
$ tye run
Loading Application Details...
Launching Tye Host...
[14:44:48 INF] Executing application from tye.yaml
[14:44:48 INF] Dashboard running on http://127.0.0.1:8000
[14:44:48 INF] Build Watcher: Watching for builds...
...
今までと同じ要領で、http://127.0.0.1:8000 をブラウザで開きましょう。
まず、worker-service-daprのログをViewから確認しましょう。
name: Job, schedule firedがあれば、Daprはスケジュールジョブをキックできています。
[worker-service-dapr_73c5055d-f]: time="2022-03-07T15:43:34.0106148+09:00" level=debug msg="name: Job, schedule fired: 2022-03-07 15:43:34.0106148 +0900 JST m=+141.014253101" app_id=worker-service instance=HX-90 scope=dapr.contrib type=log ver=1.6.0
worker-service側も確認してみましょう。

確認用にコンソールに出力していた結果が表示できていると思います。
[worker-service_75697214-b]: WorkerService.JobResponse





