AAC : Best Practices - amitbhilagude/userfullinks GitHub Wiki
- Best Practices
-
Rest API Design
- API naming conventions /orders/ or /orders/{id}. IT may have nested conventions e.g. /customers/{id}/orders
- Each convention may have Post, Put, and PATCH except no post for {id}.
- Difference between PUT and PATCH. Put will be updating existing resources or creating new ones if not exist. PATCH is a partial update that can update existing.
- HTTP protocol, formats are specified through the use of media types, also called MIME types. For non-binary data, most web APIs support JSON (media type = application/JSON) and possibly XML. This is passed using the Content-Type header in a request or response.
- Versioning
- URI Versioning e.g. https://adventure-works.com/v2
- Query String versioning e.g. https://adventure-works.com/customers/3?version=2
- Header versioning e.g. API-version=1
-
Web API Implementation
- GET, PUT, DELETE, HEAD, and PATCH actions should be idempotent. That means we should be able to call this any number of types for the same resources. E.g. First DELETE will return as 204(No contents) and subsequent delete will return 404(Not found). Head is used for partial contents.
- Use appropriate HTTP Status code Response. More details are added here
- Support content negotiation: Request for content-type with specific format, Make it default format if not explicitly mentioned,
- Provide links to support HATEOAS-style: Add link in the response if you have APIs to get additional details. E.g. Customer response may have get order Get request link
- Support of Client Side caching: Send response header Cache-Control which gives information how long data can be cached e.g. Cache-Control: max-age=600, private
- Etag: An ETag is an opaque string that indicates the version of a resource; each time a resource changes the ETag is also modified. Client can send If-Match: ETag value, If it matched then next operation will be performed to handle the concurrency.
- Handle Large binary object using Chunks or compressed data by passing Accept-Encoding: gzip request header.
- Large numbers of object to support the paginations.e.g. https://www.adventure-works.com/api/orders?limit=30&offset=50
- Sending response back to the Client from Server options
- WebSocket/Server Sent Event/ Long Polling/gRPC
- Azure Signalr
- Azure Notification Hub
- Comet (Good for old browser, new browser has above option)
-
Autoscaling
- Types: Horizontal and Vertical Autoscaling.
- Scale in and Scale-out: Decrease the instance and increase the instance.
- VM Autoscaling : Virtual Machine Scale Set
- Service Fabric Autoscaling : Virtual Machine Scale Set
- Azure App Service: has built-in autoscaling with rules.
- Azure Monitor Autoscale: provides a common set of autoscaling functionality for virtual machine scale sets, Azure App Service, and Azure Cloud Service. Scaling can be performed on a schedule, or based on a runtime metric, such as CPU or memory usage.
-
Background Jobs
- Options to trigger Background Jobs
- Event-Triggered
- Scheduled
- API to give input which will initiate another task.
- Option to inform called that background job is done
- Introduce storage which will keep the status and other information to return. Polling to check the status
- Request-Response pattern in Service Bus
- Callback to the UI using Push notification or Webhooks
- Technology choice
- Web job : -> Not available in AWS. Need to go alternate options
- Run continuously to receive event trigger from queue e.g. Service bus.
- Can run on Schedule
- Can set as a single-ton
- Recommended to choose separate app service and plan to avoid impact on existing app service.
- Azure function -> Lambda.
- Trigger and schedule options for a short run.
- Virtual Machine -> EC2
- Azure Batch -> AWS Batch
- Used for High-performance load
- AKS -> EKS
- Hangfire NuGet package for .net application
- Web job : -> Not available in AWS. Need to go alternate options
- Options to trigger Background Jobs
-
Caching
- Private and Shared Cache: Private cache is the memory used of the same Application Server. A shared cache is an external Server that can be used by any other application. ASP.Net core supports the IMemoryCache interface to use a private cache. Redis cache is a shared cache.
- Cache expiry will support Absolute expiry(Upper bound) and Sliding expiry. If sliding expiry is set cache gets expiry if it is not accessed in sliding expiry time. If it is accessed then it will expire in the absolute expiry time.
- Cache uses fixed memory by plan choose, if it gets exceeded due to a lot of data, It follows Least Recently uses(LRU) policy to remove the key.
- If Client-side caching is used e.g. Brower then there is no way to expire it. The option here is to Use URI or versioning so it will point to the new one.
- Redis cache can be used to store ASP.Net core session or Html output.
- Redis cache supports Batch update or get. The update doesn't impact the performance due to the async nature.
- Redis cache support to fetch the recently accessed items. (Algo combination of LinkedList and HashSet)
- Redis cache support sorting mechanism.
- Redis cache supports pub-sub pattern.
- AWS Elastic cache supports Cache for Redis and in-memory cache
-
CDN
- Versioning: New version of the release can be managed by adding a different folder in a container so that URI will be changed or set the TTL
- Performance can be improved by additional caching features like compressions
- Security can be managed by enabling CORS
- CDN authentication to allow trusted web app can access to it using Token authentication system. Access token retrieves from web app is passed to CDN endpoint for every request.
-
Data Partitioning
- Designing Partition
- Horizontal Partition: It is called sharding. Each partition is sub-data. E.g. SQL Server Sharding where Two tenants' data are single table but isolated with shard map and row-level security.
- Vertical Partition: Each partition is a subset of fields E.g. Tables is split into tables with frequent access data in one table
- Functional Partition: Separate tables based on entities E.g. Customer and Order in two different tables if not required in a single query.
- Benefits: Used to separate data can be stored in different stores if they don't in a single query. Easy to scale out if it grows.
- SQL Server Partitioning
- e.g. Multi tenanted architecture with sharding uses a single database for multiple tenants and with the help, Elastic database Client Library and ShardMap managed request is routed. Option to store small size tenant into single DB and Large tenant into dedicated DB with future migration support. The partition key is Tenant Id here
- Azure Table Storage Partitioning -> Dynamodb in AWS
- Partition key is PartitionKey and Row key which is unique within Partition.
- To support the scalability by adding another Azure Table.
- Azure Blob Storage Partitioning -> S3 in AWS
- Partition key is account name + container name + blob name
- If your naming scheme uses timestamps or numerical identifiers, it can lead to excessive traffic going to one partition, limiting the system from effectively load balancing. Instead, consider prefixing the name with a three-digit hash
- Types of Blob
- Block Blob: Used for Large binary objects. Use block blobs in scenarios when you need to upload or download large volumes of data quickly. Block blob can have any block of size from 64 KB to 100 MB. It will also allow in GBs
- Page BLob: Used page blobs for applications that require random rather than serial access to parts of the data. Blob size will be 4 MB only.
- Append BLob: An append blob of the same size as Block blob is composed of blocks and is optimized for append operations. When you modify an append blob, blocks are added to the end of the blob only.e.g add logs will have only spend this is best.. Blob Size from 64 KB to 4 MB.
- Azure Storage Queue Partitioning -> Simple Queue Service(SQS)
- Azure Storage queue partitioning based on Queue name.
- An Azure storage queue can handle up to 2,000 messages per second. If you need to process messages at a greater rate than this, consider creating multiple queues
- Azure Service Bus Partitioning -> Simple Notification Service(SNS)
- Azure Service partitioning can be enabled by EnablePartitioning property
- Enable partitioning will help to use separate message stores and message brokers. By Default, each queue or topic uses a single message broker. The service bus takes care of managing fragments for each message and which store and broker to use. Service bus identifies it based on SessionId, PartitionKey, and MessageId. the same id is sent to the same fragment.
- Cosmos DB partitioning -> DynamoDB
- Based on Partition Key per collection
- Fixed-sized container with same partition key data has a max of 20 GB of data. If required max size, Create unlimited container. But always define the correct partition key to exceed the limit.
- Azure Search Partition (Elastic Search)
- Azure Search can be divided into 1, 2, 3, 4, 6, or 12 partitions, and each partition can be replicated up to 6 times. The product of the number of partitions multiplied by the number of replicas is called the search unit (SU). A single instance of Azure Search can contain a maximum of 36 SUs (a database with 12 partitions only supports a maximum of 3 replicas). Search unit is used for cost unit calculations
- Redis cache partitions
- Partitioning a Redis data store involves splitting the data across instances of the Redis service. Each instance constitutes a single partition. Azure Cache for Redis abstracts the Redis services behind a façade and does not expose them directly. The simplest way to implement partitioning is to create multiple Azure Cache for Redis instances and spread the data across them.
- Partitioning Service Fabric (AWS Mesh)
- Mostly used for the reliable collection data store.
- Partitionong Azure Event Hub
- It is used for massive events and can be partitioned per publisher. Each consumer only reads a specific partition of the message stream.
- Designing Partition
-
Messaging Encoding Format
- Message sends through service but supports the different formats. Type of message sent by Sender receives deserialize it with multiple options.
- Metadata in Message: The message payload itself have details about the type of each field so that receiver can deserialize it based on it.
- Schema: Message models will be defined in sender and receiver or Shared schema will be stored in a shared place and Payload has the URL to fetch it.
- Required versioning mechanism for the schema to avoid breaking changes.
- Messaging format commonly used JSON, CSV, Apache Avro, and MessagePack.
- Message sends through service but supports the different formats. Type of message sent by Sender receives deserialize it with multiple options.
-
Monitoring and diagnostics guidance
- Common scenarios
- Ensuring that the system remains healthy
- Tracking the availability of the system
- Maintaining performance to ensure that the throughput of the system does not degrade
- Guaranteeing that the system meets any service-level agreements (SLAs)
- Protecting the privacy and security of the system, users, and their data.
- Tracking the operations that are performed for auditing or regulatory purposes.
- Monitoring the day-to-day usage of the system and spot trends.
- Tracking issues that occur, from the initial report.
- Tracing operations and debugging software releases.
- Common scenarios
-
Retry Guidance for the Services
- Azure Active Directory
- Azure Active Directory retrieves Status code with description in Authroise and Token Points to take action accordingly.
- Built-in Retry mechanism in MSAL library.
- Cosmos DB
- CosmosDBClient has a built-in retry mechanism which is passed as CosmosClientOptions. It option to how many times retry and time to retry after x seconds.
- Cosmos DB retry attempt can be captured in logs by enabling TraceListener in Appsettings.json
- EventHub
- EventHubClient class has RetryPolicy property
- Azure Cache for Redis
- StackExchange.Redis has multiple retry options.
- Azure Search
- SearchServiceClient and SearchIndexClient has SetRetryPolicy.
- Azure Service Bus
- Azure service bus implements retry policy using RetryPolicy class.
- It is supported by Microsoft.Azure.ServiceBus(client library for .NET Standard) and WindowsAzure.ServiceBus( client library for NET Framework 4.5.2)
- Need to attach an event listener to view the retry attempts logs.
- SQL DB using ADO.Net
- No built-in support but Polly library can be used.
- SQL DB using EF Core
- Support of IExecutionStrategy for retry mechanism.
- Blob, Queue, and Files
- ClientOptions Class for retry mechanism.
- REST 1. Use of Polly 2. Decision-based on status code
- Azure Active Directory
-
Transient fault handling Guidelines
- Retry mechanism with built-in SDK or external mechanism using status code or use Polly
- Determine operation is suitable for retrying. Not all method needs to retry it may go endless
- Determine the appropriate retry count and interval
- Avoid antipatterns
- Sequential services are getting called each will try the retry. it may not necessary so need to option which service can try to retry.
- Never retry endless but use circuit breaker pattern
- Test the retry strategy by injecting fault into Service
- If you have retry based on Status codes then use the Fidler Core library to change the status runtime.
- Log and track transient and nontransient faults.
- Manage operations that continually fail using DR strategy.
-
Best practices book
-