Upgrade to Pro — share decks privately, control downloads, hide ads and more …

はてなリモートインターンシップ2023 Web API 講義資料

Hatena
October 18, 2023

はてなリモートインターンシップ2023 Web API 講義資料

Hatena

October 18, 2023
Tweet

More Decks by Hatena

Other Decks in Programming

Transcript

  1. この講義で取り扱うもの • ⽬次 • API • Web API • REST

    • GraphQL • gRPC • コードを少し触ります
  2. API の例 • システム 対 アプリケーション画像 • libdrm : 描画

    • DRM(カーネル)を動かすための API • glibc : システムコール • 直接起動するのではなくラッパー関数を呼び出す • ブラウザ 対 Web アプリケーション • document.getElementById : 要素取得 • ブラウザなど 対  Web サーバー : Web API • REST • curl -s https:!"random.dog/woof.json 画像 This image is licensed under the Creative Commons Attribution- Share Alike ;.= International license. Attribution: Shmuel Csaba Otto Traian. source https://commons.wikimedia.org/wiki/ File:Linux_API.svg
  3. Web API の設計指針 • LSUDs (Large Set of Unknown Developers)

    • 最⼤公約数的な API を提供する • SSKDs (Small Set of Known Developers) • クライアントに最適化した API を提供する
  4. REST • Representational State Transfer • HTTP の仕組みをうまく使う • ⼀意な

    URI を持つ • https:!"api.github.com/repos/hatena/example/ issues/1 • 提唱者である Roy T. Fielding ⽒の 2000 年頃の論⽂
  5. GitHub のイシューコメント(再掲) • GET /repos/:owner/:repo/issues/ comments/:comment_id • POST /repos/:owner/:repo/issues/:issue_number/ comments

    • PATCH /repos/:owner/:repo/issues/ comments/:comment_id • DELETE /repos/:owner/:repo/issues/ comments/:comment_id
  6. OpenAPI • Open API Spesification の略称 • Swagger • 元々

    Swagger フレームワークの⼀部だったという歴史がある • REST API を記述するための仕様 • YAML や JSON で API の仕様を記述できる • ツールを使ってそのままドキュメントやコード⽣成をすることも できる
  7. SDL (Schema Definition Language) interface Actor { login: String! }

    type Issue { author: Actor body: String! title: String! } type Repository { issue(number: Int!): Issue } type Query { repository(name: String!, owner: String!): Repository }
  8. gRPC • RPC • Remote Procedure Call の略 • gRPC

    • Google が開発したプロトコル • IDL をもとにしてサーバーおよびク ライアントの雛形を作成するのが特 徴 • g の意味はバージョンごとに違う
  9. gRPC over HTTP/- • HTTP/& 上に構築されたもの • HEADERSフレームやDATAフレームを使って通信する • 1

    つの TCP コネクション内に複数のストリームを持つことが できる
  10. Protocol Buffers • 構造化されたデータをシリアライズする仕組み • バイナリフォーマット • IDL (Interface Description

    Language) • .protoファイル • gRPC のデフォルトの IDL • RPC をサポートしている
  11. proto ファイルの例 syntax = "proto3"; package account; service Account {

    rpc Signup(SignupRequest) returns (SignupReply); } message SignupRequest { string name = 1; string password = 2; } message SignupReply { string token = 1; }
  12. メッセージ型 message SignupRequest { string name = 1; string password

    = 2; } ϑΟʔϧυܕ ϑΟʔϧυ໊ = ϑΟʔϧυ൪߸; • フィールド番号が重要 • シリアライズ時にはこのフィールド番号が使われる • 1-15 までは 1byte(16 〜 2047 は 2byte) • 19000-19999 は内部実装で予約済み
  13. その他の proto の⽂法 (1) repeated で配列を表現することができる message Result { repeated

    int32 score = 1; } map で辞書構造を表現できる map<string, Project> projects = 3; map は厳密には型ではくシンタックスシュガーで下記の構⽂と糖化です message MapField { key_type key = 1; value_type value = 2; } repeated MapField map_field = 1;
  14. その他の proto の⽂法 (3) enum も定義できる message SearchRequest { string

    query = 1; int32 page_number = 2; int32 result_per_page = 3; enum Corpus { UNIVERSAL = 0; WEB = 1; IMAGES = 2; LOCAL = 3; NEWS = 4; PRODUCTS = 5; VIDEO = 6; } Corpus corpus = 4; }
  15. 外部ファイルの import import "google/protobuf/any.proto"; message Message { google.protobuf.Any field =

    1; } • google.protobuf.Empty • google.protobuf.Duration • google.protobuf.Timestamp
  16. オプション option go_package = "github.com/hatena/example/pb"; enum EnumAllowingAlias { option allow_alias

    = true; UNKNOWN = 0; STARTED = 1; RUNNING = 1; } message Example { int32 old_field = 6 [deprecated = true]; }
  17. サービスとストリーム service RouteGuide { rpc GetFeature(Point) returns (Feature) {} rpc

    ListFeatures(Rectangle) returns (stream Feature) {} rpc RecordRoute(stream Point) returns (RouteSummary) {} rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} }
  18. RPC の種類 (1) • Unary RPCs (SimpleRPC) • single request

    single response • シンプルな通信 • Server streaming RPC • クライアント側はすべてのメッセージを受信すると処理を完 了する
  19. RPC の種類 (2) • Client streaming RPC • クライアント側は複数のメッセージを送り単⼀のメッセージを受 信する

    • Bidirectional streaming RPC • 双⽅向ストリーミングのこと • クライアント側とサーバー側のストリームは独⽴している • そのためそれぞれ任意の順序でメッセージの読み書きができる
  20. gRPC における API 設計 CRUD + List • CreateEntity •

    GetEntity • UpdateEntity • DeleteEntity • ListEntities
  21. Cloud Functions の例 • CallFunction • CreateFunction • GetFunction •

    UpdateFunction • DeleteFunction • ListFunctions
  22. proto ファイル まずは proto ファイルを作成して定義をしていきます syntax = "proto3"; option go_package

    = "./pb"; package welcome; service Welcome { rpc Greet(GreetRequest) returns (GreetReply); } message GreetRequest { string name = 1; } message GreetReply { string message = 1; }
  23. Protocol Compiler # protoc ͷηοτΞοϓ $ sudo apt update $

    sudo apt install protobuf-compiler # macͷ৔߹ $ brew install protobuf # goͷϓϥάΠϯΛΠϯετʔϧ $ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
  24. Protocol Compiler で Go の定義を書き出す $ mkdir pb $ protoc

    !"go_out ./pb \ !"go-grpc_out ./pb \ !"go_opt=paths=source_relative \ !"go-grpc_opt paths=source_relative welcome.proto
  25. Protocol Compiler で Go の実装 (1) package main import (

    "context" "fmt" "grpc_adventure/pb" !" module໊/σΟϨΫτϦ໊ "log" "net" "os" "os/signal" "google.golang.org/grpc" "google.golang.org/grpc/reflection" )
  26. Protocol Compiler で Go の実装 (2) type welcomeServer struct {

    pb.UnimplementedWelcomeServer } func (s *welcomeServer) Greet( ctx context.Context, req *pb.GreetRequest, ) (*pb.GreetReply, error) { return &pb.GreetReply{ Message: fmt.Sprintf("Welcome %s", req.Name), }, nil } func newServer() *welcomeServer { return &welcomeServer{} }
  27. Protocol Compiler で Go の実装 (3) func main() { port

    !" 10000 lis, err !" net.Listen("tcp", fmt.Sprintf(":%d", port)) if err !# nil { log.Fatalf("failed to listen: %v", err) } grpcServer !" grpc.NewServer() pb.RegisterWelcomeServer(grpcServer, newServer()) reflection.Register(grpcServer) go func() { log.Printf("start gRPC server port: %v", port) grpcServer.Serve(lis) }() quit !" make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) !$quit log.Printf("stopping gRPC server!!%") grpcServer.GracefulStop() }
  28. grpcurl # grpcurl ͷ install go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest # αʔϏεͷҰཡ

    grpcurl -plaintext localhost:10000 list # ϝιου΍ܕͷৄࡉ grpcurl -plaintext localhost:10000 describe welcome.Welcome.Greet grpcurl -plaintext localhost:10000 describe welcome.GreetRequest # αʔϏεͷݺͼग़͠ grpcurl -plaintext -d '{"name": "John Appleseed"}' localhost:10000 welcome.Welcome/Greet