serverless / event-gateway
- суббота, 19 августа 2017 г. в 03:14:06
The Event Gateway combines both API Gateway and Pub/Sub functionality into a single event-driven experience.
The Event Gateway combines both API Gateway and Pub/Sub functionality into a single event-driven experience. It's dataflow for event-driven, serverless architectures. It routes Events (data) to Functions (serverless compute). Everything it cares about is an event! Even calling a function. It makes it easy to share events across different systems, teams and organizations!
Use the Event Gateway right now, by running the Event Gateway Example Application locally, with the Serverless Framework.
Features:
The Event Gateway is a L7 proxy and realtime dataflow engine, intended for use with Functions-as-a-Service on AWS, Azure, Google & IBM.
Website • Newsletter • Gitter • Forum • Meetups • Twitter
The easiest way to get started with the Event Gateway is using the Serverless framework. The framework is setup to automatically download and install the Event Gateway during development of a serverless service.
Check out event-gateway example app for a walkthrough of using the Event Gateway locally.
If you want to install and develop with the Event Gateway without the framework, instructions can be found here.
Discover and call serverless functions from anything that can reach the Event Gateway. Function Discovery supports the following function types:
Function Discovery stores information about functions allowing the Eveng Gateway to call them as a reaction to received event.
curl --request POST \
--url http://localhost:4001/v1/functions \
--header 'content-type: application/json' \
--data '{
"functionId": "hello",
"provider":{
"type": "awslambda",
"arn": "arn:aws:lambda:us-east-1:377024778620:function:bluegreen-dev-helloa",
"region": "us-east-1"
}
}'
const eventGateway = fdk.eventGateway({ url: 'http://localhost' })
eventGateway.registerFunction({
functionId: "sendEmail"
provider: {
type: "awslambda"
arn: "xxx",
region: "us-west-2",
}
})
curl --request POST \
--url http://localhost:4000/ \
--header 'content-type: application/json' \
--header 'event: invoke' \
--header 'function-id: createUser' \
--data '{ "name": "Max" }'
const eventGateway = fdk.eventGateway({ url: 'http://localhost' })
eventGateway.invoke({
functionId: "createUser",
data: { name: "Max" }
})
Lightweight pub/sub system. Allows functions to asynchronously receive custom events. Instead of rewriting your functions every time you want to send data to another place, this can be handled entirely in configuration using the Event Gateway. This completely decouples functions from one another, reducing communication costs across teams, eliminates effort spent redeploying functions, and allows you to easily share events across functions, HTTP services, even different cloud providers. Functions may be registered as subscribers to a custom event. When an event occurs, all subscribers are called asynchronously with the event as its argument.
curl --request POST \
--url http://locahost:4001/v1/subscriptions \
--header 'content-type: application/json' \
--data '{
"functionId": "sendEmail",
"event": "user.created"
}'
const eventGateway = fdk.eventGateway({ url: 'http://localhost' })
eventGateway.subscribe({
event: "user.created",
functionId: "sendEmail"
})
curl --request POST \
--url http://localhost:4000/ \
--header 'content-type: application/json' \
--header 'event: user.created' \
--data '{ "name": "Max" }'
const eventGateway = fdk.eventGateway({ url: 'http://localhost' })
eventGateway.emit({
event: "user.created",
data: { name: "Max" }
})
Custom event subscriptions are asynchronous. There is a special http
event type for creating synchronous subscriptions.
http
event is a HTTP request received on specified path and for specified HTTP method.
curl --request POST \
--url http://locahost:4001/v1/subscriptions \
--header 'content-type: application/json' \
--data '{
"functionId": "listUsers",
"event": "http",
"method": "GET",
"path": "/users"
}'
const eventGateway = fdk.eventGateway({ url: 'http://localhost' })
eventGateway.subscribe({
functionId: 'listUsers',
event: 'http',
method: 'GET',
path: '/users'
})
The Event Gateway exposes an API for emitting events. Events API can be used for emitting custom event, HTTP events and
for invoking function. By default Events API runs on :4000
port.
All data that passes through the Event Gateway is formatted as an Event, based on our default Event schema:
event
- string
- the event nameid
- string
- the event's instance universally unique ID (provided by the event gateway)receivedAt
- number
- the time (milliseconds) when the Event was received by the Event Gateway (provided by the event gateway)data
- type depends on dataType
- the event payloaddataType
- string
- the mime type of data
payloadExample:
{
"event": "myapp.user.created",
"id": "66dfc31d-6844-42fd-b1a7-a489a49f65f3",
"receivedAt": 1500897327098,
"data": {"foo": "bar"},
"dataType": "application/json"
}
When an event occurs, all subscribers are called with the event in above schema as its argument.
The MIME type of the data block can be specified using the Content-Type
header (by default it's
application/octet-stream
). This allows the event gateway to understand how to deserialize the data block if it needs
to. In case of application/json
type the event gateway passes JSON payload to the target functions. In any other case
the data block is base64 encoded.
Endpoint
POST <Events API URL>/
Request Headers
Event
- string
- required, event nameContent-Type
- MIME type string
- payload typeRequest
arbitrary payload, subscribed function receives an event in above schema, where request payload is passed as data
field
Response
Status code:
202 Accepted
Creating HTTP subscription requires method
and path
properties. Those properties are used to listen for HTTP events.
Endpoint
<method> <Events API URL>/<path>
Request
arbitrary payload, subscribed function receives an event in above schema. data
field has the following fields:
{
...
"data": {
"headers": <request headers>,
"query": <request query params>,
"body": <request payload>,
"path": <request URL path>,
"method": <request method>
}
...
}
Response
Status code:
200 OK
with payload with function responseEndpoint
POST <Events API URL>/
Request Headers
Event
- string
- "invoke"
Function-ID
- string
- ID of a function to callRequest
arbitrary payload, invoked function receives an event in above schema, where request payload is passed as data
field
Response
Status code:
200 OK
with payload with function responseThe Event Gateway exposes a RESTful JSON configuration API. By default Configuration API runs on :4001
port.
Endpoint
POST <Configuration API URL>/v1/functions
Request
JSON object:
functionId
- string
- required, function nameprovider
- object
- required, provider specific information about a function, depends on type:
type
- string
- required, provider type: awslambda
arn
- string
- required, AWS ARN identifierregion
- string
- required, region nameawsAccessKeyID
- string
- optional, AWS API key ID. By default credentials from the environment are used.awsSecretAccessKey
- string
- optional, AWS API key. By default credentials from the environment are used.type
- string
- required, provider type: http
url
- string
- required, the URL of an http or https remote endpointResponse
Status code:
200 OK
on success400 Bad Request
on validation errorJSON object:
functionId
- string
- function nameprovider
- object
- provider specific information about a functionEndpoint
PUT <Configuration API URL>/v1/functions/<function id>
Request
JSON object:
provider
- object
- required, provider specific information about a function, depends on type:
type
- string
- required, provider type: awslambda
arn
- string
- required, AWS ARN identifierregion
- string
- required, region nameawsAccessKeyID
- string
- optional, AWS API key IDawsSecretAccessKey
- string
- optional, AWS API keytype
- string
- required, provider type: http
url
- string
- required, the URL of an http or https remote endpointResponse
Status code:
200 OK
on success400 Bad Request
on validation error404 Not Found
if function doesn't existsJSON object:
functionId
- string
- function nameprovider
- object
- provider specific information about a functionDelete all types of functions. This operation fails if the function is currently in-use by a subscription.
Endpoint
DELETE <Configuration API URL>/v1/functions/<function id>
Response
Status code:
204 No Content
on success404 Not Found
if function doesn't existsEndpoint
GET <Configuration API URL>/v1/functions
Response
Status code:
200 OK
on successJSON object:
functions
- array
of object
- functions:
functionId
- string
- function nameprovider
- object
- provider specific information about a functionEndpoint
POST <Configuration API URL>/v1/subscriptions
Request
event
- string
- event namefunctionId
- string
- ID of function to receive eventsmethod
- string
- optionally, in case of http
event, uppercase HTTP method that accepts requestspath
- string
- optionally, in case of http
event, path that accepts requests, it starts with "/"Response
Status code:
200 OK
on success400 Bad Request
on validation errorJSON object:
subscriptionId
- string
- subscription IDevent
- string
- event namefunctionId
- ID of functionmethod
- string
- optionally, in case of http
event, HTTP method that accepts requestspath
- string
- optionally, in case of http
event, path that accepts requests, starts with /
Endpoint
DELETE <Configuration API URL>/v1/subscriptions/<subscription id>
Response
Status code:
204 No Content
on success404 Not Found
if function doesn't existsEndpoint
GET <Configuration API URL>/v1/subscriptions
Response
Status code:
200 OK
on successJSON object:
subscriptions
- array
of object
- subscriptions
subscriptionId
- string
- subscription IDevent
- string
- event namefunctionId
- ID of functionmethod
- string
- optionally, in case of http
event, HTTP method that accepts requestspath
- string
- optionally, in case of http
event, path that accepts requestsDummy endpoint (always returning 200 OK
status code) for checking if the event gateway instance is running.
Endpoint
GET <Configuration API URL>/v1/status
The Event Gateway is NOT a FaaS platform. It integrates with existing FaaS providers (AWS Lambda, Google Cloud Functions, Azure Functions, OpenWhisk Actions). The Event Gateway enables building large serverless architectures in a unified way across different providers.
┌──────────────┐
│ │
│ Client │
│ │
└──────────────┘
▲
│
Event
│
▼
┌───────────────────────────────────────────────────────────┐
│ │
│ Event Gateway Cluster │
│ │
└───────────────────────────────────────────────────────────┘
▲
│
│
┌─────────────────────────────┼─────────────────────────────┐
│ │ │
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ AWS Lambda │ │ Google Cloud │ │Azure Function │
│ Function │ │ Function │ │ │
│ │ │ │ │ Region: │
│ Region: │ │ Region: │ │ West US │
│ us-east-1 │ │ us-central1 │ │ │
└───────────────┘ └───────────────┘ └───────────────┘
The Event Gateway instances use a strongly consistent, subscribable DB (initially etcd, with support for Consul, and Zookeeper planned) to store and broadcast configuration. The instances locally cache configuration used to drive low-latency event routing. The instance local cache is built asynchronously based on events from backing DB.
The Event Gateway is a horizontally scalable system. It can be scaled by adding instances to the cluster. A cluster is a group of instances sharing the same database. A cluster can be created in one cloud region, across multiple regions, across multiple cloud provider or even in both cloud and on-premise data centers.
The Event Gateway is a stateless service and there is no direct communication between different instances. All configuration data is shared using backing DB. If the instance from region A needs to call a function from region B the invocation is not routed through the instance in region 2. The instance from region A invokes the function from region 2 directly.
┌─────────────────────────────────────────────Event Gateway Cluster──────────────────────────────────────────────┐
│ │
│ │
│ Cloud Region 1───────┐ │
│ │ │ │
│ │ ┌─────────────┐ │ │
│ │ │ │ │ │
│ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│─ ▶│etcd cluster │◀ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│ │ │ │ │ │ │
│ │ │ └─────────────┘ │ │
│ │ ▲ │ │ │
│ │ │ │ │
│ Cloud Region 2───────┐ │ │ │ Cloud Regio│ 3───────┐ │
│ │ │ │ │ │ │ │ │
│ │ ▼ │ │ ▼ │ │ ▼ │ │
│ │ ┌───────────────┐ │ │ ┌──────────────┐ │ │ ┌──────────────┐ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │ │
│ │ │ Event Gateway │ │ │ │Event Gateway │ │ │ │Event Gateway │ │ │
│ │ │ instance │◀┼──────────┐ │ │ instance │◀─┼──────────┐ │ │ instance │ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
│ │ └───────────────┘ │ │ │ └──────────────┘ │ │ │ └──────────────┘ │ │
│ │ ▲ │ │ │ ▲ │ │ │ ▲ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ │ │ │
│ │ ▼ │ │ │ ▼ │ │ │ ▼ │ │
│ │ ┌───┐ │ │ │ ┌───┐ │ │ │ ┌───┐ │ │
│ │ │ λ ├┐ │ └───┼───────▶│ λ ├┐ │ └────┼───────▶│ λ ├┐ │ │
│ │ └┬──┘│ │ │ └┬──┘│ │ │ └┬──┘│ │ │
│ │ └───┘ │ │ └───┘ │ │ └───┘ │ │
│ └────────────────────┘ └────────────────────┘ └────────────────────┘ │
│ │
│ │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
SOA came along with a new set of challenges. In monolithic architectures, it was simple to call a built-in library or rarely-changing external service. In SOA it involves much more network communication which is not reliable. The main problems to solve include:
The following systems are solutions those problems:
The main goal of those tools is to manage the inconveniences of network communication.
The greatest benefit of serverless/FaaS is that it solves almost all of above problems:
Tools like Envoy/Linkerd solve different domain of technical problems that doesn't occur in serverless space. They have a lot of features that are unnecessary in the context of serverless computing.
Service discovery problems may be relevant to serverless architectures, especially when we have a multi-cloud setup or we want to call a serverless function from a legacy system (microservices, etc...). There is a need for some proxy that will know where the function is actually deployed and have retry logic built-in. Mapping from function name to serverless function calling metadata is a different problem from tracking the availability of a changing number of service instances. That's why there is a room for new tools that solves function discovery problem rather than the service discovery problem. Those problems are fundamentally different.