21 Advanced Practical Iii How Traditional Services Migrate to the Serverless Platform

21 Advanced Practical III How traditional services migrate to the Serverless platform #

Hello, I’m Jingyuan.

Today, let’s talk about how to think and introduce new technologies when the system architecture faces the arrival of new technologies.

Building a new system architecture is relatively easy in terms of technology selection and development deployment because there is no historical burden. However, for “old” application services, there are more considerations due to existing operational business and the burden of the original technology architecture.

The same goes for Serverless. It is different from traditional services in terms of development, testing, deployment, and operation and maintenance. In recent years, there have been more and more Serverless PaaS products. Choosing the right business and finding the right way to iterate our services has become a complex engineering task.

In this lesson, I will share the experience of migrating traditional services to the Serverless technology architecture based on the accumulation of interacting with clients. Finally, we will complete a practical migration together. I hope that through this approach, you will have a relatively comprehensive understanding of the details such as “to use or not to use,” “self-built or on the cloud,” “use one or multiple functionalities,” etc., when making technological decisions.

Do you really need a migration? #

Generally speaking, there are only three factors for any technology transformation or migration.

  • Architecture: The existing technology architecture is insufficient to support the growth of business traffic, and the system can no longer handle it.
  • Personnel: There is a shortage of manpower, either due to insufficient quantity or lack of knowledge, and the workload is too much for the team to handle.
  • Cost: Ultimately, it is about cost. Especially for start-ups or innovative teams within large companies, the budget is limited before the business takes off. What should be done then?

So, whenever you encounter these three problems, should you hesitate to migrate? Before migration, I suggest you review the selection recommendations in the practical guide and carefully consider two questions.

First, is this a blind option?

For business professionals, regardless of whether they use cloud providers or internal platforms, their technology stack follows the platform, depending heavily on the supporting services and stability provided by the platform. Perhaps we can go online quickly, but we have lost control of the server.

On the other hand, the code is also given out. So, do you have backup plans for the security of code and data? Cloud providers have also experienced data security failures, which is one of the core reasons why enterprises such as financial banks need to deploy Serverless platforms privately.

Second, what impact will your migration have on technology, business, and the team?

  • In terms of technology, is it a complete transformation and migration? Or is it a partial transformation and migration? Or do you start using the new architecture and then gradually transition the old business?
  • In terms of business, it needs to be evaluated from the perspective of sustainable development. Transforming a system architecture should either reduce the cost of resource consumption for existing business (i.e., maintaining the status quo and reducing costs) or support the increase in traffic in a better way. Otherwise, the transformation will be in vain.
  • In terms of the team, are there enough talent and knowledge reserves? Can they handle problems when they arise?

Asking why a few more times may help you avoid many pitfalls on the road to transforming Serverless. Once you have a clear understanding of these questions, we can start discussing specific solutions.

Where to Migrate? #

Let’s start with an example of migration. There is a management website system for a small to medium-sized company, which hopes to further reduce website costs. The website is currently deployed on a cloud hosting application, and sometimes there are issues with accessing traffic.

Now, let’s think about how to choose among concrete product technologies such as serverless container services, application hosting services, and function computing.

Should we migrate to container services? #

The main differences between serverless container services and regular Kubernetes container services are whether they are billed on-demand, whether the nodes are visible, and whether capacity planning needs to be done.

Image

If your service is already deployed on container services and has elasticity requirements, migrating to serverless container services can be a wise move. If the team doesn’t have much experience in Kubernetes operation and maintenance, then it’s important to focus on function computing and elastic applications.

Should we migrate to function computing services? #

Remember in the runtime course, we talked about how the function computing platform supports standard runtimes and custom runtimes? Now, let’s see how we can “use” the runtime according to the purpose of migration.

  • Standard runtimes

The built-in runtimes provided by cloud vendors can already meet the code execution needs of most business scenarios, especially those that do not involve complex interactive processes. For example, for offline machine learning tasks, sometimes you only need to put the startup method of the original training logic in the function computing entry point to complete the migration.

The following pseudocode can help you understand this more clearly.

def handler(event,context):
  result = training()
  return result

def training:
  ...
  • Custom runtimes and custom images

Custom runtimes and custom images are an extension capability of function computing’s built-in runtimes, providing users with a more flexible service access mode.

Custom runtimes allow users to program without strictly adhering to the event-driven model. In other words, users do not need to define handler(event, context) as the entry point for function computing, and can create a more personalized programming environment, such as starting common web frameworks directly in custom runtimes.

Compared with custom runtimes, custom images offer even more freedom. They allow the entire environment to be packaged as a container image for deployment.

In summary, both options are more suitable for scenarios where it is troublesome to migrate to regular runtimes. For example, some web frameworks have fixed HTTP processing interfaces and cannot handle standard event parameters. In such cases, you can use custom runtimes or custom images to deploy services with customized startup methods.

In addition, the derivative capabilities of function computing can help you handle more complex scenarios and make function computing more versatile. For example, you can use the connector capability and asynchronous strategy of functions to migrate tasks such as audio and video transcoding. You can also migrate task scenarios involving state transitions using function workflows, etc. Some function computing services also consider the functional decomposition between businesses and provide the concept of an application center for management.

Should we migrate to application hosting services? #

If you are familiar with the development of microservices on cloud PaaS, it should be easy to understand that a Serverless PaaS platform oriented towards applications is an evolutionary version based on the original microservices PaaS platform. It provides fully managed, maintenance-free, on-demand, and pay-as-you-go features based on the existing support for multiple languages, frameworks, and microservices governance capabilities.

If your service is already a microservice framework based on Springboot, Dubbo, HSF, etc., using this type of Serverless product from a cloud vendor is also a good choice.

Finally, let’s answer the question about the case of managing website systems. This customer does not have high performance requirements, and the main demand is to reduce the cost of persistent instances. Currently, the minimum instance for serverless hosting services is 1, and it cannot be scaled down to 0. Therefore, FaaS is more suitable for such customers. When you do service transformation and migration, you should also consider “cost” as an important factor to plan carefully.

How to Migrate? #

After discussing the considerations and technology selection for migration, let’s take a look at the actual process of migrating traditional services to Alibaba Cloud Function Compute (FC) using a web service as an example. We will examine the migration process for both simple HTTP services and advanced web frameworks.

Migration of HTTP Services #

For general simple HTTP services, they can be run using the standard runtime and the HTTP trigger provided by Function Compute.

  • How does the HTTP request reach the business code?

The input parameters of a web request usually consist of a standard HTTP request, including the HTTP headers and parameters. However, the cloud functions we have been using handle JSON-type event strings in event-driven scenarios. Therefore, web services cannot directly use this event-driven programming model.

When creating a function, you will notice that FC provides two types of request handlers, one for handling event requests and the other for handling HTTP requests.

Image

“Handle Event Requests” is the type we commonly use for event-driven request handling. “Handle HTTP Requests” requires providing a standard HTTP handling interface in the entry method. You may recall that when we analyzed the GoLang runtime, we mentioned a branch judgment based on the funcType. This is where it comes into play. The GoLang runtime selects a specific execution method based on the function’s type, as shown in the following runtime code:

// Code for categorizing processing logic in the runtime
if fn.funcType == eventFunction {
    return fn.invokeEventFunc(invokeContext, req.Payload, response)
}
return fn.invokeHttpFunc(invokeContext, req.HttpParams, req.Payload, response)

In functions of the HTTP request processing type, the function entry needs to implement the defined interface, which includes request information, response information, and context information. For example, the HTTP function demo provided by the FC official SDK:

func HandleHttpRequest(ctx context.Context, w http.ResponseWriter, req *http.Request) error {
    w.WriteHeader(http.StatusOK)
    w.Header().Add("Content-Type", "text/plain")
    w.Write([]byte("hello, world!\n"))
    return nil
}

In invokeHttpFunc, the HTTP request content is ultimately passed to the method you defined earlier, namely HandleHttpRequest, using the transparent transmission. The corresponding code is as follows:

// Code for executing the http handler in the runtime
func (fn *Function) invokeHttpFunc(invokeContext context.Context, httpParams *string,
    reqPayload []byte, response *messages.InvokeResponse) error {
    ...
    err = fn.httpHandler.Invoke(invokeContext, resp, req)
    ...
}

In this way, we have completed a complete process of passing an HTTP request.

  • Hands-on Experience

Next, let’s start migrating a simple HTTP service. We will use the GoLang runtime as the basis for creating the function and refer to the official sample code. Choose the request handler type “Handle HTTP Requests”. The platform will automatically create an HTTP trigger for you, which can be viewed by clicking on Trigger Management:

Image

Please note that if you need public access, you also need to click Edit to configure the domain name.

Finally, let’s update the code. Here, I have printed the geekbang query parameters from the request to the response. During the actual migration, you can also process the business according to actual needs after obtaining the request information, just like the function doSomething() commented in the following code:

package main


import (
    "context"
    "net/http"


    "github.com/aliyun/fc-runtime-go-sdk/fc"
)


func main() {
    // Code for handling HTTP requests
}
fc.StartHttp(HandleHttpRequest)

}

// func doSomething(){}

func HandleHttpRequest(ctx context.Context, w http.ResponseWriter, req *http.Request) error { w.WriteHeader(http.StatusOK) w.Header().Add(“Content-Type”, “text/plain”) w.Write([]byte(req.URL.Query().Get(“geekbang”)))

//doSomething()   


return nil

}

Then compile and package the code for upload. The final effect is as follows:

Image

Advanced Web Framework Migration #

As mentioned earlier, if your legacy application is built on an advanced service framework, you can migrate by using custom runtimes, custom images, and flexible applications.

Taking Alibaba Function Compute (FC) as an example, the official recommendation is to use custom runtimes for advanced framework migration:

Image

Let’s take the commonly used Gin framework in Golang as an example and select the custom runtime option. Choose the Go runtime environment and select the example code.

Image

After creating the runtime, let’s start writing some code with Gin. You can refer to my example. In Gin, you can handle requests using custom methods. Here, I define a geekHandler to handle requests to the /geekbang path:

package main


import (
    "net/http"


    "github.com/gin-gonic/gin"
)


func main() {
    router := gin.Default()
    router.LoadHTMLGlob("templates/*")
    router.GET("/geekbang", geekHandler)
    router.Run(":9000")
}


func geekHandler(c *gin.Context) {
    c.String(http.StatusOK, "do something")
}

You’ll notice that this code is very similar to your original service code. In practice, if your service uses the Gin framework, you can almost deploy the binary as is by simply configuring the startup command on the console, which is very convenient.

After completing the code locally, you need to compile and package the binary for upload. It’s important to note that in the previous section, we used the default startup command ./main, so your binary output should match it. Alternatively, you can specify a different output name. If you’re using a non-Linux environment, you’ll need to cross-compile the code locally:

GOOS=linux GOARCH=amd64 go build -o main main.go

In the above code, GOOS and GOARCH specify the Linux operating system and the amd64 architecture respectively, while -o is used to specify the output name, and the last parameter is the file to be compiled.

After completing the deployment, let’s take a look at the actual running effect:

Image

Recalling the scenario of the management website system, if there is also a custom domain name involved, you can further add a custom domain name through the FC console using the “Domain Management” feature. Alternatively, you can use the custom domain name as the origin domain name, add an acceleration domain name for it, and configure a CNAME for the acceleration domain name, which enables CDN acceleration for the domain name.

Performance Evaluation #

Managing website systems is actually a real case. By migrating from the original resident resource application to serverless function computing, the client’s costs have been reduced by 10 times. I believe that by now you can already understand the reason: their service belongs to the long tail application, and pay-as-you-go greatly reduces the client’s costs.

So, do we have a general guideline to evaluate the effectiveness of migration? Going back to the beginning, any technological transformation or migration is mainly driven by three factors: architecture, personnel, and cost. Apart from these three aspects, the post-migration architecture can also be evaluated by testing the system’s resilience and ability to withstand traffic peaks.

Our usual approach is to simulate online traffic fluctuations as much as possible through end-to-end load testing before releasing it to production and opening it up to external traffic. We observe whether the resource pool scheduling, request concurrency, and response meet expectations. Here, it is worth noting that some cloud providers have limited default concurrency for functions and user dimensions. If the traffic exceeds the default limit, it is necessary to submit a ticket in advance to increase the quota.

Specifically, based on the characteristics of the serverless platform, your load testing can start from three points.

  • End-to-end: For chain calls, you cannot only focus on the load testing results of a single function. Think about whether there are any bottlenecks in the entire chain?
  • Simulate reality: Get as close to the business as possible and test whether the resource scheduling of the testing platform can keep up with your demands. Different vendors may optimize different parameters, so can the cloud vendor platform you choose handle it?
  • High coverage: Cover as many process branches as possible and discover potential issues before going live.

In addition, we can also pay attention to whether the team members are more efficient, and the ultimate manifestation is that the original budget is sufficient to cope with the increase in traffic.

Summary #

Alright, that’s all for the content of traditional service migration. I believe you now have a clear understanding of the four things involved in migration: whether or not to migrate, which type of serverless platform to migrate to, transformation methods and costs, and migration evaluation. So how do we apply these four key points to our daily business operations?

Regarding whether or not to migrate, the case we discussed today was due to financial pressure, considering that the client’s business was relatively lightweight with almost no transformation costs, making it very suitable for migration to a function platform. As for you, you can consider multiple aspects such as whether to hand over control to the cloud provider, whether the business fits the characteristics of serverless, the cost of architectural transformation, and the technical reserves of the team.

Regarding which type of platform to migrate to, you need to have a deep understanding of the serverless products offered by cloud providers. The serverless container, function, and application hosting services that are currently more mainstream may be joined by more serverless products tomorrow. And what we can do is to find the best matching state among business, architecture, and product form. For example, if you are using the Spring Boot and Dubbo frameworks and need service governance capabilities, then serverless application hosting services such as SAE are the preferred options for you to consider.

Regarding transformation costs and methods, cloud providers all provide good migration adaptation capabilities. You can use development tools to achieve migration of various language frameworks such as Java, Node.js, and Python. Here, it’s worth noting that although you can achieve low-cost migration through code transformation and HTTP triggers, in most cases, we develop web services based on some frameworks. So I would recommend using custom runtimes for migration if possible. If you want full control over the runtime environment, migrating with images is also a good option.

Lastly, don’t forget the original intention of your migration, and remember to evaluate the results. You can evaluate based on architecture, manpower, and costs, and from the perspective of serverless, everything can be approached from the keywords “cost reduction” and “efficiency improvement” to assess whether the migration has achieved your expected results.

Thought-Provoking Question #

Alright, this lesson comes to an end. Lastly, I have a thought-provoking question for you.

Are you preparing to migrate any services? What technical research have you done? Have you encountered any obstacles?

Please feel free to share your thoughts and answers in the comments section. Let’s discuss and exchange ideas together.

Thank you for reading, and please feel free to share this lesson with more friends for further discussion and learning.