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

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

Avatar for Hatena Hatena
October 18, 2023

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

Avatar for Hatena

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