Chuyển đến nội dung chính

Thiết lập bộ PDF generator trên AWS Lambda sử dụng python3 và thư viện wkhtmltopdf



I. GIỚI THIỆU:

Trong thời gian gần đây việc tạo một API với thuộc tính scale trở nên dễ dàng hơn trước với việc sử dụng serverless trên nên tảng hệ thống scale tự động sẵn có.

Trong bài viết này tôi sẽ set up một hệ thống API với tính năng scale có khả năng handle 1000 requests trong cùng một lúc.

Đồng thời tôi sẽ show cho bạn cách thiết lập một API với tính năng scale một cách dễ dàng đến mức nào và sau khi kêt thúc bài viết bạn có thể tạo một HTTP endpoint và bạn có thể POST lên một object JSON và nhận một liên kết link của file PDF trên AWS S3.

File JSON như sau:

{   
    "filename": "sample.pdf",   
    "html": "<html><head></head><body><h1>It works! This is the default PDF.</h1></body></html>" 

II. SET UP:

 1. Các yêu cầu cần thiết khi thiết lập:
    - Python3
    - Aws CLI được cài đặt và cấu hình
    - Serverless được cài đặt.

 2. Serverless

  Điều đầu tiên bạn phải khởi động một project dùng serverless. Serverless là một bộ công cụ đơn giản cho việc sử dụng trên môi trường cloud như AWS, Google cloud và Azure, .. những dịch vụ mà khi bạn làm việc mà không phải lo lắng về quản trị Sever thế nào.

Nếu bạn muốn tìm hiểu SERVERLESS bạn truy cập : https://serverless.com
Để khởi tạo một serverless chạy lệnh:

sls create --template aws-python3

WKHTMLTOPDF Binary:

Là bộ nhị phân dùng để turning HTML thành PDF

Bạn download tại đây : https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz

Sau khi giải nén bạn copy file  wkhtmltopdf vào thư mục làm việc của project được tạo phía trên .

./binary/wkhtmltopdf
PYTHON3:

Bây giờ bạn cần python3 để chạy và thư viện pdfkit. Trên serverless bạn không cần pip install pdfkit mà bạn chỉ cần chạy :

sls plugin install -n serverless-python-requirements

Trong file serverless.yml bạn cấu hình:

custom:
     pythonRequirements:  
          dockerizePip: true
 Tạo file: Requirements.txt

pdfkit
III. Giai đoạn DEVELOP

Hai file chính khi ta làm việc trong bài viết này là :

serverless.yml và handle.yml

Cơ bản về syntax của file YML bạn có thể tham khảo tại : https://learn.getgrav.org/16/advanced/yaml

Một phần của file serverless.yml bạn tạo file config.yml có nội dung như sau:

BucketName: 'your-s3-bucket-name' 
Về serverless.yml high-level design sẽ như sau :

service: pdf-services # name or reference to our project 
provider: # It is possible to use Azure, GCloud, or AWS 
functions: # Array of functions to deploy as Lambdas 
resources: # S3 buckets, DynamoDB tables, and other possible resources to create 
plugins: # Plugins for Serverless 
custom: # Custom variables used by you or plugins during setup and deployment

Khi deploy chúng ta cần tạo các bước sau trong file serverless.

1. Tạo S3 bucket để lưu file PDF có tên : pdf-service-bucket
2. Tạo một function để tạo PDF
3. Cấp quyền cho function để access vào S3 bucket
4. Thiết lập một API endpoint cho function.

POST https://xxxx.execute-api.xxxx.amazonaws.com/dev/new-pdf 

Nội dung của file serverless.yml :

service: pdf-service
provider:
  name: aws
  runtime: python3.7
  # Set environment variable for the S3 bucket  environment:
    S3_BUCKET_NAME: ${file(./config.yml):BucketName}
  # Gives our functions full read and write access to the S3 Bucket  iamRoleStatements:
    -  Effect: "Allow"
       Action:
         - "s3:*"
       Resource:
          - arn:aws:s3:::${file(./config.yml):BucketName}
          - arn:aws:s3:::${file(./config.yml):BucketName}/*
functions:
  generate_pdf:
    handler: handler.generate_pdf
    events:
      - http:
          path: new-pdf
          method: post
          cors: true
resources:
 # Creates an S3 bucket in our AWS account Resources:
   NewResource:
     Type: AWS::S3::Bucket
     Properties:
       BucketName: ${file(./config.yml):BucketName}
custom:
  pythonRequirements:
    dockerizePip: true
plugins:
  - serverless-python-requirements
Handle.py là file python mà ta cần, nó chứa đựng một function để generate ra PDF và lưu nó vào lambda.

Trong file này bạn chú ý đến 2 argument : event và context.

context chứa đựng các biến môi trường và các thông tin về hệ thống.
event chứa đựng các dữ liệu yêu cầu, dữ liệu này được gửi đến lambda.

Nội dung file này là:

import json
import pdfkit
import boto3
import os
client = boto3.client('s3')
# Get the bucket name environment variables to use in our code 
S3_BUCKET_NAME = os.environ.get('S3_BUCKET_NAME')
def generate_pdf(event, context):
    # Defaults    key = 'deafult-filename.pdf'
    html = "<html><head></head><body><h1>It works! This is the default PDF.</h1></body></html>"
    # Decode json and set values for our pdf        
if 'body' in event:
        data = json.loads(event['body'])
        key = data['filename']
        html = data['html']
    # Set file path to save pdf on lambda first (temporary storage)    
filepath = '/tmp/{key}'.format(key=key)
    # Create PDF    
    config = pdfkit.configuration(wkhtmltopdf="binary/wkhtmltopdf")
    pdfkit.from_string(html, filepath, configuration=config, options={})

    # Upload to S3 Bucket    
r = client.put_object(
        ACL='public-read',
        Body=open(filepath, 'rb'),
        ContentType='application/pdf',
        Bucket=S3_BUCKET_NAME,
        Key=key
    )
    # Format the PDF URI    
object_url = "https://{0}.s3.amazonaws.com/{1}".format(S3_BUCKET_NAME, key)
    # Response with result    
response = {
        "headers": {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Credentials": True,
        },
        "statusCode": 200,
        "body": object_url
    }
    return response


IV: DEPLOY

Khi deploy chạy câu lệnh sau :

sls deploy 
# or  
serverless deploy

Sau khi deploy xong ta có thông tin về HTTP endpoint  :

https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/new-pdf
Cuối cùng bạn có thể dùng curl để test function chúng ta viết ở trên : 

curl -d '{"filename":"my-sample-filename.pdf", "html":"<html><head></head><body><h1>Custom HTML -> Posted From CURL as {JSON}</h1></body></html>"}' -H "Content-Type: application/json" -X POST https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/new-pdf

Kết quả trả về bạn có thể check được là function đó work hay không ?

V. CONCLUSION

Bạn thấy đó thật sự dễ dạng cho việc tạo một API trên môi trường serverless, môi trường mà bạn không cần phải lo lắng về server như thế nào về maintain server, .... 

Reference:   https://github.com/wkhtmltopdf/wkhtmltopdf

Nhận xét

Bài đăng phổ biến từ blog này

Cách sử dụng sys.argv trong python.

Cách sử dụng sys.argv trong python.

sys.argv là môt danh sách [list] trong python, nó được sư dụng khi bạn chạy một lệnh command-line nào đó trên hệ thống.
Và argument này được đẩy vào script python để thực thi khi chạy câu lệnh.

Ví dụ: python sys.argv arg1 arg2

Trước tiên bạn phải import mô đun sys trong script.



import sys print"This is the name of the script: ", sys.argv[0]print"Number of arguments: ", len(sys.argv)print"The arguments are: ", str(sys.argv)

Tên của script này : sysargv.py
Số lượng arg là : 1
Arg là : ['sysargv.py']


python test1020.py 111 This is the name of the script:  test1020.py
Number of arguments:  2
The arguments are:  ['test1020.py', '111']

Thiết kế một RESTful API bằng python và flask.

Như các bạn đã biết thì REST viết tắt bởi REpresentational State Transfer. Bạn có thể tham khảo thêm ở đây.

Vậy REST là gì:

Có 6 yếu tố của REST như sau:

1. Client-Server: phía server side phục vụ như một service còn phía client sẽ dùng service này.

2.Stateless:  Mỗi request từ client phải chứa tất cả các thông tin mà phía server yêu cầu phải có. Nói nôm na là mỗi request chứa các thông tin riêng rẽ không liên quan đến những request khác.

3. Cacheable : Phía server side phải cảnh báo chỉ ra cho client side biết là request đó có cache hay không.

4. Hệ thống phân lớp: Giao tiếp giữa server side và client side có thể thông qua lớp trung gian ở giữa để trả lời các request được gọi mà không cân phía client phải làm những động tác khác nữa.

5. Các cổng giao tiếp là giống nhau : Các phương thức giao tiếp giữa client và server là khuôn mẫu giống nhau.

6. Mã code linh động. Phía server có thể thực thi cho môt API gọi duy nhất mà không ảnh hưởng tới các API khác.

RESTful web service là gì :

Kiế…

Cài đặt docker trên windows server 2016.

1. Cài đặt Windows Server 2016 Container Feature:  Mở PowerShell : Cài đặt các container feature dùng powershell: Dùng lệnh: InstallWindowsFeature containers Restart lại windows: 2. Cài đặt windows server 2016 base image:  Cài đặt mô đun : ContainerImage Dùng lệnh: Install-PackageProvider ContainerImage -force List các image có giá trị: Cài đặt Windows Server Core : 3. Cài đặt docker trên windows server 2016. Download script để cài đặt docker : Chạy script : Kiểm tra các image có trên server :