By Alberto Roura, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud's incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.
Serverless is the buzzword among developers recently, right? Well, do you really know how to take full advantage of it? This tutorial will help you to create a small, serverless personal webpage by using Alibaba Cloud Function Compute. We're going to do this by using the tool "Fun", because this is all about having fun with serverless.
Serverless is a new computing paradigm in which you can build applications composed of micro-services running as a response to events. Under this model the services automatically scales according to the usage. This means that you only get charge when they are executed, becoming the most "Pay-As-You-Go" model ever. Of course, this reduces the overall cost of maintenance for your apps, enabling you to more on the logic, deploying faster.
The classic approach to publish a website by your own is to have a web server, such as an Elastic Computer Service (ECS) instance, running non-stop. This means having an instance 24 hours a day, 7 days per week. Running the numbers that is about 730 hours per month. Or between $5~$15 every month depending on the plan and, on top of that, all the security and software updates involved in managing a server. I'm sure you prefer to spend that time and money on something more enjoyable, like a day on the mountains instead.
For the purpose of learning, we will keep things simple and clear by setting up a simple "About Me" page. For this, we will leverage Object Storage Service (OSS), API Gateway, Function Compute and Table Store. To make that happen, the idea is to host a static HTML file in an OSS bucket with Public Read Permissions. This page will have a visit counter that will communicate via API Gateway with Function Compute, and keeping the visits count on Table Store. Does it sound complex? Keep reading, you will find it easy.
To start, create a folder for the project. Once inside it, create the file .env for the credentials and leave it there for now.
We said this tutorial will be based on "Fun". Fun is an official Alibaba Cloud tool to arrange serverless applications resources. Therefore we will use it to deploy our website backend by describing the resources in a template.yml
file.
To install Fun, you only need to run in your terminal npm install @alicloud/fun -g
. To verify that the installation went ok, type fun -h and see if the output prints the Fun help.
Well, now that we have all ready to go, let's get the credentials. Log into the Alibaba Cloud web console and, from the top-right corner, click on AccessKey as shown below:
Once in the Security Management screen, copy the Access Key ID and the Access Key Secret into the .env
file we created before:
ACCESS_KEY_SECRET=Replace This with your Access Key Secret
ACCESS_KEY_ID=Replace This with your Access Key
ACCOUNT_ID=Replace This with your Account ID
REGION=ap-southeast-2
As we mentioned before, the way Fun works is by reading a YAML file where all the resources are described, all that apart of the specific permissions for the Function Compute Service if needed.
The template.yml
below describes the Function Compute Service AboutMePage
, the Table Store Instance AboutMePageOTS
and the API Group AboutMeAPI
. Add the following under your project folder:
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
AboutMePage:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'Function Compute Service for the About Page'
Policies:
- AliyunOTSFullAccess
visits:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: visits.handler
Runtime: nodejs8
CodeUri: './'
Timeout: 10
EnvironmentVariables:
InstanceName: AboutMePageOTS
TableName: visitsTable
AboutMePageOTS:
Type: 'Aliyun::Serverless::TableStore'
Properties:
ClusterType: HYBRID
Description: 'Table used to store visits'
visitsTable:
Type: 'Aliyun::Serverless::TableStore::Table'
Properties:
PrimaryKeyList:
- Name: count_name
Type: STRING
AboutMeAPI:
Type: 'Aliyun::Serverless::Api'
Properties:
StageName: RELEASE
DefinitionBody:
'/visits':
get:
x-aliyun-apigateway-api-name: visits_get
x-aliyun-apigateway-fc:
arn: acs:fc:::services/${AboutMePage.Arn}/functions/${visits.Arn}/
This is the heart of our project, as it will be the piece of code that will register the visits and retrieve the latest number. The code is using nodejs8 as Runtime and supports the creation of the first value in the table if it doesn't exist. So, for now, write the following code in a file called visits.js
:
const TableStore = require('tablestore')
const Long = TableStore.Long
async function getViewsCount(client) {
const response = await client.getRow({
tableName: process.env['TableName'],
primaryKey: [{ count_name: 'views' }],
maxVersions: 1,
})
return response.row && response.row.primaryKey
? response.row.attributes[0].columnValue.toNumber()
: null
}
exports.handler = function (event, context, callback) {
(async () => {
let success = false
let views = null
const client = new TableStore.Client({
accessKeyId: context.credentials.accessKeyId,
secretAccessKey: context.credentials.accessKeySecret,
stsToken: context.credentials.securityToken,
endpoint: `http://${process.env['InstanceName']}.${context.region}.ots.aliyuncs.com`,
instancename: process.env['InstanceName'],
})
do {
views = await getViewsCount(client) || 0
const tableName = process.env['TableName']
const updateOfAttributeColumns = [{ PUT: [{ count: Long.fromNumber(views + 1) }] }]
const primaryKey = [{ count_name: 'views' }]
const condition = views
? new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, new TableStore.SingleColumnCondition('count', Long.fromNumber(views), TableStore.ComparatorType.EQUAL))
: new TableStore.Condition(TableStore.RowExistenceExpectation.EXPECT_NOT_EXIST, null)
try {
await client.updateRow({
tableName,
condition,
primaryKey,
updateOfAttributeColumns,
})
success = true
} catch (ex) {
console.log(ex)
}
} while (!success)
callback(null, { isBase64Encoded: false, statusCode: 200, body: views })
})()
}
This step is very straightforward, as Fun includes a command to automatically deploy all the resources defined in the template. For this, we will run fun deploy and wait for the process to finish. It prints a very neat output to inform all what is really happening. From the output we will really need one thing, the API gateway identifier. Somewhere in the last lines, find something like URL: GET http://722919aa644345e39ac1e872cc387e25-ap-southeast-2.alicloudapi.com/time
, well, copy that URL for later, as we don't need it right now.
Traditionally, you'll serve the files using a web server installed in an ECS Instance, said server would interact with the visitor preparing the page contents and sending it back. In this serverless approach, the files will be served from an OSS bucket.
To create a bucket, go to the OSS Console and, from the right panel, click on "Create Bucket". Give a meaningful name to it and select "Public Read" under Access Control List. As a result, this will expose the contents of the bucket to anyone on the Internet. Confirm the creation clicking on "Ok". To serve static sites using the bucket, there is still something else we need to touch. For this, open the just-created bucket and go to the "Basic Settings" tab. Once in, click in the "Configure" button under "Static Pages" and type "index.html" next to "Default Homepage". That will tell OSS which file to serve by default. Just like using a web server like Apache or Nginx.
Because we need 3 files for this, I prepared a GitHub repository for you to download the files to your local machine and upload them to your bucket. Once you clone it, go to the "oss" folder. The files that need to go to the root folder of your bucket are the ones named index.html, bg.jpg
and style.css
.
Before uploading them, be sure to edit the index.html. This file is a template, so just tweak it with your own data. Most importantly, and to make the counter work, just find and replace API_ENDPOINT_URL_GOES_HERE
with the URL we copied in the "Deploy" step.
You are now ready to upload all 3 files to the bucket.
Enjoy your serverless, #NoOps life!
If you followed correctly all the steps, you now will be able to just navigate to your bucket (ie your-bucket-name.oss-ap-southeast-2.aliyuncs.com). As a result, your new shiny "About Me" page will work.
Minimizing Business Downtime with Alibaba Cloud Hybrid Disaster Recovery Solution
2,599 posts | 762 followers
FollowAlibaba Clouder - June 2, 2020
Alibaba Clouder - March 19, 2019
Alibaba Clouder - September 24, 2020
Alibaba Clouder - September 6, 2019
Alibaba Clouder - February 3, 2021
Alibaba Developer - February 1, 2021
2,599 posts | 762 followers
FollowAlibaba Cloud Function Compute is a fully-managed event-driven compute service. It allows you to focus on writing and uploading code without the need to manage infrastructure such as servers.
Learn MoreRobotic Process Automation (RPA) allows you to automate repetitive tasks and integrate business rules and decisions into processes.
Learn MoreVisualization, O&M-free orchestration, and Coordination of Stateful Application Scenarios
Learn MoreExplore Web Hosting solutions that can power your personal website or empower your online business.
Learn MoreMore Posts by Alibaba Clouder
5006456523727382 April 29, 2019 at 7:42 am
I have encountered and error when running fun deploy, as follows:-GET /services/AboutMePage failed with 403. requestid: 9bee9f1d-3424-b3c4-c6d6-095a46157e9f, message: FC service is not enabled for current user..