我們的系統中或多或少都會用到如下兩類業務技術:
異步任務,用于降低接口時延或削峰,提升用戶體驗,降低系統并發壓力;
通知類RPC,用于微服務間狀態變更,用戶行為的聯動等場景;
以上兩種場景,都十分適合使用事件驅動來實現。
但是對于事件的描述,現在還缺乏一種統一描述,服務使用方和提供方往往要花費大量的時間溝通字段定義,憑直覺設計事件屬性,并在將來的使用過程中會因為新增或修改事件的屬性而增加很大的額外工作量。
隨著云原生的到來,急需一種統一的事件定義和描述規范,以提供跨服務、跨平臺的交互能力,而這就是CloudEvents項目的誕生背景。
CloudEvents是一個用通用格式描述事件數據的規范,以提供跨服務、跨平臺和跨系統的互操作性。目前得到了大量的行業關注,從主要的云提供商到流行的SaaS公司都有。CloudEvents由云原生計算基金會(CNCF)主辦,于2018年5月15日獲批為云原生沙盒級項目。
https://github.com/cloudevents?概要地描述其標準如下:
Event描述
Event: 描述Occurrence的數據,包括data和context。
Data:最主要的業務數據,由使用者定義。
Context:上下文屬性,可以理解成發送event時候的環境信息。用來標識事件與系統或其他事件之間的關系。
Data描述
業務相關的信息都封裝在數據屬性中,由業務方自行約定,
一般來說,都是業務model,比如protobuf,這樣可以更好的管理。
data: {"metadata": {"name": "event-display.15a0a2b54007189b","namespace": "default","selfLink": "/api/v1/namespaces/default/events/event-display.15a0a2b54007189b","uid": "9195ff11-7b9b-11e9-b1f1-00163f005e02","resourceVersion": "18070551","creationTimestamp": "2019-05-21T07:39:30Z"},"involvedObject": {"kind": "Route","namespace": "default","name": "event-display","uid": "31c68419-675b-11e9-a087-00163e08f3bc","apiVersion": "serving.knative.dev/v1alpha1","resourceVersion": "9242540"},"reason": "InternalError","message": "Operation cannot be fulfilled on clusteringresses.networking.internal.knative.dev \"route-31c68419-675b-11e9-a087-00163e08f3bc\": the object has been modified; please apply your changes to the latest version and try again","source": {"component": "route-controller"},"firstTimestamp": "2019-05-21T07:39:30Z","lastTimestamp": "2019-05-26T07:10:51Z","count": 5636,"type": "Warning","eventTime": null,"reportingComponent": "","reportingInstance": ""}
Context描述
必選(REQUIRED)參數:
id:事件唯一編號,如UUID
source:數據源信息,用來區別發送方
specversion:使用的cloudEvents規范版本,如0.2
type:發送方定義的事件類型,可以用來過濾和轉發,通常此屬性用于路由、監控、安全策略等
可選(OPTIONAL)參數:
datacontentencoding:數據屬性的編碼格式
datacontenttype:數據屬性的解析方式,從json擴展到其他可選類型
schemaurl:數據的schema地址
subject:事件的主題,類似MQ里的topic
time:事件發生的時間戳
extions:擴展能力,在實現中是個List<Extension>樣式,Extension是個接口由使用方實現
示例
官方目前提供了9種語言的SDK,極大方便開發人員進行集成開發。在業界,已有包括谷歌、AWS、微軟、阿里云、騰訊云等開始使用CloudEvents規范向用戶提供云平臺內的事件通知。
下面使用sdk-go進行簡單的使用示范。
事件接收端:
func Receive(event cloudevents.Event) {fmt.Printf("event info: %v", event)
}func main() {c, err := cloudevents.NewDefaultClient()if err != nil {log.Fatalf("failed to create client, %+v", err)}log.Fatal(c.StartReceiver(context.Background(), Receive));
}
事件發送端:
func main() {t, err := cloudevents.NewHTTPTransport(cloudevents.WithTarget("xxx"),cloudevents.WithEncoding(cloudevents.HTTPBinaryV02),)if err != nil {log.Fatal("failed to create transport, err: %+v ", err)}c, err := cloudevents.NewClient(t)if err != nil {log.Fatal("failed to create client, err: %+v", err)}event := cloudevents.NewEvent()event.SetID("11111")event.SetType("com.cloudevents.ts.test")event.SetSource("xxx")data := NewXXX()event.SetData(data)if err := c.Send(ctx, event); err != nil {log.Fatal("failed to send cloudevent, err: %+v", err)}
}