Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Board Review: ServiceBus (Python and JavaScript) #1046

Closed
richardpark-msft opened this issue Feb 26, 2020 · 2 comments
Closed

Board Review: ServiceBus (Python and JavaScript) #1046

richardpark-msft opened this issue Feb 26, 2020 · 2 comments
Assignees
Labels
architecture board-review Request for an Architectural Board Review

Comments

@richardpark-msft
Copy link
Member

richardpark-msft commented Feb 26, 2020

The Basics

About this client library

Artifacts required (per language)

Python

TypeScript

Champion Scenarios

Service Bus Client: Service Bus Receiver/Sender Client Proposal

The Service Bus client library offers two primary clients for sending and receiving messages, the ServiceBusSenderClient and ServiceBusReceiverClient respectively. Each designed for different operations but unified in their approach to provide a consistent experience for developers. These clients embrace a common design philosophy in providing developers an experience optimized around ease of use, familiar patterns, and a consistent API across them.

Both of the clients are designed to be user-friendly for someone who is new and does not know backend concept of Queue, Topics in details and also to some one who is coming from legacy concept of messaging.

Concepts
Namespace : A namespace is a scoping container for all messaging components. Multiple queues and topics can reside within a single namespace, and namespaces often serve as application containers.
Topics : You can also use topics to send messages. While a queue is often used for point-to-point communication, topics are useful in publish/subscribe scenarios. Enable an application to announce events to multiple interested consumers asynchronously.
https://docs.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber

image

Subscriptions : A subscriber to a topic can receive a copy of each message sent to that topic. Subscriptions are named entities.

Queue : Messages are sent to and received from queues. Queues store messages until the receiving application is available to receive and process them.

Enable multiple concurrent consumers to process messages received on the same messaging channel. This enables a system to process multiple messages concurrently to optimize throughput, to improve scalability and availability, and to balance the workload
https://docs.microsoft.com/en-us/azure/architecture/patterns/competing-consumers

image

Things to know before reading
• Some details not related to the high-level concept are not illustrated; the scope of this is limited to the high level shape and paradigms for the feature area.

Target segment: Regular , Middleware , DIY (Do it yourself) Developers

Regular Developers: Most of the developers write to Queue/Topic and read from Queue/Subscriptions. Their use case is simple but used a lot in production. For example Read one message, process it and go to next message.
Middleware Developers : These SDK writers who wrap Queue/ Topic in middle which are agnostic of server side concept or vendor agnostic. Their point of view is "send" or "receive".
DIY Developers: These are advance users who want to do everything on their own. For example message handling, exception handling, managing transactions etc.

Champion Scenarios
Scenarios 1 : Sender can send messages

A Real world existing application:
https://www.cloudamqp.com/blog/2017-09-25-breaking-down-a-monolithic-system-into-microservices.html
https://www.parkster.com/se/parking-with-parkster/

Parkster is company which provide solution for managing parking lots, payments, billing to large number of parking lots all over the world. Parkster started out with a monolithic architecture. They wanted to have their business model proven before they went further, so they started with one application which became monolithic . A monolithic application is where the whole application is built as a single unit. All code for a system is in a single codebase that is compiled together and produces a single system.
The biggest reason we moved from monolith to microservice were decoupling. Parkster’s move from a monolith architecture to a 15-20 microservice architecture. These multiple microservices communicating via message queues.

Once a parking spot is reserved by customer, One ReservationService will send a message to "ParkingLotManagerService" microservice using a queue.
image

ReservationService ------> ParkingLotManagementService

Message : (Spot 15) is reserved for 4 hours starting at 2 PM PST.

  • ReservationService has a guaranteed delivery to the queue.

  • Message sequence is not guaranteed unless queue is session enabled and client specify that.

  • The ParkingLotManagerService does not have to be online.

Exception case:
What if the receiver hangs/takes JUST long enough to not be able to renew before lock has expired and is claimed by another consumer? : Since the receiver did not renew lock before it expired, this message will be placed in queue and next customer can receive it.

Scenarios 2 : Receiver can receive messages

The ParkingLotManagerService should be able to receive messages asynchronously. The ParkingLotManagerService will receive one message at a time and update its system with start and end time for parking. It will also start a background timer which will inform other services when parking time slot expire.

  • There could be one or more competing consumers.
  • Receiver could manage message in queue i.e. complete, defer, abandon, and dead-letter
  • Receiver could Renew locks on messages and sessions in queues.
  • Receiver could peek-lock a message.
  • The receiver can indicate message processing is complete.

Message Locking: While this message is being processed , no other thread/process can process this same message.
Receive And Delete: Sometime a receiver do not want to lock the message, It will receive a message and service delete this message from Queue.

Example :If we have "AverageCustomerPerDayService" which count how many customer uses parking lot on average everyday. It will increase count by one for each message and if it fails to do for few messages it wouldn't cause company a fortune.

Exception Cases

  • If receiver takes longer time to process, the lock will be released and which makes this message available .

  • What if receiver crashes before if complete the message, this message will be made available to other receiver for processing?

Scenarios 3 : Middleware can Send and Receive messages agnostic of Topic/Queue

Some companies build middleware products where user does not care about service concept of Queue and Topics. And user just care about sending to or receiving from "Messaging System" without knowing how it is implemented.

Scenario 1 and 2 list all features needed for this scenario.

Scenarios 4 : Publisher can publish message to a topic

  • A publisher can send/publish a message to topic which can be consumed by one or more subscribers.

For Example "Order service" publishes an order.
"Order # 101,Category=Book, Name:Programming Server Side by Jeffery Richter, Number of books = 2, Price = $100.00"

Topic Name = "ORDER_TOPIC"

  • When the message is sent to topic it is guaranteed delivery.
  • The subscribers does not have to be online.
  • The sender does not know how many subscribers are there.

image

Scenarios 5: Subscriber can subscribe to a topic

Topic Name = "ORDER_TOPIC"
Subscriber 1 Name = "User_Service Subscriber"
Subscriber 2 Name = "Price Service Subscriber"
Subscriber 3 Name = "Delivery Service Subscriber"
Subscriber 4 Name = "HeavyProduct Delivery Service Subscriber"

  • There could be more than one subscriber.

  • Each subscriber gets their own copy of message.

  • A filter could be applied on a message. For example
    Subscriber 4 Name = "HeavyProduct Delivery Service SUBSCRIBER" Filter Rule = "Category == Appliance"

Above order will be received by first three subscriber but not by Subscriber 4 because it does not satisfy filter rule.
Other common uses cases for filter
Security : In some cases, we can restrict a subscriber to see one specific type of message.
Debugging : Some MS groups uses filter 1=1, to receive all the messages and determine why other subscriber are not receiving messages.

Scenarios 6 : Receiver can receive messages in sequence

A Real world existing application:
https://www.cloudamqp.com/blog/2017-09-25-breaking-down-a-monolithic-system-into-microservices.html
https://www.parkster.com/se/parking-with-parkster/

Once a parking spot is reserved by customer, ReservationService will send a message to ParkingLotManagerService using a queue. The customer changes mind with in few minutes and decide to cancel the reservation.

This scenario need FIFO which is only guaranteed when using sessions, since otherwise things would get messed up if we get the cancel message before the reserve message.

Lets say following is message sequence executed by consumer.

Message 1 : Spot 15 is reserved for 4 hours starting at 2 PM , Session ID ="SPOT-15"
Message 2 : Spot 15 reservation for 2 PM is cancelled, Session ID ="SPOT-15"

The ParkingLotManagerService will receive these message in sequence for Session ID ="SPOT-15".

Scenarios 7 : Receiver can receive messages in sequence for next available scenario

A Real world existing application:
https://www.cloudamqp.com/blog/2017-09-25-breaking-down-a-monolithic-system-into-microservices.html
https://www.parkster.com/se/parking-with-parkster/
Once a parking spot is reserved by customer, ReservationService will send a message to ParkingLotManagerService using a queue. There are multiple messages for different parking spots.

Lets say following is message sequence executed by consumer.

Message 1 : Spot 10 is reserved for 4 hours starting at 2 PM , Session ID ="SPOT-10"
Message 3 : Spot 15 reservation for 2 PM is cancelled, Session ID ="SPOT-15"
Message 2 : Spot 10 is extended for 2 more hours , Session ID ="SPOT-10"
Message 4 : Spot 15 reservation is cancelled , Session ID ="SPOT-15"

The ParkingLotManagerService request for "any" available session for processing
Service will pick next available session, for example Session ID ="SPOT-15".

Scenarios 8: Management Scenario
There are more operation which are management in nature.
Create Queue , Topic and Subscription
Add / Remove Rule/Filter
Note : No API are discussed for management scenario here but we noted them here as reference for completeness.

Agenda for the review

A board review is generally split into two parts, with additional meetings as required

Part 1 - Introducing the board to the service:

  • Review of the service (no more than 10 minutes).
  • Review of the champion scenarios.
  • Get feedback on the API patterns used in the champion scenarios.

After part 1, you may schedule additional meetings with architects to refine the API and work on implementation.

Part 2 - the "GA" meeting

  • Scheduled at least one week after the APIs have been uploaded for review.
  • Will go over controversial feedback from the line-by-line API review.
  • Exit meeting with concrete changes necessary to meet quality bar.
@richardpark-msft richardpark-msft added architecture board-review Request for an Architectural Board Review labels Feb 26, 2020
@adrianhall
Copy link
Member

Scheduled for 3/6

@kyle-patterson
Copy link
Member

Link to recording (MSFT INTERNAL): https://msit.microsoftstream.com/video/7ef3de47-5569-41d3-8f61-a42bbd758426

Notes from the review:
Javascript review:
Topic: New changes to javascript preview

  • Introduce serviceBusClient alongside receiverClient
  • Question: Are all languages going with a top-level client?
    -- Java may be going a slightly different way
  • In javascript, iterators are returning tuples with context, which is different from python
  • Scheduling and deferring messages are consistent with other languages

Topic: Diagnostics subnamespace

  • There is a method called peek(), which is better for diagnostics (doesn't respect locking, for example, or advance through a queue/subscription). The receiver now has a diagnostics property that contains peek()
  • Question: Why do we want to hide peek()
    -- It's right off the root of the client, shouldn't be building applications with peek() but rather peeklock().
  • Subnamespaces would fit well with "session" (and later "rule") functionality
  • PeekWithNoLock was considered, but you could index into a specific sequence number

RECOMMENDATION: Let other languages stay as they are, and let javascript use a subnamespace in preview 1. User studies should investigate the experience

Topic: Subscribe doesn't return a subscription

  • Might be different from EventHub
  • There is some term overloading going on, this may cause some confusion

RECOMMENDATION: Keep this similar to EventHubs in functionality. Subscribe() should return some sort of closeable

Topic: ContextWithSettlement deadletter overloads

  • Java and python don't have deadletter options

ACTION: Feature team needs to reconcile differences

Python review:
Topic: Changes to python preview

  • Introduce servicebusclient that retrieves senders and receivers
  • Senders and receivers are now separate concepts
  • Question: Is this going to be language specific, or should all languages adopt this paradigm?
    -- User studies show users are looking for this top client first, then diving in
  • Question: Should users create sender/receiver clients directly, or only through a top-level client?
    -- It's not conflicting to keep and expose both for advanced users vs elementary use cases
    -- Storage as an example shows we should allow instantiation of specific clients. Docs could cover use cases
  • Question: How do we manage the lifetime of connections?
    -- ServiceBusClient will open/close the connection implicitly
    -- Having two objects to manage the lifetime is problematic, it's likely users will reach for the subclient specifically
    -- There may be connection sharing in this approach
  • Question: Do other languages support directly creating senders/receivers?
    -- Currently no, but they could. This would require many overloads on subclient types, however

ACTION: Feature team to revisit connection lifecycle management

  • Question: Why are there different methods for getting senders?
    -- Currently Java/JS take a "queue_or_topic_name" into a single method
    -- This is not a python-specific problem

ACTION: Feature team to revisit decision for methods

  • Question: Should it be "get" or "create" receive/sender?
    -- Javascript uses create, but it should be using get; dotnet is using get; but java will be using build (because it is using a builder) (previously was "get")
    -- This is modeled after EventHubs

RECOMMENDATION: It should be "get"

Topic: Python is explicitly operating (complete()) on messages in iterator model.

  • Feedback from service team says method directly on message cannot be distinguished from a service operation vs a client operation
  • Python has concerns that receiver.method() may try to operate over other messages

ACTION: Python team to correct w.r.t consistency with other languages

  • Question: Is there a timeout in batch operations?
    -- Yes, it's just not included in the examples

  • Question: Should SessionID should be passed with the message object?
    -- Only python is attaching SID to messages
    -- Will other languages need to meet this use case?
    -- AppConfig and etags had a similar conversation, similar to EventHubs; it's not part of event data

ACTION: Feature team to sync on use case

  • Question: Why are timeouts in seconds, not milliseconds? Should we expose milliseconds?

ACTION: Feature team to sync with service team

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
architecture board-review Request for an Architectural Board Review
Projects
None yet
Development

No branches or pull requests

3 participants