How We Launched Virto Commerce B2B eCommerce Platform in Serverless Mode on Azure Functions

Anyone interested in serverless computing has seen publications and videos with examples of small test applications in Azure Functions, AWS Lambda or Google Cloud Functions. Moreover, you can read stories of building and running serverless ecommerce applications as a minimum working product (MVP) with many simplifications.

But is it possible to run Virto Commerce, a full-featured headless B2B ecommerce platform written in .NET Core, as a serverless backend application? We set up such an experiment in the Virto DevLabs development laboratory. Yes, it works, but here are some nuances.

Why Serverless Computing Is a Hot Topic in B2B eCommerce

For B2B ecommerce, as perhaps no one business, the main advantage of serverless computing will be the possibility of unlimited website performance scaling from almost zero to bursting high.

The pay-for-value model (according to the load and without any minimum level) is also favorable for running an ecommerce platform. Saving on costs is also one of the conditions for the viability of this type of the business.

Another savings on serverless computing includes significantly reducing the cost of salaries for network engineers and system administrators. In the case of cloud or on-premises hosting, these people would be involved in setting up servers, and installing the operating system and middleware. For serverless computing, these steps and staff are unnecessary. Developers can immediately publish the application code and not think about which servers it will run on; the hosting service provider will automatically configure the IT infrastructure for the application.

Let’s go to a typical ecommerce performance-scaling example and imagine a situation for websites of the pharmacy chain during deep at night. Usually, there are not too many visitors there at this time of night. If this is serverless computing, you pay just a penny to the hosting for IT resources as the load is minimal.

However, breaking news released from the World Health Organization (WHO) that hydroxychloroquine could combat coronavirus, or COVID-19. There was a heightened demand for the antimalarial drug. Millions of visitors excitedly rushed to pharmacy websites to order this drug "just in case." Even if the drug was out of stock, such a peak load could create a DDoS attack for a pharmacy website, which could be overloaded and unable to sell the available products in stock.

In the case of serverless computing, the platform would accept such a peak load easily. Meanwhile a classic cloud hosting would probably fail even with a load balancer and live migration of virtual machines from overloaded hosts to other hosts.

The term serverless computing refers to marketing terminology in the cloud-hosting market. This does not mean that applications do not use servers. The point is that the hosting client does not buy any specific configuration of server hardware resources for the project (number of CPU cores, memory, disk space), but allows the hosting service provider to choose the appropriate server configuration depending on the load created by the application. This is convenient because all issues related to server space and IT infrastructure are resolved by the cloud-hosting service provider, and the invoice is billed upon consumed resources.

Of course, not every ecommerce platform can, in principle, run in serverless computing mode. For example, monolithic systems fall under the limitation.

Please keep in mind that headless architecture is not a mandatory requirement for running ecommerce platforms as a serverless backend on Azure Functions. But with API access, headless architecture of Virto Commerce allows to reuse automated tests and run quick tests in the test environment. Looking ahead, our platform was successfully launched as a serverless application and we learned from the API response.

Microsoft Gives the Go-Ahead

The idea of ​​Virto DevLabs developers to try an B2B ecommerce platform as a backend on Azure Functions has been discussed for a long time. But in practice, such a toolkit became available only in March 2021. At that time, Microsoft announced support for launching .NET 5 applications in Azure Functions, and this was fundamentally important because Virto Commerce is written on this technology stack.

.NET 5 Functions execution support in Azure Functions is now implemented as an independent process that decouples .NET functions from the Azure Functions host, eliminating the issue of sharing the same process.

How Serverless Computing Works in Azure Function

In September 2020, Azure Functions announced a great opportunity to use custom handlers, which significantly expanded support for running applications as a function. It became possible to run applications written in any programming languages ​​and environments which are not supported by the Azure Functions framework, such as Go, Rust, R, PHP, etc.

In short, this handler technology is very similar to the old bearded CGI, when the web server launched an external application (script) and passed HTTP requests through a special interface. The Azure Functions custom handlers are built in the same way.

Diagram of how custom handlers work (source: Microsoft)

Diagram of how custom handlers work (source: Microsoft)

When the Functions host forwards incoming events from all supported triggers to the "lightweight" web server, it runs the main code of the custom “Functions code” handler. The result is passed back to the Azure Functions host and then through the Output Binding to the function's output to the recipients.

The only prerequisite for a custom handler to use is that your language / runtime supports HTTP. Since the ASP.NET Core Web API has all of this in abundance, we could run our Functions app as Azure Functions custom handlers.

“A picture is worth a thousand words” — that is why we recorded a YouTube video of how we launched a Virto Commerce platform as a serverless application in Windows. We also ran our application under Linux. Check out more on that below.

Prerequisites to Run the Application on Azure Functions

1. First, we installed the Azure Functions Core Tools. This toolkit is needed to test and run our application locally as a serverless Azure Function.

2. We used the platform source (see Deploy from source code in Virto Commerce Documentation) and added a new step to the required files of the project. Using the custom handler, we were able to launch our B2B ecommerce platform without any code changes.

3. To continue, we added two files: host.json and function.json:

host.json tells the Azure Functions host where to send requests, pointing to a web server capable of handling HTTP events.

function.json file is in a folder whose name is used as the Function name. We chose the name of the azure-func folder, where we will transparently proxy all incoming HTTP traffic while preserving the original paths for our Web API application.

4. As a result, the file structure of the B2B ecommerce platform launch looks like this one:

Screen of the file structure of the platform with json files

Screen of the file structure of the platform with json files

5. To do this, we publish to the bin folder:

dotnet publish

Go to the publish folder

cd bin / debug / net5.0 / publish

6. Next, we launched our application function:

func start

Here we checked that our application as a function works. By default, the function listens on port 7071 (http: // localhost: 7071 / {* paths}), so we will use it to call our API.

curl http: // localhost: 7071 / api / ...

Deploy of Virto Commerce B2B eCommerce Platform to Azure Functions Serverless Environment

To deploy Virto Commerce to Azure Functions, we installed the Azure CLI because all operations were performed using the command line.

Then, we created three types of resources:

I. Resource group, which is a logical container for the corresponding resources.

Read more at “Create resource groups.” https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal#create-resource-groups.

II. Storage account, which is used to keep track of the state and other information about functions.

Read more at “Create a storage account.” https://docs.microsoft.com/en-us/azure/storage/common/storage-account-create.

III. Function app that provides an environment for executing a platform application as a function.

Let’s analyze further steps in detail:

1. Before working from the CLI command line with Azure subscription resources, you need to authenticate with the Azure portal. For this, we ran this command:

az login

This command has authenticated and mapped the account to our Azure subscription.

2. Then, the resource group was created:

az group create -l westeurope -n serverless-weather-forecast-rg

3. Next, we created a storage account to store our application code as a function:

az storage account create --name weatherfuncstorage --location westeurope --resource-group serverless-weather-forecast-rg --sku Standard_LRS

4. The final preparatory step was to create a function app in our resource group:

az functionapp create --resource-group vc-platform-func-rg --consumption-plan-location westeurope --runtime custom --functions-version 3 --name vc-platform-func-app --storage-account vcplatformfuncstorage - -os-type {Linux, Windows} --subscription <your azure subscription id>

After successfully completing all these steps, we were ready for the last step of publishing (deploying) to Azure.

func azure functionapp publish vc-platform-func-app --subscription <your azure subscription id>

Important: To reduce the time of the platform application to start, we set the parameter:

VirtoCommerce: RefreshProbingFolderOnStart for Windows or

VirtoCommerce__RefreshProbingFolderOnStart for Linux to false.


See the screenshot below showing the configuration of the Azure Functions app.

Configuration screenshot

Configuration screenshot

Challenges We Got When Running Our B2B eCommerce App as Serverless on Azure Functions

  • Cold start issue. There are well-known concerns about the possibility of slow startup issues for serverless apps. In fact, our large modular B2B ecommerce application Virto Commerce was up and running in less than 30 seconds. This did not violate the allotted limit, and there were no noticeable failures even during load testing with interruptions in activity.
  • Compliance with naming. Since the Azure Functions service enforces a certain naming convention on the route by default, it was difficult to keep the old paths for the WEB API in such a way that it was invisible to existing clients. We added this code to the host.json file:

"http": {

// This setting removes the mandatory API prefix added by default to all routes, which will keep the original routes from the application for external clients

"routePrefix": ""

}

  • Running on Linux. Linux demands some modification for host.json file, where it was necessary to remove the line from the extensionBundle. Otherwise the "provider null reference" error appeared.
  • Difference when running on Windows and Linux. It was confirmed that the application configurations on Windows and Linux are different. To override the appsettings.json settings on the Azure portal, we had to use different separators for the settings path:
  • ':' "Section: SubSection" for Windows,
  • '__' "Section__SubSection" for Linux.

These are all comments on non-obvious settings we did.

Performance Tests for Serverless Computing Against Dedicated Azure Environment for Virto Commerce App

When the application started working in serverless mode, we tested the performance in serverless mode in comparison to the classic cloud hosting. As part of our testing, the Virto Commerce application was launched on two different types of hosting:

  • Cloud hosting on Azure S1: 1 Core, 1.75 GB RAM with scale-out enabled up to three instances.
  • Serverless on Azure Functions with a consumption plan either on Windows and Linux.

The test was a series of API calls with a linearly increasing load in the form of parallel threads (which simulated ecommerce users). The load grew to 100 parallel streams in three minutes.

Based on the test results, the bandwidth of the serverless application is almost three times higher than that of the dedicated Azure environment. But at the same time, a fairly large percentage of errors were observed for Windows on serverless. These were "System.OutOfMemoryException" errors, which indicates the lack of memory of this serverless hosting plan for crucial apps. The bugs went away when we ran the application as a function in the Linux operating environment.

Learning to eliminate memory leaks in Azure Functions is still an open question. We will elaborate on this with Microsoft.
Serverless Azure Functions vs Azure S1 performance graphs

Serverless Azure Functions vs Azure S1 performance graphs

As for talking about money, yes, there may be a potential cost benefit of serverless computing over traditional cloud hosting resources. But what happens with the savings in practice depends on the app load and other factors, although it seems to us that the savings on hosting service in some cases can be significant.

Let’s compare two subscription plans.

plan1
plan2
  • Serverless - Consumption plan, 1.6 GB RAM, 30M calls per month = $ 71.40.
  • Dedicated - S1: 1 Core, 1.75 GB RAM = $ 219 per month.

Prices were taken from Azure Services Calculator https://azure.microsoft.com/en-us/pricing/calculator/.

* Prices for the date of publication or date you read the article may differ from those indicated here, depending on the region and on the Azure pricing policy.

If you think of the well-known concern about serverless computing as an uncontrolled process of debiting bucks from your account, then yes, you should be careful when using the consumption plan in Azure—and not only there. Contact your hosting service provider for establishing rules to avoid waking up in the morning with a couple hundred thousand bucks in debt just for a test deployment.

Conclusion

We have confirmed that full-featured applications like this B2B ecommerce platform can be run in a serverless environment. From our point of view, it was the first practical experience of launching a real B2B ecommerce platform as serverless. We have not found any similar cases on the Internet before. (Available links are for simplified MVP products.)

Almost no changes to the code of eCommerce .NET Core application itself are required to run. But it is important that the application supports horizontal scaling, be stateless and does not consume a lot of RAM, since for functions, especially those working under the Azure Consumption plan, there are restrictions on the allocated RAM size of 1.6 GB.

Virto Commerce thanks colleagues Evgeny Tatarintsev, Oleg Zhuk and Sergey Berezin for their contributions to this post.

Additional information is on the Virto documentation platform deployment. If there are additional questions about the subject of the article, please contact Virto Commerce for further elaboration.

Request a quick demo

Oleg Zhuk
Technical Product Owner