11 月 19 - 20 日 Apache Pulsar 社区年度盛会来啦,立即报名! 了解详情
写点什么

通过预热 Amazon WorkSpaces 提升用户操作体验

  • 2020-04-19
  • 本文字数:9566 字

    阅读完需:约 31 分钟

通过预热 Amazon WorkSpaces 提升用户操作体验

1. 前言

Amazon WorkSpaces 提供了灵活的付费方式,使得用户可以按月或按小时付费。按月计费适合需要全天使用 Amazon WorkSpaces 或将其用作主要桌面的工作人员。对于并非需要长时间运行的工作场景,比如兼职工作人员、临时性工作分担、频繁出差的人员、短期项目、在线培训和教育等,使用按小时付费是一种能够很好节约成本的方式。Amazon WorkSpaces 计费模式能够非常灵活的进行选择和切换,只需要通过配置相应实例的运行模式(Running Mode)即可。Amazon WorkSpaces 提供两种运行模式以适配不同的计价模式:


  • AlwaysOn — 按月计费,WorkSpace 将始终处于运行状态,用户可随时访问。

  • AutoStop — 按小时计费,WorkSpace 将在指定的不活动时间(小时,最少为 1 最大为 48) 之后自动停止,并在用户下次登录时恢复。


Amazon WorkSpaces 在自动停止后,当用户重新连接到已停止的 WorkSpace 时,它会恢复到其上次停止时的状态,这个恢复过程通常在 90 秒内。对于大多数用户来说,WorkSpace 客户端等待 90 秒时间才能进入是难以接受的,因此我们可以考虑通过“预热”方式提前为用户启动恢复过程,让等待时间变得更短或直接能“立即访问”,这样将会大大提高用户的操作体验。


本文按照用户的操作需要将“预热”操作分为两种模式,即按需预热和定时预热。以下将分别介绍两种预热模式的实现方式。


2. 按需预热

2.1 架构说明

按需预热模式,即终端用户对于 WorkSpaces 可访问时间有比较明确的预期,可以通过自助提交请求来实现预热,适用于如出差、定时会议或启动培训计划等场景。


按需预热的本质是接收到用户请求后,生成一个定时任务,此任务可在用户请求的时间点之前完成 WorkSpace 的恢复启动操作。定时任务通常可以使用 CloudWatch 来实现,但默认情况下 CloudWatch 规则上限为 100 条,虽然该上限限制可以通过提交后台申请来进行调整,但为所有请求各自创建一个 CloudWatch 定时规则来执行业务逻辑并不是一个非常合适的方式。因此,我们可以通过使用一个固定频率执行的 CloudWatch 规则执行 Lambda 来读取持久化保存的按需请求数据来触发预热操作。


本文使用 DynamoDB 保存按需预热请求,整体架构如下:



2.2 配置 IAM 及 DynamoDB

2.2.1 DynamoDB 配置

在 DynamoDB 里中创建一个表为 Jobs 的表,用于保存按需预热请求。Jobs 表使用 id 作为主键,并使用 on_at 字段作为二级索引。DynamoDB 将保存来自用户的按需预热请求,完整字段定义如下:


col 1col 2
字段名用途
id任务唯一编号(自动生成),主键
usernameWorkSpaces 用户名
spaceidWorkSpaces ID(可选)
on_at计划使用时间,DynamoDB 将以 ISO 格式保存,形如2020-03-03T12:12:12



2.2.2 IAM 策略配置

在 IAM 中为按需预热 Lambda 函数配置相应角色 OnDemandRequestRole,角色对应的策略定义如下:


Java


{    "Version": "2012-10-17",    "Statement": [        {            "Sid": "state1",            "Effect": "Allow",            "Action": [                "dynamodb:DeleteItem",                "dynamodb:GetItem",                "dynamodb:PutItem",                "dynamodb:Scan",                "dynamodb:UpdateItem"            ],            "Resource": "arn:<partition>:dynamodb:<region>:<account-id>:table/Jobs"        },        {            "Sid": "state2",            "Effect": "Allow",            "Action": [                "logs:CreateLogStream",                "logs:PutLogEvents"            ],            "Resource": "arn:<partition>:logs:<region>:<account-id>:log-group:/aws/lambda/OnDemandRequest:*"        },        {            "Sid": "state3",            "Effect": "Allow",            "Action": "logs:CreateLogGroup",            "Resource": "arn:<partition>:logs:<region>:<account-id>:*"        }    ]}
复制代码



2.3 创建按需请求 Lambda

接收请求并创建定时任务的 Lambda 代码(OnDemandRequest)如下:


Java


from datetime import datetime
import jsonimport uuid
import boto3
def lambda_handler(event, context): """ Lambda function export to API Gateway to recieve a json formatted post job. JSON parameters description: 'username': The username of WorkSpace. Required. 'spaceid': The WorkSpace ID request to warm-up. Optional. If not assign, will warm up all WorkSpace of the user. 'on_at': The will to be used time of the WorkSpace. Required.
For example: { "username": "xxxxx", "spaceid": "ws-1234abcd", "on_at": "2020-03-03 12:12:12" } """ print('Recieved on demand warm-up request - [%s].' % json.dumps(event))
jobID = str(uuid.uuid1()) on_at = datetime.strptime(event['on_at'], '%Y-%m-%d %H:%M:%S').isoformat()
try: dynamodb = boto3.resource('dynamodb', region_name='cn-northwest-1') table = dynamodb.Table('Jobs')
table.put_item( Item={ 'id': jobID, 'username': event['username'], 'spaceid': event.get('spaceid', '-'), 'on_at': on_at } )
print('On demand warm-up request has created with jobID [%s].' % jobID)
return { 'statusCode': 200, 'body': { 'id': jobID } } except Exception as ex: return { 'statusCode': 500, 'body': { 'error': ex } }
复制代码


在 Lambda 控制台中使用 OnDemandRequestRole 角色将 OnDemandRequest 部署为基于 Python3.7 的 Lambda 函数。



2.4 配置 API Gateway

配置 API Gateway,新建 REST API 以用于接收 HTTP Post 请求并调用 OnDemandRequest Lambda。



创建 POST 操作方法调用之前部署的 OnDemandRequest Lambda 函数



注意:若使用宁夏或北京区域的 API Gateway,需要提供 ISP 备案或配置方法请求的身份验证为 AWS_IAM。



部署 API,并记录相应 Endpoint。



2.5 配置 CloudWatch 定时任务

配置 CloudWatch,创建固定频率规则用于执行定时任务检查 DynamoDB 是否有需要执行的任务。



2.6 使用 awscurl 测试

现在我们可以通过 Endpoint 提交按需预热请求。使用基于 AWS_IAM 方式进行授权的 Endpoint,需要在对调用请求进行预签名。我们可以使用 awscurl 工具来执行预签名的 URL 的调用。


awscurl 工具可以通过以下命令来安装和使用。


Java


pip install awscurlexport AWS_ACCESS_KEY_ID="<your-account-access-key-id>"export AWS_SECRET_ACCESS_KEY="<your-account-secret-access-key>"awscurl --region <your-api-region> "<your-api-endpoint>" -X POST -d "{\"username\": \"<workspace-username>\", \"spaceid\": \"<workspace-id> \", \"on_at\": \"<request-on-datetime, format as: 2020-03-03 12:12:12>\"}"
复制代码



按需操作接收的 Post 格式如下:


Java


{  "username": "xxxxx",  "spaceid": "ws-1234abcd",  "on_at": "2020-03-03 12:12:12"}
复制代码



打开 WorkSpaces 控制台,可以看到该用户所对应的 WorkSpaces 在指定时间前 180 秒时已将状态从 STOPPED 切换为 STARTING。


3. 定时预热

3.1 架构说明

定时预热相对与按需预热的实现相对简单,可以通过配置 CloudWatch 规则执行定时 Lambda 任务来启动 WorkSpaces 实例,本文中的定时任务未对待启动的 Workspaces 进行过滤,实际使用过程中可以通过额外的配置(如 S3 文件、RDS、DynamoDB 等持久化服务)来自定义具体任务执行的条件。



定时预热整体架构如下:


3.2 配置 IAM

在 IAM 中为定时预热 Lambda 函数配置相应角色 OnScheduleScannerRole,角色对应的策略定义如下:


Java


{    "Version": "2012-10-17",    "Statement": [        {            "Sid": "state1",            "Effect": "Allow",            "Action": [                "workspaces:StartWorkspaces",                "workspaces:DescribeWorkspaces"            ],            "Resource": "arn:<aws-partitionname>:workspaces:<region>:<account-id>:workspace/*"        },        {            "Sid": "state2",            "Effect": "Allow",            "Action": [                "workspaces:DescribeWorkspaceDirectories"            ],            "Resource": " arn:<aws-partitionname>:workspaces:<region>:<account-id>:*"        }    ]}
复制代码



3.3 创建定时预热 Lambda

定时预热 Lambda 代码(OnScheduleScanner) 如下:


Java


from datetime import datetime
import boto3
def lambda_handler(event, context): """ Lambda function used with CloudWatch Rule Event to execute scheduled WorkSpaces warm-up job. Can pass in a DirectoryId as parameter, for example: event['directory'] = 'd-123456' if no DirectoryId specified, the job will scan all available Directoies and warm-up WorkSpaces. """
print('Start scheduled warm-up at %s.' % datetime.now().strftime('%Y-%m-%d %H:%M:%S')) directory = event.get('directory', None)
try: directories = [] workspaces = []
client = boto3.client('workspaces')
check = {} if directory is None else {'DirectoryIds': [directory]}
resp = client.describe_workspace_directories(**check)
while resp: directories += resp['Directories']
resp = client.describe_workspace_directories( **check, NextToken=resp['NextToken'] ) if 'NextToken' in resp else None
for dir in directories: dir_id = dir['DirectoryId'] resp = client.describe_workspaces(DirectoryId=dir_id)
while resp: workspaces += resp['Workspaces']
resp = client.describe_workspaces( DirectoryId=dir_id, NextToken=resp['NextToken'] ) if 'NextToken' in resp else None
for workspace in workspaces: if workspace['State'] == 'STOPPED': client.start_workspaces( StartWorkspaceRequests=[{ 'WorkspaceId': workspace['WorkspaceId'] }] )
print('Starting WorkSpace for id - [%s].' % workspace['WorkspaceId']) except Exception as ex: print('Error to run scheduled warm-up job - [%s].' % ex)
复制代码


在 Lambda 控制台中使用 OnScheduleScannerRole 角色将 OnScheduleScanner 部署为基于 Python3.7 的 Lambda 函数。



在 Lambda 控制台中使用 OnScheduleScannerRole 角色将 OnScheduleScanner 部署为基于 Python3.7 的 Lambda 函数。


3.4 配置 CloudWatch 定时规则

在 CloudWatch 中配置一个定时任务并选择 OnScheduleScanner 为目标。



打开 WorkSpaces 控制台,可以看到在定时任务指定的时间点之后,所有状态为 STOPPED 的实例状态已改变。



附录

本文中代码及 IAM 策略配置参数如下:


  • :资源所处分区。对于标准 AWS 区域,分区是 aws。如果资源位于其他分区,则分区是 aws-partitionname。例如,位于 中国(北京) 区域的资源的分区为 aws-cn。

  • :区域标识。如 cn-northwest-1。

  • :资源的 AWS 账户 ID(不含连字符)。如 123456789012。


作者介绍:陈昊,AWS 合作伙伴解决方案架构师,有将近 20 年的 IT 从业经验,在企业应用开发、架构设计及建设方面具有丰富的实践经验。目前主要负责 AWS (中国)合作伙伴的方案架构咨询和设计工作,致力于 AWS 云服务在国内的应用推广以及帮助合作伙伴构建更高效的 AWS 云服务解决方案。


本文转载自 AWS 技术博客。


原文链接:https://amazonaws-china.com/cn/blogs/china/enhance-user-experience-by-preheating-amazon-workspaces/


2020-04-19 17:16322

评论

发布
暂无评论
发现更多内容

大疆被制裁,请马上卸载postman!

Liam

程序员 Postman 开发工具 API swagger

python DataFrame数据合并 merge()、concat()方法,拿下我人生中第7个Offer

程序媛可鸥

Python 程序员 面试

Python GUI编程:关于 tkinter 怎么才能写出更好看的界面,华为架构师深入讲解Python开发

程序媛可鸥

程序员

向工程腐化开炮|动态链接库so治理

阿里巴巴终端技术

android 动态链接库

2022年中小企业数据安全如何保障?对比华为云与其他云计算大厂,15分钟的字节跳动视频面试

程序媛可鸥

Python 程序员 面试

Python中return和yield的区别,2021年Python笔试题总结

程序媛可鸥

Python 程序员 面试

python中把列表中的字符串转成整型的3种方法,收割快手,字节,百度,美团的Offer之旅

程序媛可鸥

Python 程序员 面试

Kafka 常用命令总结,高级Python面试题

程序媛可鸥

Python 程序员 面试

python3的变量作用域规则和nonlocal关键字,Python面试及答案

程序媛可鸥

Python 程序员 面试

Python 开发编码规范,阿里面试100%会问到的JVM

程序媛可鸥

Python 程序员 面试

python回调函数之获取jenkins构建结果,Python编程零基础

程序媛可鸥

Python 程序员 面试

飞桨助力动车3C车载智能识别,为动车组运行保驾护航

百度大脑

龙蜥开发者说:从入坑到入门 | 第 2 期

OpenAnolis小助手

开源 龙蜥社区 开发者说 技术的力量

Python“鉴黄”小程序,我离职后面试收割小米等大厂offer

程序媛可鸥

Python 程序员 面试

2021年【大学生Python学习】社区&&小博主,2021最新大厂高频微服务面试总结

程序媛可鸥

Python 程序员 面试

python3 基础小练习: 判断闰年,2021最新Python算法相关面试大

程序媛可鸥

Python 程序员 面试

使用MASA.Blazor写一个标准的查询表格页

MASA技术团队

Python中用tuple作为key,写的太详细了

程序媛可鸥

Python 程序员 面试

浅谈NIO和Epoll实现原理

Linux服务器开发

网络编程 epoll Linux服务器开发 Linux后台开发 网络io

WorkPlus移动平台 | 如何建设“智慧校园”新样态?

WorkPlus Lite

python函数练习题,万字长文

程序媛可鸥

Python 程序员 面试

nginx5种负载策略的设置方法,看完直接怼产品经理

程序媛可鸥

Python 程序员 面试

阿里巴巴副总裁陈丽娟:我对阿里云产品生态的思考 | 云原生加速器观点

阿里巴巴云原生

python 同时迭代多个序列,还没吃透内存缓存LruCache实现原理的看这篇文章

程序媛可鸥

Python 程序员 面试

2022年中国在线音乐市场年度综合分析

易观分析

Flutter 图片库高燃新登场

阿里巴巴终端技术

flutter

Python 实现二叉树前序,中序,后序,零基础也能看得懂

程序媛可鸥

Python 程序员 面试

Python代码报错看不懂?记住这些报错提示单词轻松解决bug,2021年Python开发陷入饱和,

程序媛可鸥

Python 程序员 面试

Python基础教程:print输出带颜色的方法详解,Python开发基础面试题

程序媛可鸥

Python 程序员 面试

jQuery入门到精通学习教程,收藏我这篇就够了,Alibaba高并发业务实战文档

程序媛可鸥

Python 程序员 面试

从硬件到软件,教你从零搭建智慧农业大脑

华为云开发者联盟

物联网 智慧农业 华为云IoT 小熊开发板 STM32L431芯片

通过预热 Amazon WorkSpaces 提升用户操作体验_文化 & 方法_亚马逊云科技 (Amazon Web Services)_InfoQ精选文章