在游戏运营行业,Serverless 如何解决数据采集分析痛点?

简介: 众所周知,游戏行业在当今的互联网行业中算是一棵常青树。在疫情之前的 2019 年,中国游戏市场营收规模约 2884.8 亿元,同比增长 17.1%。2020 年因为疫情,游戏行业更是突飞猛进。玩游戏本就是中国网民最普遍的娱乐方式之一,疫情期间更甚。据不完全统计,截至 2019 年,中国移动游戏用户规模约 6.6 亿人,占中国总网民规模 8.47 亿的 77.92%,可见游戏作为一种低门槛、低成本的娱乐手段,已成为大部分人生活中习以为常的一部分。

众所周知,游戏行业在当今的互联网行业中算是一棵常青树。在疫情之前的 2019 年,中国游戏市场营收规模约 2884.8 亿元,同比增长 17.1%。2020 年因为疫情,游戏行业更是突飞猛进。玩游戏本就是中国网民最普遍的娱乐方式之一,疫情期间更甚。据不完全统计,截至 2019 年,中国移动游戏用户规模约 6.6 亿人,占中国总网民规模 8.47 亿的 77.92%,可见游戏作为一种低门槛、低成本的娱乐手段,已成为大部分人生活中习以为常的一部分。

对于玩家而言,市面上的游戏数量多如牛毛,那么玩家如何能发现和认知到一款游戏,并且持续的玩下去恐怕是所有游戏厂商需要思考的问题。加之 2018 年游戏版号停发事件,游戏厂商更加珍惜每一个已获得版号的游戏产品,所以这也使得“深度打磨产品质量”和“提高运营精细程度”这两个游戏产业发展方向成为广大游戏厂商的发展思路,无论是新游戏还是老游戏都在努力落实这两点:

  • 新游戏:面向玩家需要提供更充足的推广资源和更完整的游戏内容。
  • 老游戏:通过用户行为分析,投入更多的精力和成本,制作更优质的版本内容。

这里我们重点来看新游戏。一家游戏企业辛辛苦苦研发三年,等着新游戏发售时一飞冲天。那么问题来了,新游戏如何被广大玩家看到?

首先来看看游戏行业公司的分类:

1.png

  • 游戏研发商:研发游戏的公司,生产和制作游戏内容。比如王者荣耀的所有英雄设计、游戏战斗场景、战斗逻辑等,全部由游戏研发公司提供。
  • 游戏发行商:游戏发行商的主要工作分三大块:市场工作、运营工作、客服工作。游戏发行商把控游戏命脉,市场工作核心是导入玩家,运营工作核心是将用户价值最大化、赚取更多利益。

2.png

  • 游戏平台/渠道商:游戏平台和渠道商的核心目的就是曝光游戏,让尽量多的人能发现你的游戏。

这三种类型的业务,有专注于其中某一领域的独立公司,也有能承接全部业务的公司,但无论那一种,这三者之间的关系是不会变的:

3.png

所以不难理解,想让更多的玩家看到你的游戏,游戏发行和运营是关键。通俗来讲,如果你的游戏出现在目前所有大家熟知的平台广告中,那么最起码游戏的新用户注册数量是很可观的。因此这就引入了一个关键词:买量

根据数据显示,2019 年月均买量手游数达 6000+ 款,而 2018 年仅为 4200 款。另一方面,随着抖音、微博等超级 APP 在游戏买量市场的资源倾斜,也助推手游买量的效果和效率有所提升,游戏厂商更愿意使用买量的方式来吸引用户。

但需要注意的是,在游戏买量的精准化程度不断提高的同时,买量的成本也在节节攀升,唯有合理配置买量、渠道与整合营销之间的关系,才能将宣发资源发挥到最大的效果。

通俗来讲,买量其实就是在各大主流平台投放广告,广大用户看到游戏广告后,有可能会点击广告,然后进入游戏厂商的宣传页面,同时会采集用户的一些信息,然后游戏厂商对采集到的用户信息进行大数据分析,进行进一步的定向推广。

游戏运营核心诉求

游戏厂商花钱买量,换来的用户信息以及新用户注册信息是为持续的游戏运营服务的,那么这个场景的核心诉求就是采集用户信息的完整性。

比如说,某游戏厂商一天花 5000w 投放广告,在某平台某时段产生了每秒 1w 次的广告点击率,那么在这个时段内每一个点击广告的用户信息要完整的被采集到,然后入库进行后续分析。这就对数据采集系统提出了很高的要求。

这其中,最核心的一点就是系统暴露接口的环节要能够平稳承载买量期间不定时的流量脉冲。在买量期间,游戏厂商通常会在多个平台投放广告,每个平台投放广告的时间是不一样的,所以就会出现全天不定时的流量脉冲现象。如果这个环节出现问题,那么相当于买量的钱就打水漂了。

数据采集系统传统架构

4.png

上图是一个相对传统的数据采集系统架构,最关键的就是暴露 HTTP 接口回传数据这部分,这部分如果出问题,那么采集数据的链路就断了。但这部分往往会面临两个挑战:

  • 当流量脉冲来的时候,这部分是否可以快速扩容以应对流量冲击。
  • 游戏运营具备潮汐特性,并非天天都在进行,这就需要考虑如何优化资源利用率。

通常情况下,在游戏有运营活动之前,会提前通知运维同学,对这个环节的服务增加节点,但要增加多少其实是无法预估的,只能大概拍一个数字。这是在传统架构下经常会出现的场景,这就会导致两个问题:

  • 流量太大,节点加少了,导致一部分流量的数据没有采集到。
  • 流量没有预期那么大,节点加多了,导致资源浪费。

数据采集系统 Serverless 架构

我们可以通过函数计算 FC 来取代传统架构中暴露 HTTP 回传数据这部分,从而完美解决传统架构中存在问题,参考文章:《资源成本双优化!看 Serverless 颠覆编程教育的创新实践》。

先来看架构图:

5.png

传统架构中的两个问题均可以通过函数计算百毫秒弹性的特性来解决。我们并不需要去估算营销活动会带来多大的流量,也不需要去担心和考虑对数据采集系统的性能,运维同学更不需要提前预备 ECS。

因为函数计算的极致弹性特性,当没有买量、没有营销活动的时候,函数计算的运行实例是零。有买量活动时,在流量脉冲的情况下,函数计算会快速拉起实例来承载流量压力;当流量减少时,函数计算会及时释放没有请求的实例进行缩容。所以 Serverless 架构带来的优势有以下三点:

  • 无需运维介入,研发同学就可以很快的搭建出来。
  • 无论流量大小,均可以平稳的承接。
  • 函数计算拉起的实例数量可以紧贴流量大小的曲线,做到资源利用率最优化,再加上按量计费的模式,可以最大程度优化成本。

架构解析

从上面的架构图可以看到,整个采集数据阶段,分了两个函数来实现,第一个函数的作用是单纯的暴露 HTTP 接口接收数据,第二个函数用于处理数据,然后将数据发送至消息队列 Kafka 和数据库 RDS。

1. 接收数据函数

我们打开函数计算控制台,创建一个函数:

  • 函数类型:HTTP(即触发器为 HTTP)
  • 函数名称:receiveData
  • 运行环境:Python3

6.png

  • 函数实例类型:弹性实例
  • 函数执行内存:512MB
  • 函数运行超时时间:60 秒
  • 函数单实例并发度:1

7.png

  • 触发器类型:HTTP 触发器
  • 触发器名称:defaultTrigger
  • 认证方式:anonymous(即无需认证)
  • 请求方式:GET,POST

8.png

创建好函数之后,我们通过在线编辑器编写代码:

# -*- coding: utf-8 -*-
import logging
import json
import urllib.parse
HELLO_WORLD = b'Hello world!\n'
def handler(environ, start_response):logger = logging.getLogger() context = environ['fc.context']request_uri = environ['fc.request_uri']for k, v in environ.items():if k.startswith('HTTP_'):# process custom request headerspasstry:        request_body_size = int(environ.get('CONTENT_LENGTH', 0))    except (ValueError):        request_body_size = 0   # 接收回传的数据request_body = environ['wsgi.input'].read(request_body_size)  request_body_str = urllib.parse.unquote(request_body.decode("GBK"))request_body_obj = json.loads(request_body_str)logger.info(request_body_obj["action"])logger.info(request_body_obj["articleAuthorId"])status = '200 OK'response_headers = [('Content-type', 'text/plain')]start_response(status, response_headers)return [HELLO_WORLD]

此时的代码非常简单,就是接收用户传来的参数,我们可以调用接口进行验证:

9.png

可以在函数的日志查询中看到此次调用的日志:

10.png

同时,我们也可以查看函数的链路追踪来分析每一个步骤的调用耗时,比如函数接到请求→冷启动(无活跃实例时)→准备代码→执行初始化方法→执行入口函数逻辑这个过程:

11.png

12.png

从调用链路图中可以看到,刚才的那次请求包含了冷启动的时间,因为当时没有活跃实例,整个过程耗时 418 毫秒,真正执行入口函数代码的时间为 8 毫秒。

当再次调用接口时,可以看到就直接执行了入口函数的逻辑,因为此时已经有实例在运行,整个耗时只有 2.3 毫秒:

13.png

2. 处理数据的函数

第一个函数是通过在函数计算控制台在界面上创建的,选择了运行环境是 Python3,我们可以在官方文档中查看预置的 Python3 运行环境内置了哪些模块,因为第二个函数要操作 Kafka 和 RDS,所以需要我们确认对应的模块。

14.png

从文档中可以看到,内置的模块中包含 RDS 的 SDK 模块,但是没有 Kafka 的 SDK 模块,此时就需要我们手动安装 Kafka SDK 模块,并且创建函数也会使用另一种方式。

1)Funcraft

Funcraft 是一个用于支持 Serverless 应用部署的命令行工具,能帮助我们便捷地管理函数计算、API 网关、日志服务等资源。它通过一个资源配置文件(template.yml),协助我们进行开发、构建、部署操作。
所以第二个函数我们需要使用 Fun 来进行操作,整个操作分为四个步骤:

  • 安装 Fun 工具。
  • 编写 template.yml 模板文件,用来描述函数。
  • 安装我们需要的第三方依赖。
  • 上传部署函数。

2)安装 Fun

Fun 提供了三种安装方式:

  • 通过 npm 包管理安装 —— 适合所有平台(Windows/Mac/Linux)且已经预装了 npm 的开发者。
  • 通过下载二进制安装 —— 适合所有平台(Windows/Mac/Linux)。
  • 通过 Homebrew 包管理器安装 —— 适合 Mac 平台,更符合 MacOS 开发者习惯。

文本示例环境为 Mac,所以使用 npm 方式安装,非常的简单,一行命令搞定:

sudo npm install @alicloud/fun -g

安装完成之后。在控制终端输入 fun 命令可以查看版本信息:

$ fun --version
3.6.20

在第一次使用 fun 之前需要先执行 fun config 命令进行配置,按照提示,依次配置 Account ID、Access Key Id、Secret Access Key、 Default Region Name 即可。其中 Account ID、Access Key Id 你可以从函数计算控制台首页的右上方获得:

fun config

? Aliyun Account ID *01
? Aliyun Access Key ID *qef6j
? Aliyun Access Key Secret *UFJG
? Default region name cn-hangzhou
? The timeout in seconds for each SDK client invoking 60
? The maximum number of retries for each SDK client 3

3)编写 template.yml

新建一个目录,在该目录下创建一个名为 template.yml 的 YAML 文件,该文件主要描述要创建的函数的各项配置,说白了就是将函数计算控制台上配置的那些配置信息以 YAML 格式写在文件里:

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
FCBigDataDemo:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'local invoke demo'
VpcConfig:
VpcId: 'vpc-xxxxxxxxxxx'
VSwitchIds: [ 'vsw-xxxxxxxxxx' ]
SecurityGroupId: 'sg-xxxxxxxxx'
LogConfig:
Project: fcdemo
Logstore: fc_demo_store
dataToKafka:
Type: 'Aliyun::Serverless::Function'
Properties:
Initializer: index.my_initializer
Handler: index.handler
CodeUri: './'
Description: ''
Runtime: python3

我们来解析以上文件的核心内容:

  • FCBigDataDemo:自定义的服务名称。通过下面的 Type 属性标明是服务,即 Aliyun::Serverless::Service。
  • Properties:Properties 下的属性都是该服务的各配置项。
  • VpcConfig:服务的 VPC 配置,包含:

    • VpcId:VPC ID。
    • VSwitchIds:交换机 ID,这里是数组,可以配置多个交换机。
    • SecurityGroupId:安全组 ID。
  • LogConfig:服务绑定的日志服务(SLS)配置,包含:

    • Project:日志服务项目。
    • Logstore:LogStore 名称。
  • dataToKafka:该服务下自定义的函数名称。通过下面的 Type 属性标明是函数,即 Aliyun::Serverless::Function。
  • Properties:Properties下的属性都是该函数的各配置项。
  • Initializer:配置初始化函数。
  • Handler:配置入口函数。
  • Runtime:函数运行环境。

目录结构为:

15.png

4)安装第三方依赖

服务和函数的模板创建好之后,我们来安装需要使用的第三方依赖。在这个示例的场景中,第二个函数需要使用 Kafka SDK,所以可以通过 fun 工具结合 Python 包管理工具 pip 进行安装:

fun install --runtime python3 --package-type pip kafka-python

执行命令后有如下提示信息:

16.png

此时我们会发现在目录下会生成一个.fun文件夹 ,我们安装的依赖包就在该目录下:

17.png

5)部署函数

现在编写好了模板文件以及安装好了我们需要的 Kafka SDK 后,还需要添加我们的代码文件 index.py,代码内容如下:

# -*- coding: utf-8 -*-
import logging
import json
import urllib.parse
from kafka import KafkaProducer
producer = None
def my_initializer(context):    logger = logging.getLogger() logger.info("init kafka producer")global producerproducer = KafkaProducer(bootstrap_servers='XX.XX.XX.XX:9092,XX.XX.XX.XX:9092,XX.XX.XX.XX:9092')
def handler(event, context):logger = logging.getLogger()   # 接收回传的数据event_str = json.loads(event)event_obj = json.loads(event_str)logger.info(event_obj["action"])logger.info(event_obj["articleAuthorId"])# 向Kafka发送消息global producerproducer.send('ikf-demo', json.dumps(event_str).encode('utf-8'))producer.close()return 'hello world'

代码很简单,这里做以简单的解析:

  • my_initializer:函数实例被拉起时会先执行该函数,然后再执行 handler 函数 ,当函数实例在运行时,之后的请求都不会执行 my_initializer 函数 。一般用于各种连接的初始化工作,这里将初始化 Kafka Producer 的方法放在了这里,避免反复初始化 Produer。
  •  handler:该函数只有两个逻辑,接收回传的数据和将数据发送至 Kafka 的指定 Topic。
  • 下面通过 fun deploy 命令部署函数,该命令会做两件事:

    • 根据 template.yml 中的配置创建服务和函数。
    • 将 index.py 和 .fun 上传至函数中。

18.png

登录函数计算控制台,可以看到通过 fun 命令部署的服务和函数:

19.png

进入函数,也可以清晰的看到第三方依赖包的目录结构:

20.png

3. 函数之间调用

目前两个函数都创建好了,下面的工作就是由第一个函数接收到数据后拉起第二个函数发送消息给 Kafka。我们只需要对第一个函数做些许改动即可:

# -*- coding: utf-8 -*-
import logging
import json
import urllib.parse
import fc2
HELLO_WORLD = b'Hello world!\n'
client = None
def my_initializer(context):    logger = logging.getLogger() logger.info("init fc client")global clientclient = fc2.Client(endpoint="http://your_account_id.cn-hangzhou-internal.fc.aliyuncs.com",accessKeyID="your_ak",accessKeySecret="your_sk")
def handler(environ, start_response):logger = logging.getLogger() context = environ['fc.context']request_uri = environ['fc.request_uri']for k, v in environ.items():if k.startswith('HTTP_'):# process custom request headerspasstry:        request_body_size = int(environ.get('CONTENT_LENGTH', 0))    except (ValueError):        request_body_size = 0   # 接收回传的数据request_body = environ['wsgi.input'].read(request_body_size)  request_body_str = urllib.parse.unquote(request_body.decode("GBK"))request_body_obj = json.loads(request_body_str)logger.info(request_body_obj["action"])logger.info(request_body_obj["articleAuthorId"])global clientclient.invoke_function('FCBigDataDemo','dataToKafka',payload=json.dumps(request_body_str),headers = {'x-fc-invocation-type': 'Async'})status = '200 OK'response_headers = [('Content-type', 'text/plain')]start_response(status, response_headers)return [HELLO_WORLD]

如上面代码所示,对第一个函数的代码做了三个地方的改动:

  • 导入函数计算的库:import fc2
  • 添加初始化方法,用于创建函数计算 Client:
def my_initializer(context):logger = logging.getLogger()logger.info("init fc client")global clientclient = fc2.Client(endpoint="http://your_account_id.cn-hangzhou-internal.fc.aliyuncs.com",accessKeyID="your_ak",accessKeySecret="your_sk"
)

这里需要注意的时,当我们在代码里增加了初始化方法后,需要在函数配置中指定初始化方法的入口:

21.png

  • 通过函数计算 Client 调用第二个函数
global clientclient.invoke_function('FCBigDataDemo','dataToKafka',payload=json.dumps(request_body_str),headers = {'x-fc-invocation-type': 'Async'}
)

invoke_function 函数有四个参数:

  • 第一个参数:调用函数所在的服务名称。
  • 第二个参数:调用函数的函数名称。
  • 第三个参数:向调用函数传的数据。
  • 第四个参数:调用第二个函数 Request Header 信息。这里主要通过 x-fc-invocation-type 这个 Key 来设置是同步调用还是异步调用。这里设置 Async 为异步调用。

如此设置,我们便可以验证通过第一个函数提供的 HTTP 接口发起请求→采集数据→调用第二个函数→将数据作为消息传给 Kafka 这个流程了。

使用两个函数的目的

到这里有些同学可能会有疑问,为什么需要两个函数,而不在第一个函数里直接向 Kafka 发送数据呢?我们先来看这张图:

22.png

当我们使用异步调用函数时,在函数内部会默认先将请求的数据放入消息队列进行第一道削峰填谷,然后每一个队列在对应函数实例,通过函数实例的弹性拉起多个实例进行第二道削峰填谷。所以这也就是为什么这个架构能稳定承载大并发请求的核心原因之一。

4. 配置 Kafka

在游戏运营这个场景中,数据量是比较大的,所以对 Kafka 的性能要求也是比较高的,相比开源自建,使用云上的 Kafka 省去很多的运维操作,比如:

  • 我们不再需要再维护 Kafka 集群的各个节点。
  • 不需要关心主从节点数据同步问题。
  • 可以快速、动态扩展 Kafka 集群规格,动态增加 Topic,动态增加分区数。
  • 完善的指标监控功能,消息查询功能。

总的来说,就是一切 SLA 都有云上兜底,我们只需要关注在消息发送和消息消费即可。

所以我们可以打开 Kafka 开通界面,根据实际场景的需求一键开通 Kafka 实例,开通 Kafka 后登录控制台,在基本信息中可以看到 Kafka 的接入点:

  • 默认接入点:走 VPC 内网场景的接入点。
  • SSL 接入点:走公网场景的接入点。

将默认接入点配置到函数计算的第二个函数中即可。

....
producer = KafkaProducer(bootstrap_servers='XX.XX.XX.XX:9092,XX.XX.XX.XX:9092,XX.XX.XX.XX:9092')
....

然后点击左侧控制台 Topic 管理,创建 Topic:

23.png

将创建好的 Topic 配置到函数计算的第二个函数中即可。

...
# 第一个参数为Topic名称
producer.send('ikf-demo', json.dumps(event_str).encode('utf-8'))
...

上文已经列举过云上 Kafka 的优势,比如动态增加 Topic 的分区数,我们可以在 Topic 列表中,对 Topic 的分区数进行动态调整:

24.png

25.png

单 Topic 最大支持到 360 个分区,这是开源自建无法做到的。

接下来点击控制台左侧 Consumer Group 管理,创建 Consumer Group:

26.png

至此,云上的 Kafka 就算配置完毕了,即 Producer 可以往刚刚创建的 Topic 中发消息了,Consumer 可以设置刚刚创建的 GID 以及订阅 Topic 进行消息接受和消费。

Flink Kafka 消费者

在这个场景中,Kafka 后面往往会跟着 Flink,所以这里简要给大家介绍一下在 Flink 中如何创建 Kafka Consumer 并消费数据。代码片段如下:

final ParameterTool parameterTool = ParameterTool.fromArgs(args);
String kafkaTopic = parameterTool.get("kafka-topic","ikf-demo");
String brokers = parameterTool.get("brokers", "XX.XX.XX.XX:9092,XX.XX.XX.XX:9092,XX.XX.XX.XX:9092");
Properties kafkaProps = new Properties();
kafkaProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, brokers);
kafkaProps.put(ConsumerConfig.GROUP_ID_CONFIG, "ikf-demo");
FlinkKafkaConsumer<UserBehaviorEvent> kafka = new FlinkKafkaConsumer<>(kafkaTopic, new UserBehaviorEventSchema(), kafkaProps);
kafka.setStartFromLatest();
kafka.setCommitOffsetsOnCheckpoints(false);
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStreamSource<UserBehaviorEvent> dataStreamByEventTime = env.addSource(kafka);

以上就是构建 Flink Kafka Consumer 和添加 Kafka Source 的代码片段,还是非常简单的。

压测验证

至此,整个数据采集的架构就搭建完毕了,下面我们通过压测来检验一下整个架构的性能。这里使用阿里云 PTS 来进行压测。

创建压测场景

打开 PTS 控制台,点击左侧菜单创建压测/创建 PTS 场景:

27.png

在场景配置中,将第一个函数计算函数暴露的 HTTP 接口作为串联链路,配置如下图所示:

28.png

29.png

接口配置完后,我们来配置施压:

30.png

  • 压力模式:

    • 并发模式:指定有多少并发用户同时发请求。
    • RPS模式:指定每秒有多少请求数。
  • 递增模式:在压测过程中可以通过手动调节压力,也可以自动按百分比递增压力。
  • 最大并发:同时有多少个虚拟用户发起请求。
  • 递增百分比:如果是自动递增的话,按这里的百分比递增。
  • 单量级持续时长:在未完全达到压力全量的时候,每一级梯度的压力保持的时长。
  • 压测总时长:一共需要压测的时长。

这里因为资源成本原因,并发用户数设置为 2500 来进行验证。

31.png

32.png

从上图压测中的情况来看,TPS 达到了 2w 的封顶,549w+ 的请求,99.99% 的请求是成功的,那 369 个异常也可以点击查看,都是压测工具请求超时导致的。

总结

至此,整个基于 Serverless 搭建的大数据采集传输的架构就搭建好了,并且进行了压测验证,整体的性能也是不错的,并且整个架构搭建起来也非常简单和容易理解。这个架构不光适用于游戏运营行业,其实任何大数据采集传输的场景都是适用的,目前也已经有很多客户正在基于 Serverless 的架构跑在生产环境,或者正走在改造 Serverless 架构的路上。


作者:计缘

原文链接 

本文为阿里云原创内容,未经允许不得转载

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/514245.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字节大战腾讯元宇宙;Docker 自己定制镜像;VMware 云桌面助力秦皇岛市第一医院;微软开源 Cloud Katana;...

NEWS本周新闻回顾字节大战腾讯元宇宙&#xff1a;布局社交产品Pixsoul&#xff0c;上线游戏“重启世界”字节投资的代码乾坤&#xff0c;已于近日正式上线了元宇宙游戏《重启世界》。就在两个月前&#xff0c;被称为“元宇宙第一股”的Roblox登陆国内&#xff0c;由腾讯改名为《…

从 RxJS 到 Flink:如何处理数据流?

简介&#xff1a; 前端开发的本质是什么&#xff1f;响应式编程相对于 MVVM 或者 Redux 有什么优点&#xff1f;响应式编程的思想是否可以应用到后端开发中&#xff1f;本文以一个新闻网站为例&#xff0c;阐述在前端开发中如何使用响应式编程思想&#xff1b;再以计算电商平台…

Spring RSocket:基于服务注册发现的 RSocket 负载均衡

简介&#xff1a; RSocket 作为通讯协议的后起之秀&#xff0c;核心是二进制异步化消息通讯&#xff0c;是否也能和 Spring Cloud 技术栈结合&#xff0c;实现服务注册发现、客户端负载均衡&#xff0c;从而更高效地实现面向服务的架构&#xff1f;这篇文章我们就讨论一下 Spri…

双非院校计算机系毕业的学生能进大厂吗?

谈到大厂&#xff0c;我们常常会主动匹配与之对应的高学历。其实不论是大厂还是小公司&#xff0c;都是会筛简历的&#xff0c;这个毋庸置疑。从大厂招聘的结果上看&#xff0c;高学历人才的数量占据大头&#xff0c;而那些成功进入BAT、网易等大厂的专科生、二本三本学生&…

Python - 深夜数据结构与算法之 Heap Binary Heap

目录 一.引言 二.堆与二叉堆介绍 1.Heap 堆 2.Binary Heap 二叉堆 3.HeapifyUp 添加节点 4.HeapifyDown 删除节点 5.Heap 时间复杂度 6.Insert & Delete 代码实现 三.经典算法实战 1.Smallest-K [M14] 2.Sliding-Window-Max [239] 3.Ugly-Number [264] 4.Top-…

如何 0 改造,让单体/微服务应用成为 Serverless Application

简介&#xff1a; 随着 2013 年以 Docker 为代表的容器技术、CNCF 基金会以及 K8s 的发展等&#xff0c;云原生开始被广大开发者所熟知。云原生时代之前还有两个阶段&#xff1a;一是自建 IDC 机房&#xff0c;二是简单地把原有的应用搬迁到云上。自建 IDC 机房很难获得高可用、…

一文了解阿里一站式图计算平台GraphScope

简介&#xff1a; 随着大数据的爆发&#xff0c;图数据的应用规模不断增长&#xff0c;现有的图计算系统仍然存在一定的局限。阿里巴巴拥有全球最大的商品知识图谱&#xff0c;在丰富的图场景和真实应用的驱动下&#xff0c;阿里巴巴达摩院智能计算实验室研发并开源了全球首个一…

c++如何禁用指定的键盘布局_Karabiner Elements for Mac 键盘键位自定义改键工具

文章来源于&#xff1a;风云社区Karabiner Elements for Mac 12.5Karabiner Elements&#xff08;早期是Karabiner&#xff0c;更早是KeyRemap4MacBook&#xff09;是功能强大且稳定的macOS键盘定制器。上【风云社区】&#xff0c;搜索软件名字&#xff0c;即可查看下载特征&am…

Docker Desktop 向大公司宣告收费,网友大呼:是时候弃用了!

作者 | 苏宓 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 在容器引擎 Docker 诞生的 8 年间&#xff0c;其与开源的容器编排 Kubernetes 共同推动容器技术在云计算领域的应用&#xff0c;也让自身在全球范围内受到了广泛的关注。可以说&#xff0c;做过云计算开…

如何接地气地接入微前端?

简介&#xff1a; 微前端带来明显好处的同时&#xff0c;也面临着痛点。对于已有站点&#xff0c;如何在老的技术栈基础上接入一个微前端&#xff1f;需要哪些通 一 、前言 微前端&#xff0c;这个概念已经在国内不止一次的登上各大热门话题&#xff0c;它所解决的问题也很明显…

东南亚再造天猫 Lazada品牌商城LazMall举办第二届品牌未来论坛

9月1日&#xff0c;东南亚领先的旗舰电商平台Lazada在新加坡滨海湾金沙会展中心举办了2021 LazMall Brands Future Forum年度品牌未来论坛&#xff08;以下简称“BFF”&#xff09;。该论坛以“奔向未来&#xff1a;东南亚的数字商务时代”为主题&#xff0c;在庆祝Lazada品牌商…

高可用的本质

简介&#xff1a; 无论是一个域&#xff0c;一个BG&#xff0c;还是一个站点&#xff0c;虽然范围有大有小&#xff0c;对象有所不同&#xff0c;但其高可用的理念都是相通的&#xff0c;今天将自己对高可用的一点点思考以及总结的【nPRT公式】分享给大家。 我是乐羊&#xff0…

技术干货 | 深度解构 Android 应用面临紧急发版时的救星方案:mPaaS 热修复——DexPatch

简介&#xff1a; 关于 Android 热修复方案——DexPatch 的介绍与使用说明 方案介绍 为了解决 Native 模块上线后的问题&#xff0c;mPaaS 提供了热修复功能&#xff0c;实现不发布客户端 apk 场景下的热修复。目前 Android 端热修复主要包括 andfix 和 dexpatch&#xff0c;考…

李飞飞:阿里云数据库已做好全面服务政企市场的准备

“政企市场是检验云数据库产品竞争力的黄金标准。”9月3日&#xff0c;阿里云智能数据库事业部总负责人李飞飞在北京举办的媒体沟通会上表示&#xff0c;阿里云已经做好全面服务政企数据库市场的准备&#xff0c;并已成功助力多家大型组织实现核心系统对传统商业数据库的替换。…

技术改变生活 浅谈阿里云混合云的探索与实践

简介&#xff1a; 也许你并不了解“阿里云混合云”&#xff0c;甚至没有听说过“混合云”&#xff0c;然而它却在幕后“默默”改变着人们的生活。 也许你并不了解“阿里云混合云”&#xff0c;甚至没有听说过“混合云”&#xff0c;然而它却在幕后“默默”改变着人们的生活。大…

公网访问_一文读懂阿里云访问公网的实现方式

NAT网关与EIP作为公有云服务商&#xff0c;提供互联网的访问和接入是必备的条件&#xff0c;阿里云也不例外。和AWS类似&#xff0c;阿里云访问公网的组件为NAT网关和弹性IP&#xff0c;对于刚刚接触云的童鞋&#xff0c;今天这篇文章带你彻底了解这两个组件的使用场景。弹性IP…

阿里巴巴云原生应用安全防护实践与 OpenKruise 的新领域

简介&#xff1a; 得益于 Kubernetes 面向终态的理念&#xff0c;云原生架构天然具备高度自动化的能力。然而&#xff0c;面向终态的自动化是一把“双刃剑”&#xff0c;它既为应用带来了声明式的部署能力&#xff0c;同时也潜在地会将一些误操作行为被终态化放大。 因此&#…

什么是微内核架构设计?

简介&#xff1a; 作为一名Java程序员&#xff0c;相信同学们都听说过微内核架构设计&#xff0c;也有自己的理解。那么微内核是如何被提出来的&#xff1f;微内核在操作系统内核的设计中又有什么作用&#xff1f;本文从插件化(Plug-in)架构的角度来诠释微内核架构设计&#xf…

给力!斩获 GitHub 14000 Star,两周创办开源公司获数百万美元融资

上世纪 90 年代初&#xff0c;21 岁大学生 Linus Torvalds 开源 Linux 操作系统&#xff0c;自此掀起全球开源浪潮。随后“中国 Linux 第一人”宫敏博士用手提肩背的方式将 20 盒磁带背回中国&#xff0c;磁带里装着 80G 容量的自由软件&#xff0c;组建起中国第一个自由软件库…

函数计算镜像加速:从分钟到秒的跨越

简介&#xff1a; 函数计算 FC 正式发布容器镜像加速&#xff0c;通过按需读取和更高效的解压技术在不同场景下加速 50%-80%&#xff0c;即使 GB 级别的镜像也可以在几秒内完成端到端启动。 FaaS 和容器 容器镜像因其颠覆式创新成为云原生时代应用部署格式的事实标准。头部云厂…