Introduction: In the Serverless architecture, although more attention is paid to the business code, in fact, some configuration and cost also need to be paid attention to, and when necessary, the Configuration and code optimization of Serverless applications should be carried out according to the configuration and cost.

Change in the concept of Serverless application development

In addition to a new architecture and a new programming paradigm, the Serverless architecture brings about a shift in thinking, especially in the development process. Some people say that to regard Serverless architecture as a natural distributed architecture, we need to develop Serverless applications with the idea of distributed architecture. Admittedly, this is true. But in some cases, Serverless also has some features, so change your development mindset.

1. File uploading method

Uploading files is very simple and convenient in traditional Web frameworks, such as Python’s Flask framework:

f = request.files['file']
f.save('my_file_path')
Copy the code

However, under the Serverless architecture, files cannot be uploaded directly for the following reasons:

  • In general, some cloud platform API gateway triggers convert binaries into strings, which are not easy to retrieve and store directly.
  • In general, the size of packets passed between the API gateway and the FaaS platform is limited. Many platforms limit the size of packets to 6MB.
  • FaaS platforms are mostly stateless, and even if stored in the current instance, files will be lost as the instance is released.

Therefore, the upload file scheme commonly used in traditional Web frameworks is not suitable for direct use in the Serverless architecture. In the Serverless architecture, there are usually two ways to upload files: One method is to upload files to the object storage or NAS after converting them to Base64 format. However, the size of data packets transmitted between the API gateway and FaaS platform is limited. Therefore, this method is usually applicable to service scenarios where small files such as profile pictures are uploaded.

Is another way to upload through object storage platform to upload, because the client directly through the key to the files such as direct passing to the object store there is a risk, so usually the client upload request, pre signature function calculation according to the content of the request for operation, and the signature address to return to the client, the client using the specified method to upload again, after the completion of upload Update the upload result by object storage trigger, as shown in the following figure.

Example of uploading files under the Serverless architecture

Taking aliyun function calculation as an example, Bottle is used to realize the above two common uploading methods. In the calculation of a function, initialize the objects related to the object storage first:

AccessKey = { "id": '', "secret": '' } OSSConf = { 'endPoint': 'oss-cn-hangzhou.aliyuncs.com', 'bucketName': 'bucketName', 'objectSignUrlTimeOut': Auth = oss2. auth (AccessKey['id'], AccessKey['secret']) bucket = oss2. bucket (auth, AccessKey['secret']) OSSConf['endPoint'], OSSConf['bucketName']) getUrl = lambda object, method: bucket.sign_url(method, object, OSSConf['object SignUrlTimeOut']) getSignUrl = lambda object: GetUrl (object, "GET") putSignUrl = lambda Object: getUrl(object, "PUT") # getRandomstr = lambda len: "".join(random.sample('abcdefghijklqrstuvwxyz123456789 ABCDEFGZSA' * 100, len))Copy the code

The first upload method, after uploading through Base64, persists the file to the object store:

# Method: post@bottle. Route ('/file/upload', "POST") def postFileUpload(): try: pictureBase64 = bottle.request.GET.get('picture', '').split("base64,")[1] object = randomStr(100) with open('/tmp/%s' % object, 'wb') as f: f.write(base64.b64decode(pictureBase64)) bucket.put_object_from_file(object, '/tmp/%s' % object) return response({ "status": 'ok', }) except Exception as e: print("Error: ", e) return response(ERROR['SystemError'], 'SystemError')Copy the code

In the second upload method, obtain the pre-signed object storage address and send an upload request to the object storage:

# Method: GET @bottle.route('/file/upload/url', "GET") def getFileUploadUrl(): try: object = randomStr(100) return response({ "upload": putSignUrl(object), "download": 'https://download.xshu.cn/%s' % (object) }) except Exception as e: print("Error: ", e) return response(ERROR['SystemError'], 'SystemError')Copy the code

HTML part:

<div style="width: 70%"> <div style="text-align: Center "> < h3 > Web client to upload files < / h3 > < / div > < hr > < div > < p > plan 1: This method is more intuitive. The problem is that FaaS platform and API gateway have upper limit of packet size, and it is not good for binary file processing. </p> < UpladFileFC > < UpladFileFC() onclick="UpladFileFC()" value=" upload "/> </div> <hr> <div> <p> Scheme 2: Upload directly to the object store. The process is to obtain the temporary address from the function calculation and store the data (for example, save the file information to Redis, etc.), and then upload the file to the object storage from the client, and then trigger the function through the object storage trigger to read the information from the storage system (such as stored in Redis), and then process the image. </p> <input type="file" name="file" id="fileOss"/> <input type="button" onclick="UpladFileOSS()" value=" upload "/> </div> </div>Copy the code

Client JavaScript uploaded through Base64:

function UpladFileFC() { const oFReader = new FileReader(); oFReader.readAsDataURL(document.getElementById("fileFc").files[0]); oFReader.onload = function (oFREvent) { const xmlhttp = window.XMLHttpRequest ? (new XMLHttpRequest()) : (new ActiveXObject("Microsoft.XMLHTTP")) xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { alert(xmlhttp.responseText) } } const url = "https://domain.com/file/upload" xmlhttp.open("POST", url, true); xmlhttp.setRequestHeader("Content-type", "application/json"); xmlhttp.send(JSON.stringify({ picture: oFREvent.target.result })); }}Copy the code

The client side is implemented by pre-signing the address and passing it directly to the object store in client-side JavaScript:

function doUpload(bodyUrl) {  
    const xmlhttp = window.XMLHttpRequest ? (new XMLHttpRequest()) : (new Active       
        XObject("Microsoft.XMLHTTP"));    
    xmlhttp.open("PUT", bodyUrl, true);  
    xmlhttp.onload = function () {   
        alert(xmlhttp.responseText)  
    };   
    xmlhttp.send(document.getElementById("fileOss").files[0]);
    }
    
    
function UpladFileOSS() {
    const xmlhttp = window.XMLHttpRequest ? (new XMLHttpRequest()) : (new Active
        XObject("Microsoft.XMLHTTP"))
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {            
            const body = JSON.parse(xmlhttp.responseText)         
            if (body['url']) {  
                doUpload(body['url'])   
            }
        }    
    }    
    const getUploadUrl = 'https://domain.com/file/upload/url'   
    xmlhttp.open("POST", getUploadUrl, true); 
    xmlhttp.setRequestHeader("Content-type", "application/json"); 
    xmlhttp.send();
}
Copy the code

The overall effect is shown in the figure below.File uploading experiment on Web side under Serverless architecture

At this point, we can experiment with different types of file upload schemes on the current page.

2. File read/write and persistence methods

Application execution may involve read and write operations on files or persistent operations on some files. In the traditional cloud hosting model, you can read and write files directly, or persist files in a directory, but this is not the case under the Serverless architecture.

Because the FaaS platform is stateless and destroyed after use, files cannot be persisted directly in the instance, but can be persisted in other services, such as object storage, NAS, etc.

In addition, if the NAS is not configured, only the/TMP directory is writable on the FaaS platform. Therefore, some temporary files can be cached in the/TMP directory.

3. Use some Web framework features sparingly

(1) asynchronous

Function evaluation is request-level isolation, so the request can be considered finished and the instance may enter a silent state. In function calculation, API gateway triggers are usually called synchronously (taking Ali Cloud function calculation as an example, they are usually triggered asynchronously only in several cases, such as timing triggers, OSS event triggers, MNS topic triggers and IoT triggers).

This means that when the API gateway returns the result to the client, the entire function goes silent, or is destroyed, rather than continuing through the asynchronous method. Therefore, it is often difficult for frameworks like Tornado to play an asynchronous role in Serverless architecture. Of course, if consumers need asynchronous capabilities, they can refer to the asynchronous approach provided by the cloud vendor.

Taking Ali Cloud function computing as an example, Ali Cloud function computing provides users with an asynchronous call ability. When an asynchronous call to a function is triggered, the calculation of the function puts the triggered event into an internal queue and returns the request ID, but does not return the specific call or function execution status. If the user wants to get the result of an asynchronous invocation, he can do so by configuring an asynchronous invocation target, as shown in the figure.

  Function asynchronous function schematic diagram

(2) Scheduled tasks

In the Serverless architecture, once the application completes the current request, it will go silent or even the instance will be destroyed, which makes some frameworks with scheduled tasks unable to perform scheduled tasks properly. Function calculations are usually triggered by events and are not automatically timed to start. Such as Egg set a timer task in the project, but in the actual function if not triggered by a trigger in the calculation of the function, the function will not be triggered, will not start automatically from within time to perform the task, at this point you can use the time trigger, through timed trigger specified method to replace the task.

4. Pay attention to the application composition structure

(1) Static resources and business logic

In the Serverless architecture, static resources should be provided with the support of object storage and CDN, otherwise all resources are in functions. The exposure of the function calculation not only reduces the concurrency of the function’s business logic, but also causes more cost. Especially to migrate some existing programs to Serverless architecture, such as WordPress, we should pay more attention to the separation of static resources and business logic, otherwise in the case of high concurrency, performance and cost will be severely tested.

(2) Separation of business logic

In many cloud vendors, functions are charged based on running time, configured memory, and generated traffic. If the memory of a function is not set up properly, the cost can be multiplied. To ensure proper memory Settings, the reliability of the service logic structure must be ensured.

Taking aliyun function computing as an example, an application has two external interfaces. The memory consumption of one interface is less than 128MB, and the memory consumption of the other interface is around 3000MB. The two interfaces are triggered an average of 10,000 times per day, and each takes 100 milliseconds. If the two interfaces are written to a function, the function may need to set the memory to 3072MB, and the user requests the interface that consumes less memory to achieve better performance under cold startup conditions. If the two interfaces are written separately to a function, the memory of the two functions should be set to 128MB and 3072MB respectively, as shown in the table.

It can be clearly seen from the above table that reasonable and appropriate business splitting will save costs to a certain extent. The cost savings in the above example are nearly 50%.

About the author: Liu Yu (Jiang Yu), PhD candidate in Electronic Information major of National University of Defense Technology, Ali Cloud Serverless product manager, Ali Cloud Serverless cloud preacher, CIO College distinguished lecturer.

Book recommendation

This book will introduce readers to what Serverless architecture is, how to get started with Serverless architecture, the application of Serverless architecture in different domains, and how to develop a Serverless application from scratch through multiple open source projects, cloud products from multiple cloud vendors, and various ways. This book can help readers to integrate Serverless architecture into their own fields, truly implement Serverless projects, and obtain the technical dividends brought by Serverless architecture.