Important Facts of Asynchronous Programming in .NET

Modern apps make extensive use of file and networking I/O. I/O APIs traditionally block by default, resulting in poor user experiences and hardware utilization unless you want to learn and use challenging patterns.

Task-based async APIs and the language-level asynchronous programming model invert this model, making async execution the default with few new concepts to learn.

Async code has the following characteristics:

  • Handles more server requests by yielding threads to handle more requests while waiting for I/O requests to return.
  • Enables UIs to be more responsive by yielding threads to UI interaction while waiting for I/O requests and by transitioning long-running work to other CPU cores.
  • Many of the newer .NET APIs are asynchronous.
  • It’s easy to write async code in .NET

One of the main advantages of using asynchronous methods is with I/O-based code.

By doing an await, you can let a thread be reused to do other work while the I/O is in flight.

The biggest misunderstanding about Asynchronous programming in many developers is asynchronous method automatically spawns a new thread, and that is not the case.

Recent improvements Microsoft has made towards Asynchronous programming is “Generalized Async Return Types

This means that you’re no longer limited to using Task or Task<T> as the return type for an asynchronous method. As long as the return type satisfies the asynchronous pattern, you’re good. Using this new ValueTask, you can avoid memory allocations, which can help in addressing performance issues.

Top Nuget Packages that Microsoft recommend for asynchronous programming are “System.Collections.Concurrent” and “System.Collections.Immutable“.

System.Collections.Immutable provides collections that allow a developer to use a collection (e.g. ConcurrentBag or ConcurrentDictionary) in a concurrent fashion safely. Therefore, the developer doesn’t need to do their own locking mechanisms to use the collection. Immutable collections allow developers to share collections safely because updates are only seen by the code that made the update.

Avoid void as a return type for asynchronous methods at all costs.

The only time it’s valid to do this is with an event handler. Otherwise, asynchronous methods should always return a Task type.

Immutable structures are very important when working with concurrent programming.

The main advantage with immutable data types is that you can share them across multiple tasks without worrying about synchronizing their contents. By their definition, they’re immutable, so if a task decides to “change” an immutable object, it will get a new version of that object. If another task has a reference to the original immutable object, it doesn’t change.

Take advantage of C# features to write immutable structures.

This means defining fields with the readonly keyword and properties that only have getters (not even private setters). Also, C# now allows you to specify a method parameter with the in keyword, which means that reference cannot be changed.

That’s all for now. I hope these facts will help you while doing Asynchronous Programming for your projects 🙂

Advertisements

Amazon Simple Queue Service – SQS

Amazon Simple Queue Service (SQS) is a distributed queue system that enables web services to quickly and reliably queue messages that one component in the application generates to be consumed by another component. A queue is a temporary repository for messages that await processing.

HOW IT WORKS

Below sample architecture we are going to use to understand how SQS works. There are two SQS Queue created, one for Request and another for Response.

Web Server who act as producer, who creates a message and puts it into request queue. it also read from response queue as well.

You can have multiple producers who can add multiple messages to the queue at the same time. You don’t have to worry about the traffic or peaks. SQS handles that for you.

sqs-as-workflow-diagram

Queued messages are processed by consumer. The consumer is requesting new messages periodically from the queue. You can have multiple consumers, but you have to remember that each message can be processed only once. It means that you can have multiple instances of the same consumer, but you can’t read the same message from one queue in two different components. Each of these components should use a separate SQS queue.

After a consumer processes the message, it has to be deleted from the queue. Deleting is important because SQS assumes that processing can fail. To prevent that, after the consumer receives a message, it is hidden from the queue for a defined period of time and after that, if it is not deleted, the message shows up in the queue again.

HOW TO RUN MULTIPLE EC2 INSTANCES SIMULTANEOUSLY WITH AMAZON EC2 TO HANDLE INCREASED LOAD? 

Two specific features of Amazon SQS make this possible:

  • A single Amazon SQS queue can be shared by multiple servers simultaneously.
  • A server that is processing a message can prevent other servers from processing the same message at the same time by temporarily “locking” a message. The server can specify the amount of time the message is locked. When the server is done processing the message, it should delete the message. If the server fails while processing the message, another server can get the message after the lockout period.

These two features ensure that the number of processing servers can be easily changed dynamically to handle varying load. The entire process can be automated to ensure that at any given time the optimal number of EC2 instances is running. This practice is commonly referred to as “auto-scaling.”

TYPES OF QUEUE 

Standard Queue

  • Available in all regions.
  • Unlimited Throughput – Standard queues support a nearly unlimited number of transactions per second (TPS) per API action.
  • At-Least-Once Delivery – A message is delivered at least once, but occasionally more than one copy of a message is delivered.
  • Best-Effort Ordering – Occasionally, messages might be delivered in an order different from which they were sent.
  • When to use? – Send data between applications when the throughput is important, for example:
    • Decouple live user requests from intensive background work: let users upload media while resizing or encoding it.
    • Allocate tasks to multiple worker nodes: process a high number of credit card validation requests.
    • Batch messages for future processing: schedule multiple entries to be added to a database.

FIFO Queue

  • Available in the US East (N. Virginia), US East (Ohio), US West (Oregon), and EU (Ireland) regions.
  • High Throughput – FIFO queues support up to 300 messages per second (300 send, receive, or delete operations per second). When you batch 10 messages per operation (maximum), FIFO queues can support up to 3,000 messages per second. To request a limit increase, file a support request.
  • Exactly-Once Processing – A message is delivered once and remains available until a consumer processes and deletes it. Duplicates aren’t introduced into the queue.
  • First-In-First-Out Delivery – The order in which messages are sent and received is strictly preserved.
  • When to use – Send data between applications when the order of events is important, for example:
    • Ensure that user-entered commands are executed in the right order.
    • Display the correct product price by sending price modifications in the right order.
    • Prevent a student from enrolling in a course before registering for an account.

USE CASES OF SQS

  • File processing – image scaling, video re-compression
  • Asynchronous communication with external services
  • Sending emails
  • Order Processing Application.

POST AND READ MESSAGE IN/FROM SQS USING .NET CORE 

I followed these steps to create an IAM user for authentication in SQS and then create a queue with that user having full access.

This is a very simple application that posts a message to a queue, and receives one, just by passing the credentials in the code. I have noticed that AWS nicely handles duplicates so if you send the same message multiple times, it only seems to show up once.

            

//the url for our queue
var queueUrl = "https://sqs.eu-west-1.amazonaws.com/[USERID]/[QUEUENAME]";

Console.WriteLine("Queue Test Starting!");

Console.WriteLine("Creating Client and request");

//Create some Credentials with our IAM user
var awsCreds = new BasicAWSCredentials("[ACCESSKEY]", "[SECRETKEY]");

//Create a client to talk to SQS
var amazonSQSClient = new AmazonSQSClient(awsCreds, Amazon.RegionEndpoint.EUWest1);

//Create the request to send
var sendRequest = new SendMessageRequest();
sendRequest.QueueUrl = queueUrl;
sendRequest.MessageBody = "{ 'message' : 'hello world' }";

//Send the message to the queue and wait for the result
Console.WriteLine("Sending Message");
var sendMessageResponse = amazonSQSClient.SendMessageAsync(sendRequest).Result;

Console.WriteLine("Receiving Message");

//Create a receive requesdt to see if there are any messages on the queue
var receiveMessageRequest = new ReceiveMessageRequest();
receiveMessageRequest.QueueUrl = queueUrl;

//Send the receive request and wait for the response
var response = amazonSQSClient.ReceiveMessageAsync(receiveMessageRequest).Result;

//If we have any messages available
if(response.Messages.Any())
{
    foreach(var message in response.Messages)
    {
        //Spit it out
        Console.WriteLine(message.Body);

        //Remove it from the queue as we don't want to see it again
        var deleteMessageRequest = new DeleteMessageRequest();
        deleteMessageRequest.QueueUrl = queueUrl;
        deleteMessageRequest.ReceiptHandle = message.ReceiptHandle;

        var result = amazonSQSClient.DeleteMessageAsync(deleteMessageRequest).Result;
    }
}

For more details, please refer “How Amazon SQS Queues Work” page. I have read documentation provided by amazon for SQS and believe me its really useful and all the things are very well documented.

I hope this will help !!!!

Override filters in ASP.NET Web API 2

You can now override which filters apply to a given action method or controller, by specifying an override filter. Override filters specify a set of filter types that should not run for a given scope (action or controller). This allows you to add global filters, but then exclude some from specific actions or controllers.

Key Features

  • Override filters disable higher-scoped filters of a given type.
  • Use an override when you want to vary the filter pipeline for a single action method so that controller-level and global filters won’t be executed.
  • Override filters do not affect filters applied at the same scope.

The Built-in Override Filter Attributes are

  • OverrideAuthenticationFilters – Prevents authentication filters from being executed
  • OverrideAuthorizationFilters – Prevents authorization filters from being executed
  • OverrideActionFilters – Prevents action filters from being executed
  • OverrideExceptionFilters – Prevents exception filters from being executed

Let us understand this with some example, how we can override Authorization Filter.

Example-1 : Overriding Controller wide Authorization

I applied an authorization filter to the Employee controller so that it applies to all of the action methods and then applies the OverrideAuthorizationFilters attribute to disable authorization for one of them.


using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Net;
using System;

namespace WEBAPI2Demo.Controllers
{
    public class Employee
    {
        public int EmployeeID { get; set; }
        public string FirstName { get; set; }
        public string  LastName { get; set; }
    }

    [Authorize(Roles = "admins")]
    public class EmployeeController : ApiController
    {
         private static List<Employee> employees = new List<Employee>
	 { 

		new Employee { EmployeeID = 1, FirstName = "Sandeep", LastName = "Ramani" }                

	 };

        [OverrideAuthorization]
        public IEnumerable<Employee> Get()
        {
            return employees;
        }

        public Employee Get(int id)
        {
            return employees[id];
        }

        public Employee Post(Employee emp)
        {
            emp.EmployeeID = employees.Count + 1;
            employees.Add(emp);
            return emp;
        }
    }
}

The effect of the Authorize attribute is to restrict all of the action methods in the Employee controller so they can be accessed only by authenticated users who have been assigned to the admins role.

The effect of applying the OverrideAuthorization attribute to the parameter less version of the Get action method is to prevent execution of all authorization filters for that action method, which means that any request is able to invoke the action.

Example-2 : Redefining Authorization

Override filters affect filters only at the previous scope, which means you can apply attributes of the overridden type at the same level as the override, and they will be executed.

Let us update previous example and add Authorization to restrict action method to role users only.


using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Net;
using System;

namespace WEBAPI2Demo.Controllers
{
    public class Employee
    {
        public int EmployeeID { get; set; }
        public string FirstName { get; set; }
        public string  LastName { get; set; }
    }

    [Authorize(Roles = "admins")]
    public class EmployeeController : ApiController
    {
        private static List<Employee> employees = new List<Employee>
	{ 

		new Employee {EmployeeID = 1, FirstName = "Sandeep", LastName = "Ramani" }                

	};

        [OverrideAuthorization]
	[Authorize(Roles="users")]
        public IEnumerable<Employee> Get()
        {
            return employees;
        }

        public Employee Get(int id)
        {
            return employees[id];
        }

        public Employee Post(Employee emp)
        {
            emp.EmployeeID = employees.Count + 1;
            employees.Add(emp);
            return emp;
        }
    }
}

I have applied the Authorize filter to the Get method, specifying that only authenticated users who have been assigned to the users role are allowed to invoke the action method. Without the OverrideAuthorization attribute, the filter pipeline would contain both Authorize attributes, and they would be executed one after the other, creating a combined effect of restricting access to those users who have been assigned to both the admins and users roles.

But with the OverrideAuthorization, the controller-scoped Authorize attribute is removed from the pipeline, meaning that only the Authorize filter applied directly to the action method will be used: the effect is to restrict access to the users role.

Similarly, you can use other Override Filters for Authentication, Actions and Exceptions in WEB API Services in your projects.