Slide 1

Slide 1 text

Listing Service: From Monolith to Microservices Taihei Morikuni Software Engineer (Backend)

Slide 2

Slide 2 text

Software Engineer Backend Taihei Morikuni

Slide 3

Slide 3 text

Listing Service: From Monolithic to Microservices

Slide 4

Slide 4 text

Listing Service ● Microservice for managing the listing function on Mercari ● This is the first project for transitioning from monolithic (PHP) to microservices (Go) ● Currently under development for one HTTP endpoint ● Use gRPC for connecting with other microservices

Slide 5

Slide 5 text

Strategy to Transition to Microservices Split services while maintaining API compatibility Enable independent development for each team ● The goal of transitioning to microservices is not to split the code, but to make a scalable organization ● Enable Canary Release by maintaining API compatibility, lowering the risk

Slide 6

Slide 6 text

● Implement only logic related to listings ● Link the portion left in PHP with Webhook Technological Strategy for Listing Service ● Automated app tests for the existing API app ● Manual checking by the QA team ● AQA team test tools (under development) Split services while maintaining API compatibility Enable independent development for each team

Slide 7

Slide 7 text

Challenges of Transitioning to Microservices Connecting from GCP to MySQL at Sakura Handling Additions/Modifications to Features Splitting of Transactions Compatibility with PHP Exceptions

Slide 8

Slide 8 text

Connecting from GCP to MySQL at Sakura ● Share PHP and DB until the transition to microservices has been completed ● In terms of security, don’t want to make MySQL ports available externally Problem Solution ● Develop the SQL on gRPC service and a Go library ○ In general, handle only CRUD, don’t handle Join and Transaction

Slide 9

Slide 9 text

Connecting from GCP to MySQL at Sakura message SelectRequest { repeated string columns = 1; string table = 2; Where where = 3; ... } message SelectResponse { repeated Row rows = 1; int64 count = 2; }

Slide 10

Slide 10 text

Connecting from GCP to MySQL at Sakura req := Select("id", "name", "age"). From("users"). Where(Eq("lang", "ja"), And(Gt("age", "18"))). OrderBy(ASC("created_at")). ToRequest() err := dbClient.Select(ctx, &user, req)

Slide 11

Slide 11 text

Splitting of Transactions ● Updates of items, shipping information, and analysis data were included in a single transaction Problem Solution ● For item data, Item Service (Sakura) will process the transaction ● For data that the user can see, process as much as possible within the request ● For internal data, aim for asynchronous eventual consistency using Cloud PubSub

Slide 12

Slide 12 text

Splitting of Transactions → Transaction: Unnatural if the item has been listed but there is no transaction → Synchronous: Unnatural if no image of the item was included → Asynchronous: No shipment until item sold → Asynchronous: Customer cannot see the data for analysis function listing() { $db->begin(); $item->save(); $photo->save(); $shipping->save(); $analysis->save(); $db->commit(); }

Slide 13

Slide 13 text

Handling Additions/Modifications to Features ● As listing is a core Mercari function, functions will be added and modified during the transition from PHP to Go Problem Solution ● Create an update tracking branch in the PHP repository, and delete the code transitioned to Go ○ If an update has been made, the code will conflict when merged ○ Once all of the code disappears the process is complete

Slide 14

Slide 14 text

Handling Additions/Modifications to Features function do_something() { if (is_x()) { return 1; } return hello(); } func DoSomething() int { }

Slide 15

Slide 15 text

function do_something() { if (is_x()) { return 1; } return hello(); } Handling Additions/Modifications to Features func DoSomething() int { if IsX() { return 1 } }

Slide 16

Slide 16 text

Handling Additions/Modifications to Features function do_something() { if (is_x()) { return 1; } return hello(); } func DoSomething() int { if IsX() { return 1 } return Hello() }

Slide 17

Slide 17 text

Handling Additions/Modifications to Features function do_something() { if (is_x() || is_y()) { return 1; } return hello(); } func DoSomething() int { if IsX() || IsY() { return 1 } return Hello() } Merge conflict!!

Slide 18

Slide 18 text

Handling Additions/Modifications to Features function do_something() { if (is_x() || is_y()) { return 1; } additional_process(); return hello(); } func DoSomething() int { if IsX() || IsY(){ return 1 } AdditionalProcess() return Hello() } Not migrated!!

Slide 19

Slide 19 text

Compatibility with PHP Exceptions ● A PHP exception name is included in the API response as an error code ○ The client is using PHP exception names ○ Must also return the PHP exception names from Go ● A part of the response JSON is different in each type of exception ● By transitioning to microservices, exceptions are also distributed out among each service ○ Each service must maintain compatibility with the PHP exceptions Problem

Slide 20

Slide 20 text

PHP Exception Compatiblity Solution ● Develop a shared Go library to maintain compatibility with PHP exceptions ● Add PHP exception information for handling errors in gRPC Status.details ● Retrieve the exception information from PHP-compatible HTTP endpoints, and directly generate the response JSON

Slide 21

Slide 21 text

PHP Exception Compatiblity func DoSomething(ctx context.Context, r *pb.Request) (*pb.Response, error) { ... if err != nil { s, err := exception.WithException(codes.NotFound, exception.NotFoundException) return nil, s.Err() } }

Slide 22

Slide 22 text

PHP Exception Compatiblity func HTTPServer(r http.ResponseWriter, r *http.Requeset) { res, err := client.DoSomething(ctx, &pb.Request{}) if err != nil { e, isException, err := exception.FromError(err) body, err := exception.ToJSON(e) r.Write(body) } }

Slide 23

Slide 23 text

Challenges of Transitioning to Microservices Connecting from GCP to MySQL at Sakura Handling Additions/Modifications to Features Splitting of Transactions Compatibility with PHP Exceptions

Slide 24

Slide 24 text

Summary ● In order to solve long-term problems (and not increase debt), we are keeping these issues in mind as we transition to microservices ● Because this is the first project for transitioning from monolithic (PHP) to microservices (Go), we haven’t fully organized our assets, meaning most parts of the process are difficult ● The pursuit of accuracy, when there is no correct answer, can be enjoyable ○ Believe in the setup in which I believe!

Slide 25

Slide 25 text

No content