brightecapital/service-schema

微服务服务模式


README

Software license Version Download Build status Coverage

Service-schema 是一个工具,用于处理从代理或微服务之间的消息,实现了事件存储和 Saga 模式。基于“事件模式优先”的概念,service-schema 通过引入每个服务的模式来进一步提高效率,以便通过配置在不同事件中重复使用服务和模式。

  • 每个事件可能有一个或多个监听它的服务
  • 每个服务有一个模式,将用于验证输入的 JSON

配置

"require": {
        "brightecapital/service-schema": "^1.0.0"
    }

示例代码

configs

events.json

[
  {
    "event": "Users.afterSaveCommit.Create",
    "services": [
      "ServiceSchema\\Tests\\Service\\Samples\\CreateContact",
      "ServiceSchema\\Tests\\Service\\Samples\\CreateTask"
    ]
  },
  {
    "event": "Users.afterSaveCommit.Update",
    "services": [
      "ServiceSchema\\Tests\\Service\\Samples\\UpdateContact"
    ]
  }
]

在此 events.json 中

  • 微服务正在监听 02 个事件:“Users.afterSaveCommit.Create”,“Users.afterSaveCommit.Update”
  • 每个事件都有一个监听该事件的服务的列表

services.json

[
  {
    "service": "ServiceSchema\\Tests\\Service\\Samples\\CreateContact",
    "schema": "/jsons/schemas/CreateContact.json",
    "callbacks": [
      "ServiceSchema\\Tests\\Service\\Samples\\PushMessageToSqs",
      "ServiceSchema\\Tests\\Service\\Samples\\PushMessageToLog"
    ]
  },
  {
    "service": "ServiceSchema\\Tests\\Service\\Samples\\UpdateContact",
    "schema": "/jsons/schemas/UpdateContact.json",
    "callbacks": [
      "ServiceSchema\\Tests\\Service\\Samples\\PushMessageToLog"
    ]
  },
  {
    "service": "ServiceSchema\\Tests\\Service\\Samples\\CreateTask",
    "schema": "/jsons/schemas/CreateTask.json"
  }
]

在此 services.json 中

  • 有 03 个服务:“ServiceSchema\Tests\Service\Samples\CreateContact”,“ServiceSchema\Tests\Service\Samples\UpdateContact”,“ServiceSchema\Tests\Service\Samples\CreateTask”
  • 每个服务都有一个模式和一系列回调服务

服务模式

CreateContact.json

{
  "type": "object",
  "properties": {
    "event": {
      "type": "string",
      "minLength": 0,
      "maxLength": 256
    },
    "time": {
      "type": "string",
      "minLength": 0,
      "maxLength": 256
    },
    "payload": {
      "type": "object",
      "properties": {
        "user": {
          "type": "object",
          "properties": {
            "data": {
              "type": "object"
            },
            "class": {
              "type": "string",
              "default": "\\App\\Entity\\User"
            }
          },
          "required": [
            "data"
          ]
        },
        "account": {
          "type": "object",
          "properties": {
            "data": {
              "type": "object"
            },
            "class": {
              "type": "string",
              "default": "\\App\\Entity\\Account"
            }
          },
          "required": [
            "data"
          ]
        }
      },
      "required": [
        "user",
        "account"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "event",
    "payload"
  ],
  "additionalProperties": true
}

在此 CreateContact.json 中

  • 消息需要包含 "name" 和 "payload" 字段
  • "payload" 需要 "user" 和 "account" 字段
  • "user" 需要 "data" 字段
  • "account" 需要 "data" 字段

事件

$event = new Event();
$event->setName("Users.afterSaveCommit.Create");
$event->setTime("20190730123000");
$event->setPayload(["user" => ["data" => ["name" => "Ken"]], "account" => ["data" => ["name" => "Brighte"]]]);
$message = $event->toJson();
// '{"name":"Users.afterSaveCommit.Create","time":"20190730123000","payload":{"user":{"data":{"name":"Ken"}},"account":{"data":{"name":"Brighte"}}}}'
// this message is used to push to SQS or other services

服务

namespace ServiceSchema\Tests\Service\Samples;

use ServiceSchema\Event\Message;
use ServiceSchema\Event\MessageInterface;
use ServiceSchema\Service\Service;
use ServiceSchema\Service\ServiceInterface;

class CreateContact extends Service implements ServiceInterface
{
    public function consume(MessageInterface $event = null)
    {
        echo "CreateContact";

        return new Message();
    }
}

处理器

// Receive message from SQS or other services
$message = '{"name":"Users.afterSaveCommit.Create","time":"20190730123000","payload":{"user":{"data":{"name":"Ken"}},"account":{"data":{"name":"Brighte"}}}}';
// config the Processor
$processor = new Processor(["events.json"], ["services.json"], "serviceSchemaDir");
// process the message
$result = $processor->process($message);
/*
 * In this example, event "Users.afterSaveCommit.Create" has 02 services listening to it (configued in events.json)
 * "ServiceSchema\\Tests\\Service\\Samples\\CreateContact", "ServiceSchema\\Tests\\Service\\Samples\\CreateTask"
 * When $processor->process(message): CreateContact->run(Event) and CreateTask->run(Event) will be executed.
 * Service CreateContact has 02 callback services (configured in services.json): 
 * "ServiceSchema\\Tests\\Service\\Samples\\PushMessageToSqs","ServiceSchema\\Tests\\Service\\Samples\\PushMessageToLog"
 * When CreateContact->run(Event) returns an Event then PushMessageToSqs->run(Event) and PushMessageToLog->run(Event) will be executed
 */

UUID

使用 Ramsey/Uuid 生成事件 ID

测试

请参阅测试,了解事件、服务、模式和处理器使用的示例配置

  • tests/jsons/configs/events.json:事件的配置
  • tests/jsons/config/services.json:服务的配置
  • tests/jsons/configs/schemas/:示例服务模式(CreateContact.json、CreateTask.json、UpdateContact.json)
  • tests/Main/ProcessorTest.php:如何配置和运行处理器