# huaweicloud-Serverless-FunctionGraph-RedEnvelope-Python-Sample **Repository Path**: HuaweiCloudDeveloper/huaweicloud-serverless-function-graph-red-envelope-python-sample ## Basic Information - **Project Name**: huaweicloud-Serverless-FunctionGraph-RedEnvelope-Python-Sample - **Description**: 华为云-开发者联盟-Serverles-FunctionGraph-RedEnvelope-Python示例代码 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master-dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-01-12 - **Last Updated**: 2023-04-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 华为云 FunctionGraph For Red Envelope项目演示 ## 1. 说明 本项目将演示通过华为云FunctionGraph实现抢红包场景,让开发者上手体验FunctionGraph。 ### 1.1 环境准备 * python3.9.2 * Pycharm 2022+ ### 1.2 必备PyPI包 * influxdb==5.3.1 * kafka-python==2.0.2 * redis==4.3.4 * python-redis-lock==3.7.0 * python-socketio==5.7.2 * aiohttp==3.8.3 * aiokafka==0.8.0 ### 1.3 基础云服务能力 * 分布式缓存服务(Distributed Cache Service,简称DCS) 更多详情,请参考 [分布式缓存服务 成长地图](https://support.huaweicloud.com/dcs/index.html) * 高性能云数据库 GaussDB(for Influx) 更多详情,请参考 [GaussDB(for Influx) 成长地图](https://support.huaweicloud.com/influxug-nosql/nosql_05_0039.html) * 分布式消息服务Kafka版 更多详情,请参考 [分布式消息服务Kafka版 成长地图](https://support.huaweicloud.com/kafka/index.html) * 对象存储服务(Object Storage Service,OBS) 更多详情,请参考 [对象存储服务 OBS 成长地图](https://support.huaweicloud.com/obs/index.html) * 云容器实例(Cloud Container Instance, CCI) 更多详情,请参考 [云容器实例 CCI 成长地图](https://support.huaweicloud.com/cci/index.html) * API网关(APIG) 更多详情,请参考 [API网关 APIG 成长地图](https://support.huaweicloud.com/apig/index.html) ### 1.4 核心代码介绍 * api_grab/index.py 为抢红包的业务逻辑 * api_send/index.py 为发红包的业务逻辑 * util/config_center.py 为配置中心,负责加载环境变量中的配置信息 * util/influx_connect.py 为对influxdb的连接,可以对influx进行增删改查 * util/kafka_producer_connect.py 为kafka的生产者实现,负责连接kafka发送消息 * util/middleware.py 为中间件实现,通过python装饰器实现分布式锁规避在并发情况下,抢红包金额无法正确划分问题。 * util/redis_connect.py 为对redis的连接,实现对redis进行增查功能 * util/response_format.py 为响应的格式化,FunctionGraph配置APIG触发器响应格式是必须带有个别字段。 * util/aio_kafka_consumer_connect.py 异步kafka消费者实现,负责消费kafka消息。 * util/logger.py 日志模块。 * test_case/base64_param_encode.py 在FunctionGraph配置测试事件时,body需要通过base64加密。 * test_case/common.py 存放测试用的常量值。 * test_case/kafka_client_connect.py kafka主用户实现,负责topic的增删。 * test_case/kafka_consumer_connect.py kafka消费者实现。 * test_case/test_create_terminal_for_user.py 通过打开多终端模拟多个用户抢红包。 * test_case/test_many_user.py 用户运行逻辑。 * test_case/test_prepared.py 测试准备代码。 * websocket_app/app_asyncio.py.py 异步websocket_APP代码。 ## 2.项目部署 ### 2.1 本地必备程序 1. window10操作系统 2. 下载并安装[python3.9.2](https://www.python.org/downloads/release/python-392/) 。(注意安装后需要确认是否设置了python环境变量) 3. 下载并安装[Pycharm 2022+](https://www.jetbrains.com.cn/en-us/pycharm/) 4. 下载并安装[node.js 16.17.0](https://nodejs.org/dist/v16.17.0/) 。( 注意安装后需要确认是否设置了node.js环境变量) ### 2.2 基础环境搭建 1. 创建虚拟私有云 VPC ([快速入门](https://support.huaweicloud.com/qs-vpc/vpc_qs_0001.html)) 2. 购买分布式缓存服务 DCS ([快速入门](https://support.huaweicloud.com/dcs/index.html)) 3. 购买云数据库 GaussDB(for Influx) ([快速入门](https://support.huaweicloud.com/influxug-nosql/nosql_05_0039.html)) 4. 购买分布式消息服务Kafka版 ([快速入门](https://support.huaweicloud.com/kafka/index.html)) 5. 购买API网关专享版([快速入门](https://support.huaweicloud.com/apig/index.html)) ### 2.3 部署(两个函数部署方式一致,创建的委托等资源可以复用) 1. 拉取代码 * git拉取代码,示例: >cd D:// git clone https://gitee.com/HuaweiCloudDeveloper/huaweicloud-serverless-function-graph-red-envelope-python-sample.git * 进入[代码仓](https://gitee.com/HuaweiCloudDeveloper/huaweicloud-serverless-function-graph-red-envelope-python-sample) ,下载代码zip文件,解压zip文件到任意文件夹。 ![download_code_zip](./image4md/download_code_zip.PNG) 2. 创建函数 步骤一 ![create_function01](./image4md/create_function01.PNG) 步骤二 ![create_function02](./image4md/create_function02.PNG)
3. 创建委托 步骤一 ![create_agency01](./image4md/create_agency01.PNG) 步骤二 ![create_agency02](./image4md/create_agency02.PNG) 步骤三 可以根据函数所需云服务定制权限限制的权限,Tenant Administrator为除了iam用户权限所有云服务权限。函数主要用到服务有DIS,DMS以及VPC的访问权限 ![create_agency03](./image4md/create_agency03.PNG) 步骤四 选择已创建的委托,并点击保存 ![create_agency04](./image4md/create_agency04.PNG)
4. 上传函数 步骤一 ![upload_function01](./image4md/upload_function01.PNG) 步骤二 ![upload_function02](./image4md/upload_function02.PNG)
5. 设置VPC 步骤一 建议选择与其他服务实例(Kafka, redis, influxdb)相同的VPC及子网,并点击保存 ![set_vpc](./image4md/set_vpc.PNG)
6. 设置环境变量 ![env](./image4md/env.PNG) 注意:环境变量填写完,请点击保存。 KAFKA_CLUSTERS ![kafka_cluster](./image4md/kafka_cluster.PNG) 注1:KAFKA_CLUSTERS的值格式应为["ip:port", "ip:port"], 例["110.110.111.11:9092", "110.110.111.12:9092"]
REDIS_HOST、REDIS_PORT、REDIS_PASSWORD ![redis](./image4md/redis.PNG) 注1:REDIS_PASSWORD为创建服务实例时设置密码 注2:这里的Redis服务是分布式缓存服务 Redis版
INFLUX_HOST、INFLUX_PORT、INFLUX_USERNAME、INFLUX_PASSWORD ![influx](./image4md/influx.PNG) 注1:INFLUX_PASSWORD为创建服务实例时设置密码
7. 绑定API网关专享版触发器 步骤一 创建触发器 ![create_trigger01](./image4md/create_trigger01.PNG) 步骤二 选择APIG专享版 ![create_trigger02](./image4md/create_trigger02.PNG) 步骤三 创建成功 ![create_trigger03](./image4md/create_trigger03.PNG)
8. 制作依赖/上传依赖 步骤一 制作依赖(本步骤可以选择跳过,已有制作好的依赖包直接上传,red_envelope_function\dependency.zip)
环境准备:制作函数依赖包推荐在EulerOS环境中进行,原因函数执行的操作系统为EulerOS,使用其他系统打包可能会因为底层依赖库的原因,运行出问题,比如找不到动态链接库。
编写requirements.txt文件。 > vi /tmp/requirements.txt 将所有需要的包写入其中,例: ``` influxdb==5.3.1 kafka-python==2.0.2 redis==4.3.4 python-redis-lock==3.7.0 requests==2.28.1 ``` 安装第三方依赖包 > pip install -r /tmp/requirements.txt --target=/tmp/dependency -i https://repo.huaweicloud.com/repository/pypi/simple --extra-index-url=https://pypi.tuna.tsinghua.edu.cn/simple --extra-index-url=https://pypi.mirrors.ustc.edu.cn/simple/ --trusted-host pypi.tuna.tsinghua.edu.cn --trusted-host pypi.mirrors.ustc.edu.cn 注意:可能会出现个别包版本不存在的情况,可以尝试更改-i参数后面的镜像源地址
切换到依赖包的安装目录 > cd /tmp/dependency 打包所有依赖到zip文件(zip找不到,下载并安装zip) > zip -rq dependency.zip * 下载dependency.zip到本地 步骤二 上传依赖 ![create_dependency01](./image4md/create_dependency01.PNG) ![create_dependency02](./image4md/create_dependency02.PNG) ![create_dependency03](./image4md/create_dependency03.PNG) ![create_dependency04](./image4md/create_dependency04.PNG) ### 2.4 测试 > **测试前准备** > 步骤一 购买NAT网关,并通过NAT网关开通DNAT规则,让本地PC可以访问Kafka及influxdb。(假设使用的同VPC下的ECS,该步骤可跳过,可使用各服务实例的内网地址) > ![DNAT](./image4md/DNAT.PNG) > Kafka内网IP三选一 > ![DNAT01](./image4md/DNAT01.PNG) > ![DNAT](./image4md/DNAT03.PNG) > Influxdb内网IP二选一 > ![DNAT01](./image4md/DNAT02.PNG) > 步骤二 添加本地PC环境变量 > ![window_env](./image4md/window_env.PNG) > KAFKA_CLUSTERS变量值填入"[弹性公网ip:公网端口]",例如"101.0.0.1:9090"(具体值在下一张图) > ![window_env](./image4md/env_window01.PNG) > ![kafka_host_port](./image4md/kafka_host_port.PNG) > INFLUX_HOST > ![window_env](./image4md/window_env01.PNG) > INFLUX_PORT > ![window_env](./image4md/window_env02.PNG) > ![window_env](./image4md/window_env03.PNG) > INFLUX_USER,INFLUX_PASSWORD如上操作,为创建influxdb时设置账户密码。 > 步骤三 代码创建influxdb中databases。 > ![create_influxdb_database](./image4md/create_influxdb_database.PNG) > 注意:运行程序时环境变量没生效请重启Pycharm > 注意:报错找不到相关依赖,请打开Pycharm终端执行命令 pip install -r requirements.txt > 步骤四 代码创建kafka中topic(如果已设置自动创建topic可以忽略此步骤)。 > ![create_kafka_topic](./image4md/create_kafka_topic.PNG) 1. 发红包函数测试 步骤一 配置测试事件 进入send_api函数编辑页面,点击测试及配置测试事件。 ![set_test01](./image4md/set_test01.PNG) 运行项目中test_case/base64_param_encode.py,复制base64加密参数。 ![send_params](./image4md/send_params.PNG) 加密参数粘贴至body部分,修改httpMethod为POST。 ![test_case](./image4md/test_case.PNG) 步骤二 测试 注意:首次测试时,会因为创建连接的原因,运行时间相对较久,导致函数超时。需要设置执行超时时间。例: ![time_out](./image4md/time_out.PNG) 步骤三 验证结果 ![send_success](./image4md/send_success.PNG)
2. 抢红包函数测试 步骤一 配置测试事件 进入grab_api函数编辑页面,点击测试及配置测试事件。 ![set_test01](./image4md/set_test01.PNG) 运行项目中test_case/base64_param_encode.py,修改红包id,复制base64加密参数。 ![grab_params](./image4md/grab_params.PNG) 加密参数粘贴至body部分,修改httpMethod为POST。 ![test_case](./image4md/test_case.PNG) 步骤二 测试 注意:首次测试时,会因为创建连接的原因,运行时间相对较久,导致函数超时。需要设置执行超时时间。例: ![time_out](./image4md/time_out.PNG) 步骤三 验证结果 ![grab_success](./image4md/grab_success.PNG)
3. 接口测试 步骤一 进入APIG界面,点击进入专享版控制台 [API网关](https://console.huaweicloud.com/apig) ![apig_test01](./image4md/apig_test01.PNG) 步骤二 创建应用 ![apig_test02](./image4md/apig_test02.PNG) 步骤三 绑定API ![apig_test03](./image4md/apig_test03.PNG) 步骤四 选定两个已创建API ![apig_test04](./image4md/apig_test04.PNG) 步骤五 点击调试 ![apig_test05](./image4md/apig_test05.PNG) 步骤六 调试发红包API ![apig_test06](./image4md/apig_test06.PNG) 步骤七 调试抢红包API ![apig_test07](./image4md/apig_test07.PNG)
4. 模拟多用户,开始监听消费队列 步骤一 修改 项目根路径/test_case/common.py常量值 ![common_constant](./image4md/common_constant.PNG) API网关公网IP ![apig_host](./image4md/apig_host.PNG ) 接口路径(发红包接口同理) ![api_rounter_01](./image4md/api_rounter_01.PNG) ![api_rounter_02](./image4md/api_rounter_02.PNG) 步骤二 允许接口简易认证(两个接口都需要操作) 进入接口页面 ![allow_sample_authentication01](./image4md/allow_sample_authentication01.PNG) 点击编辑 ![allow_sample_authentication02](./image4md/allow_sample_authentication02.PNG) 开启支持简易认证,点击立即完成 ![allow_sample_authentication03](./image4md/allow_sample_authentication03.PNG) 点击发布API ![allow_sample_authentication04](./image4md/allow_sample_authentication04.PNG) 选择环境,点击发布 ![allow_sample_authentication05](./image4md/allow_sample_authentication05.PNG) 步骤三 添加应用AppCode 选择自动生成 ![add_app_code](./image4md/add_app_code.PNG) 步骤四 将生成的AppCode及域名host写入访问请求头 域名host ![domain_host](./image4md/domain_host.PNG) ![grab_app_code](./image4md/grab_app_code.PNG) ![send_app_code](./image4md/send_app_code.PNG) 步骤五 多进程模拟用户监听红包消息 ![user_grab_red_envelope](./image4md/user_grab_red_envelope.PNG) ![user_grab](./image4md/user_grab.PNG)
5. 模拟用户发送红包 点击运行 ![send_red_envelope](./image4md/send_red_envelope.PNG) 成功发送 ![success_send](./image4md/success_send.PNG) 抢红包场景模拟成功 ![success_grab](./image4md/success_grab.PNG)
6. 页面交互测试 * 本地部署 > 前提条件 > 1. 本地已配置KAFKA_CLUSTERS环境变量,并测试连接成功 > 步骤一 运行Websocket APP ![local_run_websocket_app](./image4md/local_run_websocket_app.PNG) 步骤二 修改 项目根目录/red_envelope_front/.env.development 文件 ![local_dev_env](./image4md/local_dev_env.PNG) 注意:VUE_APP_DOMAIN可以使用API分组自动生成的子域名,因子域名没有备案请参考2.5 常见问题 3 进行相关操作 步骤三 新建终端,运行前端代码 > cd red_envelope_front > > npm install > > npm run dev > ![local_run_dev](./image4md/local_run_dev.PNG) 步骤四 打开Chrome浏览器,访问前端页面 ![local_test](./image4md/local_test.PNG) 步骤五 测试各功能 ![local_test_01](./image4md/local_test_01.PNG) * OBS + CCI + DNS + APIG部署 > 项目描述 通过OBS托管静态页面,CCI部署WebSocket APP,APIG统一后端服务入口。因OBS无法通过Nginx作为代理服务器代理转发请求, 所以需要两个域名分别解析前端页面及APIG网关,通过浏览器访问时,会出现跨域问题。 > > 前提条件 > 1. 拥有已备案通过的公网域名,详见[域名注册](https://support.huaweicloud.com/domain/index.html) > 2. CCI, APIG, KAFKA, INFLUXDB, REDIS都在同一个VPC内 > 步骤一 制作WebSocket APP镜像及CCI部署WebSocket APP(操作在linux环境下完成) 拉取代码 > cd /tmp > git clone https://gitee.com/HuaweiCloudDeveloper/huaweicloud-serverless-function-graph-red-envelope-python-sample.git 进入项目根目录 > cd huaweicloud-serverless-function-graph-red-envelope-python-sample > 登录华为云SWR(可在SWR总览右侧登录指令复制登录命令) > docker login xxx > 注意:留意所在Region > docker build -t red_envelope_websocket:test . > docker tag red_envelope_websocket:test swr.cn-south-1.myhuaweicloud.com/{组织名}/red_envelope_websocket:test > docker push swr.cn-south-1.myhuaweicloud.com/{组织名}/red_envelope_websocket:test > 注意:请根据自定义组织名修改命令行中组织名 CCI页面操作步骤,单击创建无状态负载 ![CCI_Websocket_01](./image4md/CCI_Websocket_01.PNG) 注意:因业务逻辑原因,POD数量只需1个。 ![CCI_Websocket_02](./image4md/CCI_Websocket_02.PNG) ![CCI_Websocket_03](./image4md/CCI_Websocket_03.PNG) 步骤二 WebSocket APP绑定APIG接口 ![CCI_Websocket_APIG_01](./image4md/CCI_Websocket_APIG_01.PNG) ![CCI_Websocket_APIG_02](./image4md/CCI_Websocket_APIG_02.PNG) ![CCI_Websocket_APIG_03](./image4md/CCI_Websocket_APIG_03.PNG) 后端服务地址于websocket工作负载页面-访问配置-内网访问地址,如下图: ![CCI_Websocket_APIG_04](./image4md/CCI_Websocket_APIG_04.PNG) ![CCI_Websocket_APIG_05](./image4md/CCI_Websocket_APIG_05.PNG) ![CCI_Websocket_APIG_06](./image4md/CCI_Websocket_APIG_06.PNG) 步骤三 APIG绑定域名 ![APIG_Domain](./image4md/APIG_Domain.PNG) ![APIG_Domain_01](./image4md/APIG_Domain_01.PNG) ![APIG_Domain_02](./image4md/APIG_Domain_02.PNG) 步骤四 修改 项目根目录/red_envelope_front/.env.production 文件 ![obs_pro_env](./image4md/obs_pro_env.PNG) 步骤五 构建前端代码 通过PyCharm新建终端,切换目录 > cd red_envelope_front > > npm run build > 步骤六 上传前端代码至OBS(建议通过[OBS Browser+](https://support.huaweicloud.com/intl/zh-cn/browsertg-obs/obs_03_1003.html) 上传) ![upload_obs](./image4md/upload_obs.PNG) ![upload_obs](./image4md/upload_obs_01.PNG) 步骤七 配置静态页面托管 ![set_static_page](./image4md/set_static_page.PNG) ![set_static_page_01](./image4md/set_static_page_01.PNG) 步骤八 配置自定义域名 ![set_domain](./image4md/set_domain.PNG) ![set_domain](./image4md/set_domain_01.PNG) 步骤九 DNS解析 ![set_APIG_Domain](./image4md/set_APIG_Domain.PNG) ![set_OBS_Domain](./image4md/set_OBS_Domain.PNG) OBS静态页面域名,如下图: ![OBS_domain](./image4md/OBS_domain.PNG) 步骤十 配置跨域预校验OPTION请求 ![create_option_api](./image4md/create_option_api.PNG) ![create_option_api_01](./image4md/create_option_api_01.PNG) ![create_option_api_02](./image4md/create_option_api_02.PNG) ![CCI_Websocket_APIG_05](./image4md/CCI_Websocket_APIG_05.PNG) ![CCI_Websocket_APIG_06](./image4md/CCI_Websocket_APIG_06.PNG) 步骤十一 打开Chrome浏览器,访问前端页面 ![pro_test](./image4md/pro_test.PNG) 步骤十二 测试各功能 ![pro_test_01](./image4md/pro_test_01.PNG) ### 2.5 常见问题 1. 实例需要打开对应的端口安全组入方向规则,让各服务之间可以互相访问。
2. 导致各数据库或消息队列实例连接超时原因,一般为安全组入方向规则没有打开或者打开错误。
3. 未备案域名,服务器配置IP映射域名。 > * windows >> 修改 C:\WINDOWS\system32\drivers\etc\hosts 文件。 >> ![](./image4md/windows_hosts.PNG) >> 打开cmd,测试域名是否能访问。 >> ``` >> ping 域名 >> ``` >> ![](./image4md/windows_ping.PNG) > * linux >> 修改 /etc/hosts 文件。 >> ``` >> vim /etc/hosts >> ``` >> ![](./image4md/linux_hosts.PNG) >> ``` >> ping 域名 >> ``` >> ![](./image4md/linux_ping.PNG) > > 注意:域名是网址的组成部分,例如http://localhost.com/test 中localhost.com为域名