$30 off During Our Annual Pro Sale. View Details »

かにさんタワーバトル

 かにさんタワーバトル

   🦀
  🦀
🦀🦀🦀 🦀
🦀🦀🦀🦀🦀🦀🦀
🦀🦀🦀🦀🦀🦀🦀🦀

sadnessOjisan

October 21, 2023
Tweet

More Decks by sadnessOjisan

Other Decks in Programming

Transcript

  1. 🦀 tower battle / Rust Tokyo 2023
    Yuta Ide (@sadnessOjisan)

    View Slide

  2. About me
    {
    “name”: “Yuta Ide”,
    “account”: “@sadnessOjisan”,
    “belong”: “Nikkei / Japanese News Paper Company”,
    “lang”: [“JS/TS(2018-)”, “Rust(2022-)”],
    “misc”: “rust.tokyo 2019 stuff”
    }

    View Slide

  3. Section0: About Nikkei

    View Slide

  4. Nikkei is a Japanese Newspaper Company
    https://www.nikkei.com/

    View Slide

  5. We adopt micro frontend architecture
    https://hack.nikkei.com/blog/denshiban-ssr/
    https://hack.nikkei.com/blog/denshiban-ssr/
    About Nikkei Denshiban (https://www.nikkei.com)

    View Slide

  6. We adopt micro frontend architecture
    CDN
    (Fastly)
    Node.js
    Article Detail
    Search
    Market
    Article Index
    connect by anchor tags
    We love HTTP and HTML

    handlebars
    handlebars
    VCL +
    handlebars
    react
    split with vertical
    aggregate

    View Slide

  7. https://hack.nikkei.com/blog/denshiban-ssr/

    View Slide

  8. We adopt micro frontend architecture
    CDN
    (Fastly)
    Node.js
    Article Detail
    Topic Index
    Search
    Market
    Article Index
    connect by anchor tags
    We love HTTP and HTML
    handlebars
    handlebars
    handlebars
    VCL +
    handlebars
    We maintain 24 micro frontend services
    with limited resource

    View Slide

  9. We adopt micro frontend architecture
    CDN
    (Fastly)
    Node.js
    Article Detail
    Topic Index
    Search
    Market
    Article Index
    connect by anchor tags
    We love HTTP and HTML
    handlebars
    handlebars
    handlebars
    VCL +
    handlebars
    We maintain 24 micro frontend services
    with Node.js v12 (current is v21)
    (Including tooling, we maintain 40↑ projects with old Node.js)

    View Slide

  10. We adopt micro frontend architecture
    CDN
    (Fastly)
    Node.js
    Article Detail
    Topic Index
    Search
    Market
    Article Index
    connect by anchor tags
    We love HTTP and HTML
    handlebars
    handlebars
    handlebars
    VCL +
    handlebars
    We are now replacing v12 → v16 → v18→ v20
    for 11 months 😇

    View Slide

  11. Updating Node.js and library is so hard
    ● Node.js releases a major update every 6 months. It is frequent.
    ● We must update Node.js version for EOL.
    ● After updating Node.js, sometimes (I often experience) fail npm install, or fail building app
    with bundler. Due to node-gyp, node-sass, --openssl-legacy-provider… 😭
    We need maintanability

    View Slide

  12. Should we follow the new lang and lib version?
    application
    With UI
    JSON API
    Developing
    Stable
    Sometimes it needs maintenance
    e.g. serious security patch, EOL
    We always doesn’t have to keep up with
    each new version.
    Always it needs maintenance

    View Slide

  13. Should we follow the new lang and lib version?
    application
    With UI
    JSON API
    Developing
    Stable
    Sometimes it needs maintenance
    e.g. serious security patch, EOL
    We always doesn’t have to keep up with
    each new version.
    Always it needs maintenance
    We considered replacing a new tech stack

    View Slide

  14. Our requirements for the new tech stack are…
    ● Typing
    ● Lint
    ● Test
    ● OAS (Open API Schema)
    ● Documentation / Gen Doc
    ● Clever pkg manager
    ● Error handling
    ● Logging / Tracing
    Rich and modern feature
    help our maintenance

    View Slide

  15. We want to replace it…
    The choice is…
    ● Node.js v20 + TypeScript + eslint + vitest
    ● Golang
    ● Rust
    How about Rust?

    View Slide

  16. Rust includes…
    ● Typing → strict typing. e.g. lifetime, no hatch except for unsafe
    ● Lint → Clippy
    ● Test → cargo test, in-source testing
    ● OAS → 3rd party lib. e.g. utopia
    ● Documentation / Gen Doc → cargo doc, utopia
    ● Clever pkg manager → cargo
    ● Error handling → Result. thiserror (de facto 3rd party lib)
    ● Logging / Tracing → tracing (de facto 3rd party lib)

    View Slide

  17. Rust with Nikkei
    Some teams at Nikkei adopted Rust in production
    ● Using Fastly Computing@Edge for delivery and handling access log.
    ○ access log server handles 6500 req/sec
    ● Wave BFF Server uses Rust for schemaful endpoint with gRPC and HTTP.
    ○ Wave: https://hack.nikkei.com/blog/advent20201218/
    So I’m in a good environment to choose Rust. But…

    View Slide

  18. Is choosing Rust appropriate?
    My concern is
    ● Rust is not batteries-included lang. We must choose 3rd party libs.
    ○ async runtime
    ○ web server
    ○ common util (serializer, date, …)
    ● Long-term stability of 3rd party ecosystems.

    View Slide

  19. But we chose Rust
    ● Rust itself is solid
    ● Although Rust is not batteries-included lang, there are many de facto libs. (e.g. tokio,
    thiserror, anyhow, chrono…)
    ● Rust can find breaking changes easily at compile time.

    View Slide

  20. We choose axum as Web FW
    ● hyper
    ○ primitive. I need router.
    ● actix-web
    ○ good choice
    ● axum
    ○ tokio-rs maintain this. I believe maintenance continue to
    If we choose a web fw, the choices are

    View Slide

  21. Section1: About Axum

    View Slide

  22. Hello World!

    View Slide

  23. Axum architecture
    ● Axum is HTTP Server FW.
    ● Axum = hyper + tower.
    hyper
    future
    future
    future
    future
    tower service call
    user req response
    tokio

    View Slide

  24. HTTP Server with Hyper
    ● Hyper is a tokio based HTTP library.
    ● It’s too primitive. (e.g. Hyper doesn’t have
    a router.)
    Hyper is not for web app developer
    but for library developer
    https://hyper.rs/

    View Slide

  25. Tower provides abstract of req → res
    ● Official description is `async fn(Request)
    -> Result`
    ● Tower provides a trait for creating middleware.
    ● HTTP Server can be described as composition
    of middlewares. Router, Auth, Logger, Retry,
    Rate Limit, Timeout, and so on.
    https://github.com/tower-rs/tower

    View Slide

  26. Service is a main concept of tower
    ● Service is an abstract model of
    processing req -> res.
    ● Main part is call function. This
    accepts a request and returns a
    response future.
    https://docs.rs/tower/latest/tower/trait.Service.html

    View Slide

  27. Layer can stack Services
    ● Each tower service should have a
    single role. (SRP of SOLID)
    ● User can combine services. In
    mental model, that’s stacking
    service on layer.
    requests
    |
    v
    +----- layer_three -----+
    | +---- layer_two ----+ |
    | | +-- layer_one --+ | |
    | | | | | |
    | | | handler | | |
    | | | | | |
    | | +-- layer_one --+ | |
    | +---- layer_two ----+ |
    +----- layer_three -----+
    |
    v
    responses
    https://docs.rs/axum/latest/axum/middleware/index.html

    View Slide

  28. LIVE READING
    axum depends on tower

    View Slide

  29. ● Router is a Tower Service in axum. call
    return Oneshot which is tower service
    and have handler Fn.
    ● Register path and handler
    ● Handler value is into HTTP Response,
    the converter is also tower service

    View Slide

  30. Router is a Tower Service in axum
    ● Router’s role is matching path,
    and execute handler.
    ● Router is implemented as tower
    Service. call finds matched
    path, and execute handler
    function. handler is also service.
    ● Router’s call return
    RouteFuture. This includes
    Oneshot struct which impl Future
    poll of calling handler service.
    https://docs.rs/axum/latest/axum/struct.Router.html

    View Slide

  31. Register path and handler
    ● Router is a KV store.
    ● key is path
    ● value is handler
    https://docs.rs/axum/latest/axum/struct.Router.html#method.route

    View Slide

  32. Handler value is into HTTP Response, the converter is also
    tower service
    ● Routing handler is a function. The return value
    can be HTTP Response with any Status Code.
    ● IntoResponse trait control it. str and Result
    and many struct has default IntoResponse
    impl. So, automatically convert to HTTP.
    ● Endpoint have MapResponse struct which has
    into_response Fn. MapResponse is also
    tower service. The service is called in polling
    Oneshot.
    HTTP/1.1 200 OK
    content-type: text/plain; charset=utf-8
    content-length: 13
    date: Thu, 19 Oct 2023 03:22:40 GMT
    Hello, World

    View Slide

  33. Section2: How to use axum

    View Slide

  34. I want to avoid tight coupling with axum
    ● Although axum is popular Web FW, it is 3rd party.
    ● Sometimes our app may fail updating axum version because of our wrong implement.

    View Slide

  35. How to avoid tight coupling with axum
    ● Introduce Layered architecture, don’t use axum except for controller
    ● Use tower service
    ● Create E2E test

    View Slide

  36. Introduce Layered Architecture
    ● Cargo can manage dependency graph through its
    workspaces feature.(e.g. controller cannot import
    repository)
    ● I recommend you split your application into modules
    as it grows
    ● And use axum only in controller and router.
    entity
    repository
    service
    usecase
    controller
    [package]
    name = "controller"
    [dependencies]
    axum = "0.6.20"
    entity = { path = "../entity" }
    usecase = { path = "../usecase" }

    View Slide

  37. Separation of cross-cutting concerns
    ● Separation of cross-cutting concerns with tower.
    ● Middleware is auth, logging, rate limit, delay, retry
    and so on.
    ● Any layer from any framework is reusable if it
    implements tower interface.
    axtix-web is not tower based FW. But
    that middleware is like tower service.
    https://actix.rs/docs/middleware

    View Slide

  38. Service is not only for tower
    https://tokio.rs/blog/2021-05-14-inventing-the-service-trait

    View Slide

  39. Case: Easily move to hyper
    ● Axum = hyper + tower
    ● We can use hyper directly
    ● service_fn transform function to Service
    ● Axum router’s handler is just function which
    return &str, Result and so on. It’s reusable.
    ● For hyper v1, it may need
    tower-hyper-http-body-compat. Service is
    general.
    can run axum
    router handler

    View Slide

  40. Conclusion
    ● Although developing HTTP server in Rust require 3rd party FW, Rust would be good
    choice.
    ● Most FW use simple function as router, so you can easily replace to each library.
    ● For replace, let’s adopt layered architecture, and use FW in only router and controller.
    ● About AOP logic, If we adopt tower interface, we may be able to replace to each library
    because other library also adopt tower or tower like Service. So I use tower based FW.

    View Slide