Pub/Sub 트리거의 Cloud Functions를 Go로 만들 때는 pubsub.Message를 사용합시다.

배경



Cloud Functions에서 Go를 사용할 수 있게 되고 나서 상당히 지났기 때문에 자신도 사용해 보자고 생각했습니다만, Pub/Sub의 데이터 취득이 아무래도 능숙하지 않고 빠졌습니다.

그래서 비망록을 남겨 둡니다.

덧붙여서 Go는 초보자로 Cloud Functions로 만지기 시작한 정도의 레벨입니다.

기세 function 만들기



Cloud Functions에서 Go를 넣으려고 할 때 먼저 Cloud Functions 페이지에서 함수를 만들려고 할 것입니다.

런타임에 Go 1.11 , 트리거에 Cloud Pub/Sub 를 지정해 작성하면 디폴트로 이런 녀석을 써 둡니다. Google 친절!

cloud-functions
// Package p contains a Pub/Sub Cloud Function.
package p

import (
    "context"
    "log"
)

// PubSubMessage is the payload of a Pub/Sub event. Please refer to the docs for
// additional information regarding Pub/Sub events.
type PubSubMessage struct {
    Data []byte `json:"data"`
}

// HelloPubSub consumes a Pub/Sub message.
func HelloPubSub(ctx context.Context, m PubSubMessage) error {
    log.Println(string(m.Data))
    return nil
}

덧붙여서 트리거를 Pub/Sub로 하면 토픽도 지정할 필요가 있습니다.
이번에는 적절하게 go_pubsub_test 로 함수를 만듭니다.

Pub/Sub 주제에서 publish 테스트해보기



최근 GCP는 정말 편리하며, Pub/Sub 화면에서 message publish가 가능합니다.



테스트 메시지라는 것으로 메시지 본문에 hello world , 메시지 속성의 키에 key , 값에 value


functions측에서 이 메시지의 로그를 토출하도록 하고 있으므로, 아래의 公開 버튼을 눌러 publish 해 봅니다.

로그를 살펴보기



publish 에 성공하면(자) functions측의 호출 회수의 그래프가 튕겨집니다. 로그 표시를 눌러 logging으로 전환하면 로그가 나오는지 확인할 수 있습니다.



이것을 보면, 메세지 본체의 hello world 는 출력되고 있습니다만, key/value 의 정보는 보이지 않습니다.

이러한 것은 당연하고 이번에는 구조체 PubSubMessage로 메시지를 받았지만 PubSubMessage에는 Data가 없으므로 메시지 이외의 정보는 출력할 수 없습니다.

pubsub.Message 사용



여러가지 조사해 보면, 타이틀에 쓴 pubsub.Message라는 것이 나왔습니다.
type Message struct {
    // ID identifies this message.
    // This ID is assigned by the server and is populated for Messages obtained from a subscription.
    // This field is read-only.
    ID  string

    // Data is the actual data in the message.
    Data []byte

    // Attributes represents the key-value pairs the current message
    // is labelled with.
    Attributes map[string]string

    // The time at which the message was published.
    // This is populated by the server for Messages obtained from a subscription.
    // This field is read-only.
    PublishTime time.Time
    // contains filtered or unexported fields
}

여기에 다양한 정보가 들어있는 것 같습니다.
방금 설정한 keyvalue 에 대해서는 Attributes 로 취할 수 있게 됩니다.

코드 수정



그래서 이것을 이용하여 다른 message 정보도 출력할 수 있도록 해보겠습니다.

pubsub.Message는 cloud.google.com/go/pubsub에서 얻을 수 있습니다.

Cloud Functions에서 편집을 수행하고 다음과 같이 다시 작성합니다.
// Package p contains a Pub/Sub Cloud Function.
package p

import (
    "context"
    "log"
    "cloud.google.com/go/pubsub"
)

// HelloPubSub consumes a Pub/Sub message.
func HelloPubSub(ctx context.Context, m *pubsub.Message) error {
    log.Println(string(m.Data))
    if len(m.Attributes) > 0 {
        for k, v := range m.Attributes {
            log.Println("key", k)
            log.Println("value", v)
        }
    }
    return nil
}

배포하고 완료한 후 마찬가지로 topic을 보냅니다.



제대로 데이터를 취득할 수 있었습니다.

공식도 이것을 정의해 두었으면 합니다만, 분명 그 근처는 스스로 조사할 정도로 Pub/Sub 이해하지 않으면 사용하지 않는다는 메시지라고 생각합니다. 여드름.

덤: 메타데이터 정보 얻기



Cloud Functions에서는 metadata 라이브러리을 사용하여 다른 정보를 검색할 수 있습니다.

시험에 어떤 데이터를 얻을 수 있는지 로그를 내 보겠습니다.

cloud-functions
// Package p contains a Pub/Sub Cloud Function.
package p

import (
    "context"
    "log"
    "cloud.google.com/go/pubsub"
    "cloud.google.com/go/functions/metadata"
)

// HelloPubSub consumes a Pub/Sub message.
func HelloPubSub(ctx context.Context, m *pubsub.Message) error {
    // metadata
    meta, _ := metadata.FromContext(ctx)

    log.Println("EventID", meta.EventID)
    log.Println("Timestamp", meta.Timestamp)
    log.Println("EventType", meta.EventType)

    log.Println("Resource.Service", meta.Resource.Service)
    log.Println("Resource.Name", meta.Resource.Name)
    log.Println("Resource.Type", meta.Resource.Type)

    return nil
}

출력 결과는 다음과 같은 느낌입니다.



pubsub의 경우는 Resource.Typetype.googleapis.com/google.pubsub.v1.PubsubMessage 가 되어 오는 것 같네요.
또, 어느 topic으로부터 왔는지는 Resource.Name
metadata에 관해서는 pubsub 이외의 트리거도 취급할 수 있으므로 Resource.Type에 따라 처리를 바꾸는 것이 좋을 것 같습니다.

우선 알았던 것은 여기까지. 그 밖에도 알았던 적이 있으면 추기하려고 생각합니다.

좋은 웹페이지 즐겨찾기