AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > Serverless-GameServer-Workshop # 全局参数段 Globals: Function: Timeout: 300 # Lambda 函数执行超时时间,单位是秒 # 资源段 # 服务端所有的资源会在 SAM template 中定义 # SAM 底层的原理是会创建一个 cloudformation 来进行资源的管理 Resources: ###--- HTTP Service ---### PlayerMgr: # 资源的名称 Type: AWS::Serverless::Api # 资源的类型,这里是 APIGateway Properties: # 资源的属性配置 Name: Workshop-PlayerMgr # APIGATEWAY 的名称 StageName: dev # APIGATEWAY 的 stage name PlayerInfoFunction: Type: AWS::Serverless::Function # 资源类型,此处是 Lambda Properties: Description: 'Player Info' # 函数说明 CodeUri: player-manager/ # Lambda 函数代码所在的目录 Handler: main.main_handler # Lambda 函数处理的 method Runtime: python3.9 # Lambda 执行代码的 runtime,支持 NodeJS, Python, Java, Golang 等 Architectures: # 底层运行代码的 CPU 架构 - arm64 # 一般代码没有特殊依赖推荐 ARM 架构,更高性价比 Role: "arn:aws:iam::123456789:role/Workshop-Lambda-Role" # Lambda 执行时的权限 Events: # Lambda 事件触发配置 CreateUserEvent: # 名称 Type: Api # 事件触发类型,此处为 APIGATEWAY Properties: # 事件触发配置,以下表示通过刚刚配置的"PlayerMgr" APIGATEWAY 的 Endpoint "/create_user" 这个 path 访问时,触发 Lambda Path: /create_user Method: post RestApiId: !Ref PlayerMgr DeleteUserEvent: # 名称 Type: Api Properties: Path: /delete_user Method: post RestApiId: !Ref PlayerMgr CreateUserOptionsEvent: Type: Api Properties: Path: /create_user Method: options RestApiId: !Ref PlayerMgr DeleteUserOptionsEvent: Type: Api Properties: Path: /delete_user Method: options RestApiId: !Ref PlayerMgr PlayerInfoTable: Type: AWS::DynamoDB::Table # 资源类型,此处是 Dynamodb table Properties: AttributeDefinitions: # Dynamodb 中的字段定义 - AttributeName: "user_id" AttributeType: "S" # user_id 字段为 string KeySchema: # Primary key 配置,这里使用单个 Partition key 做 Primary key - AttributeName: "user_id" KeyType: "HASH" ProvisionedThroughput: # 预置 throughput ReadCapacityUnits: 5 WriteCapacityUnits: 5 SSESpecification: SSEEnabled: True # Server Side Encryption 开启服务端加密 TableName: "player_info" # DDB table 名称 ###--- Websocket Service ---### # MainServer Websocket 服务的 APIGateway MainEntry: Type: AWS::ApiGatewayV2::Api Properties: Name: Workshop-MainEntry ProtocolType: WEBSOCKET RouteSelectionExpression: "$request.body.action" # APIGateway 的 stage Stage: Type: AWS::ApiGatewayV2::Stage Properties: StageName: dev Description: "dev env" ApiId: !Ref MainEntry AutoDeploy: true # 处理 MainServer 服务的 Lambda MainServerFunction: Type: AWS::Serverless::Function Properties: Description: 'Handle all connections' CodeUri: main-server/ Handler: main.main_handler Runtime: python3.9 Architectures: - arm64 Role: "arn:aws:iam::123456789:role/Workshop-Lambda-Role" # APIGateway 的 Integration 资源,用于连接 Lambda 和 Websocket APIGateway 的 route MainServerIntegration: Type: AWS::ApiGatewayV2::Integration Properties: ApiId: !Ref MainEntry IntegrationType: AWS_PROXY IntegrationUri: !Join - '' - - 'arn:' - !Ref AWS::Partition - ':apigateway:' - !Ref AWS::Region - ':lambda:path/2015-03-31/functions/' - !GetAtt MainServerFunction.Arn - '/invocations' # 默认的 APIGateway route DefaultRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref MainEntry RouteKey: "$default" AuthorizationType: NONE OperationName: DefaultRoute Target: !Join - '/' - - 'integrations' - !Ref MainServerIntegration # Websocket client 连接时的 route ConnectRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref MainEntry RouteKey: "$connect" AuthorizationType: NONE OperationName: ConnectRoute Target: !Join - '/' - - 'integrations' - !Ref MainServerIntegration # Websocket client 连接时的 route DisconnectRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref MainEntry RouteKey: "$disconnect" AuthorizationType: NONE OperationName: DisconnectRoute Target: !Join - '/' - - 'integrations' - !Ref MainServerIntegration # APIGateway 调用 Lambda 的 resource-based policy MainServerPermission: Type: AWS::Lambda::Permission DependsOn: - MainEntry Properties: Action: lambda:InvokeFunction FunctionName: !Ref MainServerFunction Principal: apigateway.amazonaws.com # Dynamodb 用于存储 connection_id 和 user_id 对应关系 MainServerTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: "connection_id" AttributeType: "S" KeySchema: - AttributeName: "connection_id" KeyType: "HASH" ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5 SSESpecification: SSEEnabled: True TableName: "main_server" # 用于处理匹配房间逻辑 RoomMgrFunction: Type: AWS::Serverless::Function Properties: Description: 'Battle room service' CodeUri: room-manager/ Handler: main.main_handler Runtime: python3.9 Architectures: - arm64 Role: "arn:aws:iam::123456789:role/Workshop-Lambda-Role" # 用于连接 APIGateway 和 Lambda RoomMgrIntegration: Type: AWS::ApiGatewayV2::Integration Properties: ApiId: !Ref MainEntry IntegrationType: AWS_PROXY IntegrationUri: !Join - '' - - 'arn:' - !Ref AWS::Partition - ':apigateway:' - !Ref AWS::Region - ':lambda:path/2015-03-31/functions/' - !GetAtt RoomMgrFunction.Arn - '/invocations' JoinRoomRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref MainEntry RouteKey: "joinroom" AuthorizationType: NONE OperationName: JoinRoomRoute Target: !Join - '/' - - 'integrations' - !Ref RoomMgrIntegration ExitRoomRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref MainEntry RouteKey: "exitroom" AuthorizationType: NONE OperationName: ExitRoomRoute Target: !Join - '/' - - 'integrations' - !Ref RoomMgrIntegration DestroyRoomRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref MainEntry RouteKey: "destroyroom" AuthorizationType: NONE OperationName: DestroyRoomRoute Target: !Join - '/' - - 'integrations' - !Ref RoomMgrIntegration # 用于允许 APIGateway 调用 Lambda RoomMgrPermission: Type: AWS::Lambda::Permission DependsOn: - MainEntry Properties: Action: lambda:InvokeFunction FunctionName: !Ref RoomMgrFunction Principal: apigateway.amazonaws.com # 存储游戏内通用的资源数据 CommonResourceTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: "resource_name" AttributeType: "S" KeySchema: - AttributeName: "resource_name" KeyType: "HASH" ProvisionedThroughput: ReadCapacityUnits: 5 WriteCapacityUnits: 5 SSESpecification: SSEEnabled: True TableName: "common_resources" # 用于处理战斗逻辑 BattleMgrFunction: Type: AWS::Serverless::Function Properties: Description: 'Battle' CodeUri: battle-manager/ Handler: main.main_handler Runtime: python3.9 Architectures: - arm64 Role: "arn:aws:iam::123456789:role/Workshop-Lambda-Role" # 用于连接 APIGateway 和 Lambda BattleMgrIntegration: Type: AWS::ApiGatewayV2::Integration Properties: ApiId: !Ref MainEntry IntegrationType: AWS_PROXY IntegrationUri: !Join - '' - - 'arn:' - !Ref AWS::Partition - ':apigateway:' - !Ref AWS::Region - ':lambda:path/2015-03-31/functions/' - !GetAtt BattleMgrFunction.Arn - '/invocations' AttackRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref MainEntry RouteKey: "attack" AuthorizationType: NONE OperationName: AttackRoute Target: !Join - '/' - - 'integrations' - !Ref BattleMgrIntegration DieRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref MainEntry RouteKey: "die" AuthorizationType: NONE OperationName: DieRoute Target: !Join - '/' - - 'integrations' - !Ref BattleMgrIntegration SyncScoreRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref MainEntry RouteKey: "syncscore" AuthorizationType: NONE OperationName: SyncScoreRoute Target: !Join - '/' - - 'integrations' - !Ref BattleMgrIntegration # 用于允许 APIGateway 调用 Lambda BattleMgrPermission: Type: AWS::Lambda::Permission DependsOn: - MainEntry Properties: Action: lambda:InvokeFunction FunctionName: !Ref BattleMgrFunction Principal: apigateway.amazonaws.com