阿里云服务-米姆科技官方网站 http://www.51mimu.com 广州米姆信息科技有限公司,深度服务阿里云用户,为用户提供产品及技术支持:云服务器ECS、数据库RDS、网站加速CDN、阿里云邮箱、对象存储OSS、阿里云企业邮箱、WAF防火墙、高防IP、企业短信等产品服务,为用户给予阿里云优惠折扣解决方案、阿里云沙龙及阿里云峰会、 免费云主机试用、阿里云促销优惠活动、代金券优惠等活动,让用户享受米姆服务中心阿里云全栈服务。,在线咨询电话:020-22822863 Thu, 29 Oct 2020 12:16:11 +0800 zh-CN hourly 1 https://www.s-cms.cn/?v=4.7.5 公司文化 Thu, 29 Oct 2020 12:16:11 +0800

目前米姆采用人性化管理及制度综合管理相结合的方式让企业管理效率最大化,目前我公司的管理制度,涉及到安全、流程、认证等各方面,各种制度健全合理,包含部分岗位流程SOP、销售服务准则、职能认证规范及要求等十数种程序文件。从各种制度的执行情况来看,各种制度制定的有效合理,能够有效地给予生产进行指导和员工行为规范的约束


   

米姆核心目标:

米姆立志并已致力成为全球领先的企业数字化转型一站式解决方案和营销一体化的服务提供商。价值观:技术创新、诚信合作、以人为本、服务企业员工:员工相互信任、尊重、积极向上,为员工提供更多的培训机会,鼓励员工技术与管理创新、分享知识与经验,为员工提供一个公平公正的可持续发展平台,为客户提供一个搞效率服务平台。
诚信:铸诚魂 弘商誉品质:品质第一 客户至上创新:持续创新 不断超越分享:整合资源 分享世界
]]>
米姆(MEME)科技简介 Thu, 29 Oct 2020 12:16:11 +0800



米姆信息科技专注企业IT服务,技术创新驱动的企业服务专家,主要开展网络安全、信息化建设、公有云服务、私有云建设、中台开发、等保测评、DevOps构建&应用、K8s&容器云搭建、云MSP服务、自动化运维等业务。目前已经在全国服务了超千家企业。



微信图片_20201028154418.png

]]>
【升级】10月微消息队列MQTT升级公告 Thu, 29 Oct 2020 12:16:14 +0800

【阿里云】【微消息队列MQTT】【升级通知】

升级窗口:

北京时间2020年10月12日 23:00 - 2020年10月13日 07:00

北京时间2020年10月14日 23:00 - 2020年10月15日 07:00

北京时间2020年10月19日 23:00 - 2020年10月20日 07:00

北京时间2020年10月21日 23:00 - 2020年10月22日 07:00

北京时间2020年10月26日 23:00 - 2020年10月27日 07:00

北京时间2020年10月28日 23:00 - 2020年10月29日 07:00

升级内容:所有地域的MQTT服务。

升级影响:

升级期间MQTT控制台和集群中每个服务节点可能出现秒级闪断(闪断时间和集群规模正相关),客户端应用需要设置自动重连,以免影响业务。

升级期间,消息发送可能会有少量失败,应用做好断连失败重试机制;同时可能会有消息延迟的现象。如需在控制台进行管理操作,请避开维护时间段。

给您带来的不便敬请谅解,有任何问题,可随时通过工单联系反馈。

]]>
【升级】10月消息服务MNS升级计划通知 Thu, 29 Oct 2020 12:16:14 +0800

【阿里云】【消息服务MNS】【升级通知】
升级窗口:

北京时间2020年10月15日 00:00 - 06:00

北京时间2020年10月22日 00:00 - 06:00

北京时间2020年10月29日 00:00 - 06:00

升级内容:华北1(青岛)、华北2(北京)、华北3(张家口)、华北5(呼和浩特)、华东1(杭州)、华东2(上海)、华南1(深圳)、华东2金融云、华南1金融云、华北2政务云、香港、亚太东南1(新加坡)、亚太东南2(悉尼)、亚太东南5(雅加达)、亚太南部1(孟买)、中东东部1(迪拜)、欧洲中部1(法兰克福)、美国东部1(弗吉尼亚)、美国西部1(硅谷)、英国(伦敦)等地域的消息服务升级。
升级影响:升级期间MNS相关服务及控制台访问可能会出现闪断或者拒绝连接现象,每次闪断或拒绝连接不会超过1分钟,请在客户端中做好重连重试机制。如需在控制台进行管理操作,请避开维护时间段。

给您带来的不便敬请谅解,有任何问题,可随时通过工单或服务电话95187联系反馈。

]]>
【升级】10月21日消息队列AMQP升级通知 (更新) Thu, 29 Oct 2020 12:16:14 +0800

【阿里云】【消息队列AMQP】【升级通知】

升级窗口:(已更新)北京时间2020年10月21日 00:00 - 03:00
升级内容:华北1(青岛)、华北2(北京)、华北3(张家口)、华北5(呼和浩特)、华东1(杭州)、华东2(上海)、华南1(深圳)、香港等全部地域(及铂金版)的服务升级。
升级影响:升级期间消息队列AMQP相关服务访问可能会出现多次闪断或者拒绝连接现象,每次闪断或拒绝连接不会超过 5 分钟,请在客户端中做好重连重试机制。如需在控制台进行管理操作,请避开维护时间段。

给您带来的不便敬请谅解,有任何问题,可点击联系我们进行咨询反馈。

]]>
【升级】10月17日CNNIC注册局系统维护通知 Thu, 29 Oct 2020 12:16:14 +0800

【阿里云】【域名】【注册局维护通知】

维护时间:北京时间2020年10月17日 08:00 - 22:00

维护内容:接到注册局的通知,注册局将于上述时间对后台系统进行维护升级。

维护影响:届时 .cn/.中国 域名的注册、续费、信息修改和查询域名注册信息等操作,将会无法使用,在此期间会对您造成的影响如下:

1、您提交的域名注册、续费、转入、赎回、一口价域名购买等业务在支付费用后状态为“处理中”,待维护结束后将变为相应的处理结果和状态。

2、维护过程中,您无法对域名注册信息进行修改,将提示修改失败。

3、维护过程中,您无法下载相关域名的域名证书,将提示下载失败。

4、维护过程中,.cn/.中国域名实名认证不能正常提交至注册局,将为“审核中”状态,待维护结束后按顺序提交。

如果您需要注册或管理以上业务操作,建议您避开该时间段,以免给您的业务造成影响。

由此给您带来的不便,我们表示歉意,敬请谅解。

]]>
【升级】10月21日Datahub公有云2.18版本产品稳定性升级通知 Thu, 29 Oct 2020 12:16:14 +0800

【阿里云】【Datahub】【产品稳定性升级】

升级窗口:北京时间2020年10月21日 10:00 - 19:00

升级内容:

1. 公有云HTTPS证书更新

2. 版本统一升级到2.18版本

升级区域:华北,华东,华南,新加坡,吉隆坡,孟买,德国

升级影响:在升级过程中,有服务短暂抖动重试,属于正常现象,其他如有任何问题,可点击联系我们进行咨询反馈。

给您带来的不便敬请谅解。

]]>
【漏洞预警】Apache Solr configset upload文件上传漏洞(CVE-2020-13957) Thu, 29 Oct 2020 12:16:14 +0800

2020年10月13日,阿里云应急响应中心监测到Apache Solr发布安全更新,其中修复了CVE-2020-13957 Apache Solr configset upload文件上传漏洞。攻击者通过构造特定的请求,成功利用该漏洞可直接获取服务器权限。


漏洞描述

Apache Solr是一个开源的搜索服务,使用Java语言开发。Apache Solr Configset Api上传功能存在未授权漏洞。在特定条件下,攻击者可以构造特定请求,上传相关恶意文件,从而直接获取到服务器权限。阿里云应急响应中心提醒Solr用户尽快采取安全措施阻止漏洞攻击。


影响版本

Apache Solr 6.6.0 - 6.6.5

Apache Solr 7.0.0 - 7.7.3

Apache Solr 8.0.0 - 8.6.2


安全版本

Apache Solr 8.6.3


安全建议

1. 升级至安全版本

2. 如果未使用ConfigSets API,请禁用UPLOAD命令,将系统属性: configset.upload.enabled 为 false ,可参考官方文档:https://lucene.apache.org/solr/guide/8_6/configsets-api.html

3. 增加身份验证/授权,可参考官方文档:https://lucene.apache.org/solr/guide/8_6/authentication-and-authorization-plugins.html

4. 使用在SOLR-14663中提到的补丁程序:https://issues.apache.org/jira/browse/SOLR-146634

5. 禁止Solr API 以及管理 UI 直接对公网开放。设置防火墙,以便只允许受信任的计算机和人员访问。


相关链接

https://issues.apache.org/jira/browse/SOLR-14925

https://issues.apache.org/jira/browse/SOLR-14663



阿里云云安全中心应急漏洞模块已支持对该漏洞一键检测

阿里云云防火墙已可防御此漏洞攻击


我们会关注后续进展,请随时关注官方公告。

如有任何问题,可随时通过工单或服务电话95187联系反馈。

阿里云应急响应中心

2020.10.13

]]>
【漏洞预警】Windows TCP/IP远程执行代码漏洞(CVE-2020-16898) Thu, 29 Oct 2020 12:16:14 +0800

2020年10月13日,阿里云应急响应中心监测到微软发布补丁修复了TCP/IP远程执行代码漏洞(CVE-2020-16898),官方评级严重。目前微软官方已提供相应的月度安全补丁以修复该漏洞。


漏洞描述

微软官方于10月13日发布安全更新,其中修复了一个TCP/IP远程执行代码漏洞(CVE-2020-16898),攻击者通过构造并发送恶意的ICMPv6(路由通告)数据包,从而控制目标主机。同时,微软10月补丁中还涉及其他多个高危漏洞,阿里云应急响应中心提醒 Windows 用户尽快安装补丁阻止漏洞攻击。


漏洞评级

CVE-2020-16898 严重


影响版本

Windows Server 2019

Windows Server 2019 (Server Core installation)

Windows Server, version 1903 (Server Core installation)

Windows Server, version 1909 (Server Core installation)

Windows Server, version 2004 (Server Core installation)


安全建议

1、前往微软官方下载相应补丁进行更新:https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-16898

2、阿里云云安全中心Windows系统漏洞模块已支持对该漏洞补丁一键检测和修复,详情登陆云安全中心

Windows Server 2019 补丁:KB4577668



3、可以通过禁用ICMPv6 RDNSS来缓解风险。

使用以下PowerShell命令禁用ICMPv6 RDNSS,以防止攻击者利用此漏洞。此解决方法仅适用于Windows 1709及更高版本。

netsh int ipv6 set int *INTERFACENUMBER* rabaseddnsconfig=disable


注意:进行更改后,无需重新启动。

可以使用以下PowerShell命令禁用上述缓解方法。

netsh int ipv6 set int *INTERFACENUMBER* rabaseddnsconfig=enable


注意:禁用替代方法后,无需重新启动。


相关链接

https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-16898



我们会关注后续进展,请随时关注官方公告。

如有任何问题,可随时通过工单或服务电话95187联系反馈。

阿里云应急响应中心

2020.10.13

]]>
【漏洞预警】VMware vCenter任意文件读取漏洞 Thu, 29 Oct 2020 12:16:14 +0800

2020年10月14日,阿里云应急响应中心监测到VMware vCenter特定版本存在任意文件读取漏洞,攻击者通过构造特定的请求,可以读取服务器上任意文件。


漏洞描述

VMware vCenter 服务器是一种高级服务器管理软件,提供一个用于控制 VMware vSphere 环境的集中式平台。VMware vCenter特定版本存在任意文件读取漏洞,攻击者通过构造特定的请求,可以读取服务器上任意文件。阿里云应急响应中心提醒VMware vCenter用户尽快采取安全措施阻止漏洞攻击。


已知影响版本

VMware vCenter 6.5.0a-f


安全版本

VMware vCenter 6.5u1


安全建议

升级至安全版本


相关链接

https://www.vmware.com/products/vcenter-server.html



阿里云云安全中心应急漏洞模块已支持对该漏洞一键检测


我们会关注后续进展,请随时关注官方公告。

如有任何问题,可随时通过工单或服务电话95187联系反馈。

阿里云应急响应中心

2020.10.14

]]>
【漏洞预警】Nexus Repository Manger 2&3 Shiro身份验证绕过漏洞 Thu, 29 Oct 2020 12:16:14 +0800

2020年10月15日,阿里云应急响应中心监测到 sonatype官方 发布了 Nexus Repository Manger 2&3 Shiro验证绕过漏洞。


漏洞描述

Sonatype Nexus Repository 是一个开源的仓库管理系统,在安装、配置、使用简单的基础上提供了更加丰富的功能。近日Sonatype官方发布安全公告披露了在Nexus Repository Manager 2 & 3 版本中使用了旧版本的Shiro组件,存在权限绕过漏洞。攻击者可利用该权限绕过漏洞访问到后台功能,并可能导致命令执行。阿里云应急响应中心提醒Nexus Repository Manager 2&3用户尽快采取安全措施阻止漏洞攻击。


影响版本

Nexus Repository Manager OSS/Pro version 2.x < 2.14.19

Nexus Repository Manager OSS/Pro version 3.x < 3.27.0


安全版本

Nexus Repository Manager 2 versions 2.14.19

Nexus Repository Manager 3 versions 3.27.0


安全建议

1. 升级至安全版本

2. 该漏洞检测请参考 【漏洞预警】Apache Shiro < 1.6.0 权限绕过漏洞(CVE-2020-13933)


相关链接

https://support.sonatype.com/hc/en-us/articles/360053556313-CVE-2020-13933-Nexus-Repository-Manger-2-3-Shiro-Authentication-Bypass


阿里云云安全中心应急漏洞模块已支持对该漏洞一键检测


我们会关注后续进展,请随时关注官方公告。

如有任何问题,可随时通过工单或服务电话95187联系反馈。

阿里云应急响应中心

2020.10.15

]]>
【漏洞预警】Adobe Magento 远程代码执行漏洞(CVE-2020-24407) Thu, 29 Oct 2020 12:16:14 +0800

2020年10月19日,阿里云应急响应中心监测到 Adobe官方发布了 CVE-2020-24407 Magento 远程代码执行漏洞通告。


漏洞描述

Magento是一套专业开源的电子商务系统。近日Adobe官方发布安全公告披露了在 Magento Commerce/Open Source 2.3以及2.4版本中存在CVE-2020-24407远程代码执行、CVE-2020-24400 SQL注入等多个漏洞。在具有管理特权的情况下,攻击者可构造恶意请求,绕过文件上传限制,从而造成远程代码执行,控制服务器。阿里云应急响应中心提醒Magento用户尽快采取安全措施阻止漏洞攻击。


影响版本

Magento Commerce/Open Source <= 2.3.5-p2

Magento Commerce/Open Source <= 2.4.0

Magento Commerce/Open Source <= 2.3.5-p1


安全版本

Magento Commerce/Open Source 2.4.1

Magento Commerce/Open Source 2.3.6


安全建议

升级至安全版本


相关链接

https://helpx.adobe.com/security/products/magento/apsb20-59.html



我们会关注后续进展,请随时关注官方公告。

如有任何问题,可随时通过工单或服务电话95187联系反馈。

阿里云应急响应中心

2020.10.19

]]>
【漏洞预警】Apache Kylin API未授权访问漏洞(CVE-2020-13937) Thu, 29 Oct 2020 12:16:14 +0800

2020年10月20日,阿里云应急响应中心监测到 Apache Kylin官方修复 CVE-2020-13937 API未授权访问漏洞。


漏洞描述

Apache Kylin™是一个开源的、分布式的分析型数据仓库。近日Apache Kylin官方修复 CVE-2020-13937 API未授权访问漏洞。攻击者可构造恶意请求,访问API地址,可以获取Apache Kylin的相关配置信息,从而导致身份凭证等信息泄漏。阿里云应急响应中心提醒 Apache Kylin 用户尽快采取安全措施阻止漏洞攻击。


影响版本

Kylin 2.x.x

Kylin <= 3.1.0

Kylin 4.0.0-alpha


安全版本

Kylin 3.1.1


安全建议

升级至安全版本


相关链接

https://www.mail-archive.com/dev@kylin.apache.org/msg12170.html



我们会关注后续进展,请随时关注官方公告。

如有任何问题,可随时通过工单或服务电话95187联系反馈。

阿里云应急响应中心

2020.10.20

]]>
3分钟短文:太爽了,用Laravel写API接口!-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 引言

我们一直在讲,通过路由传达到控制器,处理好数据并渲染到视图,但是对于现代的应用,
前后端分离的情况下,后端写个接口就完事儿了。

img

本期为大家说一说用laravel写restful风格的API,看看能有多简单。

以路由开端

写API接口,与传统的渲染前端模板页面有什么区别?少了视图,只需要准备好数据,
并按照规则格式化,返回就可以了。

laravel默认的api接口路由在 routes/api.php 文件内定义,默认的情况下预定义了一个资源类型的api接口,代码如下:

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

调用了 auth:api 中间件用于验证用户的授权,如果授权通过,声明的get方法获取用户的信息,并返回 User 模型。这在之前的章节是很常见的操作,我们不做赘述了。

那么这个路由文件,是什么时候加载上去的呢?在文件 app/Providers/RouteServiceProvider.php 内,看这样一段:

protected function mapApiRoutes()
{
    Route::prefix('api')
        ->middleware('api')
        ->namespace($this->namespace)
        ->group(base_path('routes/api.php'));
}

该服务提供者声明路由使用 api 字符前缀,并调用 api 中间件,该中间件定义在 app/Http/Kernel.php 文件内:

protected $middlewareGroups = [
    'api' => [
        'throttle:60,1',
        IlluminateRoutingMiddlewareSubstituteBindings::class,
    ],
];

至于命名空间 $this->namespace 一般返回 AppHttpControllers,我们为了区分API与其他应用,在目录 app/Http/Controller 下创建 API 目录,用于存储所有API相关的控制器。

那么上述的 RouteServiceProvider.php 文件内 mapApiRoutes 方法内的 namespace 需要这样写:

->namespace($this->namespace . 'API')

仍然以 Event 模型作为示例,在 routes/api.php 文件内声明一个资源类型的路由:

Route::resource('/events', 'APIEventsController');

注意命名空间上多出来的前缀 API ,这说明我们是把 EventController 文件放在了 API 目录下。

用户权限

让我们把目光还聚焦在系统默认声明的那条路由:

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

注意中间件 auth:api,因为api请求是无状态的,每次请求之间没有任何关联,所以使用用户权限区分资源的返回。那么我们怎么拿到用户授权呢?这在 config/auth.php 文件内定义,看系统自带的这一段配置代码:

'guards' => [
    'api' => [
        'driver' => 'token',
        'provider' => 'users',
        'hash' => false,
    ],
],

这一段定义了我们使用何种方式认证用户的身份。默认的驱动 token 定义在框架文件 laravel/framework/src/Illuminate/Auth/TokenGuard.php 内。长话短说,默认构造类传入的字段如下:

UserProvider $provider,
Request $request,
$inputKey = 'api_token',
$storageKey = 'api_token',
$hash = false

简单说,就是使用 users 表的 api_token 字段用户鉴权。那么默认我们 users 表显然缺少一个这样的字段,现在使用迁移文件补上:

php artisan make:migration add_api_token_field_to_users_table --table=users

首先是迁移方法 up 函数:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('api_token', 60)->unique();
    });
}

还有回滚使用的 down 方法:

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('api_token');
    });
}

这些都是常规操作,我们在之前的章节,使用了N多次了。执行指令迁移数据库:

php artisan migrate

看看效果

准备好了路由,而且路由内声明了一个get方法返回用户模型数据。也准备好了数据库表字段 api_token。我们在数据库表内找到一个用户数据,把api_token值设置为 1234,用于测试。

现在在浏览器内请求类似如下的url地址:

http://www.example.com/api/user?api_token=1234

如无异常,顺利会输出一个 json 字符串,

{
    "id":1,
    "provider":null,
    "provider_id":null,
    "first_name":"Tom",
    "last_name":"Hanks",
    "email":"tom@admin.com",
    "city":"",
    "state_id":null,
    "zip":"43016",
    "lat":null,"lng":null,
    "timezone":"America/New_York",
    "title":"Laravel Developer",
    "created_at":"2020-10-14 17:46:19",
    "updated_at":"2020-10-14 17:46:20",
    "last_login_at":null,
    "is_admin":0,
    "api_token":"1234"
}

这个json格式的数据是怎么来的呢?是在路由内,$request->user() 方法返回的User模型,使用 toArray() 格式化方法获得的。为了演示,很多字段与实际可能有所出入。

特别需要注意的是,关键的密码字段,以及 token 字段,是默认隐藏的,这得益于 User 模型内 $hiden 属性的定义:

protected $hidden = [
    'password', 'remember_token',
];

这些字段都对对外不公开访问。

写在最后

本文介绍了如何声明api地址,已经解释了api从中间件到路由的由来,明白了api授权的方式,可以为我们更灵活地定制授权方式提供便利。这在laravel内都是可插拔的,替换为我们的逻辑代码就可以愉快工作了。

Happy coding :-)

我是@程序员小助手,专注编程知识,圈子动态的IT领域原创作者

]]>
面对复杂业务,if-else coder 如何升级?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 1.png

作者 | 张建飞  阿里巴巴高级技术专家

导读:针对业务在不同场景下的差异,我们常常会习惯性地使用 if-else 来实现不同的业务逻辑,久而久之代码越来越难以维护。那么如何消除这些 if-else?面对复杂业务应如何思考和分析?本文分享阿里高级技术专家张建飞(Frank)关于复杂业务治理的方法论,介绍一种多维度分析问题的方法:矩阵分析法。

You should not be a if-else coder, should be a complexity conquer. 
——Frank

这篇文章,是对之前我在《阿里高级技术专家方法论:如何写复杂业务代码?》说的“自上而下的结构化分解 + 自下而上的抽象建模”方法论的升级。因为在之前的方法论中,我们缺少一个多维度看问题的视角,这种维度思维的缺失,可能会导致 miss 掉一些重要的业务信息,从而使我们制定软件设计策略的时候,陷入困难。

有了维度思维,我们便可以更加方面的去看清业务的全貌,更加全面的掌握业务信息,从而帮助我们更加体系化的去治理复杂性。

从 if-else 说起

我经常说,我们不要做一个 if-else coder。这里的 if-else,不是说我们在 coding 的时候不能使用 if-else,而是说我们不应该简陋地用 if-else 去实现业务的分支流程,因为这样随意的代码堆砌很容易堆出一座座“屎山”。

业务的差异性是 if-else 的根源。以零售通的商品业务为例。不同的处理场景,其业务逻辑实现是有差异性的。如下图所示,商品业务的差异性,主要体现在商品类型、销售方式和仓储方式的不同。

2.png

这三个维度上的差异组合起来,有 2 3 2 = 12 之多。这就是为什么在老代码中,到处可以看到 if(组合品) blabla,if(赠品) blabla,if(实仓) blabla 之类的代码。

那么,要如何消除这些讨厌的 if-else 呢?我们可以考虑以下两种方式:

  • 多态扩展:利用面向对象的多态特性,实现代码的复用和扩展。
  • 代码分离:对不同的场景,使用不同的流程代码实现。这样很清晰,但是可维护性不好。

1. 多态扩展

多态扩展可以有继承和组合两种方式。继承勿用多言,组合有点像策略模式,也就是把需要扩展的部分封装、抽象成需要被组合的对象,然后对其进行扩展,比如星环的能力扩展点就是这种方式。

这里,我们举一个继承的例子,商品在上架的时候要检查商品的状态是否可售,普通商品(Item)检查自己就好了,而组合商品(CombineItem)需要检查每一个子商品。

用过程式编码的方式,很容易就能写出如下的代码:

public void checkSellable(Item item){
    if (item.isNormal()){
        item.isSellable(); 
        //省略异常处理
    }
    else{
        List<Item> childItems = getChildItems();
        childItems.forEach(childItem -> childItem.isSellable()); 
        //省略异常处理
    }
}

然而,这个实现不优雅,不满足 OCP,也缺少业务语义显性化的表达。更好的做法是,我们可以把 CombineItem 和 Item 的关系通过模型显性化的表达出来。

3.png

这样一来,一方面模型正确的反应了实体关系,更清晰了。另一方面,我们可以利用多态来处理CombineItem和Item的差异,扩展性更好。重构后,代码会变成:

public void checkSellable(Item item){
    if (!item.isSellable()){
        throw new BizException("商品的状态不可售,不能上架");
    }
}

2. 代码分离

所谓的代码分离是指,对于不同的业务场景,我们用不同的编排代码将他们分开。以商品上架为例,我们可以这样写:

/**
* 1. 普通商品上架
*/
public void itemOnSale(){
    checkItemStock();//检查库存
    checkItemSellable();//检查可售状态
    checkItemPurchaseLimit();//检查限购
    checkItemFreight();//检查运费
    checkItemCommission();//检查佣金
    checkItemActivityConflict();//检查活动冲突

    generateCspuGroupNo();//生成单品组号
    publishItem();//发布商品
}

/**
* 2. 组合商品上架
*/
public void combineItemOnSale(){
    checkCombineItemStock();//检查库存
    checkCombineItemSellable();//检查可售状态
    checkCombineItemPurchaseLimit();//检查限购
    checkCombineItemFreight();//检查运费
    checkCombineItemCommission();//检查佣金
    checkCombineItemActivityConflict();//检查活动冲突

    generateCspuGroupNo();//生成单品组号
    publishCombineItem();//发布商品
}

/**
* 3. 赠品上架
*/
public void giftItemOnSale(){
    checkGiftItemSellable();//检查可售状态
    publishGiftItem();//发布商品
}

这种方式,当然也可以消除 if-else,彼此独立,也还清晰。但复用性是个问题。

3. 多维分析

细心的你可能已经发现了,在上面的案例中,普通商品和组合商品的业务流程基本是一样的。如果采用两套编排代码,有点冗余,这种重复将不利于后期代码的维护,会出现散弹式修改(一个业务逻辑要修改多处)的问题。

一个极端情况是,假如普通商品和组合商品,只有 checkSellable() 不一样,其它都一样。那毫无疑问,我们使用有多态(继承关系)的 CombineItem 和 Item 来处理差异,会更加合适。

而赠品上架的情况恰恰相反,它和其他商品的上架流程差异很大。反而不适合和他们合用一套流程代码,因为这样反而会增加他人的理解成本。还不如单独起一个流程来的清晰。

那么,问题来了,我们什么时候要用多态来处理差异,什么时候要用代码分离来处理差异呢?

接下来,是我今天要给你着重介绍的多维度分析问题的方法论之一:矩阵分析法。

我们可以弄一个矩阵,纵列代表业务场景,横列代表业务动作,里面的内容代表在这个业务场景下的业务动作的详细业务流程。对于我们的商品业务,我们可以得到如下的矩阵:

4.png

通过上面的矩阵分析,我们不难看出普通品和组合品可以复用同一套流程编排代码,而赠品和出清品的业务相对简单,更适合有一套独立的编排代码,这样的代码结构会更容易理解。

维度思维

1. 多维度的重要性

上面的案例不是我编造出来的,而是我在和张文(我同事)讨论应该用哪种方式去处理业务差异的真实故事。

我记得在和大学讨论完,开车回去的路上,我一直在想这个问题,然后在第二个路口等红灯的时候,突然有一个灵感冒出来。我抑制不住兴奋,一边开车,一边发消息给张文说:“我想到了一个很 NB 的方法论,能解决在‘多态扩展’和‘代码分离’之间如何做选择的问题”。

其实,我知道我兴奋的不仅仅是解决了这个问题。我兴奋的是,我第一次真正领悟到了多维度思考的重要性。从而有机会从一个“单维度”生物,升级成一个“多维度”思考者。妈妈再也不用担心我被“降维打击”了 :)

结构化思维有用、很有用、非常有用,只是它更多关注的是单向维度的事情。比如我要拆解业务流程,我要分解老板给我的工作安排,我要梳理测试用例,都是单向维度的。

而复杂性,通常不仅仅是一个维度上的复杂,而是在多个维度上的交叉复杂性。当问题涉及的要素比较多,彼此关联关系很复杂的时候,两个维度肯定会比一个维度要来的清晰,这也是为什么说矩阵思维是比结构化思维更高层次的思维方式。

实际上,我们从汉语的词汇上,也不难看出一个人的思维层级,是和他的思考维度正相关的。当我们说这个人很“轴”、“一根筋”的时候,实际上是在说他只有一维的线性思维。所以,观察事物的视角越多,维度越丰富,其思维层级也会越高。

5.png

2. 无处不在的多维思考

有了这些感悟,我开始系统的整理关于多维度思考分析的资料,发现这种思考方式真是无处不在。发现的越多,我越是感慨,为什么如此重要的思维方式,我到现在才领悟到。

1)波士顿矩阵

比如,在做产品分析的时候,有对产品发展前景进行分析的波士顿矩阵。

6.png

2)订单要素分析

当年,我在 1688 做交易下单业务的时候,有非常多的下单场景,每种场景下,买家享受的权益是不一样的(如下表所示)。我们当时也是使用了矩阵去表达这个复杂的关系,只是当时还没有想到要将其提升到方法论的高度。

7.png

3)数据交叉分析

在数据分析中,维度分析是非常重要的,特别是维度很多的时候,我们可以通过皮尔逊积矩相关系数,做交叉分析,从而弥补独立维度分析没法发现的一些问题。

8.png
简单相关系数矩阵

4)分析矩阵

最近我碰巧看到 Alan Shalloway 写的《设计模式解析:Design Patterns Explained》,这是一本非常经典的关于 OOP 的书,里面的第十六章就是专门讲“分析矩阵”的,作者创造这个方法论的初衷也是因为业务涉及的要素太多,信息量太大,他需要一种组织海量数据的新方式。

9.png

我和 Alan 的路径不一样,但是都得出了同样的结论。由此可见,这种矩阵分析的方式的确是对复杂业务进行分析的一把利器,业务场景越多,交叉关系越是复杂,越需要这样的分析。

5)组织阵型

生产关系决定生产力,对于一个管理者来说,如何有效的设置组织结构是决定团队是否能高效协作的关键。所以我们可以看到公司里面,每年都有比较大的关于组织结构和人员安排的调整。

对于技术团队来说,我们习惯于按领域划分工作范围,这样做的好处是责任到人、职责清晰。然而,领域只是一个维度,我们工作通常都是以项目的形式的开展,而项目通常是贯穿多个领域的。所以,在做团队组织规划的时候,我们可以通过业务领域和业务项目两个维度去看。

比如,在我负责的商品团队,我会按照如下的形式去做职责划分。

10.png

6)时间维度

除了工作,生活中也到处可见多维思考的重要性。

比如,我们说浪费可耻,应该把盘子舔的很干净,岂不知加上时间维度之后,你当前的舔盘,后面可能要耗费更多的资源和精力去减肥,反而会造成更大的浪费。

我们说代码写的丑陋,是因为要“快速”支撑业务,加上时间维度之后,这种临时的妥协,换来的是意想不到的 bug,线上故障,以及无止尽的 996。

7)RFM 模型

简单的思考是“点”状的,比如舔盘、代码堆砌就是当下的“点”;好一点的思考是“线”状,加上时间线之后,不难看出“点”是有问题的;再全面一些的思考是“面”(二维);更体系化的思考是“体”(三维);比如,RFM 模型就是一个很不错的三维模型。可惜的是,在表达上,我们人类只能在二维的空间里去模拟三维,否则四维可能会更加有用。

11.png

复杂业务治理总结

在前言部分,我已经说过了,多维分析是对之前方法论的升级。加上以前的方法论,完整的方法论应该是“业务理解-->领域建模-->流程分解-->多维分析”。

为了方便大家理解,下面我把这些方法论做一个简单的串联和解释。

1. 业务理解

理解业务是所有工作的起点。首先,我们要找到业务的核心要素,理解核心概念,梳理业务流程。

比如,在零售通的商品域,我们要知道什么是商品(Item),什么是单品(CSPU),什么是组合品(CombineItem)。在下单域,我们要知道订单(order)的构成要素是商品、优惠、支付。在 CRM 领域,我们要理解客户、机会、联系人、Leads 等等。

这里,我想再次强调下语言的重要性,语言是我们思考的载体,就像维特根斯坦说的:“凡是能够说的事情,都能够说清楚”。

你不应该放过任何一个模糊的业务概念,一定要透彻的理解它,并给与合理的命名(Ubiquitous Language)。唯有如此,我们才能更加清晰的理解业务,才能更好的开展后续的工作。

2. 领域建模

在软件设计中,模型是指实体,以及实体之间的联系,这里需要我们具备良好的抽象能力。能够透过庞杂的表象,找到事务的本质核心。

再复杂的业务领域,其核心概念都不应该太复杂,抓住了核心,我们就抓住了主线,业务往往都是围绕着这些核心实体展开的。

比如,商品域虽然很复杂,但其核心的领域模型,无外乎就如下图所示:

12.png

3. 流程分解

关于流程分解,在《阿里高级技术专家方法论:如何写复杂业务代码?》里面已经有非常详细的阐述,这里就不赘述了。

简单来说,流程分解就是对业务过程进行详细的分解,使用结构化的方法论(先演绎、后归纳),最后形成一个金字塔结构。

比如,在商品领域,有创建商品、商品上架、上架审核、商品下架、下架审核、修改商品、删除商品等一些列动作(流程),每个动作的背后都有非常复杂的业务逻辑。我们需要对这些流程进行详细的梳理,然后按步骤进行分解。最后形成一个如下的金字塔结构:

13.png

4. 多维分析

关于多维分析,我以二维的矩阵分析为例,我想我前面应该已经说清楚了。

业务的复杂性主要体现在流程的复杂性和多维度要素相互关联、依赖关系上,结构化思维可以帮我们梳理流程,而矩阵思维可以帮忙我们梳理、呈现多维度关联、依赖关系。二者结合,可以更加全面的展现复杂业务的全貌。从而让我们的治理可以有的放矢、有章可循。

既然是方法论,在这里,我会尝试给出一个矩阵分析的框架。试想下,如果我们的业务很简单,只有一个业务场景,没有分支流程。我们的系统不会太复杂。之所以复杂,是因为各种业务场景互相叠加、依赖、影响。

因此,我们在做矩阵分析的时候,纵轴可以选择使用业务场景,横轴是备选维度,可以是受场景影响的业务流程(如文章中的商品流程矩阵图),也可以是受场景影响的业务属性(如文章中的订单组成要素矩阵图),或者任何其它不同性质的“东西”。

14.png

通过矩阵图,可以清晰的展现不同场景下,业务的差异性。基于此,我们可以定制满足差异性的最佳实现策略,可能是多态扩展,可能是分离的代码,也可能是其它。

这就是矩阵分析的要义,其本质是一种多维度思考的方法论。

篇后寄语

最后,我想说世界是熵增的(即万物都在缓慢的分崩离析),控制复杂度是我们这些从业者无法推卸的责任和使命。

软件行业的发展才几十年,还是一门年轻的学科,软件工程就像一个刚学会走路的小孩,还很不成熟,有时还很幼稚。

但毕竟还是有几十年的沉淀,还是有一些好的方法和实践可以参考,我的这些总结沉淀只是在前人的基础上,多走了一点点而已。但就是这一点点,也实属来自不易,其中冷暖,只有自己能体会。可以说,这一路走来,是一场对心力、脑力和体力的持续考验。

15.png

  • 心力是指不将就的匠心,不妥协的决心,不满足的好奇心、以及不放弃的恒心。
  • 脑力是指那些必要的思维能力、学习能力、思考能力、思辨能力。
  • 之所以说“业务理解-->领域建模-->流程分解-->多维分析”是体力,是因为实现它们就像是在做填空题,只要你愿意花时间,再复杂的业务都可以按部就班的清晰起来。

梳理清晰了,再配合 COLA(https://start.aliyun.com/)的指导,我们就有可能写出清晰、易读的代码,就有可能从一个 if-else coder 升级为一个 complexity conquer。

而这不正是我们工程师孜孜不倦的追求吗?

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

]]>
阿里云rds并发性能解读-大分区表高并发性能提升100倍?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 阿里云某客户发现自己使用读写分离实例,master的cpu特别高,而读写分离中承担读流量的slave节点却相对空闲。用户CPU打满后,访问到主节点的的线上服务受到了较大影响。关于阿里云RDS请参考云数据库RDS详情链接

Redis读写分离实例的原理是:key统一写入到master,然后通过主从复制同步到slave,用户的请求通过proxy做判断,如果是写请求,转发到master;如果是读请求,分散转发到slave,这种架构适合读请求数量远大于写请求数量的业务,读写分离架构示意图如下所示。
1.png
阿里云Redis读写分离版读写命令转发示例

bitfield命令

经过和客户沟通查看后,客户使用了大量的bitfield做读取,首先介绍一下这个命令的用法和场景,bitfield 是针对bitmap数据类型操作的命令,bitmap通常被用来在极小空间消耗下通过位的运算(AND/OR/XOR/NOT)实现对状态的判断,常见的使用场景例如:

  • 通过bitmap来记录用户每天应用登录状态,即如果$ID用户登录,就SETBIT logins:20200404 $ID 1,表示用户$ID在20200404这一天登录了,通过BITCOUNT logins:20200404可以得到这一天所有登录过的用户数量;通过对两天的记录求AND,可以判断哪个用户连续两天登录了,即BITOP AND logins:20200404-05 logins:20200404 logins:20200404。
    判断用户是否阅读了共同的文章,观看了共同的视频等。

前一阵子,答题领奖活动非常火爆,“答对12道题的同学有机会瓜分奖池”,这种如果使用bitmap来实现,就非常容易判断出用户是否全部答对。

1.png
一个使用Redis BITMAP设计的答题游戏系统

答题系统设计如:

  • 每个用户每轮答题,设置一个key,比如user1在第一轮答题的key是 round:1:user1
    每答对一道题,设置相关的bit为1,比如user1答对了第5题,那么就设置第5个bit为1就可以了,如: SETBIT round:1:user1 5 1 ;如果用户1在第一轮答对了第9题,那么就把第9个bit设置为1,SETBIT round:1:user1 9 1;值得注意的是,bitfield默认bit都是0,答错可以不设置

计算用户总共答对了几道题,就可以使用 BITCOUNT 命令统计1的bit个数。如user1答对了3道题,user2在第一轮全部答对,那么user2就有机会参与答题(第1轮)的后续玩法

可见,Redis的bitmap接口可以用非常高的存储效率和计算加速效果。回到bitfiled命令,它的语法如下所示:

BITFIELD key  
[GET type offset] // 获取指定位的值
[SET type offset value] // 设置指定位的值
[INCRBY type offset increment] // 增加指定位的值
[OVERFLOW WRAP|SAT|FAIL] // 控制INCR的界限

读写分离实例处理bitfield的问题

从上文可知,bitfield的子命令中,GET命令是读属性,SET/INCRBY命令为写属性,因此Redis将其归类为写属性,从而只能被转发到master实例,如下图所示为bitfield的路由情况。

1.png

这就是为什么客户使用了读写分离版,而只有master节点cpu使用高,其余slave节点却没有收到这个命令的打散的原因。

解决方案

  • 方案一:改造Redis内核,将bitfield命令属性标记为读属性,但是当其包含SET/INCRBY等写属性的子命令时候,仍旧将其同步到slave等。此方案优点是外部组件(proxy和客户端)不需要做修改,缺点是需要对bitfiled命令做特殊处理,破坏引擎命令统一处理的一致性。
    方案二:增加bitfield_ro命令,类似于georadius_ro命令,用来只支持get选项,从而作为读属性,这样就避免了slave无法读取的问题。此方案优点是方案清晰可靠,缺点是需要proxy和客户端做适配才能使用。

经过讨论,最终采取了方案二,因为这个方案更优雅,也更标准化。

添加bitfield_ro

{"bitfield_ro",bitfieldroCommand,-2,
"read-only fast @bitmap",
0,NULL,1,1,1,0,0,0},

完成之后,下图是在slave上执行bitfield_ro命令,可以看到被正确执行。

tair-redis > SLAVEOF 127.0.0.1 6379
OK
tair-redis > set k v
(error) READONLY You can't write against a read only replica.
tair-redis > BITFIELD mykey GET u4 0
(error) READONLY You can't write against a read only replica.
tair-redis > BITFIELD_RO mykey GET u4 0
1) (integer) 0

Proxy转发

为了保持用户不做代码修改,我们在proxy上对bitfiled命令做了兼容,即如果用户的bitfield命令只有get选项,proxy会将此命令转换为bitfield_ro分散转发到后端多个节点上,从而实现加速,用户不用做任何改造即可完成加速,如下图所示。

1.png

添加BITFIELD_RO命令后处理BITFIELD逻辑流程

贡献社区

我们将自己的修改回馈给了社区,并且被Redis官方接受

值得一提的是,阿里云在国内是最大的Redis社区contributer,如在新发布的Redis-6.0rc中,阿里云的贡献排第三,仅次于作者和Redis vendor(Redis Labs)。阿里云仍旧在不断的回馈和贡献社区。

阿里云Redis通过增加bitfield_ro命令,解决了官方bitfield get命令无法在slave上加速执行的问题。

除过bitfield命令,阿里云Redis也同时对georadius命令做了兼容转换,即在读写分离实例上,如果georadius/georadiusbymember命令没有store/storedist选项,将会被自动判断为读命令转发到slave加速执行。

我们思考读写分离版的场景,为什么用户需要读写分离呢?为什么不是用集群版呢?我们做一下简单对比,比如设置社区版的服务能力为K,那么表的对比如下(我们只添加了增强版Tair的主备做对比,集群版可以直接乘以分片数):

方式 Redis社区版集群 Redis社区版读写分离 Redis(Tair增强版)主备
写(key均匀情况) K分片数 K K3
读(key均匀情况) K分片数 K只读节点数 K*3
写(单key或热key) K(最坏情况) K K*3
读(单key或热key) K(最坏情况) K只读节点数 K3
​表1. Redis社区版(集群/读写分离)和增强版(主备)简单场景对比

可见,其实读写分离版属于对单个key和热key的读能力的扩展的一种方法,比较适合中小用户有大key的情况,它无法解决用户的突发写的瓶颈,比如在这个场景下,如果用户的bitfield命令是写请求(子命令中带有INCRBY和SET),就会遇到无法解决的性能问题。

从表的对比看,这种情况下,用户如果能把key拆散,或者把大key拆成很多小key,就可以使用集群版获得良好的线性加速能力。大key带来的问题包含但不仅限于:

大key会造成数据倾斜,使得Redis的容量和服务能力不能线性扩展
大key意味着大概率这个key是热点
一旦不小心针对大key有range类的操作,会出现慢查询,还容易打爆带宽
这也是Tair增强版在阿里集团内各个应用建议的:“避免设计出大key和慢查,能避免90%以上的Redis问题”。

但是在实际使用中,用户仍旧不可避免的遇到热点问题,比如抢购,比如热剧,比如超大型直播间等;尤其是很多热点具备“突发性”的特点,事先并不知晓,冲击随时可达。Redis增强版的性能增强实例具备单key在O(1)操作40~45w ops的服务能力和极强的抗冲击能力,单机主备版就足够应对一场中大型的秒杀活动!同时如果用户没有大key,增强性能集群版能够近乎赋予用户千万甚至几千万OPS的服务能力,这也是Tair作为阿里重器,支持每次平稳渡过双11购物节秒杀的关键

原文链接:https://www.9i0i.com/article-95490-1.html

]]>
全面上云这条路,洋葱学院已经走了近7年 -阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 洋葱学院在2013年末成立,原名洋葱数学,是一家K12在线教育公司。课程里没有真人老师授课,而是采用100%人机交互学习方式,每节课5-8分钟动画视频的形式精讲一个知识点或解题思维,希望有趣生动的讲解方式让更多的孩子们爱上学习。

创新且锐意进取,是这个公司的基因。

洋葱学院由杨临风、朱若辰和李诺联合创办,团队希望通过技术方式促进教育均衡。在创立之初,团队就做出了一个意识超前的决定:整套业务系统均基于阿里云搭建。
image.png
要知道,2013年,能选择全面上云的中国企业屈指可数。

上云先锋洋葱学院这一路走来,也是和阿里云一同携手成长的难忘历程。几年前,由于某个特殊使用场景,线上业务受到严重影响,洋葱学院和阿里云紧急沟通、快速排查问题,阿里云云数据库的专家同学进行了重启、备份等一系列工作。

早先,洋葱学院起步于初中数学、物理课程,但是随着不断发展,开始加入语文和英语等学科,这些课程特点不同、相应的学习流程不同。除了早先选用的ECS云服务、SLB负载均衡、阿里云云数据库等经典基础产品之外,洋葱学院也尝试将新的业务应用搭建于一些新兴阿里云产品,如ACK容器服务、RSS弹性伸缩、SLS日志服务、Blink实时计算、ARMS前端监控等,来满足日趋复杂和多样化的业务需求。

如今,从初中理科逐渐扩展到小初高全学段全学科,为130多万教师以及3600多万的中小学生提供24小时在线的“云课堂”。

疫情大考突如其来,IT架构稳如泰山

疫情期间(近一个月以来),有超过700万学生、35万教师使用洋葱学院APP在线学习或辅助授课,同时还将课程资源开放给学习强国、快手等第三方平台播放,帮助更广泛的学生远程学习。

能应对猝不及防的疫情流量洪峰,洋葱都做了怎样的努力、下足了哪些功夫呢?

在线教育业务的一个重要特点,就是波峰波谷比较规律,可预测。在学校下课或放假时期,业务会达到上升,洋葱学院便会在数分钟扩容云上资源,待学生返校上课之时,再根据业务情况释放资源,这样持续保持较高的资源利用率,既节省成本又确保业务响应。

3年前,洋葱学院开始尝试微服务改造,将复杂的单体架构进行拆分和解耦。同时采用容器技术,并也将swarm迁移至阿里云容器服务ACK之上,原本每个模块都对应一套ECS与SLB,但是随着微服务越拆越细,开始出现资源浪费的情况,而且调度复杂度都在迅速膨胀。容器服务可以根据不同模块的配置所需,资源分配更加合理,按照定义规则自动弹性伸缩避免了复杂的调度维护。

image.png

容器的弹性

基本功夯实的基础上,洋葱学院还做了一些方案优化和升级。

延期开学的这段时间里,广大学生学习时间较为集中,面对大流量、高并发访问需求,洋葱学院需要确保业务稳定性,采用阿里云容器服务与云数据库融合解决方案,在应用不变的情况下,快速平稳实现扩容的问题。阿里云容器服务可以在几分钟内扩充底层资源,满足快速部署数千个应用实例的需求。阿里云容器服务团队的建议下,洋葱学院还进一步优化了整体的ECS服务器配置,将大量的小规格ECS服务器更换成30至50核大规格ECS,从容应对10倍扩容,同时运维管控更加便捷。

针对疫情延期开学,洋葱学院作为头部K12在线教育公司,免费向全国师生开放了平台的全部核心课程资源,这期间每天的学习访问人数持续飙升。使用云容器之后,系统在资源利用率上提升了约60%,出现问题后可快速隔离,当面对急剧增长的业务量,也可以在短时间内扩容进行业务支撑。——李诺 洋葱学院联合创始人&CTO

image.png

数据库的升级

为了确保平台使用起来“丝般顺滑”,阿里云为洋葱学院提供了综合架构解决方案:数据库层将云数据库Redis数据库做高速缓存,RDS PostgreSQL+MongoDB做持久化存储;应用层对微服务进行改造,以及容器化部署。这是完成挑战的核心能力。

洋葱学院还对冷用户和冷热数据做了优化:冷用户,即第一次来的用户信息较少,此期间冷用户过多,亟需优化冷用户的流程处理,这需要提高高压下的数据快速处理能力,处理变得更快;老师和学生的作业数据,会有冷热数据之分,每隔一段时间进行数据迁移,但是热数据增长过快,此前方案逐渐应接不暇。在阿里云云数据专家的建议下,将冷用户缓存增加,升级数据库,对数据库进行了分库分表,还进行了一系列索引优化、语句改写以及业务改造等工作。

在此次疫情中,洋葱学院利用阿里云数据库的极致弹性、无缝升级扩容能力,一晚上便完成了几十个核心数据库的容量升级以及PG实例版本升级。单个云Redis集群可承载千万级访问的超高性能,确保了即使流量数十倍增长也不会有业务瓶颈。同时,持久化存储RDS PostgreSQL、MongoDB有更强的承载能力,不仅可以应对复杂查询,还可做到极致超强弹性水平扩展,全面保障了洋葱学院的运行,在业务量比历史同期翻了10倍的情况下仍然保持平稳。

故障检测

此外,原本只能依靠负载均衡的定时扫描错误节点,故障检测存在一定时延;而Kubernetes自带容灾和错误发现机制,容器内部pod之间自动实现切换,大大缩短问题发现时间,同时基于阿里云云监控、ARMS Prometheus、ARMS前端监控和日志服务,实现云资源、容器集群、容器节点、Pod等指标的完善监控,对集群变更状态、pod创建拉起删除、组件异常等信息,基本可以覆盖到各种监控报警问题,将重大故障‘扼杀于摇篮之中’。

AI辅助教学,学生老师个性化“Friday”

image.png
看过复仇者联盟的朋友们,都记得钢铁侠的AI助手Friday,每次关键时刻都协助钢铁侠力挽狂澜。

洋葱学院的APP,其实早已经成为很多学生和老师的AI助手Friday。2017年,洋葱学院成立人工智能实验室,并尝试将AI赋能引入其教学体系。最主要的原因,是希望为学生们打造完整的学习闭环,产品能根据学生的学习现状和效果,动态规划学习路径,推送个性化学习内容。

而老师则可以通过数据后台实时充分掌握班上每名学生的学习能力和知识掌握情况,为同班同学一键布置不同的教学任务。

用心做产品,以诚待客

image.png
洋葱学院自成立之处,便决心搭建于云上。在他们看来,自己研究开源方案或重新搭建系统,是"事倍功半"的,意味着巨大的运维负担;因此,每当有新的业务需求时,洋葱学院都会首先考虑能否使用云上已有方案,他们相信阿里云服务的稳定性、专业性。

洋葱学院将更多的人力和精力投入到了课程研发之中,打磨课程。如今,洋葱的用户遍布全国,深受师生和家长的喜爱,多达3600万学生自发推荐,社科院白皮书显示其教师推荐度和家长满意度分别高达85%和90%。

洋葱学院以匠人之心打造“ 云 ”课堂,是一群践行教育初心的梦想家和冒险家。

]]>
双11大战必备神器——DataV数据可视化-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 突然的降温和强冷空气告诉我,是时候为保暖秋裤来一波购物血拼了。今年的双十一马上到达战场,你准备贡献多少战绩呢!
是不是每年都很期待阿里巴巴汇报双十一最后的成交额,我们可以搬个小板凳一起观看一下那块弥漫着八亿人硝烟的大屏幕。

每年双十一都会出现的这块大屏到底有什么神通广大呢?要想今年双十一吹不一样的牛逼,就要了解一下不一样的神器——DataV数据可视化

专业解释:DataV是一个拖拽式可视化工具,可以在零售、物流、电力、水利、环保,还有交通领域,通过交互式实时数据可视化视屏墙来帮助业务人员发现、诊断业务问题。

它到底有什么样的魅力?

专业级的数据可视化

专精于地理信息与业务数据融合的可视化,提供丰富的行业模版和交互组件,支持自定义组件接入。
组件.jpg

来瞅一眼这个组件有多丰富,DataV的开发小伙伴也太为大家着想了一点。(开发小伙伴还偷偷告诉我,第三方的组件包购买之后也可以接入DataV哦!我真的不是商业间谍)

指挥中心、实时监控、地理分析、汇报展示等等这么多的屏幕模板,真的不用怕没有设计师!
模板.jpg

多种数据源支持

支持接入包括阿里云分析型数据库、关系型数据库、本地CSV上传和在线API等,而且支持动态请求。
数据源.jpg

大数据计算的能力有没有发挥的很棒!(请跟我一起竖起大拇指)

图形化编辑界面

拖拽即可完成样式和数据配置,无需编程就能轻松搭建数据大屏。
拖拽.jpg

只要轻轻动动你的小手指,拖拖拽拽,不需要编程能力,就可以创造出专业的可视化应用!(我真的不是DataV的脑残粉)

灵活部署和发布

适配非常规拼接大屏,创建的可视化应用能够发布分享,没有购买DataV产品的用户也可以访问到应用,作为对外数据业务展示的窗口。或者通过密码/Token的方式进行访问权限控制,保护数据隐私安全。还可以通过历史快照来保存历史版本,并在历史版本之间切换并发布。
发布.jpg

在某些场景,如数据涉密无法上云、展示现场网络条件有限等条件下,还可以采用 DataV 本地部署的方式。

部署和发布如此流畅,不如一起来拖拖拽拽一个可视化界面,展示一下你真正的实力。

双十一期间购买DataV可享受超级福利折扣价!
详情优惠请戳:购买链接

]]>
阿里云物联网平台如何订阅异步服务调用的返回结果?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 业务场景

image.png

1、云端向设备发送的下行消息或者异步服务调用到平台也算结束,平台再向设备进行一个透传
2、设备端向平台发送的上行消息到平台就算结束
3、云端通过服务端订阅来获取设备上行的消息

原理
1、要想获取异步服务调用的返回结果,首先设备得有返回
(1) 设备接收平台端透传过来的异步服务调用
image.png

(2)设备端收到数据后进行响应
image.png
2、这里的设备响应结果发送给平台之后,平台可通过
云产品流传或服务端订阅,再将消息发送给云端
方式一:云平台流转,注意选择Topic:
/${productKey}/${deviceName}/thing/downlink/reply/message
image.png
这个为什么可行?可参考官方文档说明
image.png
然后添加操作为发布到AMQP消费组
image.png

方式二:AMQP服务端订阅
订阅什么呢?勾选设备上报消息即可(前提是设备端有返回,即满足原理1的前提)
image.png

操作步骤
不多说了,直接上步骤
1、准备测试用的产品和设备
主要是定义一个异步服务:这里不详细阐述
image.png

2、准备测试用的云端调试工具
可以是集成云端SDK的Demo,可以是业务逻辑应用调用云端API,最简单的直接使用云端API在线调试工具
具体参数填写规范,这里也不做详细阐述
image.png

3、物联网平台控制台上配置好规则引擎
(1)云平台流转
image.png
选择好产品设备和topic

image.png
注意SQL语句的编写,这里的字段就是要发送给AMQP客户端的消息内容,可以事先进行调试。
image.png
image.png

这里要注意AMQP客户端都是按照既定的协议格式进行过滤数据的,所以这里的消息内容需要按照协议进行配置
image.png

确定好消息内容后

SQL语句:

SELECT timestamp('yyyy-MM-dd'T'HH:mm:ss'Z'') as 云平台流转至AMQP测试,deviceName() as deviceName, code as code,data as data,topic() as topic,messageId() as requestId,id as id,topic(1) as productKey,iotId as iotId FROM "/a16hDZJpRCl/IoTDeviceDemo1thing/downlink/reply/message" WHERE

(2)服务端订阅
image.png
勾选设备上报消息即可,具体消费组怎么创建就不详细阐述

实测效果:
image.png

4、设备端接收消息+响应reply
image.png
image.png

代码示例:
pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>MQTTClient</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>aliyun-java-sdk-core</artifactId>
            <version>3.5.1</version>
        </dependency>
    </dependencies>

</project>

AliyunIoTSignUtil:

package com.alibaba.taro;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
import java.util.Map;

/**
 * AliyunIoTSignUtil
 */

public class AliyunIoTSignUtil {
    public static String sign(Map<String, String> params, String deviceSecret, String signMethod) {
        //将参数Key按字典顺序排序
        String[] sortedKeys = params.keySet().toArray(new String[] {});
        Arrays.sort(sortedKeys);

        //生成规范化请求字符串
        StringBuilder canonicalizedQueryString = new StringBuilder();
        for (String key : sortedKeys) {
            if ("sign".equalsIgnoreCase(key)) {
                continue;
            }
            canonicalizedQueryString.append(key).append(params.get(key));
        }

        try {
            String key = deviceSecret;
            return encryptHMAC(signMethod,canonicalizedQueryString.toString(), key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * HMACSHA1加密
     *
     */
    public static String encryptHMAC(String signMethod,String content, String key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key.getBytes("utf-8"), signMethod);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
        byte[] data = mac.doFinal(content.getBytes("utf-8"));
        return bytesToHexString(data);
    }

    public static final String bytesToHexString(byte[] bArray) {

        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }
}

Demo:


package com.alibaba;

import com.alibaba.taro.AliyunIoTSignUtil;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;


public class CustomTopicMessageDemo2 {

    public static String productKey = "a16hD*****";
    public static String deviceName = "IoTDevice****";
    public static String deviceSecret = "0895205d*********";
    public static String regionId = "cn-shanghai";


    // 物模型-属性上报topic
    //private static String pubTopic = "/sys/" + productKey + "/" + deviceName + "/thing/event/property/post";
    //private static String subTopic = "/sys/" + productKey + "/" + deviceName + "/thing/service/property/set";
    // 自定义topic,在产品Topic列表位置定义
    //private static String pubTopic = "/"+productKey + "/" + deviceName+"/user/DemoTest";
    //private static String subTopic = "/"+productKey + "/" + deviceName+"/user/DemoTest";
    private static String pubTopic = "/"+productKey + "/" + deviceName+"/user/get";
    private static String subTopic = "/"+productKey + "/" + deviceName+"/user/get";

    private static MqttClient mqttClient;

    public static void main(String [] args){

        initAliyunIoTClient();
//        ScheduledExecutorService scheduledThreadPool = new ScheduledThreadPoolExecutor(1,
//                new ThreadFactoryBuilder().setNameFormat("thread-runner-%d").build());
//
//        scheduledThreadPool.scheduleAtFixedRate(()->postDeviceProperties(), 10,10, TimeUnit.SECONDS);
        // 汇报属性
        //String payloadJson = "{"params":{"MasterLightSwitch":0,"LivingLightSwitch":0,"SecondaryLightSwotch":0,"MasterCurtainSwitch":1,"SecondaryCurtainSwitch":1,"LivingCurtainSwitch":1}}";
        //String payloadJson = "{"params":{"Temp":77,"yyy":{"tttt":"123"}}}";
        String payloadJson = "{"params":{"Temp":77,"yyy":"8888"}}";
        //String payloadJson = "{"tts":"ss"}";
        //String payloadJson = "34454545";
        postDeviceProperties(payloadJson);

        try {
            mqttClient.subscribe(subTopic); // 订阅Topic
        } catch (MqttException e) {
            System.out.println("error:" + e.getMessage());
            e.printStackTrace();
        }

        // 设置订阅监听
        mqttClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable throwable) {
                System.out.println("connection Lost");

            }

            @Override
            public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
                String payload =  new String(mqttMessage.getPayload());
                System.out.println(" 接收消息:");
                System.out.println("Topic : " + s);
                System.out.println(payload); //打印输出消息payLoad
                System.out.println("=================================================================");

//                String subTopic = "/sys/" + productKey + "/" + deviceName + "/thing/service/property/set";
//                if(s.equals(subTopic)) {
//                    JSONObject jsonProperty = new JSONObject(payload);
//                    if(jsonProperty.has("params"))
//                    {
//                        String paramsJson = jsonProperty.get("params").toString();
//                        System.out.println("test paramsJson is:n" + paramsJson);
//                        String params = "{"params": " +  paramsJson + "}";
//                        System.out.println("test params is:n" + params);
//                        System.out.println("收到属性设置后,再上报一次属性:");
//                        postDeviceProperties(params);
//                    }
//                }

                //收到服务调用,给予返回reply
//                下行(Alink JSON):
//                请求Topic:/sys/{productKey}/{deviceName}/thing/service/{tsl.service.identifier}
//                响应Topic:/sys/{productKey}/{deviceName}/thing/service/{tsl.service.identifier}_reply
                String subTopic = "/sys/" + productKey + "/" + deviceName + "/thing/service/StartP2PStreaming";
                String replyTopic = "/sys/" + productKey + "/" + deviceName + "/thing/service/StartP2PStreaming_reply";
                if(s.equals(subTopic)) {
                    JSONObject jsonProperty = new JSONObject(payload);
                    if(jsonProperty.has("id"))
                    {
                        String id = jsonProperty.get("id").toString();
                        String replyJson = "{"data":{},"code":200,"id":""+ id +""}";
                        //System.out.println("test replyJson is:n" + replyJson);
                        //String replys = "{"params": " +  replyJson + "}";
                        //System.out.println("test reply is:n" + replys);
                        System.out.println("收到服务调用后,给予返回");
                        postServiceReply(replyJson,replyTopic);
                    }
                }
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

            }
        });

    }

    /**
     * 初始化 Client 对象
     */
    private static void initAliyunIoTClient() {

        try {
            // 构造连接需要的参数
            String clientId = "java" + System.currentTimeMillis();
            Map<String, String> params = new HashMap<String, String>(16);
            params.put("productKey", productKey);
            params.put("deviceName", deviceName);
            params.put("clientId", clientId);
            String timestamp = String.valueOf(System.currentTimeMillis());
            params.put("timestamp", timestamp);
            // cn-shanghai
            String targetServer = "tcp://" + productKey + ".iot-as-mqtt."+regionId+".aliyuncs.com:1883";

            String mqttclientId = clientId + "|securemode=3,signmethod=hmacsha1,timestamp=" + timestamp + "|";
            String mqttUsername = deviceName + "&" + productKey;
            String mqttPassword = AliyunIoTSignUtil.sign(params, deviceSecret, "hmacsha1");

            connectMqtt(targetServer, mqttclientId, mqttUsername, mqttPassword);

        } catch (Exception e) {
            System.out.println("initAliyunIoTClient error " + e.getMessage());
        }
    }

    public static void connectMqtt(String url, String clientId, String mqttUsername, String mqttPassword) throws Exception {

        MemoryPersistence persistence = new MemoryPersistence();
        mqttClient = new MqttClient(url, clientId, persistence);
        MqttConnectOptions connOpts = new MqttConnectOptions();
        // MQTT 3.1.1
        connOpts.setMqttVersion(4);
        connOpts.setAutomaticReconnect(false);
        connOpts.setCleanSession(false);
        //connOpts.setCleanSession(true);

        connOpts.setUserName(mqttUsername);
        connOpts.setPassword(mqttPassword.toCharArray());
        connOpts.setKeepAliveInterval(60);

        mqttClient.connect(connOpts);
    }

    /**
     * 汇报属性
     */
    private static void postDeviceProperties(String payloadJson) {

        try {
            //上报数据
            //高级版 物模型-属性上报payload
            System.out.println("上报属性值:");
            //String payloadJson = "{"params":{"Status":0,"Data":"15"}}";
            //String payloadJson = "{"GeoLocation":{"Longitude":120.99,"Latitude":30.13,"Altitude":39.01},"BatteryPercentage":40.703533, "Temperature":2.233362}";
            //String payloadJson = "{"id":"3","version":"1.0","params":{"GeoLocation":{"Longitude":120.999,"Latitude":30.13,"Altitude":39.01},"BatteryPercentage":42.99999, "Temperature":2.233362}}";
            //String payloadJson = "{"params":{"MasterLightSwitch":0,"LivingLightSwitch":0,"SecondaryLightSwotch":0,"MasterCurtainSwitch":1,"SecondaryCurtainSwitch":1,"LivingCurtainSwitch":1}}";
            System.out.println(payloadJson);
            MqttMessage message = new MqttMessage(payloadJson.getBytes("utf-8"));
            message.setQos(0);
            mqttClient.publish(pubTopic, message);
            System.out.println("=================================================================");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * 服务返回
     */
    private static void postServiceReply(String payloadJson,String relpyTopic) {

        try {
            //上报数据
            //高级版 物模型-属性上报payload
            System.out.println("服务调用返回:");
            //String payloadJson = "{"params":{"Status":0,"Data":"15"}}";
            System.out.println("Topic:");
            System.out.println(relpyTopic);
            System.out.println(payloadJson);
            MqttMessage message = new MqttMessage(payloadJson.getBytes("utf-8"));
            message.setQos(0);
            mqttClient.publish(relpyTopic, message);
            System.out.println("=================================================================");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

}


实测效果:
image.png

5、云端使用AMQP客户端登录,并接收消息

参考官方文档,这里就不作详细阐述。
https://help.aliyun.com/document_detail/143601.html?spm=a2c4g.11186623.6.624.304e354e2OEGFh

代码示例:
pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!-- amqp 1.0 qpid client -->
<!--        <dependency>-->
<!--            <groupId>org.apache.qpid</groupId>-->
<!--            <artifactId>qpid-jms-client</artifactId>-->
<!--            <version>0.47.0</version>-->
<!--        </dependency>-->


        <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.10</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.apache.qpid/qpid-jms-client -->
        <dependency>
            <groupId>org.apache.qpid</groupId>
            <artifactId>qpid-jms-client</artifactId>
            <version>0.47.0</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>maven-surefire-common</artifactId>
            <version>2.12.4</version>
        </dependency>


        <!-- util for base64-->

<!--        <dependency>-->
<!--            <groupId>commons-codec</groupId>-->
<!--            <artifactId>commons-codec</artifactId>-->
<!--            <version>1.3</version>-->
<!--        </dependency>-->
    </dependencies>


</project>

Demo

package com.alibaba;

import org.apache.commons.codec.binary.Base64;
import org.apache.qpid.jms.JmsConnection;
import org.apache.qpid.jms.JmsConnectionListener;
import org.apache.qpid.jms.message.JmsInboundMessageDispatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.net.URI;
import java.util.Hashtable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class AmqpJavaClientDemo {

    private final static Logger logger = LoggerFactory.getLogger(AmqpJavaClientDemo.class);

    //业务处理异步线程池,线程池参数可以根据您的业务特点调整,或者您也可以用其他异步方式处理接收到的消息。
    private final static ExecutorService executorService = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),
            Runtime.getRuntime().availableProcessors() * 2,
            60,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(50000));


    public static void main(String[] args) throws Exception {
        //参数说明,请参见AMQP客户端接入说明文档。
        String accessKey = "LTAI4G2*****";
        String accessSecret = "Mp2f4qopmULI6*****";
        String consumerGroupId = "e0oRIYMSOYwQ*****";
        //iotInstanceId:购买的实例请填写实例ID,公共实例请填空字符串""。
        String iotInstanceId = "";
        long timeStamp = System.currentTimeMillis();
        //签名方法:支持hmacmd5、hmacsha1和hmacsha256。
        String signMethod = "hmacsha1";
        //控制台服务端订阅中消费组状态页客户端ID一栏将显示clientId参数。
        //建议使用机器UUID、MAC地址、IP等唯一标识等作为clientId。便于您区分识别不同的客户端。
        String clientId = "yangboClientId";

        //userName组装方法,请参见AMQP客户端接入说明文档。
        String userName = clientId + "|authMode=aksign"
                + ",signMethod=" + signMethod
                + ",timestamp=" + timeStamp
                + ",authId=" + accessKey
                + ",iotInstanceId=" + iotInstanceId
                + ",consumerGroupId=" + consumerGroupId
                + "|";
        //计算签名,password组装方法,请参见AMQP客户端接入说明文档。
        String signContent = "authId=" + accessKey + "&timestamp=" + timeStamp;
        String password = doSign(signContent,accessSecret, signMethod);
        //接入域名,请参见AMQP客户端接入说明文档。
            String connectionUrl = "failover:(amqps://1875496626634053.iot-amqp.cn-shanghai.aliyuncs.com:5671?amqp.idleTimeout=80000)"
                + "?failover.reconnectDelay=30";

        Hashtable<String, String> hashtable = new Hashtable<String, String>();
        hashtable.put("connectionfactory.SBCF",connectionUrl);
        hashtable.put("queue.QUEUE", "default");
        hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
        Context context = new InitialContext(hashtable);
        ConnectionFactory cf = (ConnectionFactory)context.lookup("SBCF");
        Destination queue = (Destination)context.lookup("QUEUE");
        // Create Connection
        Connection connection = cf.createConnection(userName, password);
        ((JmsConnection) connection).addConnectionListener(myJmsConnectionListener);

        System.out.println("connection success");
        // Create Session
        // Session.CLIENT_ACKNOWLEDGE: 收到消息后,需要手动调用message.acknowledge()。
        // Session.AUTO_ACKNOWLEDGE: SDK自动ACK(推荐)。
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        connection.start();
        // Create Receiver Link
        MessageConsumer consumer = session.createConsumer(queue);
        consumer.setMessageListener(messageListener);
    }

    private static MessageListener messageListener = new MessageListener() {
        @Override
        public void onMessage(Message message) {
            try {
                //1.收到消息之后一定要ACK。
                // 推荐做法:创建Session选择Session.AUTO_ACKNOWLEDGE,这里会自动ACK。
                // 其他做法:创建Session选择Session.CLIENT_ACKNOWLEDGE,这里一定要调message.acknowledge()来ACK。
                // message.acknowledge();
                //2.建议异步处理收到的消息,确保onMessage函数里没有耗时逻辑。
                // 如果业务处理耗时过程过长阻塞住线程,可能会影响SDK收到消息后的正常回调。
                executorService.submit(new Runnable() {
                    public void run() {
                        processMessage(message);
                    }
                });
            } catch (Exception e) {
                logger.error("submit task occurs exception ", e);
            }
        }
    };

    /**
     * 在这里处理您收到消息后的具体业务逻辑。
     */
    private static void processMessage(Message message) {
        try {
            byte[] body = message.getBody(byte[].class);
            String content = new String(body);
            String topic = message.getStringProperty("topic");
            String messageId = message.getStringProperty("messageId");


            System.out.println("receive message"
                    + ", topic = " + topic
                    + ", messageId = " + messageId
                    + ", content = " + content);
            logger.info("receive message"
                    + ", topic = " + topic
                    + ", messageId = " + messageId
                    + ", content = " + content);
        } catch (Exception e) {
            logger.error("processMessage occurs error ", e);
        }
    }

    private static JmsConnectionListener myJmsConnectionListener = new JmsConnectionListener() {
        /**
         * 连接成功建立。
         */
        @Override
        public void onConnectionEstablished(URI remoteURI) {
            logger.info("onConnectionEstablished, remoteUri:{}", remoteURI);
        }

        /**
         * 尝试过最大重试次数之后,最终连接失败。
         */
        @Override
        public void onConnectionFailure(Throwable error) {
            logger.error("onConnectionFailure, {}", error.getMessage());
        }

        /**
         * 连接中断。
         */
        @Override
        public void onConnectionInterrupted(URI remoteURI) {
            logger.info("onConnectionInterrupted, remoteUri:{}", remoteURI);
        }

        /**
         * 连接中断后又自动重连上。
         */
        @Override
        public void onConnectionRestored(URI remoteURI) {
            logger.info("onConnectionRestored, remoteUri:{}", remoteURI);
        }

        @Override
        public void onInboundMessage(JmsInboundMessageDispatch envelope) {}

        @Override
        public void onSessionClosed(Session session, Throwable cause) {}

        @Override
        public void onConsumerClosed(MessageConsumer consumer, Throwable cause) {}

        @Override
        public void onProducerClosed(MessageProducer producer, Throwable cause) {}
    };

    /**
     * 计算签名,password组装方法,请参见AMQP客户端接入说明文档。
     */
    private static String doSign(String toSignString, String secret, String signMethod) throws Exception {
        SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), signMethod);
        Mac mac = Mac.getInstance(signMethod);
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(toSignString.getBytes());
        return Base64.encodeBase64String(rawHmac);

//        return Arrays.toString(Base64.encodeBase64(rawHmac));
    }
}

实测效果:
云平台流转方式的返回结果:
image.png

AMQP订阅方式返回结果:
image.png

]]>
视图在SQL中的作用是什么,它是怎样工作的?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800

首发公众号:码农架构
视图就是虚拟表:

image.png

如何创建,更新和删除视图

创建视图:CREATE VIEW

CREATE VIEW player_above_avg_height AS
SELECT player_id, height
FROM player
WHERE height > (SELECT AVG(height) from player)

当视图创建之后,它就相当于一个虚拟表,可以直接使用:

SELECT * FROM player_above_avg_height

嵌套视图

CREATE VIEW player_above_above_avg_height AS
SELECT player_id, height
FROM player
WHERE height > (SELECT AVG(height) from player_above_avg_height)

修改视图:ALTER VIEW

ALTER VIEW view_name AS
SELECT column1, column2
FROM table
WHERE condition

删除视图:DROP VIEW

DROP VIEW view_name

需要说明的是,SQLite 不支持视图的修改,仅支持只读视图,也就是说你只能使用 CREATE VIEW 和 DROP VIEW,如果想要修改视图,就需要先 DROP 然后再 CREATE。

如何使用视图简化 SQL 操作

利用视图完成复杂的连接

CREATE VIEW player_height_grades AS
SELECT p.player_name, p.height, h.height_level
FROM player as p JOIN height_grades as h
ON height BETWEEN h.height_lowest AND h.height_highest

利用视图对数据进行格式化

CREATE VIEW player_team AS 
SELECT CONCAT(player_name, '(' , team.team_name , ')') AS player_team FROM player JOIN team WHERE player.team_id = team.team_id

使用视图与计算字段

CREATE VIEW game_player_score AS
SELECT game_id, player_id, (shoot_hits-shoot_3_hits)*2 AS shoot_2_points, shoot_3_hits*3 AS shoot_3_points, shoot_p_hits AS shoot_p_points, score  FROM player_score

总结

使用视图有很多好处,比如安全、简单清晰。
image.png

码农架构-公众号2.jpg

]]>
什么是存储过程,在实际项目中用得多么?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 存储过程是程序化的 SQL,可以直接操作底层数据表,相比于面向集合的操作方式,能够实现一些更复杂的数据处理。存储过程可以说是由 SQL 语句和流控制语句构成的语句集合,它和我们之前学到的函数一样,可以接收输入参数,也可以返回输出参数给调用者,返回计算结果。

存储过程像是函数.

什么是存储过程,如何创建一个存储过程

定义一个存储过程:

CREATE PROCEDURE 存储过程名称([参数列表])
BEGIN
    需要执行的语句
END    

删除已经创建的存储过程:

DROP PROCEDURE

更新存储过程:

ALTER PROCEDURE

实现一个简单的存储过程:

CREATE PROCEDURE `add_num`(IN n INT)
BEGIN
       DECLARE i INT;
       DECLARE sum INT;
       
       SET i = 1;
       SET sum = 0;
       WHILE i <= n DO
              SET sum = sum + i;
              SET i = i +1;
       END WHILE;
       SELECT sum; -- 在调用的时候会打印这个值
END

mysql> call study_stored_procedure(50);
+------+
| sum  |
+------+
| 1275 |
+------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

使用这个存储过程:

CALL add_num(50);

DELIMITER

如果你使用 Navicat 这个工具来管理 MySQL 执行存储过程,那么直接执行上面这段代码就可以了。如果用的是 MySQL,你还需要用 DELIMITER 来临时定义新的结束符。因为默认情况下 SQL 采用(;)作为结束符,这样当存储过程中的每一句 SQL 结束之后,采用(;)作为结束符,就相当于告诉 SQL 可以执行这一句了。但是存储过程是一个整体,我们不希望 SQL 逐条执行,而是采用存储过程整段执行的方式,因此我们就需要临时定义新的 DELIMITER,新的结束符可以用(//)或者($$)。如果你用的是 MySQL,那么上面这段代码,应该写成下面这样:

DELIMITER //
CREATE PROCEDURE `add_num`(IN n INT)
BEGIN
       DECLARE i INT;
       DECLARE sum INT;
       
       SET i = 1;
       SET sum = 0;
       WHILE i <= n DO
              SET sum = sum + i;
              SET i = i +1;
       END WHILE;
       SELECT sum;
END //
DELIMITER ;

存储过程的 3 种参数类型

image.png
IN 参数必须在调用存储过程时指定,而在存储过程中修改该参数的值不能被返回。而 OUT 参数和 INOUT 参数可以在存储过程中被改变,并可返回。

CREATE PROCEDURE `get_hero_scores`(
       OUT max_max_hp FLOAT,
       OUT min_max_mp FLOAT,
       OUT avg_max_attack FLOAT,  
       s VARCHAR(255)
       )
BEGIN
       SELECT MAX(hp_max), MIN(mp_max), AVG(attack_max) FROM heros WHERE role_main = s INTO max_max_hp, min_max_mp, avg_max_attack;
END

调用:

  • 调用的时候需要在变量前面加 @ , 否则报错
CALL get_hero_scores(@max_max_hp, @min_max_mp, @avg_max_attack, '战士');
SELECT @max_max_hp, @min_max_mp, @avg_max_attack;

流控制语句

  1. BEGIN…END:BEGIN…END 中间包含了多个语句,每个语句都以(;)号为结束符。
  2. DECLARE:DECLARE 用来声明变量,使用的位置在于 BEGIN…END 语句中间,而且需要在其他语句使用之前进行变量的声明。
  3. SET:赋值语句,用于对变量进行赋值。
  4. SELECT…INTO:把从数据表中查询的结果存放到变量中,也就是为变量赋值。
  5. IF…THEN…ENDIF:条件判断语句,我们还可以在 IF…THEN…ENDIF 中使用 ELSE 和 ELSEIF 来进行条件判断。
  6. CASE:CASE 语句用于多条件的分支判断,使用的语法是下面这样的。
  7. LOOP、LEAVE 和 ITERATE:LOOP 是循环语句,使用 LEAVE 可以跳出循环,使用 ITERATE 则可以进入下一次循环。如果你有面向过程的编程语言的使用经验,你可以把 LEAVE 理解为 BREAK,把 ITERATE 理解为 CONTINUE。
  8. REPEAT…UNTIL…END REPEAT:这是一个循环语句,首先会执行一次循环,然后在 UNTIL 中进行表达式的判断,如果满足条件就退出,即 END REPEAT;如果条件不满足,则会就继续执行循环,直到满足退出条件为止。
  9. WHILE…DO…END WHILE:这也是循环语句,和 REPEAT 循环不同的是,这个语句需要先进行条件判断,如果满足条件就进行循环,如果不满足条件就退出循环。
CASE 
  WHEN expression1 THEN ...
  WHEN expression2 THEN ...
  ...
    ELSE 
    --ELSE语句可以加,也可以不加。加的话代表的所有条件都不满足时采用的方式。
END

关于存储过程使用的争议

存储过程有很多好处:
• 存储过程可以一次编译多次使用
• 存储过程的安全性强
• 可以减少网络传输量
缺点也是很明显的:
• 可移植性差
• 调试困难
• 版本管理也很困难
• 不适合高并发的场景

码农架构-公众号2.jpg

]]>
AnalyticDB向量检索+AI 实战: 声纹识别-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 一、背景

近年来,随着人工智能对传统行业的赋能改造,越来越多的基于人工智能的业务解决方案被提出来,声纹识别在保险行业中的身份认证便是一个很好的例子. 声纹识别是根据说话人发音的生理和行为特征,自动识别说话人身份的一种生物识别技术,对应在电话销售场景下,它主要解决以下安全问题:一方面,有不法分子窃取电话销售人员账号信息,非法获取客户个人信息资料并进行贩卖、泄露,严重侵犯了公民个人的信息隐私权,另一方面,部分行业从业人员利用一些规则漏洞,通过套保、骗保等非法手段实施金融诈骗. 针对这些安全问题,可以通过实时声纹认证加以解决,以电话销售人员为监管核心,利用每个人独一无二的声纹进行严密的个人身份认证,保证电话销售人员对接客户时是本人注册登录,规范电销人员行为,从源头上有效规避信息泄露、漏洞利用等风险。

二、声纹识别原理

640.png

上图是端对端的深度学习训练和推理过程。对比传统声纹识别模型,我们的模型在实际使用中优势明显,在用户远程身份验证场景,通过注册用户说一段话,即可轻松快速的确认注册用户身份,识别准确率达到95%以上,秒级响应,实时声纹核身。下面简要介绍我们模型的特点。

2.0 度量学习

实验发现,在声纹识别中采用softmax进行网络训练 ,用余弦相似度的测试性能往往不如传统声纹识别模型,尤其是在鲁棒性上。分析发现[6]基于softmax的分类训练,为了得到更小的loss,优化器会增大一些easy samples的L2 length,减小hard examples 的L2 length,导致这些样本并没有充分学习,特征呈现放射状,以MNIST识别任务为例,基于softmax学到的特征分布如图3(a)所示. 同类别特征分布并不聚拢,在L2 长度上拉长,呈放射状,且每个类别的间距并不大,在verification的任务中,会导致相邻的两个类别得分很高。

为了达到类内聚拢,类间分散的效果,我们研究了在图像领域中应用较为成功的几种softmax变种,包括AM-softmax[4],arcsoftmax[5]等,从图3(b)可以看到,基于margin的softmax,相比纯softmax,类间的分散程度更大,且类内特征更聚拢,对声纹1:1比对和1:N搜索的任务友好。
2.png

2.1 噪音鲁棒性

在特征提取时,对于简单加性噪音,我们提出了基于功率谱减法,实现噪音抑制;对于其他复杂噪音,我们提出了基于降噪自动编码器的噪音补偿模型,将带噪语音特征映射到干净语音特征,实现噪音消除。

在模型训练时,我们采用数据增强的训练机制,将噪音数据通过随机高斯的形式加入到声纹模型的训练中,使得训练后的模型对噪音数据具有更好的鲁棒性。

2.2 短音频鲁棒性

为了提高短音频鲁棒性,我们提出了基于短时帧级别的模型训练机制,使模型能够在极短的语音时长(约0.5秒)下即可完成声纹识别. 在此基础上,我们在模型训练中引入了更多高阶的音频统计信息和正则化方法,进一步提升了模型在短语音条件下(2~3秒)的识别精度。

三、如何使用AnalyticDB搭建声纹对比系统

3.0 创建插件

使用一下SQL来分别创建AnalyticDB的非结构化分析插件OpenAnalytic和向量检索插件fastann。
20201019144723.jpg

3.1 建表

我们可以建立一个表来保存所有说话人的声音和声音的特征,后续我们可以从这个表中搜索说话人。
3.jpg

3.2 创建索引

我们可以为特征向量列创建向量检索索引。
3.2.jpg

3.3 创建声纹识别算法pipeline

通过以下sql,我们可以在数据库中创建声纹特征提取的算法模型。
3.3.jpg

3.4 获取说话人声纹特征

通过以下sql可以使用3.3创建的pipeline。这个UDF的输入是pipeline名称和目标文本。输出是一个说话人声音的特征向量。
`# 通过声音文件识别
SELECT open_analytic.pipeline_run_dist_random('speaker_feature_extractor',

                    <声音文件>);`

3.5 说话人声纹特征导入AnalyticDB

获取声音特征后, 我们可以使用一下sql来讲数据插入3.1创建的表中。
5.jpg

3.6 在数据库中搜索最相似的的人

通过以下sql,我们可以在声音特征库中搜索最相似的说话人。然后我们可以根据特征间距离是否满足预设的阈值来判断是否是同一个人。
6.jpg

3.7 比较两个声音是否为同一个人

我们还可以提取出两个人的声音特征然后直接计算二者的距离来判断这两个声音是否来自同一个说话人。SQL如下
7.jpg

四、AnalyticDB介绍

分析型数据库(AnalyticDB)是阿里云上的一种高并发低延时的PB级实时数据仓库,可以毫秒级针对万亿级数据进行即时的多维分析透视和业务探索。AnalyticDB for MySQL 全面兼容MySQL协议以及SQL:2003 语法标准, AnalyticDB forPostgreSQL 支持标准 SQL:2003,高度兼容 Oracle 语法生态。

向量检索和非结构化数据分析是AnalyticDB的进阶功能。目前两款产品都包含向量检索功能, 可以支持人脸, 人体, 车辆等的相似查询和推荐系统。AnalyticDB在真实应用场景中可以支持10亿级别的向量数据的查询, 毫秒级别的响应时间。AnalyticDB已经在多个城市的重大项目中大规模部署。

在一般的包含向量检索的的应用系统中, 通常开发者会使用向量检索引擎(例如Faiss)来存储向量数据, 然后使用关系型数据库存储结构化数据。在查询时也需要交替查询两个系统, 这种方案会有额外的开发工作并且性能也不是最优。AnalyticDB支持结构化数据和非结构化数据(向量)的检索,仅仅使用SQL接口就可以快速的搭建起以图搜图或者图片+结构化数据混合检索等功能。AnalyticDB的优化器在混合检索场景中会根据数据的分布和查询的条件选择最优的执行计划,在保证召回的同时,得到最优的性能。AnalyticDB向量版采用了多项创新性技术, 这些技术在我们的论文 AnalyticDB-V: A Hybrid Analytical Engine Towards Query Fusion for Structured and Unstructured Data 中有详细介绍介绍。目前论文已经被数据库三大顶会之一的VLDB接受, 具有技术领先性。

结构化信息+非结构化信息(图片)混合检索在实际应用中被广泛使用的。例如人脸门禁系统被部署在多个小区时, 我们使用一张表存储了所有小区的人脸特征, 在人脸检索时我们只需要检索当前小区的人脸特征。在这种情况下, 使用AnalyticDB我们只需要在SQL中增加where 小区名 ='xxx' 就可以轻易实现。AnalyticDB同时提供了先进的图像文本分析算法, 能够提取非结构化数据的特征和标签, 用户仅仅需要使用SQL就可以完成图像文本内容的分析。

五、参考文献

[1] Heigold G, Moreno I, Bengio S, et al. End-to-end text-dependent speaker verification[C]//2016 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2016: 5115-5119.
[2]Li C, Ma X, Jiang B, et al. Deep speaker: an end-to-end neural speaker embedding system[J]. arXiv preprint arXiv:1705.02304, 2017.
[3] Snyder D, Garcia-Romero D, Sell G, et al. X-vectors: Robust den embeddings for speaker recognition[C]//2018 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2018: 5329-5333.
[4] Wang F, Cheng J, Liu W, et al. Additive margin softmax for face verification[J]. IEEE Signal Processing Letters, 2018, 25(7): 926-930.
[5] Dang J, Guo J, Xue N, et al. Arc face: Additive angular margin loss for deep face recognition[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2019: 4690-4699.
[6] Ranjan R, Castillo C D, Chellappa R. L2-constrained softmax loss for discriminative face verification[J]. arXiv preprint arXiv:1703.09507, 2017.

六、结语

本文介绍了如何使用AnalyticDB来搭建声纹比对系统。AnalyticDB还支持其他多种多样人工智能算法如目标检测, 商品识别, 基因识别等等。想了解更多请用钉钉扫码加入AnalyticDB向量版交流群。

]]>
CNCC 数据库校企合作论坛丨如何构建数据库产业人才培养的生态圈?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 1978年,中国人民大学经济信息管理系首任系主任萨师煊第一次将“数据库”这三个字写在人大教室的黑板上,从那一刻起“数据库”技术真正开始在中国的土壤上扎根发芽。

到如今2020年,中国数据库的发展已经历时四十多年,国产数据库在这片土壤上开始逐渐繁茂,从最初的盲目模仿到如今越来越多的数据库企业走向自主研发,国产数据库正在以一种前所未有的速度和力量成长。

计算技术领域的年度盛会 CNCC 将于 10 月 22-24 日在北京盛大召开,届时10月23日下午,“数据库领域校企合作探索”论坛将在北京新世纪日航饭店(主会场)举办,本次论坛邀请了四位行业资深技术专家及学界泰斗带来精彩演讲,从国产数据库在产业实践的经验体会分享,到全新的产教研融合创新模式的探讨,再到数据库行业人才生态战略的深入探索。

本论坛将为大家邀请业界及学界共同探讨如何通过产研合作,充分发挥企业业务场景和高校研究能力的优势,突破核心技术、人才培养等难题,实现中国数据库产业自主创新。

论坛议程

16:00-16:40 杨传辉 蚂蚁集团
蚂蚁集团数据库产业实践

16:40-17:10 钱卫宁 华东师范大学
应用驱动与产教研联动的数据库研发和人才培养实践

17:10-17:40 彭智勇 武汉大学
国产数据库研制人才培养实践

17:40-18:00 梁刘红 蚂蚁集团
构建 OceanBase 全连接的学术合作与人才培养的生态圈

议题简介

嘉宾一:杨传辉(花名:日照)

FD579B4E-1742-4548-9B5D-051DBF678B87.png

嘉宾介绍:蚂蚁集团资深总监、OceanBase 研发总经理,全面负责 OceanBase 研发工作。作为 OceanBase 创始成员和首席架构师,主导了 OceanBase 技术架构设计,实现分布式数据库在核心金融场景零的突破,完成蚂蚁集团核心数据库100%上 OceanBase ,主导 OceanBase TPC-C 测试并打破世界纪录。曾在百度负责云存储与云计算系统研究工作,著有专著《大规模分布式存储系统:原理与实践》。

演讲议题:蚂蚁集团数据库产业实践

议题介绍:蚂蚁集团为何选择自研数据库,自研数据库从0到1的发展历程、技术方案以及后续规划,并分享国产数据库从学术研究到产业实践的经验体会。

嘉宾二:钱卫宁

232.jpg

嘉宾介绍:华东师范大学教授、博士生导师,数据科学与工程学院院长。在复旦大学获得计算机科学与技术学士、硕士与博士学位。上海市优秀学术带头人,入选教育部新世纪人才计划和上海市青年科技启明星计划。作为项目负责人主持包括国家“核高基”重大专项课题、国家重点研发计划课题、国家自然科学基金项目重点项目和面上项目在内的多项科研项目。

目前担任中国计算机学会数据库专委会常务委员,教育部人工智能科技创新专家工作组成员。曾获国家科技进步二等奖奖1次(第二完成人)、上海市科技进步一等奖1次(第一完成人),以及教育部科技进步一等奖、二等奖、教育部自然科学二等奖各1次。研究兴趣包括可扩展事务处理,大数据管理系统基准评测,海量数据分析处理及其应用,以及计算教育学。

演讲议题:应用驱动与产教研联动的数据库研发和人才培养实践

议题介绍:数据库系统是支撑关键核心业务(mission-critical applications)的基础软件。在诸多领域数字化转型的背景下,数据库系统面临着海量数据和互联网级负载的双重压力。自主研发数据库系统,助力行业转型,实现替代工程,无论是对于这些行业领域,还是对于我国的信息技术产业,都具有极为重要的意义。

数据库系统研发的基础知识面广、研究-工程-应用链条长,涉及大规模分布式系统和新硬件利用与优化等前沿技术,需要创新性研究思路,需要核心技术攻坚,还需要大规模工程实现验证,是典型的工程研究问题。报告将介绍我们在应用驱动和校企联动的分布式数据库系统研究和人才培养方面的探索和初步成果,并讨论新的产教研融合创新模式。

嘉宾三:彭智勇

233.jpg


嘉宾介绍:武汉大学教授、博士生导师、大数据研究院副院长,国务院软件工程学科评议组成员,中国计算机学会会士、数据库专业委员会副主任、大数据专家委员会成员。1985年获武汉大学理学学士,1988年获国防科技大学工学硕士,1995年获日本京都大学工学博士。1995-1997年在日本京都高度技术研究所工作,研究员。1997-2000年在美国惠普公司的研究所工作,研究员。提出了一个新的数据库模型:对象代理模型,发表在数据库国际顶级会议 IEEE ICDE 和权威期刊 IEEE TKDE上,得到了学术界认可;分析了开源数据库 PostgreSQL 源代码,出版了《PostgreSQL 数据库内核分析》专著,受到了产业界欢迎;研制了对象代理数据库管理系统 TOTEM,形成了自主知识产权,获教育部科技进步二等奖;目前主要从事对象代理数据库、大数据管理系统、制造业大数据、科技大数据、教育大数据、可信云数据和地理数据水印等方面的研究。

演讲议题:国产数据库研制人才培养实践

议题介绍:研制国产数据库需要大量掌握数据库内核实现技术人才。目前国内各大高校数据库教学过于偏重原理性知识传授以及特定数据库系统的应用技能培养,而忽视了对于数据库管理系统内核实现机制的教学。我们构建了“基础知识-应用技术-科研创新”的分层次数据库教学体系,引进美国斯坦福“数据库系统实现”课程,自编“数据库内核分析”课程教材,引导学生分析数据库管理系统 PostgreSQL 源代码,指导学生参与国产数据库核心技术开发,为华为、阿里、腾讯、百度等企业培养了很多国产数据库研制人才。

嘉宾四:梁刘红

234.jpg

嘉宾介绍:现任蚂蚁集团 OceanBase 合作伙伴和生态合作部总经理。复旦大学计算机系硕士研究生毕业,加入 OceanBase 前,先后供职于微软、IBM,本土云计算创业公司青云 QingCloud,拥有15+年云计算领域及企业软件行业的丰富经验,擅长战略规划,生态合作、商业运营等。

演讲议题:构建 OceanBase 全连接的学术合作与人才培养的生态圈

议题介绍:蚂蚁集团 OceanBase 期望构建全联接的学术和人才生态,助力学术界产研实践和人才培养,与各大高校共同培养兼具理论与实践能力的创新型复合人才。本次报告将发布全连接的学术和人才生态战略。

其中,OceanBase 的研发总经理杨传辉及生态合作部总经理梁刘红也将分别从数据库技术产业发展、数据库产业人才培养等维度为大家带来 OceanBase 的经验分享。

据悉,今年9月,OceanBase 已经与华东师范大学签署战略合作,共建“华东师范大学-北京奥星贝斯分布式数据库联合实验室”,未来 OceanBase 还将连接更多的高校联合培养优秀的科技人才。

OceanBase 坚定地相信分布式数据库就是未来的主流。OceanBase 愿意也期待积极地通过自身实践来加速新的数据库生态的建立,以帮助更多的开发者 / DBA 更好地成长,为社会输出更多的分布式数据库人才。

]]>
分库分表背后那些事儿-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800
  • 概述

    目前行业内OLTP类的数据库单库单表支撑不了几十亿数据的在线处理,包括一些NoSQL数据库,因此对于数据量较大的场景需要进行数据库拆分,如mysql单表建议数据量再500w以内,一些强大的NoSQL单表可以支撑几亿的数据量,但是对于几十亿的数据量一样无法直接支撑,因此我们要做分库分表
    
  • 分库分表类型
    •垂直拆分:充分利用数据库的缓存,提升访问性能。
  •     垂直切分是将一个表的不同属性切分到不同的表中,可以将访问频率高的、长度短的、或者经常一起访问的放在一个表里,
    

    其它的放在另一个表里,从而提升数据库本身缓存的命中率来提升性能,但是单表大数据量依然存在性能瓶颈问题。
    •水平拆分:借用分布式的优势,使用多个数据库的能力来提升存储容量和性能。

    将数据均匀的分布在多个数据库多个表中

    1. 拆分键的选择

    拆分键是水平分库分表的关键,怎么选择拆分键是能否做好分库分表的关键

    1)找到业务主体,确保核心的数据库操作都是围绕这个主体数据进行,然后使用该主体对应的字段作为拆分键

    1)选择拆分键的核心是要保证数据量均匀和请求量均匀

    2)要考虑热点查询语句,尽量保证其不会进行跨库查询

    3)要兼顾关联表,尽可能保证关联表的分库分表规则和主表一致

    1. 非拆分键的加速查询

    1)多维度表法:如订单表,本身按照订单进行拆分,按照实际场景又分别按照买家和卖家生成订单表

    2)缓存映射法:缓存中记录查询条件->拆分键的映射关系,如fpdm+fphm -> fpid

    3)基因融入法: 将查询条件融入到拆分键生成中,如假设分8个库,采用id%8路由,潜台词是,id的后3个bit决定这条数据落在哪个库上,这3个bit就是所谓的基因。

    name -> 基因生成函数 -> name_gene -> 3bit

    id(64 bit) = 生成全局唯一id(61 bit)+ 3bit

    4)数据冗余法:使用外置索引(搜索引擎)或者大数据处理(如hive、hbase)来冗余数据进行解决

    1. 分库分表的查询过程

    分库分表的查询一般使用DRDS、MyCat等中间件来实现,但是用哪款中间件不重要,重要的是我们要了解其核心原理,原理是基础,其他都是表现形式,有了内功之后做什么都无往不利,如令狐冲独孤九剑+吸星大法+易筋经

    1)分片规则:自定义分片策略,主要是根据拆分键值计算出将该条数据放在哪个库哪个表里

    2)JDBC规范重写:针对DataSource、Connection、Statement、PreparedStatement和ResultSet接口封装,对外提供的是逻辑实例,在内部封装多个真实物理实例实现类集合

    3)sql解析:解决sql语法,可以直接使用druid的SQLParser

    4)sql改写:修改逻辑表名->真实表名;替换不支持的功能,如:avg->sum和count;有可能一条sql语句变成多条,如avg查询会变成 2 * 分表数 的sql语句

    5)sql路由:单表路由(不一定落在单表上,如in、between查询)、binding表路由(路由规则一致,如fpzxx和fpmx)、笛卡尔积路由(两个关联表路由不一致,性能很低,占用连接数很高,一般不使用)

    6)sql执行:多线程并发执行sql

    7)结果归并:遍历类、排序类(归并排序)、聚合类(比较型、累加型、平均型)、分组类

    ]]>
    基于DTS+Tablestore的海量订单系统架构设计-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 订单系统概述

    订单场景是人们高频接触的一类场景,无论是线下商场购物、吃喝玩乐消费,还是线上淘宝、会员充值、外卖预定。只要涉及人就会有交易,只要有交易就会产生订单。毫不夸张的讲,所有的应用都会涉及到支付与订单的管理,因此,完善的订单管理架构是每一个架构师或开发人员都要直面的挑战。

    对于订单系统,保证事务与强一致是前提,架构师们通常都会选择MySQL等TP型数据库。但是遇到大规模数据场景下也不得不面临一定的问题。首先,需要通过分库分表等方式提供一个分布式能力提升数据库数据存储、吞吐量,其次数据量大对于查询与聚合等需求难以支持,严重会影响表服务能力与性能。但是在大规模数据下,订单的多维检索、订单分析、以及周期性报表等需求,也是不能够舍弃的。因此需要一个历史订单库,将订单数据派生到其他存储引擎,从而拓展数据的查询、分析、聚合等能力。

    这时,用户会考虑数据双写、数据同步等方式将数据派生一份到搜索引擎或其他NoSQL分布式数据存储,来扩展MySQL性能成本非常高的使用场景。多写的方案一般很少,这对写入一致性项目运维成本与写入性能会有很大的挑战。当前,更被大众所接受的是基于TP数据库的binlog订阅做数据同步,虽然数据同步上会有延时(通常秒级别甚至更低),但是在运维成本、能力扩展、数据一致性上表现优异。

    DTS+Tablestore方案

    本文主要介绍一套基于DTS与Tablestore实现一套完善的订单系统架构。实时订单数据主要针对用户侧的实时生产与修改,实例订单数据则是基于数据同步服务DTS,全、增量订阅TP库中的订单数据,从而保证Tablestore中数据与TP库数据的最终一致性。异步同步的方式不可避免的存在延时,但历史订单库在实时性上要求会适当放宽,但其派生出来的数据在服务能力与功能扩展上得到了极大的提升,尤其是Tablestore这种分布式服务能力强、下游计算生态丰富的NoSQL存储服务。

    系统架构设计

    系统架构如下图,架构基于订单数据的使用功能与实时性分两部分:实时在线订单数据与历史订单数据。

    • • 在线订单数据:存储在TP型数据库,如MySQL、PolarDB等,用于保证订单的强事务能力;
    • • 历史订单数据:存储在Tablestore,分布式存储,支持多维检索与聚合能力,拥有完善的大数据生态;
    • • 同步链路:DTS(数据传输服务),支持全量数据迁移与实时数据同步,实时同步延时秒级别;
      image.png

    Tablestore的能力与生态

    Tablestore的服务性能、分析查询能力以及下游生态,值得着重强调,丰富的能力扩展正是数据派生的核心价值。这里主要展示多元索引、大数据生态两个亮点,更多Tablestore场景与功能,请参考《表格存储Tablestore权威指南》

    • • 多元索引:
      基于倒排索引和列式存储,可以解决大数据的复杂查询难题,包括非主键列查询、全文检索、前缀查询、模糊查询、多字段自由组合查询、嵌套查询、地理位置查询等功能。适用于元数据管理、历史订单维护、地理围栏等场景。

    深入了解多元索引:多元索引官网文档、《TableStore发布多元索引功能,打造统一的在线数据平台》

    • • 大数据架构
      Tablestore 作为一款高性能低成本的存储引擎,海量的数据存储伴随的就是大数据生态对接,并已经形成了一套稳定、高性能的大数据架构,产品在核心功能的升级迭代的过程中,也不断的加强计算引擎对接,目前已经对接了阿里云几个核心计算引擎,包含:MaxCompute、EMR Spark、Blink、DLA 、FC,更总结出一套流批一体处理框架(Lambda plus)。

    深入了解数据中台、大数据体系:《数据中台之结构化大数据存储设计》、《基于 Tablestore 的大数据分析 Lambda 架构 - 云原生、弹性、流批一体》
    架构搭建实战

    准备工作

    1、服务准备

    • • 开通RDS服务:并购买MySQL实例,此处不做详细介绍,可参考《文档》;
    • • 开通Tablestore服务:创建实例(免费),不做详细介绍,可参考《文档》;
    • • 开通DTS服务:并购买MySQL同步Tablestore实例
      目前仅上线MySQL、PolarDB到Tablestore,其中PolarDb需要主动开启binlog开关才能支持增量同步。Tablestore暂时开发上海、北京、深圳,本例使用上海实例。

    image.png

    2、资源准备

    创建子账号AccessKey

    并对子账号实例级别授权,权限为操作Tablestore资源权限,让DTS有权限操作用户该实例资源(注意region跟实例名)

    • • 创建子账号
      image.png
    • • Tablestore实例授权
    {
        "Version": "1",
        "Statement": [
            {
                "Action": "ots:*",
                "Resource": "acs:ots:[myInstanceRegion]:*:instance/[myInstanceName]/*",
                "Effect": "Allow"
            },
            {
                "Action": [
                    "ots:ListInstance",
                    "ots:GetInstance"
                ],
                "Resource": "*",
                "Effect": "Allow"
            }
        ]
    }

    建表语句

    /******************************************/
    /*   DatabaseName = dts_demo   */
    /*   TableName = order_contract   */
    /******************************************/
    CREATE TABLE `order_contract` (
      `oId` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '订单id',
      `createTime` datetime NOT NULL COMMENT '下单时间',
      `payTime` datetime DEFAULT NULL COMMENT '支付时间',
      `hasPaid` tinyint(1) NOT NULL COMMENT '是否支付',
      `cId` varchar(20) NOT NULL COMMENT '消费者id',
      `cName` varchar(20) NOT NULL COMMENT '消费者姓名',
      `pBrand` tinytext NOT NULL COMMENT '产品品牌',
      `pCount` mediumint(10) NOT NULL COMMENT '产品数量',
      `pId` varchar(20) NOT NULL COMMENT '产品id',
      `pName` varchar(20) NOT NULL COMMENT '产品名',
      `pPrice` decimal(10,2) NOT NULL COMMENT '产品价格',
      `sId` varchar(20) NOT NULL COMMENT '售货员id',
      `sName` varchar(20) NOT NULL COMMENT '售货员姓名',
      `totalPrice` decimal(10,2) NOT NULL COMMENT '总价格',
      PRIMARY KEY (`oId`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='在线订单表';

    用户下单

    直接通过sql写入,模拟用户下单与应用订单数据写入

    INSERT INTO order_contract (oId, payTime, createTime, hasPaid, cId, cName, pBrand, pCount, pId, pName, pPrice, sId, sName, totalPrice)
    VALUES 
    ("00000001", null, "2020-08-05 11:11:11", false, "c00001", "消费者1", "iphone", 1, "p00001", "iphone 7 plus",  9999.80, "s00001", "售货员1", 9999.80),
    ("00000002", null, "2020-08-05 12:11:11", false, "c00001", "消费者1", "iphone", 1, "p00002", "iphone 8 plus",  10999.80, "s00001", "售货员1", 10999.80),
    ("00000003", null, "2020-08-05 13:11:11", false, "c00002", "消费者2", "小米", 2, "p00010", "小米 7 plus",  999.81, "s00001", "售货员1", 1999.62);

    同步配置

    • • 配置DTS实例
      image.png
    • • 配置目标、源配置
      image.png
    • • 配置同步表、字段与类型转换
      image.png

    字段类型映射不建议全部选用默认,根据需求做定制,其中Boolean在MySQL中表现为tinyint(1),需要主动设置成Boolean,时间默认使用String如需转换为时间戳,目标类型主动配置成Integer类型。
    image.png

    启动任务

    启动并进入预检

    image.png
    image.png

    预检完成会自动进入结构迁移(初始化建表)、全量迁移、增量同步阶段。然后用户可以基于DTS控制台查看结构迁移与同步状态。

    目标检查

    结构迁移

    结构迁移完成,Tablestore实例下表初始化成功,主键符合预期
    image.png

    存量数据

    进入存量阶段,开始同步MySQL库已有数据,同步成功后目标库数据可见。
    image.png

    增量校验

    使用样例中的SQL模拟下单、更新订单、删除订单等操作,观察Tablestore实例中表的数据变化

    下单

    INSERT INTO order_contract (oId, payTime, createTime, hasPaid, cId, cName, pBrand, pCount, pId, pName, pPrice, sId, sName, totalPrice)
    VALUES ("00000004", null, "2020-08-05 11:11:11", false, "c00003", "消费者3", "iphone", 1, "p00001", "iphone 7 plus",  9999.80, "s00001", "售货员1", 9999.80);

    支付修改订单状态

    update order_contract set payTime = "2020-08-05 21:11:11", hasPaid = true WHERE oId = "00000004";

    删除数据

    DELETE FROM order_contract WHERE oId = "00000004";

    扩展能力

    多元索引聚合查询

    多元索引对于历史订单的管理,我们曾给出过最佳实践,用户可以参考《基于Tablestore打造亿量级订单管理解决方案》与控制台样例了解功能使用的详细方案。您只需在Tablestore相应的表中直接创建多元索引,便可完成历史订单数据的多条件组合查询、模糊查询、地理位置查询、存在性查询、简单的统计聚合与分析等。通过对产品名做分词,支持模糊查询能力,实例中查询"iphone"关键字,会从全量订单数据中检索出相应的2行数据。
    image.png

    多元索引的订单实战样例,可以参考文章《基于Tablestore打造亿量级订单管理解决方案》,并提供了直观感受的demo样例,如下图。用户可以参考借鉴。

    image.png

    除了多维组合查询,多元索引还是统计、聚合的能力,该能力没有在控制台上暴露,需要通过sdk使用,这里暂不距离,具体使用,可以参考《文档:多元索引的统计聚合》。
    使用统计聚合功能可以实现求最小值、求最大值、求和、求平均值、统计行数、去重统计行数、按字段值分组、按范围分组、按地理位置分组、按过滤条件分组、嵌套查询等;同时多个统计聚合功能可以组合使用,满足复杂的查询需求。

    流批一体的电商大屏

    订单对于电商场景的最根本数据源,如何让海量的订单数据易分析、易可视化是场景的重要需求点,电商大屏或周期交易报表是最直接的数据价值挖掘的方式。这里以大屏为例,大屏可以包含全量订单、实时订单的聚合,全量订单的聚合提供的是全景的综合数据视图,而实时订单的聚合展示的是实时的运营指标数据。
    谈完流批计算对数据价值挖掘的作用,就要见一下实现。Tablestore已经拥有较多的实战案例与架构文章,这里不做重复输出,用户可以直接前往文章《Tablestore结合Spark的流批一体SQL实战》,了解构建方案与效果。大屏效果如下图。
    image.png

    免费专家服务

    欢迎加入Tablestore社区了解产品或参与讨论,更多文章欢迎前往《表格存储Tablestore权威指南》。
    表格存储 (Tablestore) 提供专业的免费的技术咨询服务,期待您的加入。群号 : 23307953
    image.png

    ]]>
    数据中台交付专家告诉你,数据架构的分层怎样更加合理?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800
    -更多关于数智化转型、数据中台内容请加入阿里云数据中台交流群—数智俱乐部 和关注官方微信公总号(文末扫描二维码或点此加入

    -阿里云数据中台官网 https://dp.alibaba.com/index

    作者:柯根

    从整体上看,数据中台体系架构可分为:数据采集层、数据计算层、数据服务层三大层次。通过这三大层次对上层数据应用提供数据支撑。

    数据采集层

    对于企业来说,每时每刻都在产生海量的数据,数据采集作为数据体系第一环尤为重要。

    因此在数据采集层需要建立了一套标准的数据采集体系方案,并致力全面、高性能、规范地完成海量数据的采集,将其传输到大数据平台。

    互联网日志采集体系包括两大体系:Web端日志采集技术方案;APP端日志采集技术方案。

    在采集技术之上,企业可以用面向各个场景的埋点规范,来满足日志数据打通等多种业务场景。同时,还可以建立了一套高性能、高可靠性的数据传输体系完成数据从生产业务端到大数据系统的传输;在传输方面,采集技术可既包括数据库的增量数据传输,也包括日志数据的传输;既需要能支持实时流式计算、也能实时各种时间窗口的批量计算。另一方面,也通过数据同步工具直连异构数据库(备库)来抽取各种时间窗口的数据。

    下图展示数据采集层在数据分层中的位置:
    1.png

    数据计算层

    从采集系统中收集了大量的原始数据后,数据只有被整合、计算才能被用于洞察商业规律、挖掘潜在信息,实现大数据价值,达到赋能商业、创造商业的目的。从采集系统中收集到的大量原始数据,将进入数据计算层中被进一步整合与计算。

    面对海量的数据和复杂的计算,数据计算层包括两大体系:数据存储及计算云平台和数据整合及管理体系。

    - 数据存储及计算云平台
    例如,MaxCompute是阿里巴巴自主研发的离线大数据平台,其丰富的功能和强大的存储及计算能力使得企业的大数据有了强大的存储和计算引擎;StreamCompute是阿里巴巴自主研发的流式大数据平台,在内部较好地支持了企业流式计算需求。

    - 数据整合及管理体系
    “OneModel”是数据整合及管理的方法体系和工具,大数据工程师在这一体系下,构建统一、规范、可共享的全域数据体系,避免数据的冗余和重复建设,规避数据烟囱和不一致,充分发挥在大数据海量、多样性方面的独特优势。借助这一统一化数据整合及管理的方法体系,构建企业数据公共层,并可以帮助相似大数据项目快速落地实现。

    数据中台数据加工链路也是遵循业界的分层理念:包括操作数据层(ODS,Operational Data Store)、明细数据层(DWD,Data Warehouse Detail)、汇总数据层(DWS, Data Warehouse Summary)和应用数据层(ADS,Application Data Store)。通过数据中台不同层次之间的加工过程实现从数据资产向信息资产的转化,并且对整个过程进行有效的元数据管理及数据质量处理。

    下图展示数据公共层(ODS+DWD+DWS)与数据应用层(ADS)在数据分层中的位置:
    2.png
    图:数据公共层与数据应用层关系

    (1)统一数据基础层
    我们通过各种方式采集到的丰富数据,在清洗、结构化后进入统一的ODS数据基础层。

    其主要功能包括:
    -同步:结构化数据增量或全量同步到数据中台
    -结构化:非结构化(日志)结构化处理并存储到数据中台
    累积历史、清洗:根据数据业务需求及稽核和审计要求保存历史数据、数据清洗

    在权责方面,所有数据应该在源头统一,统一所有的数据基础层,并由一个团队负责和管控,其他团队无权复制数据基础层的数据。

    (2)数据中间层
    我们进行数据建模研发,并处理不因业务特别是组织架构变动而轻易转移的数据中间层。包括DWD明细数据中间层和DWS汇总数据中间层。

    其主要功能包括:
    -组合相关和相似数据: 采用明细宽表,复用关联计算,减少数据扫描。
    -公共指标统一加工:基于OneData体系构建命名规范、口径一致和算法统一的统计指标,为上层数据产-品、应用和服务提供公共指标;建立逻辑汇总宽表;
    -建立一致性维度:建立一致数据分析维度表,降低数据计算口径、算法不统一的风险。

    在权责方面,面向业务提供服务之前,由统一的团队负责从业务中抽象出源于业务而又不同于业务的数据域,再主导统一建设数据中间层,包括侧重明细数据预JOIN等处理的明细中间层、侧重面向应用可复用维度和指标的汇总数据中间层。特别是要由唯一团队负责将核心业务数据统一加入数据中间层。允许部分业务数据有独立的数据团队按照统一的OneModel体系方法论建设数据体系,ODS数据基础层和DWD+DWS数据中间层因其统一性和可复用性,被称为数据公共层。

    (3)数据应用层
    在面向应用提供服务时,业务团队或深入业务线的数据团队有极大的自由度,只要依赖数据公共层,即可自由的建设ADS数据应用层。

    其主要功能包括:
    -个性化指标加工:不公用性;复杂性(指数型、比值型、排名型指标)
    -基于应用的数据组装:大宽表集市、横表转纵表、趋势指标串

    数据服务层

    当数据已被整合和计算好之后,需要提供给产品和应用进行数据消费,为了更好的性能和体验,需要构建数据服务层,通过接口服务化方式对外提供数据服务。针对不同的需求,数据服务层的数据源架构在多种数据库之上,如Mysql和Hbase等。

    数据服务可以使应用对底层数据存储透明,将海量数据方便高效地开放给集团内部各应用使用。如何在性能、稳定性、扩展性等多方面更好地服务用户;如何满足应用各种复杂的数据服务需求;如何保证数据服务接口的高可用。随着业务的发展,需求越来越复杂,因此数据服务也在不断地前进。

    不管是数据公共层还是应用层,最终都需要面向业务提供服务。为了让业务部门找数据、看数据、用数据更加方便,我们将OpenAPI升级为能缓解业务变化对数据模型冲击的包括方法论+产品在内的OneService体系,使其在提供统一的公用服务的同时,兼容面向个性化应用的服务。

    下图为数据服务层在数据分层中的位置:
    3.png
    图:数据应用层与数据服务层关系

    综上,企业数据中台依托数据采集层、数据计算层、数据服务层,为上层数据产品、业务系统等提供数据支撑。云上数据中台产品Dataphin从“采、建、管、用”为企业提供一站式数据中台各层次的实现,配合阿里云系列产品,可实现企业数据中台全链路稳定、高效构建。


    数据中台是企业数智化的必经之路,阿里巴巴认为数据中台是集方法论、工具、组织于一体的,“快”、“准”、“全”、“统”、“通”的智能大数据体系。

    目前正通过阿里云对外输出系列解决方案,包括通用数据中台解决方案零售数据中台解决方案金融数据中台解决方案互联网数据中台解决方案政务数据中台解决方案等细分场景。

    其中阿里云数据中台产品矩阵是以Dataphin为基座,以Quick系列为业务场景化切入,包括:

    官方站点:
    数据中台官网 https://dp.alibaba.com
    钉钉沟通群和微信公众号
    数据中台钉钉群二维码2.jpg

    ]]>
    【福利】实时计算及 Flink 社区招聘信息汇总-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 招聘.jpg

    大家好,为帮助大家更好的找到适合的岗位,拿到心仪公司的offer,社区收集了多家实时计算及 Flink 企业用户的招聘需求,如:知乎、VIPKID、新氧、作业帮、得物、好未来、阿里巴巴等招聘信息,整理如下,供大家参考。

    欢迎更多企业投递实时计算及 Flink 相关招聘信息,更欢迎 Flink 专家、技术爱好者自荐。相关需求可联系小松鼠(微信 ID:Ververica2019)。

    本期招聘企业及岗位如下,找工作或有意向换工作的同学快到碗里来!

    image.png

    知乎 | 大数据实时处理平台研发工程师
    VIPKID | 实时计算研发工程师
    得物APP | 实时数据开发
    作业帮 | 实时计算架构研发工程师
    新氧科技 | 大数据开发工程师
    好未来 | 实时计算 Flink 专家岗 / 数据平台开发 - Flink 实时&离线岗
    阿里云计算平台事业部 | 研发工程师

    知乎:大数据实时处理平台研发工程师

    知乎数据架构团队正在围绕 Apache Flink 为核心打造大数据实时计算平台,为知乎内部业务提供批流融合的大数据计算能力,加入知乎数据架构团队共同探索新一代的大数据技术。欢迎大家推荐简历!

    岗位描述

    1. 参与 Apache Flink 的二次开发,建设 Flink 批流融合大数据计算引擎
    2. 深入理解业务并与业务部门密切合作,基于 Apache Flink + Kubernetes 建设知乎的实时计算平台

    岗位要求

    1. 计算机、通信、数学等相关专业,具备良好的计算机技术基础
    2. 熟悉 Java,具备扎实的数据结构和算法基础
    3. 具备良好的沟通和团队协作能力,做事主动积极,有技术热情和激情面对挑战
    4. 深入理解 Flink 或 Spark Streaming 原理者优先
    5. 有 PB 级数据处理经验和实时计算平台开发经验者优先
    6. 熟悉 Hadoop Ecosystem 例如 -- Flink/Spark/Hadoop/Hive/Kafka/Pulsar 以及 Kubernetes,向社区贡献过代码者优先

    简历投递

    • 工作地点:北京
    • 简历投递:sunxiaoguang@zhihu.com

    VIPKID:实时计算研发工程师

    岗位职责

    1.参与实时计算平台建设和架构设计开发,维护与优化;
    2.负责海量数据的采集,清洗等工作。

    岗位要求

    1.5年以上工作经验;
    2.熟练掌握hadoop、spark、storm、flink等大数据相关组件,深入理解系统原理,并有丰富Flink开发及运维经验
    3.精通数据采集、实时计算
    4.3年以上的Java或scala开发经验(熟练使用java、scala、python等开发语言);
    5.了解数据结构及算法(基本算法即可)
    6.具有较强的学习能力,自我管理能力、驱动能力
    
    加分项:
    
    有过主导和设计实时计算平台的系统规划,并落地的经验优先

    简历投递

    • 工作地点:北京
    • 简历投递:yangliang@vipkid.com.cn

    得物APP:实时数据开发

    岗位职责

    负责公司实时相关的业务数据统计需求的开发,包括实时数仓,标签体系,日志和业务数据的etl等工作。

    岗位要求

    1. 熟悉 Java、Scala 中至少一门语言,熟练使用 SQL。
    2.有大数据组件使用经验,熟悉大数据相关技术,如 Spark、Flink、HBase、Hive、Clickhouse 等。
    3. 使用 Flink 开发过复杂业务,熟悉 Datastream 和 Table/Sql API,有flink 作业线上调优经验优先。
    4.良好的业务理解能力和沟通表达能力,主动性强。

    简历投递

    • 工作地点:上海市杨浦区互联宝地
    • 简历投递:luoziyu@theduapp.com

    作业帮:实时计算架构研发工程师

    岗位职责

    1. 负责作业帮业务数据内容规划和设计,实现数据互通共享体系,解决海量数据面临的挑战;
    2. 负责公司流量数据OLAP引擎和实时计算框架的设计、开发和优化,构建实时数据的公共层;
    3. 负责Spark、Flink集群的管理和优化,保证集群持续稳定;
    4. 根据业务需求进行上游数据平台设计开发,打造高可用的数据平台;

    岗位要求

    1. 有一线互联网公司2年数据开发经验,或独立负责大中型业务大数据实时架构的经验;
    2. 熟悉Linux系统,具备Java/Scala/Python等一种或几种语言的开发能力;
    3. 熟悉Flink/Spark/Kafka/Presto/Hadoop/HBase等大数据相关技术,对源码有研究或者有调优经验者优先;
    4. 熟悉并行计算或者分布式计算原理,熟悉高并发、高稳定性、海量数据的系统特点和技术方案;
    5. 有大数据系统平台项目经验,掌握实时数据处理系统搭建和开发;
    6. 学习能力强,热衷开源技术,有团队观念,具备独立解决问题的能力;

    简历投递

    • 工作地点:北京
    • 简历投递邮箱:zhangying14@zuoyebang.com

    北京新氧科技有限公司:大数据开发工程师

    岗位职责

    1. 负责新氧实时业务数据支撑;
    2. 主要参与新氧流量、内容、电商、会员等各主题域实时数据仓库开发。
    3. 负责实时数据仓库程序上线并持续迭代优化以及日常运维

    岗位要求

    1. 本科以上,计算机相关专业;
    2. 3年以上的大数据研发经验,有flink实时作业开发部署调优经验。对kafka有较深入研究,对性能调优、故障恢复有一定的处理经验。
    3. 熟悉Linux操作环境,有良好的至少一门语言 (Java、Scala) 开发调试经验;
    4. 熟悉大数据开发相关技术,如hadoop、hive、spark、kafka、 spark streaming、Flink等;
    5. 熟练数据仓库,对多维数据建模有深入理解;
    6. 对数据系统热爱,乐于解决具有挑战性的问题, 具备优秀的分析问题、解决问题能力;

    简历投递

    • 工作地点:北京
    • 简历投递:gaohongchao@soyoung.com;liuyuquan@soyoung.com

    好未来:实时计算 Flink 专家岗 / 数据平台开发 - Flink 实时&离线岗

    实时计算 Flink 专家岗

    岗位职责

    1.负责行业实时计算开发平台的架构设计,完善实时计算方案
    2.支撑公司内部的实时业务开发
    3.对 Flink 以及周边技术进行源码级探索改进

    岗位要求

    1.有实时计算引擎设计项目经验,并能完成相应系统设计研发
    2.有丰富的Flink线上部署/日常运维/性能分析/故障定位能力
    3.精通 Java 编程语言,计算机基础知识(网络/操作系统/分布式基础等)扎实
    4.有过 SQL 引擎开发经验,或者对编译原理有所了解
    5. 有过完整实时开发平台项目经验者优先

    简历投递

    • 工作地点:北京
    • 简历投递:liuwenlin@tal.com

    数据平台开发:Flink 实时&离线岗

    岗位职责

    离线
    1.参与集团数据中台大数据基础设施建设
    2. 负责大数据生态组件的调优和二次开发
    3. 负责大数据平台开发套件相关子系统开发
    实时
    1.实现行业实时计算开发平台
    2. 支撑公司内部的实时业务开发
    3. 对flink以及周边技术进行源码级探索改进

    岗位要求

    1.3-5年相关工作经验,计算机相关专业本科以上学历
    2.精通java语言,熟悉常用设计模式、主流开发框架,3年以上相关开发经验;

    离线

    1.参与过大数据开发套件产品的后端开发者优先,包括大数据离线任务调度系统,元数据管理系统,数据质量系统等。
    2. 熟悉Hadoop集群及相关生态组件(HDFS、Zookeeper、YARN、Hive、Spark、Kerberos、AirFlow、Flink、Presto、Kudu等),有调优和二次开发经验者优先。
    3. 熟悉集群权限控制及开发者优先
    4. 熟悉数据安全管理和实践经验优先

    实时

    1. 有实时计算引擎设计项目经验,并能完成相应系统设计研发
    2. 有丰富的Flink线上部署/日常运维/性能分析/故障定位能力
    3. 有过SQL引擎开发经验,或者对编译原理有所了解
    4. 有过完整实时开发平台项目经验者优先

    简历投递

    • 工作地点:北京
    • 简历投递:liuwenlin@tal.com

    阿里云计算平台事业部:研发工程师

    团队介绍

    1. 基于Hadoop、Spark、Hive、HBase、Flink,Kafka,TensorFlow等开源大数据组件,构建云原生大数据平台,提供大规模计算能力;
    2. 提供一站式大数据应用开发平台, 包括大数据安全体系,数据治理,作业调度,交互式查询,专项领域监控,通过机器学习算法帮助用户智能诊断复杂问题;
    3. 打造世界顶级的开源大数据平台,在公共云、裸机、私有云和混合云等环境, 为阿里云客户提供云原生大数据全家桶服务;
    4. 参与阿里云城市大脑、智慧交通等多项国家战略项目建设,利用实时/批技术处理真实世界中的海量数据。

    职位描述

    1. 计算机、通信、数学等相关专业,具备良好的计算机技术基础;
    2. 熟悉Java/C++/Python/GO等至少一种编程语言,具备扎实的数据结构和算法基础;
    3. 具备良好的沟通和团队协作能力,做事主动积极,有技术热情和激情面对挑战;
    4. 熟悉主流JAVA框架,包括spring、netty、mybatis等技术者优先;
    5. 熟悉Hadoop/Spark/Flink/Storm/HBase/Hive/Kafka/TensorFlow/Kubernetes/Prometheus技术者优先。

    简历投递

    • 工作地点:北京
    • 简历投递:wali.rcd@taobao.com

    ▼ 实时计算 Flink 技术交流群 ▼

    实时计算交流群 200.jpeg

    ]]>
    凯伦陈洪进:中国防水行业亟待拥抱数字化变革 | 阿里CIO学院名人堂-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 image.png

    9月10日,陈洪进与来自全国各地的36家大型企业的43位信息化高管共聚美丽的北国春城,参加由阿里巴巴与中国一汽联合举办的阿里CIO学院走进一汽共创会,从智能制造、新营销和新IT三个角度探寻企业转型中的“数字化力量”。

    活动期间,陈洪进与其他学员们就企业数字化转型进行了深入交流。会后,陈洪进接受CIO学院的新媒体访谈,他表示对传统的制造企业而言,数字经济带来的不是数字化转型,而是数字化升级,中国防水行业亟待拥抱数字化变革。

    image.png

    走进一汽感受数字化力量

    在参加完走进一汽的活动后,陈洪进对两个内容感触较深:

    第一,数字化工厂的实践。对传统的制造型企业而言,红旗数字化工厂不像媒体上宣传的各种类型的无人产线那么高不可攀,现场有很多人在不同工序从事各种作业,各种AGV设备也有明显地自行改造的影子,但通过优化现场流程实现了生产效率的大幅度提升。除了遍布全厂的AGV小车外,无人值守库房、工序配件的自动调度、车间电子看板取代纸质单据等内容,都令人印象深刻,值得借鉴。

    第二,产品数字化在价值链上的拓展。一汽提出根据服务的价值链不同,构建不同的数字孪生主体,包括研发孪生、制造孪生、营销孪生、运营孪生等。当前传统制造型企业讨论的孪生大多偏重于设备领域,以设备模拟和预防性维护为主要方向,一汽的孪生理念拓展了产品数字化的边界,以产品为载体,整合企业价值链的各种数据形成适应每个价值模型的数字化产品,这种理念超越了对个别业务进行数字孪生的认知,对于指导制造型企业进行全面数字化转型具有很好的引领作用。

    image.png

    陈洪进在活动现场

    凯伦股份全力加速数字化转型

    凯伦股份是中国建筑防水行业首家创业板上市公司,缔造了传统制造领域民营企业6年上市的传奇速度。2017年上市至今,年复合增长率63%。

    凯伦股份在信息化建设上具有前瞻性。2012年工厂投产即投用了定制的金蝶ERP系统,良好的支撑了企业运营和上市;上市后,2018年即着手实施Oracle ERP系统,于2019年1月1日顺利上线,支持了企业由单一工厂到多工厂、单一组织到多组织的快速发展。

    2019至2020年进一步实施了MES、HR、BI、智能化大屏等系统。

    凯伦的信息化面临的主要挑战是如何为公司的快速发展保驾护航,涉及集团管控、异地工厂管理、新业务模式涌现等课题。凯伦所在的行业是建材领域,面对的客户主要是传统的建筑工程市场客户,产品非常标准化,属于典型的“toB”业务,企业管理的重点是提升自身的运营效率。

    根据如上情况,凯伦提出了“数字化运营,可视化管理”的信息系统三年战略目标,要求在经营、生产的全过程实现数字化,同时对每个职能通过报表、大屏等实现可视化管理。进而凯伦设定了核心的管控指标:部门KPI指标覆盖率,要求由系统出具考核数据的部门KPI指标占比60%以上。

    数字化转型?数字化升级!

    在下午举行的阿里CIO学院走进一汽共创会上,来自中国一汽数字化部、启明信息、阿里巴巴的6位讲师针对 “新制造”、“新基建”、“新营销”等话题进行了深度分享,深度讲解以云数智为代表新兴数字技术正在为汽车产业赋能,加速行业向智能化、电动化、网联化、共享化的出行服务转型。

    陈洪进表示,对传统的制造企业而言,数字经济带来的不是数字化转型,而是数字化升级。以阿里为代表的互联网企业带来了很多新技术、新理念、新做法,值得传统制造企业借鉴。

    2019年,阿里的“中台”概念火热却在制造业鲜有案例,关键原因应该是制造业中很少涉及一个公司内要在较短的时间内、由不同部门实现类似业务快速上线的应用场景。但在不到一年的时间内,苏州的一家企业使用中台、微服务的理念,以单点登录为切入点,重构了企业内部系统,极大提升了员工使用业务系统的效率;在一汽参观中,启明信息更是提出基于中台架构,通过微服务设计,将传统的ERP系统拆解成分布式、开放式和服务化的业务平台。

    在当前各行各业都面临巨大挑战,业务的瞬息万变,要求对应的信息系统具有良好的弹性,开放化、服务化将成为永恒的主题。在这种背景下,中台、微服务的理念对于在现有的业务系统基础上,快速构建全新的业务支持系统具有重要的理念引导作用,无疑是阿里输出给社会的成功经验。架构中台化也将是凯伦未来三年要重点实现的技术目标。

    在陈洪进看来,阿里还有很多如云平台、弹性计算这些可以直接使用的技术,阿里的管理理念也是当前企业管理界的热点。传统制造业应该充分借鉴和应用这些理念和技术,提升自身的管理能力和经营效率,加快转型和升级,以更好的状态参与市场竞争。

    image.png

    陈洪进参与圆桌论坛环节

    数字化转型人才和开放合作至关重要

    当前中国防水市场正在加速转型,目前规模每年2000亿元,绝大部分业务是toB业务,但头部企业已经涉足C端市场,直接面向消费者;同时,随着凯伦为代表的高分子防水市场的拓展,中国的防水行业深入参与国际市场竞争也是可以预见的未来。

    在这种背景下,陈洪进认为,以下三个方面是防水行业数字化升级的主要内容:首先,以“提质、降本、增效”为核心的内部管理的数字化升级;其次,面向防水工程的施工过程管理的数字化升级;再次,面向家装领域即C端的业务模式、营销模式的数字化创新,未来防水行业的数字化升级的亮点就在这三个方向上。

    更重要的是,传统制造型企业转型,对业务部门而言是理念的挑战,对IT部门而言是技术和业务的双重挑战,这可能是制造型企业的共同痛点。业务部门由于不懂IT技术,很难理解IT技术的边界,也很少会用IT的视角诠释业务需求,所以需要在理念上认同数字化;IT部门首先要立足业务需求解决业务问题,其次要用更合理的技术确保可扩展性,两个方面要兼顾。归根结底,企业需要培养数字化复合型人才,这是一个永恒的话题。

    陈洪进指出,凯伦需要培育核心的数字化复合型人才,需要兼顾业务和IT技术。制造型企业的信息化往往不是技术创新驱动型,需要精通行业特点的人才,立足于业务本身,使用IT技术解决实际问题。防水行业如今整体信息化水平一般的问题核心是复合型人才稀缺。凯伦的目标不仅仅局限于国内市场,所以必须培养出核心的数字化复合型人才,才能支持各种可能的业务方向。

    对于技术,陈洪进倾向于开放合作。他认为制造型企业不像互联网行业一样有众多精英IT人才。所以,凯伦应该有懂得IT边界的、精通业务流程的人才,能阐明业务需求,而对于业务的具体技术实现,可以根据实际情况选择。

    在陈洪进看来,大数据和人工智能将会带来行业的巨变。他记得在此次参观中,一汽的领导在分享业务对象数字化的认识时,提出:一个设备,最早只是一个代码,不到1K的信息;当数据累计到10M时,可以支持设备的全生命周期管理;1G时,可以开展预防性维修;10G时,可以支持虚拟仿真。这个例子比较形象的说明了业务对象的数据累积到一定程度,大数据、人工智能等技术可以带来量变到质变的过程。

    “因为相信,所以看见”,“仰望星空,脚踏实地”,陈洪进表示,阿里的这两句话最代表他对大数据、人工智能技术的感触。

    阿里CIO学院应考虑建立行业分院

    陈洪进:首先很感激阿里给CIO创造的这样一个公益平台,让大家有机会深入学习和了解阿里,也有机会互相学习。通过阿里CIO学院的组织走进中国一汽,观摩标杆企业的精益制造;领略前沿的数字化转型,学习先进的数字化方法论;专家老师全程相伴,并与阿里巴巴和中国一汽的数字化高管面对面交流,倾听实战分享、可谓一场完美的主题活动。

    我觉得未来可以考虑行业分院的形式,让学员更加有针对性。同时也可以开展分院之间的交流互动,取长补短。

    公司简介

    image.png

    凯伦股份是一家集防水材料研发、制造、销售及施工服务于一体的国家高新技术企业。先后获得“中国防水行业质量提升示范企业”、“中国房地产500强首选供应商”、“江苏省优秀企业”等荣誉称号。企业以“融合防水”为旗,于国内首创MBP高分子自粘胶膜防水卷材和白色抗流挂聚氨酯防水涂料,填补了国内高分子防水领域的技术空白,引领行业转型升级。2017年10月26日,凯伦股份实现A股上市,成为中国建筑防水行业首家创业板上市公司。

    公司目前在华东、华北、华中和西南建有现代化生产基地,引进全套进口成型生产线和先进的胶体磨等设备,精细化和自动化程度达到国际同行先进水平。为快速响应市场,公司不断完善产业布局,在西北、华南和华东(新)投资建设产业基地,抓住长三角生态绿色一体化发展示范区机遇,在苏州建设世界一流的高分子防水材料生产基地。

    秉承“精细化的融合、看得见的诚实”的经营理念,公司短短几年内把业务推向多个建筑防水领域,先后与万科、恒大、碧桂园、绿地等20多个龙头房地产建立战略合作关系,承接了多个高铁、地铁、隧道、核电站和地下管廊等防水项目;凯伦股份放眼全球,销售遍布美国、英国、德国、澳大利亚、以色列、新加坡、印度等60多个国家和地区。

    凯伦股份坚守“高品质”和“绿色生产”的战略定位,致力成为国际领先的功能性建材制造商,以稳健的步伐,确保基业长青,效力百年建筑,造福人类,回馈社会。

    文章来源:阿里飞天CIO学堂微信公众号

    名人堂

    名人堂是阿里CIO学院打造的一档大伽访谈栏目,每周一期。以推动企业创新与数智化升级为愿景,通过采访行业顶尖客户,帮你更好地了解和思考企业数字化转型中可能面临的挑战,梳理行业痛点和方法路径,从而相互滋养,共同成长。

    更多文章

    点击查看青岛华通集团智能研究院明磊:拥抱数字化转型正在成为CIO头等大事 | 阿里CIO学院名人堂>>>

    点击查看ERIC,ZHANG:地产业数字化转型按下“加速键”美好人居正当时 | 阿里CIO学院名人堂>>>

    点击查看李锋:联接数智化生态,打造“数字化越秀” | 阿里CIO学院名人堂>>>

    点击查看龙湘君:基金行业奏响数字化转型五部曲 | 阿里CIO学院名人堂>>>

    点击查看段晓力:从一个小目标的对立 到万个小目标的融合 | 阿里CIO学院名人堂>>>

    点击查看贾坤:扶贫基金事业借数字化转型助力决胜脱贫攻坚战 | 阿里CIO学院名人堂>>>

    点击查看郑荣:世界的香格里拉——从“藏在深闺无人识”到“网红旅游目的地” | 阿里CIO学院名人堂>>>

    点击查看魏琴:前海再保险以科技创新打破保险行业传统疆域 | 阿里CIO学院名人堂>>>

    点击查看王丽静:深挖“数据宝藏”打造新型高端智库 | 阿里CIO学院名人堂>>>

    点击查看石廷洪:推动数字化转型 打造世界一流企业 | 阿里CIO学院名人堂>>>

    点击查看韩海潮:数字化浪潮引领基金行业转型新方向 | 阿里CIO学院名人堂>>>

    点击查看谢钧棋:以“数”转型 用“脉”管理 | 阿里CIO学院名人堂>>>

    ]]>
    应用架构之道:分离业务逻辑和技术细节-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 头图.png

    作者 | 张建飞  阿里巴巴高级技术专家

    架构

    什么是架构?

    关于架构这个概念很难给出一个明确的定义,也没有一个标准的定义。

    硬是要给一个概述,我认为架构就是对系统中的实体以及实体之间的关系所进行的抽象描述。

    架构始于建筑,是因为人类发展(原始人自给自足住在树上,也就不需要架构),分工协作的需要,将目标系统按某个原则进行切分,切分的原则,是要便于不同的角色进行并行工作。

    为什么需要架构?

    有系统的地方就需要架构,大到航空飞机,小到一个电商系统里面的一个功能组件都需要设计和架构。

    我很喜欢《系统架构:复杂系统的产品设计与开发》里面的一句话:结构良好的创造活动要优于毫无结构的创造活动

    与之相对应的,现在很多敏捷思想提倡 no design,只要 work 就好。期待好的架构可以在迭代中自然涌现。这个想法有点太理想化了,在现实中,只要能 work 的代码,工程师是很少有动力去重构和优化的。

    架构师的职责

    作为架构师,我们最重要的价值应该是“化繁为简”。但凡让事情变得更复杂,让系统变得更晦涩难懂的架构都是值得商榷的。

    架构师的工作就是要努力训练自己的思维,用它去理解复杂的系统,通过合理的分解和抽象,使哪些系统不再那么难懂。我们应该努力构建易懂的架构,使得在系统上工作的其他人员(例如设计者、实现者、操作员等)可以较为容易地理解这个系统。

    软件架构

    软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件。各个组件之间的连接则明确和相对细致地描述组件之间的通信。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口来实现。

    软件架构为软件系统提供了一个结构、行为和属性的高级抽象,由构件的描述、构件的相互作用、指导构件集成的模式以及这些模式的约束组成。软件架构不仅显示了软件需求和软件结构之间的对应关系,而且指定了整个软件系统的组织和拓扑结构,提供了一些设计决策的基本原理。

    软件架构的核心价值应该只围绕一个核心命题:控制复杂性。他并不意味着某个特定的分层结构,某个特定的方法论(贫血、DDD 等)。

    软件架构分类

    在介绍应用架构之前,我们先来看一下软件架构的分类。

    随着互联网的发展,现在的系统要支撑数亿人同时在线购物、通信、娱乐的需要,相应的软件体系结构也变得越来越复杂。软件架构的含义也变得更加宽泛,我们不能简单地用一个软件架构来指代所有的软件架构工作。按照我个人理解,我将软件架构划分为:

    1.png

    业务架构:由业务架构师负责,也可以称为业务领域专家、行业专家。业务架构属于顶层设计,其对业务的定义和划分会影响组织结构和技术架构。例如,阿里巴巴在没有中台部门之前,每个业务部门的技术架构都是烟囱式的,淘宝、天猫、飞猪、1688 等各有一套体系结构。而后,成立了共享平台事业部,打通了账号、商品、订单等体系,让商业基础实施的复用成为可能。

    应用架构:由应用架构师负责,他需要根据业务场景的需要,设计应用的层次结构,制定应用规范、定义接口和数据交互协议等。并尽量将应用的复杂度控制在一个可以接受的水平,从而在快速的支撑业务发展的同时,在保证系统的可用性和可维护性的同时,确保应用满足非功能属性要求(性能、安全、稳定性等)。

    分布式系统架构:分布式系统基本是稍具规模业务的必选项。它需要解决服务器负载,分布式服务的注册和发现,消息系统,缓存系统,分布式数据库等问题,同时架构师要在 CAP(Consistency,Availability,Partition tolerance)之间进行权衡。

    数据架构:对于规模大一些的公司,数据治理是一个很重要的课题。如何对数据收集、数据处理提供统一的服务和标准,是数据架构需要关注的问题。其目的就是统一数据定义规范,标准化数据表达,形成有效易维护的数据资产,搭建统一的大数据处理平台,形成数据使用闭环。

    物理架构:物理架构关注软件元件是如何放到硬件上的,包括机房搭建、网络拓扑结构,网络分流器、代理服务器、Web服务器、应用服务器、报表服务器、整合服务器、存储服务器和主机等。

    运维架构:负责运维系统的规划、选型、部署上线,建立规范化的运维体系。

    典型应用架构

    分层架构

    分层是一种常见的根据系统中的角色(职责拆分)和组织代码单元的常规实践。常见的分层结构如下图所示:

    2.png

    CQRS

    CQS(Command Query Separation,命令查询分离),最早来自于 Betrand Meyer(Eiffel 语言之父,OCP 提出者)提出的概念。其基本思想在于,任何一个对象的方法可以分为两大类:

    • 命令(Command): 不返回任何结果(void),但会改变对象的状态。
    • 查询(Query): 返回结果,但是不会改变对象的状态,对系统没有副作用。

    3.png

    六边形架构

    六边形架构是 Alistair Cockburn 在 2005 年提出,解决了传统的分层架构所带来的问题,实际上它也是一种分层架构,只不过不是上下,而是变成了内部和外部(如下图所示)。

    4.png

    六边形架构又称为端口-适配器架构,这个名字更容器理解。六边形架构将系统分为内部(内部六边形)和外部,内部代表了应用的业务逻辑,外部代表应用的驱动逻辑、基础设施或其他应用。

    适配器分为两种类型(如下图所示),左侧代表 UI 的适配器被称为主动适配器(Driving Adapters),因为是它们发起了对应用的一些操作。而右侧表示和后端工具链接的适配器,被称为被动适配器(Driven Adapters),因为它们只会对主适配器的操作作出响应。

    5.png

    洋葱圈架构

    洋葱架构与六边形架构有着相同的思路,它们都通过编写适配器代码将应用核心从对基础设施的关注中解放出来,避免基础设施代码渗透到应用核心之中。这样应用使用的工具和传达机制都可以轻松地替换,可以一定程度地避免技术、工具或者供应商锁定。

    不同的是洋葱架构还告诉我们,企业应用中存在着不止两个层次,它在业务逻辑中加入了一些在领域驱动设计的过程中被识别出来的层次(Application,Domain Service,Domain model,Infrastructure等)。

    另外,它还有着脱离真实基础设施和传达机制应用仍然可以运行的便利,这样可以使用 mock 代替它们方便测试。

    6.png

    在洋葱架构中,明确规定了依赖的方向:

    • 外层依赖内层;
    • 内层对外层无感知。

    COLA 应用架构

    COLA 架构是我团队自主研发的应用架构,目前已经开源。在 COLA 的设计中,我们充分汲取了经典架构的优秀思想。除此之外,我们补充了规范设计和扩展设计,并且使用 Archetype 的方式,将架构固化下来,以便可以快速的在开发中使用。

    COLA 开源地址:https://github.com/alibaba/COLA

    分层设计

    COLA 的分层是一种改良了的三层架构。主要是将传统的业务逻辑层拆分成应用层、领域层和基础实施层。如下图所示,左边是传统的分层架构,右边是 COLA 的分层架构。

    7.png

    其每一层的作用范围和含义如下:

    1)展现层(Presentation Layer):负责以 Rest 的格式接受 Web 请求,然后将请求路由给 Application 层执行,并返回视图模型(View Model),其载体通常是 DTO(Data Transfer Object);

    2)应用层(Application Layer):主要负责获取输入,组装上下文,做输入校验,调用领域层做业务处理,如果需要的话,发送消息通知。当然,层次是开放的,若有需要,应用层也可以直接访问基础实施层;

    3)领域层(Domain Layer):主要是封装了核心业务逻辑,并通过领域服务(Domain Service)和领域对象(Entities)的函数对外部提供业务逻辑的计算和处理;

    4)基础实施层(Infrastructure Layer)主要包含 Tunnel(数据通道)、Config 和 Common。这里我们使用 Tunnel 这个概念来对所有的数据来源进行抽象,这些数据来源可以是数据库(MySQL,NoSql)、搜索引擎、文件系统、也可以是 SOA 服务等;Config 负责应用的配置;Common 是通用的工具类。

    扩展设计

    对于只有一个业务的简单场景,对扩展性的要求并不突出,这也是为什么扩展设计常被忽略的原因,因为我们大部分的系统都是从单一业务开始的。但是随着业务场景越来越复杂,代码里面开始出现大量的if-else逻辑。此时除了常规的策略模式以外,我们可以考虑在架构层面提供统一的扩展解决方案。

    在扩展设计中,我们提炼出两个重要的概念,一个是业务身份,另一个是扩展点

    业务身份是指业务在系统唯一标识一个业务或者一个场景的标志。在具体实现中,我们使用 BizCode 来表示业务身份,其中 BizCode 采用类似 Java 包名命名空间的方式。例如,我们可以用“ali.tmall”表示阿里天猫业务,用“ali.tmall.car” 表示阿里天猫的汽车业务,而用"ali.tmall.car.aftermarket"代表这是阿里天猫的汽车业务的后市场场景。

    每个业务或者场景都可以实现一个或多个扩展点(ExtensionPoint),也就是说一个业务身份加上一个扩展点,可以唯一地确定一个扩展实现(Extension)。而这个业务身份和扩展点的组合,我们将其称之为扩展坐标(ExtensionCoordinate),如下图所示。

    8.png

    这样,通过业务身份+扩展点,我们就可以从框架层面实现对不同租户,不同业务,不同场景的扩展定制了。整个阿里业务中台正是基于这个思想,实现的多业务支撑的。

    规范设计

    任何事物都是规则性和随机性的组合。规范的意义就在于我们可以将规则性的东西固化下来,尽量减少随心所欲带来的复杂度,一致性可以降低系统复杂度。从命名到架构皆是如此,而架构本身就是一种规范和约束,破坏这个约束,也就破坏了架构。

    COLA 制定了一些列的规范:包括组件(Module)结构、包(Package)结构、命名等。

    比如对于组件,我们要求使用 COLA 的应用都应该遵循如下图所示的组件划分:

    9.png

    COLA 架构总览

    在架构思想上,COLA 主张像六边形架构那样,使用端口-适配器去解耦技术细节;主张像洋葱圈架构那样,以领域为核心,并通过依赖倒置反转领域层的依赖方向。最终形成如下图所示的组件关系。

    10.png

    换一个视角,从 COLA 应用处理响应一个请求的过程来看。COLA 使用了 CQRS 来分离命令和查询的职责,使用扩展点和元数据来提升应用的扩展性。整个处理流程如下图所示:

    11.png

    应用架构的核心

    纵观上面介绍的所有应用架构,我们可以发现一个共同点,就是“核心业务逻辑和技术细节分离”。

    12.png

    是的,六边形架构、洋葱圈架构、以及 COLA 架构的核心职责就是要做核心业务逻辑和技术细节的分离和解耦。

    试想一下,业务逻辑和技术细节糅杂在一起的情况,所有的代码都写在 ServiceImpl 里面,前几行代码是做 validation 的事,接下来几行是做 convert 的事,然后是几行业务处理逻辑的代码,穿插着,我们需要通过 RPC 或者 DAO 获取更多的数据,拿到数据后,又是几行 convert 的代码,在接上一段业务逻辑代码,然后还要落库,发消息.....等等。

    再简单的业务,按照上面这种写代码的方式,都会变得复杂,难维护。

    因此,我认为应用架构的核心使命就是要分离业务逻辑和技术细节。让核心业务逻辑可以反映领域模型和领域应用,可以复用,可以很容易被看懂。让技术细节在辅助实现业务功能的同时,可以被替换。

    最后我们发现,应用架构的道就是:“让上帝的归上帝,凯撒的归凯撒。”

    阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

    ]]>
    玩转ECS第1讲 | 云上自动化部署和运维的正确姿势-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 演讲嘉宾简介:吴君印,阿里云资深技术专家。负责ECS整体服务层面的技术和产品架构工作,并负责阿里云智能内部OnECS的技术和产品架构工作,包括产品ECS云助手,运维编排OOS,资源编排ROS以及内部OnECS产品宙斯,致力于打造以ECS为中心的系统管理、自动化和DevOps体验。

    以下内容根据演讲视频以及PPT整理而成。观看回放
    更多课程请进入玩转ECS详情页”了解

    本次分享主要围绕以下三个方面:

        一、云上部署和运维的特点
        二、资源编排ROS
        三、运维编排OOS
    

    今天主要分享的内容是云上自动化部署和运维的正确姿势,下面先来看看云上部署相比于传统的RDC部署有哪些不同。

    一、云上部署和运维的特点

    无论是部署还是运维,在云上都有如下四个特点:

    image.png

    首先,可重复。在云上部署相对于传统RDC部署而言更加灵活,只需要编写一次模版就可以随时随地拉起一套环境,做到一键部署。目前有两种类型的环境部署,一种是测试环境、预发环境、生产环境。第二种是在不同地域进行部署,如北京地域、上海地域以及杭州地域。

    第二点,多环境保持一致。因为使用的是相同的模版进行部署,所有环境部署出来的结果都一样,这样可以避免人为错误,避免问题排查时的环境影响,环境造成的问题往往是最难排查的问题之一。

    第三点,可审计。所有操作均通过API,所有API操作都可以被审计,集成操作审计服务ActionTrail即可。

    第四点是DevOps。从环境部署到应用部署都模板化,版本管理使用Git,可以做代码评审、代码回滚。

    资源编排ROS和运维编排OOS

    阿里云针对云上部署和运维特点,推出了两个产品,包括资源编排ROS(Resource Orchestration Service)——解决自动化部署问题,运维编排OOS(Operation Orchestration Service)——解决自动化运维问题。两款编排产品除了支持ECS的实例,还支持其它阿里云的产品,如负载均衡,关系型数据库RDS,对象存储OSS等。

    image.png

    二、资源编排ROS

    资源编排ROS的典型场景

    资源编排ROS的典型场景主要有四种:
    • 第一种是部署模版,资源编排ROS是通过模版方式达到可以重复部署的目的,使用模版可以在任何时间任何地点拉起一套环境。
    • 第二种是MSP、ISV提供自己的部署模版,可以一键开出复杂的业务系统,如SAP HANA等系统,将部署时间缩短为几个小时。由于云上的环境都是标准的,只要有测试通过后的模版就可以在不同的环境、不同的账号中重复部署。
    • 第三是解决方案中心,阿里云通过自身多年服务客户和双11的经验,总结了大量的最佳实践,在解决方案中心中提供了很多高质量的模版,支持开箱即用。
    • 第四是CI/CD集成,在DevOps开发模式下,只有将部署模版放到CI/CD中才能打造DevOps的开发模式,轻松的做到蓝绿部署,并且支持阿里云云效。

    image.png

    ROS控制台及操作演示

    下图是资源编排ROS主页https://rosnext.console.aliyun.com/ ,上方对ROS产品进行了简单的介绍;下方是常见的部署架构作为示例模版。

    image.png

    左侧菜单栏中有“我的模版”和“模版示例”,其中我的模版是需要自定义的模版,模版示例中提供了大量常见的部署形式,如Jenkins、Kafka等。解决方案中心中是由阿里云解决方案架构师团队、最佳实践团队、各业务方团队和资源编排团队合作共建,将阿里云多年沉淀的最佳实践和针对各种场景的解决方案沉淀为资编排源模版,用户可以使用这些最佳实践模版使得云上部署更加安全高效。

    image.png

    “资源类型”模块中展示了ROS支持的阿里云云产品。

    image.png

    下面以构建我的模版LNMP-deom-1作为例子,模版以JSON格式表达,也支持YAML格式,最重要的是,还提供了可视化的架构图。

    image.png

    可以发现所有的资源都在VPC内部,包括关系型数据库RDS和ECS实例。图中两个ECS实例挂在负载均衡LoadBalance下面。

    image.png

    接着可以使用此模版创建资源栈,之后通过事件tab知道每一步创建步骤。在资源tab中看到所有被模版创建的资源,只需要点击资源ID,就可以打开实例详情页面。在输出tab在有显示一个网站链接,可以发现此次网站部署成功。参数tab中提供了每次模版的参数。当用户手动修改一些资源,与模版出现不一致时,可以使用检查资源偏差查看不同点。

    image.png

    三、运维编排OOS

    运维编排OOS的典型场景

    运维编排OOS的典型场景同样分为四种:
    • 首先是批量操作实例和执行远程命令,例如启动、停止等,相比于其它方式无需密码,无需登录,无需使用跳板机,且无需担心安全问题,运维编排使用了阿里云RAM进行控制。
    • 第二种场景是定时运维,在固定的时间执行制定的命令,相当于云上Cron服务,并且免托管,分布式。
    • 第三种场景是支持报警和事件驱动运维,当某个事件发生时自动触发告警任务。
    • 第四是提供大量丰富的公共模版,阿里云总结了大量的典型运维场景,并将总结成果开源到了Github上,欢迎大家贡献优质模版,共同打造运维社区。

    image.png

    OOS控制台及操作演示

    下图是运维编排OOS主页https://oos.console.aliyun.com/ ,左侧菜单栏中有批量操作实例模块,任务类型包含发送进程命令、批量下载文件、实例操作、实例属性修改等。批量管理软件模块中可以批量的给实例下载和安装常见的软件,在我的软件模块可以自行部署和卸载。

    image.png

    定时开关机模块中可以选择在指定的时间关闭、开启或重启实例。在包年包月的服务器情况下,客户需要在固定的时间升级临时宽带,等高峰过去后再下降,以达到节约成本的目的。在创建更新镜像模块中可以基于已有的实例进行更新,也可以基于已有的镜像创建实例,进一步更新,再创建新的镜像。

    定时运维模块可以在固定的时间和固定的地域执行指定的任务。告警与事件运维模块中若控制台上显示当某个事件发生时自动触发模版,比如CPU使用率过高时重启实例操作。

    image.png

    所有的模版都提供了可视化视图,提供了更加直观的展示方式,还提供了YAML和JSON两种格式的文本,方便用版本管理软件如Git进行管理。

    image.png

    下图展示的是批量操作实例,发送远程命令,命令内容是发送输出命令。之后选择实例,可以手动选择,可以指定实例标题,也可以指定实例资源组,或者上传csv文件,从ECS实例表中导出csv文件来选择实例。

    image.png

    在高级选项部分可以配置执行模式,如出现错误时继续执行还是暂停实例,设置并发速率,允许的最大错误次数等。

    image.png

    此外还有更加快速的执行实例命令方式,在实例列表模块中选择具体的实例,进入实例详情页后会显示本实例远程命令,显示了历史的执行命令,同时可以发送新的远程命令。其次在实例列表中同时选择多台实例,选择更多,发送远程命令,这时多台实例就可以同时执行命令。

    image.png

    使用ROS、OOS的部分阿里云产品

    下图中列出了支持ROS、OOS的常见阿里云产品,包括ACS容器服务、FC函数计算、SLS日志服务、SMC服务迁移中心等等,这与产品本身的部署场景契合。

    image.png

    云产品需要支持多种地域,阿里云有22个地域,使用ROS和OSS可以最大提高部署和运维效率。阿里云对内部系统变更有非常严格的要求,需要提供信息完整的变更单、申请、审批、以及需要为变更过程中可能出现的问题提前准备脚本。因此OSS会预先提供变更模版和回滚模版,从而提供自动化运维程度,降低人工错误。

    客户对自动化运维有不同的需要,从下图左侧可以分出运维的几个层次,从最底层的手动运维、到半手工,半自动化运维、再到高度自动化运维、标准化运维以及智能运维(AIOps)、大部分客户的需求集中在中间三层,大部分的公司处于半手工,半自动化运维,异或高度自动化的方式,少部分的公司更加激进的走到了更加标准化运维,享受到了更加DevOps的方式,阿里云自动化部署ROS和自动化运维OOS的主打场景可以满足这三个主要层次的自动化需求。

    image.png

    今天的分享到此结束,感兴趣的同学可持续关注云上自动化部署ROS和运维OOS产品动态。

    ]]>
    数据湖解决方案——广告行业解读-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 行业综述

    游戏市场需求旺盛,行业景气度持续提升
    据相关数据显示,我国广告投放刊例花费整体呈负增长趋势,2019年2月下降幅度最大达到18.3%,下降幅度虽然有所放缓,但是整体而言,我国广告投放刊例花费下降幅度仍然较大。2020年1月,我国广告投放刊例花费下滑5.6%。
    分媒体来看,传统广告媒介主要包括报纸媒体、杂志、广播、电视、户外媒体和售点等。2020年1月,报纸、杂志、广播等较为传统的广告媒介刊例下降幅度较大,报纸、杂志等纸媒下降了30%以上,广播媒介下降了19.5%。电视、传统户外同样下降了4.9%和9%;整体而言,传统媒体广告刊例花费呈下降趋势。
    与传统媒体广告相比,互联网广告市场规模逐渐上升。根据中关村互动营销实验室的数据,2010-2019年我国互联网广告市场增速虽然放缓,但是我国互联网广告市场规模呈现出逐年上升的发展趋势,2010-2019年我国互联网广告市场规模复合增速达40%以上。2019年我国互联网广告总收入约4367亿元人民币,相较上年增长18.22%,增幅较2018年略有放缓,但仍保持增长的态势。

    行业发展方向

    互联网广告时代正在来临,大数据驱动智能化精准广告投放
    随着互联网的普及,以及精准化程度高、性价比高、媒体质量优等优势,互联网广告迅速崛起,不断持续冲击传统媒介,市场份额持续上升:2016-2019年,我国互联网广告规模占整体广告市场规模比重持续上升,到2019年,互联网广告所占比重已超过50%。

    互联网媒体广告相对于传统广告而言具有较多优势,例如互联网广告形式更新频率比报刊广告、广播广告、电视广告等传统媒体更快,能快速适应市场环境的变化,是高度综合的媒体,扩容性高。互联网媒体广告的发展迅速较快,已不仅仅是展示广告,而是更加精准化、个性化和自动化,能够紧紧地把握市场潮流以及引领着技术的进步。
    

    面临的痛点

    大数据驱动下数据存储成难题,资源浪费成难题
    互联网广告平台的增加,一方面为读者提供了更多的阅读平台,但是背后产生了大量的阅览、订阅、购买数据,而这些数据的产生已经从过去的TB级向PB级甚至EB级跨越,而要利用好这些数据,需要大量的存储空间和计算资源,尤其是为了提高广告推送的准确率以及点击率,需要对大量的数据进行复杂的运算,而这给企业提出了难题。持有的资源过多,虽然可以满足业务需求,但是在空闲期间限制,如果不持有相应的资源,那么又不能很好的解决业务问题。如何很好的寻找业务和资源消耗的平衡点,摆在了各个广告投放企业眼前。

    数据湖解决方案

    阿里云数据湖解决方案,助力企业真正释放数据价值
    15.png
    基于阿里云对象存储OSS构建的数据湖解决方案,可以全面满足数据的存储、离线分析、交互查询等各种业务诉求,帮助解决上面提到的这些难题。
    首先,数据湖解决方案可为用户存储的数据提供高达12个9的可靠性,让数据安全存放,保障用户数据不丢不坏。

     其次,阿里云的数据湖解决方案,也是一套十分智能的解决方案。其中对象存储OSS,可以对接个多业务系统,存储来自不同业务系统的多种数据源,如些系统的原始数据、游戏日志数据等。等数据汇聚到数据湖之后,它的上层系统可以兼容多种计算引擎,如开源大数据引擎像Hive,Spark,阿里云EMR、DLA等,帮助用户便捷地实现数据处理和分析,不需要再重复拷贝多份。同时采用 Jindofs提供缓存加速方案,还可以获得比使用HDFS更好的体验。

    这样一套整体的数据存储、处理分析解决方案,能很大程度地减少系统兼容性问题,管理维护也更加简单,帮助IT人员从复杂且繁琐的运维中解放出来,更加专注在产品创新和业务模式的运营上。

    最佳案例实践

    客户简介
    客户是一家致力于为广告主企业构建贯穿消费者生命周期的流量网络,形成企业私有化的消费者数字资产。在国内享有很高的知名度。

    业务挑战
    1、智能流量平台的数据量在急剧增长,每天的业务日志数据在持续的产生和上传,曝光、点击、推送的数据在持续处理,每天新增的数据量已经在5TB左右,对整个数据处理系统提出了更高的要求。
    2、通过运用AI图像识别技术对内容场景进行智能识别与自动匹配,实现不同场景下的创意的精准匹配,真正实现千人千面千种场景的沟通。
    3、不断升级AI运算技术能力,建立不同营销目的下的流量协同过滤模型,实时进行流量优选,实现不同场景下的流量的高效使用。另外,从触达、互动到消费、忠诚,全面升级消费者各阶段的沟通体验,增值企业消费者数字资产。

    解决方案
    1、利用DLA+ OSS极致分析能力来应对业务波峰波谷。一方面轻松应对来自品牌客户的临时分析。另一方面利用DLA的强大计算能力,分析按月、季度广告投放,精确计算出一个品牌下面会有多少个活动,每个活动分媒体,分市场,分频道,分DMP的投放效果,进一步增强了加和智能流量平台为品牌营销带来的销售转化率。
    2、DLA提供的Serverless的弹性服务为按需收费,不需要购买固定的资源,完全契合业务潮汐带来的资源波动,满足弹性的分析需求,同时极大地降低了运维成本和使用成本。

    客户价值
    为客户的智能流量平台提供了性价比极高的处理方案。
    1、相对性价比提升30%,无需专门维护人员,按量付费,成本低。
    2、临时业务需求承接率提升200%~300%。
    3、即需即用,准备成本低,响应快速。平均任务耗时降低67%。
    4、代码通用,支持数据业务无缝迁移。
    5、海量资源存储在OSS上,对业务支撑效果超过自建平台。
    6、计费简明,业务成本方便计算。

    ]]>
    MySQL死锁系列-线上死锁问题排查思路-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 前言

    MySQL 死锁异常是我们经常会遇到的线上异常类别,一旦线上业务日间复杂,各种业务操作之间往往会产生锁冲突,有些会导致死锁异常。这种死锁异常一般要在特定时间特定数据和特定业务操作才会复现,并且分析解决时还需要了解 MySQL 锁冲突相关知识,所以一般遇到这些偶尔出现的死锁异常,往往一时没有头绪,不好处理。

    本篇文章会讲解一下如果线上发生了死锁异常,如何去排查和处理。除了系列前文讲解的有关加锁和锁冲突的原理还,还需要对 MySQl 死锁日志和 binlog 日志进行分析。

    线上死锁异常分析

    正文

    日常工作中,应对各类线上异常都要有我们自己的 SOP (标准作业流程) ,这样不仅能够提高自己的处理问题效率,也有助于将好的处理流程推广到团队,提高团队的整体处理异常能力。

    所以,面对线上偶发的 MySQL 死锁问题,我的排查处理过程如下:

    1. 线上错误日志报警发现死锁异常
    2. 查看错误日志的堆栈信息
    3. 查看 MySQL 死锁相关的日志
    4. 根据 binlog 查看死锁相关事务的执行内容
    5. 根据上述信息找出两个相互死锁的事务执行的 SQL 操作,根据本系列介绍的锁相关理论知识,进行分析推断死锁原因
    6. 修改业务代码

    根据1,2步骤可以找到死锁异常时进行回滚事务的具体业务,也就能够找到该事务执行的 SQL 语句。然后我们需要通过 3,4步骤找到死锁异常时另外一个事务,也就是最终获得锁的事务所执行的 SQL 语句,然后再进行锁冲突相关的分析。

    第一二步的线上错误日志和堆栈信息一般比较容易获得,第五步的分析 SQL 锁冲突原因中涉及的锁相关的理论在系列文章中都有介绍,没有了解的同学可以自行去阅读以下。

    下面我们就来重点说一下其中的第三四步骤,也就是如何查看死锁日志和 binlog 日志来找到死锁相关的 SQL 操作。

    死锁日志的获取

    发生死锁异常后,我们可以直接使用 show engine innodb status 命令获取死锁信息,但是该命令只能获取最近一次的死锁信息。所以,我们可以通过开启 InnoDB 的监控机制来获取实时的死锁信息,它会周期性(每隔 15 秒)打印 InnoDb 的运行状态到 mysqld 服务的错误日志文件中。

    InnoDb 的监控较为重要的有标准监控(Standard InnoDB Monitor)和 锁监控(InnoDB Lock Monitor),通过对应的系统参数可以将其开启。

    -- 开启标准监控
    set GLOBAL innodb_status_output=ON;
    -- 关闭标准监控
    set GLOBAL innodb_status_output=OFF;
    -- 开启锁监控
    set GLOBAL innodb_status_output_locks=ON;
    -- 关闭锁监控
    set GLOBAL innodb_status_output_locks=OFF;

    另外,MySQL 提供了一个系统参数 innodb_print_all_deadlocks 专门用于记录死锁日志,当发生死锁时,死锁日志会记录到 MySQL 的错误日志文件中。

    set GLOBAL innodb_print_all_deadlocks=ON;

    死锁日志的分析

    通过上述手段,我们可以拿到死锁日志,下图是我做实验触发死锁异常时获取的日志(省略的部分信息)。

    该日志会列出死锁发生的时间,死锁相关的事务,并显示出两个事务(可惜,多事务发生死锁时,也只显示两个事务)在发生死锁时执行的 SQL 语句、持有或等待的锁信息和最终回滚的事务

    下面,我们来一段一段的解读该日志中给出的信息,我们按照图中标注的顺序来介绍:

    TRANSACTION 2078, ACTIVE 74 sec starting index read // -1 事务一的基础信息,包括事务ID、活跃时间,当前运行状态

    表示的是 ACTIVE 74 sec 表示事务活动时间,starting index read 为事务当前正在运行的状态,可能的事务状态有:fetching rows,updating,deleting,inserting, starting index read 等状态。

    mysql tables in use 1, locked 1  // -2 使用一个table,并且有一个表锁
    LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1  // -3 涉及的锁结构和内存大小 

    tables in use 1 表示有一个表被使用,locked 1 表示有一个表锁。LOCK WAIT 表示事务正在等待锁,3 lock struct(s) 表示该事务的锁链表的长度为 3,每个链表节点代表该事务持有的一个锁结构,包括表锁,记录锁或 autoinc 锁等。heap size 1136 为事务分配的锁堆内存大小。

    2 row lock(s) 表示当前事务持有的行锁个数,通过遍历上面提到的 11 个锁结构,找出其中类型为 LOCK_REC 的记录数。undo log entries 1 表示当前事务有 1 个 undo log 记录,说明该事务已经更新了 1条记录。

    下面就是死锁日志中最为重要的持有或者待获取锁信息,如图中-5和-6行所示,通过它可以分析锁的具体类型和涉及的表,这些信息能辅助你按照系列文章的锁相关的知识来分析 SQL 的锁冲突

    RECORD LOCKS space id 2 page no 4 n bits 80 index PRIMARY of table `test`.`t` trx id 2078 lock_mode X locks rec but not gap  // -5 具体持有锁的信息
    RECORD LOCKS space id 2 page no 4 n bits 80 index PRIMARY of table `test`.`t` trx id 2078 lock_mode X locks rec but not gap waiting // -6 等待获取锁的信息

    《锁类型和加锁原理》 一文中我们说过,一共有四种类型的行锁:记录锁,间隙锁,Next-key 锁和插入意向锁。这四种锁对应的死锁日志各不相同,如下:

    • 记录锁(LOCK_REC_NOT_GAP): lock_mode X locks rec but not gap
    • 间隙锁(LOCK_GAP): lock_mode X locks gap before rec
    • Next-key 锁(LOCK_ORNIDARY): lock_mode X
    • 插入意向锁(LOCK_INSERT_INTENTION): lock_mode X locks gap before rec insert intention

    所以,按照死锁日志,我们发现事务一持有了 test.t 表上的记录锁,并且等待另一个记录锁。

    通过死锁日志,我们可以找到最终获得锁事务最后执行的 SQL,但是如果该事务执行了多条 SQL,这些信息就可能不够用的啦,我们需要完整的了解该事务所有执行的 SQL语句。这时,我们就需要从 binlog 日志中获取。

    binlog的获取和分析

    binlog 日志会完整记录事务执行的所有 SQL,借助它,我们就能找到最终获取锁事务所执行的全部 SQL。然后再进行具体的锁冲突分析。

    我们可以使用 MySQL 的命令行工具 Mysqlbinlog 远程获取线上数据库的 binlog 日志。具体命令如下所示:

    Mysqlbinlog -h127.0.0.1 -u root -p --read-from-remote-server binlog.000001 --base64-output=decode-rows -v

    其中 --base64-output=decode-rows 表示 row 模式 binlog日志,所以该方法只适用于 row 模式的 binlog日志,但是目前主流 MySQL 运维也都是把 binlog 日志设置为 row 模式,所以这点限制也就无伤大雅。-v 则表示将行事件重构成被注释掉的伪SQL语句。

    我们可以通过死锁日志中死锁发生的具体事件和最终获取锁事务正在执行的SQL的参数信息找到 binlog 中该事务的对应信息,比如我们可以直接通过死锁日志截图中的具体的时间 10点57分和 Tom1、Teddy2 等 SQL 的具体数据信息在 binlog 找到对应的位置,具体如下图所示。

    根据 binlog 的具体信息,我们可以清晰的找到最终获取锁事务所执行的所有 SQL 语句,也就能找到其对应的业务代码,接下来我们就能进行具体的锁冲突分析。

    小节

    死锁系列终于告一段落,如果大伙有什么疑问或者文中有什么错误,欢迎在下方留言讨论。也希望大家继续持续关注。

    个人博客,欢迎来玩

    ]]>
    【升级】10月消息队列MQ升级计划通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【消息队列MQ】【升级通知】

    升级窗口:

    北京时间2020年10月14日 22:00 - 2020年10月15日 04:00

    北京时间2020年10月21日 22:00 - 2020年10月22日 04:00

    北京时间2020年10月28日 22:00 - 2020年10月29日 04:00

    升级内容:所有地域的MQ服务(包含TCP、MQTT、HTTP接入方式)。

    升级影响:升级期间MQ控制台和集群中每个服务节点可能出现秒级闪断(闪断时间和集群规模正相关),客户端会自动重试机制,一般不会影响业务,但会有异常日志。

    升级期间,消息可能会有重复,应用应该按最值实践,做好消息的幂等;同时可能会有消息延迟的现象。如需在控制台进行管理操作,请避开维护时间段。HTTP接入可能会出现闪断或者拒绝连接现象,每次闪断或拒绝连接不会超过1分钟,请在客户端中做好重连重试机制。同时,您可使用监控管理功能对重要业务进行监控,具体设置方法请点击MQ控制台左侧监控报警菜单。

    给您带来的不便敬请谅解,有任何问题,可点击联系我们进行咨询反馈。

    ]]>
    【升级】10月13日Donuts注册局维护通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【域名】【Donuts注册局维护通知】

    维护时间:北京时间2020年10月13日 20:00-22:00

    维护内容:接到注册局的通知,注册局 / 注册商将于上述时间对后台系统进行维护升级。

    维护影响:届时 .chat 域名的注册、续费、信息修改和查询域名注册信息等操作,将会无法使用,在此期间会对您造成的影响如下:

    1、您提交的注册(购买)、续费、转入、赎回、一口价域名业务在支付费用后状态为“处理中”,待维护结束后将变为正常的“成功”状态;

    2、维护过程中您无法对域名注册信息进行修改,将提示修改失败。

    如果您需要注册或管理以上业务操作,建议您避开该时间段,以免给您的业务造成影响。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    【升级】堡垒机升级通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【堡垒机】【升级通知】

    1、升级窗口:2020年10月10日-11月30日 ;

    2、升级区域:升级国内站、国际站区域

    3、升级内容:

    堡垒机产品V3.2.10版本升级至V3.2.13版本,V3.2.13版本在系统架构、用户/主机配置、双因子手机号、支持语言等均进行了优化升级:  

    1)系统架构:支持高可用的双节点版本,提供带宽扩展包

    2)主机/用户配置:新建主机或用户可直接指定到相应的组

    3)用户向导:新增用户向导功能,更迅速的配置使用

    4)双因子手机号新增德国、澳洲、美东、美西、迪拜、东京、英国、印度、中国澳门的手机号码

    5)主机配置:标记已经释放的ecs,详细区分主机账号的报错信息

    6)维护功能:支持tcp端口检测

    4、升级方式:系统自动升级到最新版本

    5、升级影响:需要您提前断开正在运维的会话,保存会话数据

    ]]>
    【其他】8月28日边缘容器服务商业化通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【边缘容器服务】【商业化通知】

    商业化时间:

    北京时间2020年8月28日 14:30
    商业化内容:

    阿里云边缘容器服务已于2020年8月28日正式转商用化。

    边缘容器服务基于标准Kubernetes运行环境,提供Kubernetes 集群云端托管、边缘计算业务高度自治的能力。通过将边缘算力快速接入、统一管理、统一运维,轻松实现云边一体化协同的容器应用交付、运维和管控。

    商用后收费模式请参考产品计费文档:https://help.aliyun.com/document_detail/178718.htm

    关于边缘容器服务:https://help.aliyun.com/document_detail/124723.html


    ]]>
    【其他】9月29日ESSD PL0规格云盘商业化通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【ESSD PL0】【商业化通知】

    阿里云ESSD PL0规格云盘已经结束公测,于2020年9月29日正式商业化上线。此次上线的ESSD PL0规格云盘拥有最低百微秒时延,最大10000的IOPS,并且支持无损变配至ESSD系列其他规格。详细功能介绍以及价格信息请参考官网介绍

    ]]>
    【其他】10月23日ACK Pro商业化通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【ACK Pro】【商业化】

    商业化时间:

    北京时间2020年10月23日00:00

    商业化内容:

    容器服务ACK Pro版集群将于2020年10月23日00:00正式转为商用。针对许多对于生产环境有着高稳定性和高安全性要求的企业客户,ACK Pro版集群在ACK托管版集群的基础上进一步增强了可靠性、安全性,并且提供可赔付的SLA。

    转商用后定价计费请点此查看

    了解ACK Pro请点此查看


    ]]>
    【其他】商标局国庆/中秋期间服务器维护停止商标审核/递交申请通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【商标】【商标局国庆/中秋期间服务器维护停止商标审核/递交申请通知】

    维护时间:北京时间2020年10月1日-8日

    维护内容:因商标局国庆/中秋假期服务器维护,阿里云商标服务将于北京时间2020年10月1日-8日停止商标订单审核、递交商标申请。

    维护影响:阿里云商标服务将于2020年9月30日16:00停止递交商标注册申请,届时对您产生的影响包括:

    1、2020年9月30日16:00之后审核通过的订单将顺延至2020年10月9日递交;

    2、2020年9月30日递交的申请回执(申请号)将顺延至2020年10月9日后同步到订单中;

    3、2020年9月30日提交审核的商标订单将顺延至2020年10月9日开始审核

    在此期间购买阿里云商标服务、填写订单、支付费用及补齐材料等不受影响。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    【其他】OpenAPI相关服务IP变更计划通知 Thu, 29 Oct 2020 12:16:14 +0800 【阿里云】【OpenAPI】【变更通知】

    变更窗口:

    北京时间2020年10月20日 00:00 - 2020年11月1号00:00

    变更内容:华北1(青岛)、华北2(北京)、华北3(张家口)、华北5(呼和浩特)、华东1(杭州)、华东2(上海)、华南1(深圳)、华东2金融云、华南1金融云、华北2政务云、香港、亚太东南1(新加坡)、亚太东南2(悉尼)、亚太东南5(雅加达)、亚太南部1(孟买)、中东东部1(迪拜)、欧洲中部1(法兰克福)、美国东部1(弗吉尼亚)、美国西部1(硅谷)、英国(伦敦)等地域的OpenAPI服务IP变更。

    变更影响:OpenAPI旧的的服务IP将下线不可用,如果您所负责的应用或安全策略中有涉及到硬编码阿里云OpenAPI的服务IP,请在变更前及时修改,以免变更后影响应用的正常运行。

    给您带来的不便敬请谅解,有任何问题,可随时通过工单或服务电话95187联系反馈。

    特别提醒:OpenAPI各服务的IP不定时会有变动,请不要以任务形式绑定固定IP,包括(不限于)自定义DNS、添加Hosts绑定、在安全组策略中绑定等行为,以免IP变动时对业务造成影响

    ]]>
    【升级】9月20日 .COM/.NET域名注册局系统维护通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【域名】【注册局维护通知】

    维护时间:北京时间2020年9月20日 09:00 - 09:45

    维护内容:接到注册局的通知,注册局将于上述时间对后台系统进行维护升级。

    维护影响:届时 .com/.net 域名的注册、续费、信息修改和查询域名注册信息等操作,将会无法使用,在此期间会对您造成的影响如下:

    1、您提交的注册(购买)、续费、转入、赎回、一口价域名业务在支付费用后状态为“处理中”,待维护结束后将变为正常的“成功”状态;

    2、维护过程中您无法对域名注册信息进行修改,将提示修改失败。

    如果您需要注册或管理以上业务操作,建议您避开该时间段,以免给您的业务造成影响。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    【升级】9月22日MMX注册局维护通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【域名】【MMX注册局维护通知】

    维护时间:北京时间 2020年9月22日 13:00 - 15:00

    维护内容:接到注册局的通知,注册局将于上述时间对后台系统进行维护升级。

    维护影响:届时 .Vip/.Work/.Beer/.Luxe/.Fit/.Yoga 域名的注册、续费、信息修改和查询域名注册信息等操作,将会无法使用,在此期间会对您造成的影响如下:

    1、您提交的注册(购买)、续费、转入、赎回、一口价域名业务在支付费用后状态为“处理中”,待维护结束后将变为正常的“成功”状态;

    2、维护过程中您无法对域名注册信息进行修改,将提示修改失败。

    如果您需要注册或管理以上业务操作,建议您避开该时间段,以免给您的业务造成影响。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    【升级】9月29日Donuts注册局维护通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【域名】【Donuts注册局维护通知】

    维护时间:北京时间2020年9月29日 01:00-2:30

    维护内容:接到注册局的通知,注册局 / 注册商将于上述时间对后台系统进行维护升级。

    维护影响:届时,您的 .ltd/.group/.pub/.live/.rocks/.band/.market/.software/.social/.lawyer/.engineer/.news/.video/.studio/.today /.plus/.world/.run/.show/.city/.gold/.today/.cool/.zone/.chat/.company/.企业/.游戏 等域名的续费、转入转出、信息修改和过户域名等操作,将会无法使用,在此期间会对您造成的影响如下:

    1、您提交的续费、转入、转出域名等操作在支付费用后状态为“处理中”,且可能出现“不成功”等状态;

    2、维护过程中您无法对域名注册信息进行修改,将提示修改失败。

    如果您需要注册或管理以上业务操作,建议您避开该时间段,以免给您的业务造成影响。

    如您的业务操作失败,建议维护后再次尝试。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    【升级】9月25日消息队列AMQP升级通知 Thu, 29 Oct 2020 12:16:14 +0800

    【阿里云】【消息队列AMQP】【升级通知】

    升级窗口:北京时间2020年9月25日 00:00 -  03:00

    升级内容:华北1(青岛)、华北2(北京)、华北3(张家口)、华北5(呼和浩特)、华东1(杭州)、华东2(上海)、华南1(深圳)、香港等全部地域(及铂金版)的服务升级。

    升级影响:升级期间消息队列AMQP相关服务访问可能会出现多次闪断或者拒绝连接现象,每次闪断或拒绝连接不会超过 5 分钟,请在客户端中做好重连重试机制。如需在控制台进行管理操作,请避开维护时间段。

    给您带来的不便敬请谅解,有任何问题,可点击联系我们进行咨询反馈。

    ]]>
    【漏洞预警】FastAdmin 远程代码执行0day漏洞 Thu, 29 Oct 2020 12:16:14 +0800

    2020年9月22日,阿里云应急响应中心监测到FastAdmin爆发远程代码执行0day漏洞,黑客登录前台会员中心,即可远程GetShell,风险极大。


    漏洞描述

    FastAdmin是一款基于ThinkPHP和Bootstrap的后台开发框架、开放会员中心的站点,上传特定文件可直接GetShell。阿里云应急响应中心提醒FastAdmin用户尽快采取安全措施阻止漏洞攻击。


    影响版本

    全版本(截止2020年9月22日官方暂未发布安全补丁或修复版本)


    漏洞评级

    严重


    安全建议

    1、关闭站点会员中心功能,在/application/config.php文件中,设置'usercenter' => false

    2、暂时关闭文件上传功能


    相关链接

    https://github.com/karsonzhang/fastadmin/issues/73



    我们会关注后续进展,请随时关注官方公告。

    如有任何问题,可随时通过工单联系反馈。

    阿里云应急响应中心

    2020.9.22

    ]]>
    【漏洞预警】Linux内核AF_PACKET内存破坏导致权限提升漏洞(CVE-2020-14386) Thu, 29 Oct 2020 12:16:14 +0800

    近日,阿里云应急响应中心监测到Openwall社区披露一个Linux内核AF_PACKET原生套接字内存破坏漏洞,该漏洞出现在net/packet/af_packet.c中,由整数溢出导致越界写,可以通过它进行权限提升。该漏洞危害评级为高,编号为CVE-2020-14386。


    漏洞描述

    Linux发行版高于4.6的内核版本net/packet/af_packet.c中,在处理AF_PACKET时存在整数溢出漏洞,可以通过它进行权限提升。阿里云应急响应中心提醒用户尽快采取安全措施阻止漏洞攻击。


    受影响Linux发行版系统

    1、Ubuntu Bionic (18.04) 及后续的版本

    2、Debian 9/10

    3、CentOS 8/RHEL 8


    漏洞评级

    CVE-2020-14386  高危


    安全建议

    1、升级内核至安全版本

    2、禁用CAP_NET_RAW功能

    3、阿里云云安全中心Linux软件漏洞模块已支持对该漏洞一键检测和修复,详情登陆云安全中心





    相关链接

    https://www.openwall.com/lists/oss-security/2020/09/03/3

    https://github.com/cgwalters/cve-2020-14386

    https://sysdig.com/blog/cve-2020-14386-falco/



    我们会关注后续进展,请随时关注官方公告。

    如有任何问题,可随时通过工单联系反馈。

    阿里云应急响应中心

    2020.9.22

    ]]>
    魔橙科技赋能商业银行,推动区块链金融场景应用落地-阿里云开发者社区 Thu, 29 Oct 2020 12:16:14 +0800 在魔橙科技CEO陈敏涛看来,区块链技术是以数据加密、时间戳和分布式共识算法为依托,实现链式存储、智能合约和隐私保护等高级功能的分布式账本技术。区块链技术更像数据库和操作系统,是IT基础产业,是下一代互联网的基础设施,是一个未来技术的发展路径。快速发展的区块链技术被认为是可以用于解决新一代互联网价值交换问题以及网络传输的信用问题。

    他认为,区块链技术并非单纯点对点和去中心化。区块链技术的出现会让整个传统互联网平台更加可信、更加透明、更加公平。目前使用区块链技术提供的应用程序,更加互联网化,更加强调公平与双向激励,方便每个人参与进来,分享生态的成果,这才是最好的商业模式。

    魔橙在应用场景中实现有效“信用传递”
    区块链技术的落地就是在一个没有中心的业务模式中,帮助多方建立跨主体的信任环境,否则区块链技术可能并不是最好的解决方案。实际上,区块链技术是一个由所有节点共同维护、共同记账的“公共大账本”。

    魔橙科技独创的联盟链底层技术,结合了多个共识算法优势,实现可伸缩的网络节点准入机制,允许多重共识组合相互切换。极大降低区块链网络开发成本,使得商用网络在构建及运营阶段更加灵活可控,规避了因需求调整带来的潜在风险。

    核心模块包含:高性能共识算法,可伸缩节点,跨共识引擎及链上治理机制等
    魔橙联盟链底层技术.png

    通过区块链底层混沌系统,能够确保参与联盟链共建节点的完全可控性,保证联盟链整体运营的稳定。链上数据公开,联盟见证者可通过区块链浏览器对所有链上数据查询,保证了联盟链的数据公开完整及数据公平。在实际企业项目中,魔橙联盟链能够基于丰富行业应用经验,并结合联盟链的底层技术,以及数据隐私保护和多方安全技术等应用框架的构建,适用于想通过区块链改进商业应用性能的商业需求。

    与银行如何擦出火花?
    金融一直被认为是区块链最合适的落地场景之一,在魔橙的合作方中有不少是大型银行、城商行以及券商。

    在说到区块链应用的细分赛道时,陈敏涛坦言,供应链金融对魔橙来说是很重要的一个主推方向。2020年年初,魔橙参与服务世界500强商业银行的项目中。在该项目中,魔橙提供了结合业务应用场景的整体解决方案,在根据银行单一应用场景细化实现方式。因为是创新技术在金融领域的试点,项目采用敏捷方式开展实施,快速迭代如期交付。(因合作方要求,对于合作银行名字予以保密)

    据魔橙科技负责该项目的总监黄洋表示,在这个项目中,魔橙的主要作用是协同银行,基于“区块链+”模式重构银行生态系统,构建新型的区块链金融服务业务模式和拓展商业银行多类应用场景拓展。目前项目搭建基于区块链技术的微服务控制台系统,包含区块链服务接口、合约网关、安全合规、链上账户管理、智能合约管理;通用服务、可信存证、交易查询中心、通用监控,前端控制台等模块。

    “我们提供的是基础设施,让客户基于我们的服务,去做自己的金融服务,目的是让他们用魔橙的区块链。同时,供应链金融一个很大的特性是参与方越多越好,而且不同参与方的链与链之间是有交集的,最终市场将形成网状。”黄洋表示,魔橙的愿景是,通过底层,把所有的核心企业、上下游企业、金融机构,包括保理,券商之类的企业链接在一起,他们做他们的业务,我们降低他们的交易和信任成本。只要规模做大了,就是魔橙的诉求。
    **
    魔橙的目标和定位是什么**

    区块链是个基础设施,最终市场上同类企业不会太多,做底层技术的也不会有几家,但是在这个基础设施上做应用的公司非常多。我们要把基础设施做好,目的是让其他业务公司用我们的区块链。

    每个行业都是有门槛的,但是以技术为依托,我们会有很多合作伙伴,魔橙会和行业专家一起做事情,争取行业的支持。2020年7月,魔橙与复旦大学、上海海事大学、上海海洋大学联合研发推出“跨境贸易风险监测与可信溯源”平台正式上线。

    接下来,魔橙科技将与更多金融机构共建跨产业、跨机构的数字经济新模式,实现真正意义上的产业数字化。

    ]]>
    阿里云小程序PHP环境怎么搭建-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 最近想着阿里云能不能搭建小程序官方的demo,之前用过基于腾迅云的小程序解决方案,虽然很好,但夸何没有在腾迅云注册备案过域名,而曾经在阿里云上注册备案过域名.本文主要和大家分享阿里云如何搭建小程序PHP环境,希望能帮助到大家。image.png
    现在立即选购赠送3000元大礼包

    基本环境 CentOS 7.3
    (一)安装 Nginx

    yum -y install nginx

    查看是否安装成功

    nginx -v

    如果安装成功则显示

    (二)安装 PHP
    Wafer 的 Demo 需要 5.6 以上版本的 PHP,添加 remi 源.

    wget 'https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi.repo' -O /etc/yum.repos.d/remi.repo

    查看是否安装成功

    php -v

    php版本要大于5.6
    (三)配置 Nginx 和 HTTPS
    申请一个 SSL 证书,可以到阿里云申请免费的 SSL 证书,申请成功之后下载证书,并把压缩包中 Nginx 目录下的证书文件上传到服务器的 /data/release/nginx 目录,如果没有这个目录则新建:上传完证书以后,配置 Nginx,进入服务器的 /etc/nginx/conf.d 目录,新建一个 weapp.conf 文件,内容为以下,注意(www.xx.com改为自己的域名,1_www.xx.com_budle.crt和2_www.xx.com.key分别改为自己的证书文件)

    # 重定向 http 到 https
    
    www.xx.com
    server { listen 80; server_name www.xx.com; rewrite ^(.*)$ https://$server_name$1 permanent;}server { listen 443; server_name www.xx.com; ssl on; ssl_certificate /data/release/nginx/1_www.xx.com_bundle.crt; ssl_certificate_key /data/release/nginx/2_www.xx.com.key; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA; ssl_session_cache shared:SSL:50m; ssl_prefer_server_ciphers on; root /data/release/php-demo; location ~ .php$ { root /data/release/php-demo; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location /weapp/ { root /data/release/php-demo; index index.html index.htm index.php; try_files $uri $uri/ /index.php; }}

    运行nginx

    nginx -t

    (四)安装mysql
    安装mysql5.7

    1、配置YUM源

    下载mysql源安装包

    wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm

    安装mysql源

    yum localinstall mysql57-community-release-el7-8.noarch.rpm

    检查mysql源是否安装成功
    yum repolist enabled | grep "mysql.-community."
    image.png

    2、安装MySQL

    yum install mysql-community-server

    3、启动MySQL服务

    systemctl start mysqld

    查看MySQL的启动状态
    shell> systemctl status mysqld
    image.png

    4、开机启动

    systemctl enable mysqld
    systemctl daemon-reload

    5、修改root本地登录密码

    mysql安装完成之后,在/var/log/mysqld.log文件中给root生成了一个默认密码。通过下面的方式找到root默认密码,然后登录mysql进行修改:
    grep 'temporary password' /var/log/mysqld.log

    登陆并修改默认密码
    mysql -u root -p

    mysql>ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码!';

    新建一个数据库名为 cAuth,排序规则为 utf8mb4_unicode_ci,小程序后台用到
    mysql>CREATE DATABASE IF NOT EXISTS cAuth,排序规则为 DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;
    image.png
    (五)上传 Demo 和启动
    到 wafer2-quickstart-php 仓库下载最新的 Demo 代码,修改 server/config.php:

    <?php/**

    Wafer php demo 配置文件
    */$config = [ 'rootPath' => '', // 微信小程序 AppID

    'appId' => '', // 微信小程序 AppSecret
    'appSecret' => '', // 使用腾讯云代理登录
    'useQcloudLogin' => false, //不使用腾迅云代理登录 /**

    这里请填写云数据库的
    */
    'mysql' => [ 'host' => 'localhost', 'port' => 3306, 'user' => 'root', 'db' => 'cAuth', 'pass' => '数据库密码', 'char' => 'utf8mb4'
    ], 'cos' => [ /**

    区域上海:cn-east广州:cn-sorth北京:cn-north广州二区:cn-south-2成都:cn-southwest新加坡:sg@see https://cloud.tencent.com/document/product/436/6224
    */

    'region' => 'cn-sorth', // Bucket 名称

    'fileBucket' => 'wafer', // 文件夹
    'uploadFolder' => ''

    ], // 微信登录态有效期
    'wxLoginExpires' => 7200, 'wxMessageToken' => 'abcdefgh', // 其他配置
    'serverHost' => 'wx.wafersolution.com', 'tunnelServerUrl' => 'http://tunnel.ws.qcloud.la', 'tunnelSignatureKey' => '27fb7d1c161b7ca52d73cce0f1d833f9f5b5ec89', // 腾讯云相关配置可以查看云 API 秘钥控制台:https://console.cloud.tencent.com/capi
    'qcloudAppId' => 1200000000,// 必须是数字
    'qcloudSecretId' => '你的腾讯云 SecretId', 'qcloudSecretKey' => '你的腾讯云 SecretKey', 'networkTimeout' => 30000];

    接着将 server 目录下的所有文件都上传到 /data/release/weapp/php-demo 目录下:

    相关推荐:

    linux下apache重启并查看php环境

    PHP环境配置

    LNMP环境搭建(一)搭建PHP环境

    以上就是阿里云如何搭建小程序PHP环境的详细内容。

    云服务器ECS地址:链接地址
    阿里云2000元通用代金券:点击领取

    ]]>
    9.25直播预告|如何0基础获得Apache Cassandra Administrator国际认证?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 本周五(9月25号)下午4点不见不散哦~
    • 本期直播主题:如何0基础获得Apache Cassandra Administrator国际认证?
    • 直播时间:9月25号(周五)16:00-17:00
    • 直播讲师:米诺|阿里云NoSQL数据库产品专家
    • 直播简介:Apache Cassandra在宽表数据库流行度中持续8+年排第一,已成为国内外流行度最高的宽表数据库。本次技术直播将为您分享0基础拿Cassandra Administrator国际认证的考试经验。

    参与方式:

    钉钉扫描下方海报二维码进群观看直播
    米诺.png

    ]]>
    传统服务器和ECS区别-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 传统服务器:

    金钱成本 服务周期

    资源限制 人力投入

    阿里云ECS服务器:

    根据企业运行环境按需购买

    数据多次备份

    超A级数据中心--双路独市电,三路网络,N+1柴油发电机后备电源

    自动化运维自动迁移到其他物理机 ----稳定性和联系性

    云盾----安全防护

    将企业数据库资源,存储资源,计算资源打通,连接资源孤岛,应用孤岛,数据孤岛,全局快速进行市场洞察

    ]]>
    ECS训练营-第一天-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 ECS训练营-第一天

    今天完成了6个课程,首先了解了什么是ECS(elastic compute service),然后创建了服务器实例,安装CentOS系统,用ssh远程连接了系统,完成了Apache、SQL的安装。
    image.png

    ]]>
    Class 4 使用PolarDB和ECS搭建门户网站-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 使用PolarDB和ECS搭建门户网站

    1.创建资源

    1. 在页面左侧,单击 云产品资源 下拉菜单,查看本次实验资源。
    2. 单击 免费开通 创建所需资源。

    1-01.png

    资源创建过程需要1~3分钟。完成实验资源的创建后,您可以在 云产品资源 列表查看已创建的资源信息,例如:IP地址、用户名和密码等。

    2.创建PolarDB数据库账号

    1. 单击页面左侧 云产品资源 > 一键复制登录url

    4-02.png

    1. 打开浏览器隐身窗口(无痕模式),粘贴已复制的url地址前往 RAM用户登录 界面,登录 阿里云管理控制台

    以Chrome浏览器为例,打开新的无痕窗口,登录 阿里云管理控制台

    1. 依次单击更多>打开新的无痕窗口。
    2. 在地址栏粘贴登录url,访问 RAM用户 登录页面
    3. 在登录用户名称处,输入 子用户名称 ,单击 下一步
    4. 输入密码,单击 登录 进入 阿里云管理控制台
    1. 阿里云控制台首页 左侧导航栏,依次单击 产品与服务 > 云数据库PolarDB ,进入 云数据库PolarDB管理控制台

    4-03.png

    1. 单击左侧 集群列表 ,然后选择云产品资源提供的地域。例如:华东2(上海)

    4-04.png

    1. 创建数据库账号。

      1. 集群列表 页面,单击 集群ID ,进入 集群详情界面

    4-05.png

    1. 单击左侧导航栏 配置与管理 > 账号管理
    2. 单击左上方 创建账号

    4-06.png

    1. 参考说明配置账号信息,然后单击 确定

    4-07.png

    • 数据库账号:输入数据库账号名称,例如:test_user 。
    • 账号类型:此处选择普通账号。
    • 密码:设置账号密码,例如:Password1213。
    • 确认密码:再次输入密码。
    1. 创建数据库。

      1. 在实例详情页,单击左侧导航栏的 数据库管理 ,然后单击 创建数据库

    4-08.png

    1. 参考说明配置数据库信息,然后单击 创建

    4-09.png

    • 数据库(DB)名称:输入数据库名称,例如:pbootcms 。
    • 支持字符集:默认设为utf8mb4。
    • 授权账号:选择上一步创建的数据库账号test_user。
    • 账号类型:默认设置为读写。
    • 备注说明:非必填。用于备注该数据库的相关信息,便于后续数据库管理,最多支持256个字符。
    1. 设置数据库白名单。

    连接数据库需要设置数据库白名单,点击 [集群白名单],然后点击 [设置] 设置数据库集群白名单。

    4-10.png

    在白名单界面将默认的白名单地址127.0.0.1更改为 0.0.0.0/0,然后点击 [确定] 使白名单地址生效。

    4-11.png

    连接ECS服务器

    1. 打开终端工具。
    • Windows:打开命令窗口。
    • MAC:打开命令行终端Terminal。

    Windows用户请检查系统中是否安装有SSH工具。检查方法:

    在终端中输入命令 ssh -V 。

    ssh -V

    如果显示SSH版本则表示已安装,如下图所示。

    1-02.png

    如果未安装,请下载安装 OpenSSH工具。

    1. 在终端中输入连接命令 ssh [username]@[ipaddress] 。

    您需要将其中的username和ipaddress替换为步骤一中创建的ECS服务器的弹性公网IP。例如:

    ssh root@123.123.123.123

    4-12.png

    命令显示结果如下:

    2-03.png

    1. 输入 yes。
    2. 同意继续后将会提示输入登录密码。 密码为已创建的云服务的ECS的登录密码。

    2-04.png

    登录成功后会显示如下信息。

    2-05.png

    安装LAMP环境

    LAMP是指运行在Linux下的Apache、MySQL和PHP的环境。参考以下操作在云服务器上安装开发环境。

    1. 在ECS服务器上,执行以下命令安装Apache服务及其扩展包。
    yum -y install httpd httpd-manual mod_ssl mod_perl mod_auth_mysql

    返回类似如下图结果则表示安装成功。

    4-13.png

    1. PbootCMS是使用PHP语言开发的CMS系统。参考以下操作安装PHP环境。

    执行以下命令,安装PHP。

    yum -y install php php-mysql gd php-gd gd-devel php-xml php-common php-mbstring php-ldap php-pear php-xmlrpc php-imap
    1. 执行以下命令下载并安装MySQL。
    wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
    yum -y install mysql57-community-release-el7-10.noarch.rpm
    yum -y install mysql-community-server
    1. 执行以下命令启动MySQL数据库。
    systemctl start mysqld

    搭建门户网站

    在完成环境部署后,参考以下操作搭建门户网站。

    1. 在ECS服务器上,执行以下命令,安装Git。
    yum -y install git
    1. 在ECS服务器上,执行以下命令下载PbootCMS源码文件。
    cd ~ && git clone https://gitee.com/hnaoyun/PbootCMS.git
    1. 执行以下命令将安装包拷贝到Apache的wwwroot目录下。
    cp -r PbootCMS/* /var/www/html/
    1. 执行以下命令修改站点根目录文件权限。
    chmod -R a+w /var/www/html
    1. 向数据库中导入CMS的初始数据。

    执行以下命令初始化数据库pbootcms的表结构和数据。

    说明: 在执行命令前,请修改一下三个参数。

    • 数据库连接地址参见集群详情页面下方链接地址板块。
    • test_user为步骤二中创建的数据库账号。
    • Password1213步骤二中创建的数据库密码。
    sql_file="/var/www/html/static/backup/sql/"$(ls /var/www/html/static/backup/sql/) &&
    mysql -h数据库连接地址 -utest_user -pPassword1213 -Dpbootcms < $sql_file
    1. 执行以下命令,修改CMS系统数据库配置。

    说明: 在执行命令前,请根据参数说明替换您的数据库配置。

    cat > /var/www/html/config/database.php << EOF
    <?php
    return array(
        'database' => array(
            'type' => 'mysqli', // 数据库连接驱动类型: mysqli,sqlite,pdo_mysql,pdo_sqlite
            'host' => '数据库连接地址', // PolarDB数据库链接地址
            'user' => 'test_user', // PolarDB数据库的用户名
            'passwd' => 'Password1213', // PolarDB数据库的密码
            'port' => '3306', // 数据库端口
            'dbname' => 'pbootcms' //数据库名称
        )
    );
    EOF
    1. 返回ECS控制台,在ECS实例列表页面,单击已创建的ECS实例ID链接进入ECS详情页。
    2. 在左侧导航栏,单击 本实例安全组 ,然后单击安全组的ID链接查看安全组配置。

    确保安全组开放了80端口访问,否则无法访问已搭建的门户网站。安全组是一种虚拟防火墙,具备状态检测和数据包过滤能力,用于在云端划分安全域。通过配置安全组规则,您可以控制安全组内一台或多台ECS实例的入流量和出流量。

    4-14.png

    1. 访问程序。

    执行以下命令重启 Apache服务。

    systemctl restart httpd

    在浏览器地址栏输入云服务器的公网IP地址,进入门户网站首页

    系统后台默认访问路径为http://<ECS公网IP地址>/admin.php。默认账号为admin,密码为123456

    至此您已完成门户网站的搭建,您可以根据公司的需求自定义门户网站的内容。

    4-15.png

    ]]>
    Class 5 搭建个人Leanote云笔记本-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 搭建个人Leanote云笔记本

    本教程将介绍如何搭建个人Leanote云笔记本。

    场景体验目标

    本场景将提供一台配置了CentOS 7.7的ECS实例(云服务器)。您可以参考本教程的操作基于已有的环境搭建一个Leanote云笔记本。

    背景知识

    Leanote是一款在线的云笔记应用,有如下特点:

    • 支持网页、PC、手机APP客户端和微信版,随时记录,方便分享,支持语音,图片输入。
    • 代码高亮,涵盖所有主流语言的代码高亮,随心所欲在Leanote里写代码,记知识。
    • Markdown 编辑器,实时同步预览。
    • 专业数学公式编辑,像Word和Latex能编辑数学公式。
    • 支持创建思维脑图,将散乱的想法以树状信息分层展示。
    • 详细历史纪录,每次保存都在后端备份,轻松查找,一键恢复。
    • 实时同步云端。

    1.创建资源

    1. 请点击页面左侧的 云产品资源,在下拉栏中,查看本次实验资源信息;
    2. 在资源下拉栏点击 免费开通 按钮,开始创建实验资源。

    1-01.png

    说明:资源创建过程需要1-3分钟。完成实验资源的创建后,用户可以通过 云产品资源 查看实验中所需的资源信息,例如:IP地址、用户名、密码等。

    2.连接ECS服务器

    1. 打开系统自带的终端工具。
    • Windows:CMD或Powershell。
    • MAC:Terminal。
    1. 在终端中输入连接命令ssh [username]@[ipaddress]。您需要将其中的username和ipaddress替换为第1小节中创建的ECS服务器的登录名和公网地址。例如:
    ssh root@123.123.123.123

    5-02.png

    命令显示结果如下:

    2-03.png

    1. 输入yes。
    2. 同意继续后将会提示输入登录密码。 密码为已创建的云服务的ECS的登录密码。

    2-04.png

    登录成功后会显示如下信息。

    2-05.png

    3.安装MongoDB

    MongoDB是一个基于分布式文件存储的高性能数据库,介于关系数据库和非关系数据库之间,它支持的数据结构非常松散是类似于json和bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

    Leanote云笔记使用MongoDB作为后端数据库,按照以下步骤按照MongoDB数据库。

    1. 执行以下命令,安装MongoDB。
    yum -y install mongodb mongodb-server.x86_64 mariadb-devel.i686
    1. 执行以下命令,启动MongoDB服务。
    systemctl start mongod
    1. 执行以下命令,查看MongoDB运行状态。
    systemctl status mongod

    5-03.png

    4.安装Leanote

    1. 下载Leanote二进制安装包。
    wget https://nchc.dl.sourceforge.net/project/leanote-bin/2.6.1/leanote-linux-amd64-v2.6.1.bin.tar.gz
    1. 解压安装包。
    tar -zxvf leanote-linux-amd64-v2.6.1.bin.tar.gz
    1. 编辑文件leanote/conf/app.conf,在文件中找到app.secret项,将该项的值改为任意字符串。(如不修改将会有安全风险)。

    说明: 根据Leanote官方文档,如不修改app.secret项的值,将会有安全隐患。

    1. 使用vim编辑器打开文件leanote/conf/app.conf。
    vim leanote/conf/app.conf
    1. 进入vim编辑器后,输入:/app.secret=并按下回车查找app.secret位置。
    2. 找到该项位置后按下i键进入编辑模式,修改该项的值为任意字符串。
    3. 修改完成后,按下esc键退出编辑模式,输入:wq保存并退出vim编辑器。

    修改后如图所示。

    5-04.png

    1. 初始化数据库。
    mongorestore -h localhost -d leanote --dir /root/leanote/mongodb_backup/leanote_install_data/
    1. 启动服务。
    nohup bash /root/leanote/bin/run.sh > /root/leanote/run.log 2>&1 &
    1. 访问云笔记。

    在浏览器中访问http://<ECS公网地址>:9000,请将<ECS公网地址>替换为左侧资源栏中的ECS公网IP地址。默认管理用户为admin,密码为abc123。登录成功后如下图所示。

    5-05.png

    ]]>
    ECS七天训练营入门笔记(1)-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 使用云计算的优势:
    1 无需采购硬件设备,按需购买资源;
    2 拥有至少50多种操作系统,轻松实现LAMP系统或者windows服务器;
    3购买简单配置灵活。
    阿里云计算的优点:
    1 多层次的备份;
    2 多路供电保证服务器无断电;
    3 云盾安全防护保障服务器安全;
    4 将数据库、存储和计算资源统一。

    ]]>
    ECS学习心得1-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 传统服务器具有价格高昂,采购周期长,资源闲置浪费率高,维护成本高的缺点。

    阿里云ECS覆盖50多款操作系统,包含开源LAMP组合和常见的Windows平台。

    包含传统x86服务器及GPU和FPGA的异构计算,包含通用型,内存型,网络增强型,本地SSD型和计算型,甚至企业级Oracle数据库所需的超大规格独占物理机,配置及使用更为灵活。

    ECS在底层对每份数据进行多次备份,物理层面拥有超A级数据中心,通过双路独市电引入、三路网络和N+1柴油发电机后备电源确保数据安全。

    ECS自动化运维将数据迁移到其他物理机,将数据恢复到故障前最后状态,屏蔽硬件故障同时保证业务稳定和连续。

    ECS可在底层打通企业数据库资源,存储资源和计算资源,联通传统IT烟囱式架构下的资源孤岛,应用孤岛和数据孤岛,提高信息整合能力。

    ]]>
    Class 6 案例分享——钉钉-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 Q:钉钉背后的技术架构是怎样的?应用了阿里云的哪些服务?
    A:钉钉作为一个企业级产品,使用了热门的平台技术SaaS。钉钉很多的设计都面向云去设计,这样产品可以随着云建设更快地部署,更多地适应客户需求。钉钉目前使用了ECS、OSS、OTS,未来还将用到Open Search。钉钉很多的数据都部署在阿里云的ECS上,因此数据也就存在RDS上,即阿里云的数据库,这些数据的安全,整体服务的可靠十分重要,阿里云已有的基础设施,符合钉钉对稳定性,对性能的要求。
    Q:可否具体谈谈使用云计算后为钉钉解决问题或者带来的价值?
    A:钉钉上有一个非常受客户喜欢的应用叫日志,通过日志。员工每天可以发日报、周报,也可以发一些月报,钉钉的模板是可以定制化的,适合每家公司对日志的要求。日志的整体服务,实际上就部署在阿里云的ECS,这是我们和一家ISV共同开发的。如果没有阿里云,那整个数据的安全性,以及整体服务的稳定性都存在疑问,随着用户量不断增大,整个架构能不能水平扩容,都会有很大的担忧。
    Q:企业级用户对应用的安全性有更高的要求,钉钉如何介入阿里云保障企业信息安全?
    A:我们把安全作为钉钉的一个重要功能来设计和保障,首先从信息的存储、传输,无论是在客户端的存储还是在服务端的存储,我们都采用了最高的加密程序,对它进行加密,首先我们阿里云的基础设施安全,提供了很周全的防护,包括黑客攻击。包括DDoS攻击等,保障了网站的稳定性,阿里云这些安全方面的产品,实际上给钉钉节省了很多工作,我们不需要再担心主机被第三方,破解账号登录的问题了,我们能花费更多的时间去考虑怎样让我们的产品变得更安全。

    ]]>
    在ECS上部署门户网站-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800
  • 根据PolarDB官方文档创建一个数据库集群,并设置白名单为ECS IP.
  • 然后在ECS上使用LAMP一键安装,安装的时候选择MySQL5.7版本的数据库.
  • 通过git下载PbootCM的源码并放到Apache的wwwroot目录下,并对这些文件加上所有人都可以写的权限.
    然后导入CMS的初始数据:
  • $ sql_file="/var/www/html/static/backup/sql/"$(ls /var/www/html/static/backup/sql/) &&
    mysql -h数据库连接地址 -utest_user -pPassword1213 -Dpbootcms < $sql_file
    1. 修改CMS的数据库配置,使用PolarDB数据库:
    $ cat > /var/www/html/config/database.php << EOF
    <?php
    return array(
        'database' => array(
            'type' => 'mysqli', // 数据库连接驱动类型: mysqli,sqlite,pdo_mysql,pdo_sqlite
            'host' => '数据库连接地址', // PolarDB数据库链接地址
            'user' => 'test_user', // PolarDB数据库的用户名
            'passwd' => 'Password1213', // PolarDB数据库的密码
            'port' => '3306', // 数据库端口
            'dbname' => 'pbootcms' //数据库名称
        )
    );
    EOF
    1. 在ECS控制台上开放80端口,然后重启apache服务,即可通过ECS IP访问到该门户网站.
    ]]>
    wordpress 网站安装主题-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 1、在主题库中直接搜索安装。

    2、上传主题包,安装主题。

    3、安装主题碰到的问题

    (1)、上传的文件尺寸超过upload_max_filesize文件中定义的php.ini值.

            解决方法:
            修改/etc/php.ini文件中的   
    
            post_max_size = 20M
            upload_max_filesize = 20M
            然后保存,重启一下apache服务。
    

    (2)、Wordpress上传文件提示“无法建立目录wp-content/uploads/2020/09。有没有上级目录的写权限?”

           解决方法:找到wordpress数据库,打开wp_options表,修改表中键名为upload_path的键值 这个值是一个路径,里面是空的(也可能不是空的),添加 “wp-content/uploads” 就解决了。 ===双引号必加!类似于注册表键值
    ]]>
    阿里云服务器选择及使用体验!-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    ]]>
    用图机器学习探索 A 股个股相关性变化-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 在本系列的前文 [1,2]中,我们介绍了如何使用 Python 语言图分析库 NetworkX [3] + Nebula Graph [4] 来进行<权力的游戏>中人物关系图谱分析。

    在本文中我们将介绍如何使用 Java 语言的图分析库 JGraphT [5] 并借助绘图库 mxgraph [6] ,可视化探索 A 股的行业个股的相关性随时间的变化情况

    JGraphT

    数据集的处理

    本文主要分析方法参考了[7,8],有两种数据集:

    股票数据(点集)

    从 A 股中按股票代码顺序选取了 160 只股票(排除摘牌或者 ST 的)。每一支股票都被建模成一个点,每个点的属性有股票代码,股票名称,以及证监会对该股票对应上市公司所属板块分类等三种属性;

    表1:点集示例

    顶点id 股票代码 股票名称 所属板块
    1 SZ0001 平安银行 金融行业
    2 600000 浦发银行 金融行业
    3 600004 白云机场 交通运输
    4 600006 东风汽车 汽车制造
    5 600007 中国国贸 开发区
    6 600008 首创股份 环保行业
    7 600009 上海机场 交通运输
    8 600010 包钢股份 钢铁行业

    股票关系(边集)

    边只有一个属性,即权重。边的权重代表边的源点和目标点所代表的两支股票所属上市公司业务上的的相似度——相似度的具体计算方法参考 [7,8]:取一段时间(2014 年 1 月 1 日 - 2020 年 1 月 1 日)内,个股的日收益率的时间序列相关性 $P_{ij}$ 再定义个股之间的距离为 (也即两点之间的边权重):

    $$l_{ij} = sqrt{2(1-P_{ij})}$$

    通过这样的处理,距离取值范围为 [0,2]。这意味着距离越远的个股,两个之间的收益率相关性越低

    表2: 边集示例

    边的源点 ID 边的目标点 ID 边的权重
    11 12 0.493257968
    22 83 0.517027513
    23 78 0.606206233
    2 12 0.653692415
    1 11 0.677631482
    1 27 0.695705171
    1 12 0.71124344
    2 11 0.73581915
    8 18 0.771556458
    12 27 0.785046446
    9 20 0.789606527
    11 27 0.796009627
    25 63 0.797218349
    25 72 0.799230001
    63 115 0.803534952

    这样的点集和边集构成一个图网络,可以将这个网络存储在图数据库 Nebula Graph 中。

    JGraphT

    JGraphT 是一个开放源代码的 Java 类库,它不仅为我们提供了各种高效且通用的图数据结构,还为解决最常见的图问题提供了许多有用的算法:

    • 支持有向边、无向边、权重边、非权重边等;
    • 支持简单图、多重图、伪图;
    • 提供了用于图遍历的专用迭代器(DFS,BFS)等;
    • 提供了大量常用的的图算法,如路径查找、同构检测、着色、公共祖先、游走、连通性、匹配、循环检测、分区、切割、流、中心性等算法;
    • 可以方便地导入 / 导出 GraphViz [9]。导出的 GraphViz 可被导入可视化工具 Gephi[10] 进行分析与展示;
    • 可以方便地使用其他绘图组件,如:JGraphX,mxGraph,Guava Graphs Generators 等工具绘制出图网络。

    下面,我们来实践一把,先在 JGraphT 中创建一个有向图:

    import org.jgrapht.*;
    import org.jgrapht.graph.*;
    import org.jgrapht.nio.*;
    import org.jgrapht.nio.dot.*;
    import org.jgrapht.traverse.*;
    
    import java.io.*;
    import java.net.*;
    import java.util.*;
    
    Graph<URI, DefaultEdge> g = new DefaultDirectedGraph<>(DefaultEdge.class);

    添加顶点:

    URI google = new URI("http://www.google.com");
    URI wikipedia = new URI("http://www.wikipedia.org");
    URI jgrapht = new URI("http://www.jgrapht.org");
    
    // add the vertices
    g.addVertex(google);
    g.addVertex(wikipedia);
    g.addVertex(jgrapht);

    添加边:

    // add edges to create linking structure
    g.addEdge(jgrapht, wikipedia);
    g.addEdge(google, jgrapht);
    g.addEdge(google, wikipedia);
    g.addEdge(wikipedia, google);

    图数据库 Nebula Graph Database

    JGraphT 通常使用本地文件作为数据源,这在静态网络研究的时候没什么问题,但如果图网络经常会发生变化——例如,股票数据每日都在变化——每次生成全新的静态文件再加载分析就有些麻烦,最好整个变化过程可以持久化地写入一个数据库中,并且可以实时地直接从数据库中加载子图或者全图做分析。本文选用 Nebula Graph 作为存储图数据的图数据库。

    Nebula Graph 的 Java 客户端 Nebula-Java [11] 提供了两种访问 Nebula Graph 方式:一种是通过图查询语言 nGQL [12] 与查询引擎层 [13] 交互,这通常适用于有复杂语义的子图访问类型; 另一种是通过 API 与底层的存储层(storaged)[14] 直接交互,用于获取全量的点和边。除了可以访问 Nebula Graph 本身外,Nebula-Java 还提供了与 Neo4j [15]、JanusGraph [16]、Spark [17] 等交互的示例

    在本文中,我们选择直接访问存储层(storaged)来获取全部的点和边。下面两个接口可以用来读取所有的点、边数据:

    // space 为待扫描的图空间名称,returnCols 为需要读取的点/边及其属性列,
    // returnCols 参数格式:{tag1Name: prop1, prop2, tag2Name: prop3, prop4, prop5}
    Iterator<ScanVertexResponse> scanVertex(
                String space, Map<String, List<String>> returnCols);
    Iterator<ScanEdgeResponse> scanEdge(
                String space, Map<String, List<String>> returnCols);

    第一步:初始化一个客户端,和一个 ScanVertexProcessor。ScanVertexProcessor 用来对读出来的顶点数据进行解码:

    MetaClientImpl metaClientImpl = new MetaClientImpl(metaHost, metaPort);
    metaClientImpl.connect();
    StorageClient storageClient = new StorageClientImpl(metaClientImpl);
    Processor processor = new ScanVertexProcessor(metaClientImpl);

    第二步:调用 scanVertex 接口,该接口会返回一个 scanVertexResponse 对象的迭代器:

    Iterator<ScanVertexResponse> iterator =
                    storageClient.scanVertex(spaceName, returnCols);

    第三步:不断读取该迭代器所指向的 scanVertexResponse 对象中的数据,直到读取完所有数据。读取出来的顶点数据先保存起来,后面会将其添加到到 JGraphT 的图结构中:

    while (iterator.hasNext()) {
      ScanVertexResponse response = iterator.next();
      if (response == null) {
        log.error("Error occurs while scan vertex");
        break;
      }
      
      Result result =  processor.process(spaceName, response);
      results.addAll(result.getRows(TAGNAME));
    }

    读取边数据的方法和上面的流程类似。

    在 JGraphT 中进行图分析

    第一步:在 JGraphT 中创建一个无向加权图 graph:

    Graph<String, MyEdge> graph = GraphTypeBuilder
                    .undirected()
        .weighted(true)
        .allowingMultipleEdges(true)
        .allowingSelfLoops(false)
        .vertexSupplier(SupplierUtil.createStringSupplier())
        .edgeSupplier(SupplierUtil.createSupplier(MyEdge.class))
        .buildGraph();

    第二步:将上一步从 Nebula Graph 图空间中读出来的点、边数据添加到 graph 中:

    for (VertexDomain vertex : vertexDomainList){
        graph.addVertex(vertex.getVid().toString());
        stockIdToName.put(vertex.getVid().toString(), vertex);
    }
    
    for (EdgeDomain edgeDomain : edgeDomainList){
        graph.addEdge(edgeDomain.getSrcid().toString(), edgeDomain.getDstid().toString());
        MyEdge newEdge = graph.getEdge(edgeDomain.getSrcid().toString(), edgeDomain.getDstid().toString());
        graph.setEdgeWeight(newEdge, edgeDomain.getWeight());
    }

    第三步:参考 [7,8] 中的分析法,对刚才的图 graph 使用 Prim 最小生成树算法(minimun-spanning-tree),并调用封装好的 drawGraph 接口画图:

    普里姆算法(Prim's algorithm),图论中的一种算法,可在加权连通图里搜索最小生成树。即,由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。

    SpanningTreeAlgorithm.SpanningTree pMST = new PrimMinimumSpanningTree(graph).getSpanningTree();
    
    Legend.drawGraph(pMST.getEdges(), filename, stockIdToName);

    第四步:drawGraph 方法封装了画图的布局等各项参数设置。这个方法将同一板块的股票渲染为同一颜色,将距离接近的股票排列聚集在一起

    public class Legend {
      
    ...
      
      public static void drawGraph(Set<MyEdge> edges, String filename, Map<String, VertexDomain> idVertexMap) throws IOException {
         // Creates graph with model
         mxGraph graph = new mxGraph();
         Object parent = graph.getDefaultParent();
    
         // set style
         graph.getModel().beginUpdate();
         mxStylesheet myStylesheet =  graph.getStylesheet();
         graph.setStylesheet(setMsStylesheet(myStylesheet));
    
         Map<String, Object> idMap = new HashMap<>();
         Map<String, String> industryColor = new HashMap<>();
    
         int colorIndex = 0;
    
         for (MyEdge edge : edges) {
           Object src, dst;
           if (!idMap.containsKey(edge.getSrc())) {
             VertexDomain srcNode = idVertexMap.get(edge.getSrc());
             String nodeColor;
             if (industryColor.containsKey(srcNode.getIndustry())){
               nodeColor = industryColor.get(srcNode.getIndustry());
             }else {
               nodeColor = COLOR_LIST[colorIndex++];
               industryColor.put(srcNode.getIndustry(), nodeColor);
             }
             src = graph.insertVertex(parent, null, srcNode.getName(), 0, 0, 105, 50, "fillColor=" + nodeColor);
             idMap.put(edge.getSrc(), src);
           } else {
             src = idMap.get(edge.getSrc());
           }
    
           if (!idMap.containsKey(edge.getDst())) {
             VertexDomain dstNode = idVertexMap.get(edge.getDst());
    
             String nodeColor;
             if (industryColor.containsKey(dstNode.getIndustry())){
               nodeColor = industryColor.get(dstNode.getIndustry());
             }else {
               nodeColor = COLOR_LIST[colorIndex++];
               industryColor.put(dstNode.getIndustry(), nodeColor);
             }
    
             dst = graph.insertVertex(parent, null, dstNode.getName(), 0, 0, 105, 50, "fillColor=" + nodeColor);
             idMap.put(edge.getDst(), dst);
           } else {
             dst = idMap.get(edge.getDst());
           }
           graph.insertEdge(parent, null, "", src, dst);
         }
    
    
         log.info("vertice " + idMap.size());
         log.info("colorsize " + industryColor.size());
    
         mxFastOrganicLayout layout = new mxFastOrganicLayout(graph);
         layout.setMaxIterations(2000);
         //layout.setMinDistanceLimit(10D);
         layout.execute(parent);
    
         graph.getModel().endUpdate();
    
         // Creates an image than can be saved using ImageIO
         BufferedImage image = createBufferedImage(graph, null, 1, Color.WHITE,
                                                   true, null);
    
         // For the sake of this example we display the image in a window
         // Save as JPEG
         File file = new File(filename);
         ImageIO.write(image, "JPEG", file);
    
       }
      
      ...
        
    }

    第五步:生成可视化:

    图1中每个顶点的颜色代表证监会对该股票所属上市公司归类的板块

    可以看到,实际业务近似度较高的股票已经聚拢成簇状(例如:高速板块、银行版本、机场航空板块),但也会有部分关联性不明显的个股被聚类在一起,具体原因需要单独进行个股研究。

    JGraphT

    图1: 基于 2015-01-01 至 2020-01-01 的股票数据计算出的聚集性

    第六步:基于不同时间窗口的一些其他动态探索

    上节中,结论主要基于 2015-01-01 到 2020-01-01 的个股聚集性。这一节我们还做了一些其他的尝试:以 2 年为一个时间滑动窗口,分析方法不变,定性探索聚集群是否随着时间变化会发生改变

    JGraphT

    图2:基于 2014-01-01 至 2016-01-01 的股票数据计算出的聚集性

    JGraphT

    图3:基于 2015-01-01 至 2017-01-01 的股票数据计算出的聚集性

    JGraphT

    图4:基于 2016-01-01 至 2018-01-01 的股票数据计算出的聚集性

    JGraphT

    图5:基于 2017-01-01 至 2019-01-01 的股票数据计算出的聚集性

    JGraphT

    图6:基于 2018-01-01 至 2020-01-01 的股票数据计算出的聚集性

    粗略分析看,随着时间窗口变化,有些板块(高速、银行、机场航空、房产、能源)的板块内部个股聚集性一直保持比较好——这意味着随着时间变化,这个版块内各种一直保持比较高的相关性;但有些板块(制造)的聚集性会持续变化——意味着相关性一直在发生变化。

    Disclaim

    Disclaim

    本文不构成任何投资建议,且作者不持有本文中任一股票。

    受限于停牌、熔断、涨跌停、送转、并购、主营业务变更等情况,数据处理可能有错误,未做一一检查。

    受时间所限,本文只选用了 160 个个股样本过去 6 年的数据,只采用了最小扩张树一种办法来做聚类分类。未来可以使用更大的数据集(例如美股、衍生品、数字货币),尝试更多种图机器学习的办法。

    本文代码可见[18]

    Reference

    [1] 用 NetworkX + Gephi + Nebula Graph 分析<权力的游戏>人物关系(上篇)https://nebula-graph.com.cn/posts/game-of-thrones-relationship-networkx-gephi-nebula-graph/

    [2] 用 NetworkX + Gephi + Nebula Graph 分析<权力的游戏>人物关系(下篇) https://nebula-graph.com.cn/posts/game-of-thrones-relationship-networkx-gephi-nebula-graph-part-two/

    [3] NetworkX: a Python package for the creation, manipulation, and study of the structure, dynamics, and functions of complex networks. https://networkx.github.io/

    [4] Nebula Graph: A powerfully distributed, scalable, lightning-fast graph database written in C++. https://nebula-graph.io/

    [5] JGraphT: a Java library of graph theory data structures and algorithms. https://jgrapht.org/

    [6] mxGraph: JavaScript diagramming library that enables interactive graph and charting applications. https://jgraph.github.io/mxgraph/

    [7] Bonanno, Giovanni & Lillo, Fabrizio & Mantegna, Rosario. (2000). High-frequency Cross-correlation in a Set of Stocks. arXiv.org, Quantitative Finance Papers. 1. 10.1080/713665554. 

    [8] Mantegna, R.N. Hierarchical structure in financial markets. Eur. Phys. J. B 11, 193–197 (1999).

    [9] https://graphviz.org/

    [10] https://gephi.org/

    [11] https://github.com/vesoft-inc/nebula-java

    [12] Nebula Graph Query Language (nGQL). https://docs.nebula-graph.io/manual-EN/1.overview/1.concepts/2.nGQL-overview/

    [13] Nebula Graph Query Engine. https://github.com/vesoft-inc/nebula-graph

    [14] Nebula-storage: A distributed consistent graph storage. https://github.com/vesoft-inc/nebula-storage

    [15] Neo4j. www.neo4j.com

    [16] JanusGraph. janusgraph.org

    [17] Apache Spark. spark.apache.org.

    [18] https://github.com/Judy1992/nebula_scan

    ]]>
    直播 | 阿里、携程、网易共同出品, 后端架构工程实践系列直播-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 本次后端架构工程实践专场,由阿里技术、携程技术、网易技术共同出品。

    携程框架架构研发部负责携程后端框架和中间件的研发,包括异地多活、ServiceMesh、消息队列、配置中心等10多个产品,支撑携程的整体业务研发。

    阿里技术(阿里云开发者社区)提供分享、学习、认证、工具、资源、大赛、社群、MVP等一站式服务能力,满足开发者全生命周期成长需求。

    议题简介

    《携程DRC-MySQL数据双向复制实践》(戳我观看)

    直播时间:

    2020-09-21 19:00

    讲师介绍

    李明冬,携程软件技术专家, 围绕数据异地多活项目,负责DRC(数据实时双向或多向复制)项目设计与开发工作、 负责DAL(数据库访问中间件)项目设计和演进。

    内容简介

    DRC通过将部署在不同机房的MySQL数据进行双向复制,实现单机房保存全量数据,业务本地读写。单机房故障时,分钟级机房流量切换。本次演讲将深入剖析DRC内部设计和实现原理。你将了解到:
    1、DRC基本架构;
    2、DRC高可用设计方案;

    《携程第二代API网关设计与实践》(戳我观看)

    直播时间:

    2020-09-23 19:00

    讲师介绍

    俞炯,携程软件技术专家, 2016年加入携程,主要负责携程API网关的维护与研发,以及公共反爬相关基础设施建设。

    内容简介

    API网关是携程路由体系内的重要一环,在隔离&解耦网络环境、海外加速、单元化等场景内都承担着重要角色。网关同时也是公共业务需求的载体,包括安全认证、反爬、限流熔断、监控告警等。作为公共基础设施,保证自身稳定性,同时支撑业务发展是我们的首要目标。

    本次将着重分享内容包括:
    1、业务流量增长带来的性能问题;
    2、出海、上云、异地多活对架构的要求;
    3、多协议、多场景带来的治理问题;

    《Envoy 架构在网易轻舟的落地实践》(戳我观看)

    直播时间:

    2020-09-30 19:00

    讲师介绍

    王佰平,网易数帆轻舟事业部 工程师, 负责轻舟Envoy网关与轻舟Service Mesh数据面开发、功能增强、性能优化等工作。对于Envoy数据面开发、增强、落地具有较为丰富的经验。

    内容简介

    Envoy 是一款由 Lyft 开源的高性能数据和服务代理软件,CNCF 毕业项目。新兴 API 网关如 Gloo,Ambassador 都基于 Envoy 进行扩展开发;而在服务网格中,Istio、Kong 社区 Kuma、亚马逊 AMS App Mesh、微软 Open Service Mesh 都使用 Envoy 作为默认数据面。

    本次分享将详细介绍 Envoy 整体架构以及其功能特性,及经验总结:
    1、Envoy 是什么?
    2、Envoy 有什么?
    3、Envoy 能做什么?

    《云开发Serverless架构服务》(戳我观看)

    直播时间:

    2020-10-13 19:00

    讲师介绍

    杜欢(风驰),阿里云Serverless云开发平台负责人, 阿里巴巴前端委员会委员,致力于推动研发生态实现云端Serverless研发能力升级,实现云的开箱即用。 ​

    内容简介

    随着函数计算等 FaaS 云产品的不断完善,研发生态对 Serverless 的认知也日渐清晰,尝试也越来越多。在诸多实践中,许多人开始陷入一种迷思,FaaS 是不是只能用在一些 “计算任务” 场景?是不是只能在小程序这个场景才能用?K8S是不是很大规模的公司才能用?云原生,Serverless是不是只是说的好听,离我其实还很远呢?我们将为你揭示,一个真正人人可用的云时代研发模式已经到来!

    在此分享中,你会了解到阿里云Serverless云开发平台如何通过三套Serverless架构服务帮助应用落地到Serverless架构。包括:
    1、云原生时代的架构应该怎么做?
    2、Serverless架构有什么优势?
    3、应用如何落地?

    ]]>
    “云见教育 共享未来”阿里云让教育服务加速进步-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800     9月17日是2020年云栖大会拉开序幕的日子,今年的云栖大会以“数智未来·全速重构”为主题,进行了真正的“线上+线下”的深度尝试,除线上大会外,还在北京、上海、杭州、昆明、天津等城市开设了云栖大会阿里云MVP专场。其中,校宝在线独家承办“云见教育·共享未来”为主题的云栖大会的杭州分场,也是教育行业的专场。校宝在线作为中国深受欢迎的教育信息化综合服务提供商,一直以来以“推动教育服务加速进步”为使命,经过在教育SaaS领域的十年深耕,校宝在线已经帮助超90000个教育品牌实现信息化管理,帮助超过180000个校区实现“互联网+教育”的业务升级,服务教育从业者超100万。
        随着互联网技术的蓬勃发展,“互联网+教育”的转型升级已成为教育产业发展的重要议题,而云计算作为一门新兴技术正在改变各行各业的生产方式,其高可靠性、可扩展性和高度灵活性也正逐渐影响着教育行业的发展。2020年,教育行业正处于转型升级的关键时期,教育的形态焕新,秩序重组,如何借助互联网与云计算技术,实现教育行业的创新发展,成为本次云栖大会教育专场的重要议题。
    pt2020_09_21_13_45_42.jpg

        第一位嘉宾浙江大学教授、阿里巴巴-浙江大学前沿技术联合研究中心(AZFT)智能计算机系统实验室主任--陈文智,给大家分享了《教研云助力高效数字化转型》。陈教授展示了基于教研云的新一代教学平台,能够实现教学场景的全覆盖、AI优化教学质量、云化提升教学体验以及教学数据的多维分析,未来高校科研新模式将实现科研的数字化运营,打造科研协作空间,从而构建科研新生态。
        第二位嘉宾校宝在线CPO&创新事业部总经理--李杰,他是浙江大学管理学硕士、原阿里巴巴高级产品专家、原百度商业产品经理,这次给大家分享的主题是《透过疫情,看教培行业的DT未来》,现在IT时代正在逐步迈入DT时代,未来教育越来越多的基于数据驱动,因此教育行业也要顺势而为,拥抱DT,实现机构业务数据化、行业数据标准化、产业服务生态化的三步升级。
        第三位嘉宾阿里云智能解决方案架构师--胡中泉,作为十年阿里巴巴DBA,一直从事企业数字化转型数据库解决方案架构设计,这次带来的是《鱼熊兼得——云原生数据库技术解析》。云原生数据库存储计算分离,分别无限弹性,可具备HTAP特性,同时,云原生数据库关注弹性、性能和成本优化等上层需求,相比传统数据库,云原生数据库拥有更低的TCO、更好的性能与吞吐量,更便捷的使用体验更科学的使用方式。
        第四位嘉宾校宝在线架构师--李同刚,他是阿里云MVP、校宝在线共享技术部基建业务负责人,负责并参与了校宝云服务平台、DevOps平台、开放平台建设,这次分享了非常落地的《教育信息化平台DevOps实践》。DevOps 业务链路较长,因此我们要始终从业务问题出发,实现客户价值结合业务痛点,找到切入点,团队 Leader 要想好客户价值,聚焦、不要贪,“少则得,多则惑”,同时坚持大道至简,规范先行,从客户场景出发,方案做简单些,并且制定规范,做好期望管理。
    pt2020_09_21_14_01_58.jpg
        在四位精彩的嘉宾演讲之后,本次云栖大会教育专场还专门圆桌讨论了《云时代的教育SaaS平台技术演进之路》,校宝在线架构师肖伟宇、资深net开发工程师王斌与阿里云智能容量服务产品经理范捷惟、杭州互次方技术VP金立四位嘉宾在现场给大家带来了精彩有深入的交流探讨。
    pt2020_09_21_14_04_36.jpg

        每一位演讲嘉宾分享之后,现场的参会嘉宾也都提出了自己的疑惑和问题,现场交流气氛浓厚,大家对于新技术、新教育充满激情和能量。

    XO4A0510.JPG
    XO4A0503.JPG

    ]]>
    如何度量研发效能?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 image.png
    没有可靠的度量就无法有效的改进,高度数字化的软件研发领域一直是进行各类效能度量尝试的创新重地。

    阿里云·云效服务的内部版本“Aone”承载着阿里集团数百个BU协同研发和持续交付的职责,笔者在数月前短暂的参与了该平台的效能透视镜板块建设,因而得以从平台的“上帝视角”重新审视效能度量这件事,随着项目开展,略微摸索了些门道。此文中观点源于这段时间里笔者在团队内以及与周边相关团队的讨论和个人思考,且作抛砖引玉之用。

    度量的分类

    度量的分类方式有很多,其中比较有意思的一种角度,是根据目标意图将度量划分为“针对人的度量”和“针对事的度量”。

    任何协作系统都离不开人的参与,加之可与绩效、考核等事情牵上关系,即使相关指标的分析往往伴随着争议,针对人的度量在企业里有时依然被视为一种“刚需”。譬如“代码量”、“代码质量”、“工作时长”等数据评判都是常见的依据指标。从产品实现而言,由于对结果可解释性要求高,这类度量的单因素指标居多,计算方案通常不会太复杂,宜采用小范围同维度横向比较,防止过度泛化。

    相比之下,针对事度量的范畴和方法更加灵活。既包括简单的数值指标,譬如产研中的发布频率、需求交付时长;也包括需要对比分析的多元指标,譬如需求在各阶段的停留时长、缺陷在各环境的漏测率等。在就事论事的基础上,为了更全面的理解事实的客观规律,还经常需要将一组数据向上聚合(譬如整个部门、整个项目的情况)或者跨领域关联(譬如业务领域需求关联到相关代码提交情况),从而获得更宽的观察视角。由于涉及的度量主体更多,有时为了确定哪个主体是主要的影响因素,还需要进行额外的归因判定。相较于以人为目标的度量,对事进行度量时,可以包含更多的经验和推理因素。

    对人或对事主要是针对度量目的而言,在实际运用时,两者采用的具体指标会有许多共同之处,并不能一概而论。根据管理学中的“平衡计分卡(The Balanced ScoreCard)”理论,度量活动要遵循“目标-度量-指标-行动”的规则,指标最终服务于目标的达成,好的度量产品不仅应当反映“发生了什么”,还应当能根据目标提供“该怎么做”的辅助建议。因此度量类产品的成败,不仅是对指标设计者的领域理解、抽象能力的挑战,而且对产品自身的业务目标清晰度也会提出很高的要求。

    效能的本质

    归根究底而言,效能的本质是对价值流动速度和质量的评价。

    “价值流”的概念伴随着精益思想的传播,被越来越多行业所接纳。不过很少有其他哪个行业能够像软件研发行业这样,能够让价值交付的各个环节几乎完全在线数字化,从而提供大量可分析的过程数据样本。

    所谓价值流动过程可以表示为,“价值原料”在可被度量的价值加工活动之间有序传递,不断叠加价值增量,最终形成可被消费的“价值产物”。下图将这一过程的度量抽象为一种非常简洁的表示结构,可称为效能度量的“元模型”。

    image.png

    度量中所用的各类“领域特征”则是由在此元模型之上的领域对象,以及基于这些对象的“领域指标”来定义的。

    譬如在研发领域,“价值原料”可以是一个业务方的需求,或是一个开发者突发奇想的创意。可被度量的活动包括需求拆解、任务指派、代码编写、测试、部署、验证、发布等等。每个活动本身都具有可被观测的属性,实体之间也具有可被量化的关系。这些实体、属性、关系就组成了特定领域的模型,下图展示了一种简化的研发度量领域模型(为了美观省略掉很多实体关系连接,仅作示意)。

    image.png

    有了领域模型,就可以基于规则制定指标。指标通常被描述为各种量化特征和实体属性的数值计算。有些指标是领域无关的,譬如端到端流通时长;有些指标是多个领域之间可以复用的,譬如许多行业都会有单位时间任务吞吐量、任务按时完成率这样的指标;有些指标是领域特有的,譬如研发领域的千行代码缺陷率等等。

    在指标之上,还需要有与具体运用场景相匹配的工具或平台来将度量结果转换为便于观察分析的表现形式。譬如各种图表、报表,以及事件通知。

    元模型和领域对象的分离,似乎能够形成一种足够抽象的通用度量产品,通过领域相关的指标规则、展示规则、通知告警规则,快速适配不同目标和场景,然而现实情况其实更复杂。一方面受制于计算能力,有些指标实际无法根据模型+规则实时计算出来,必须单独预先算好,以空间换时间。另一方面受限于价值增值过程的可观测性,并非所有行为的结果都能立即被简单量化(否则说服人们坚持锻炼身体就容易多了),即使在高度数字化的软件研发领域,依然存在数据质量和时效性问题,在使用数据时需要加以考虑。因此各种效能的场景虽然具有十分相似的流动特征,实际产品依然会不可避免的根据业务定制化,万能的度量工具或公式是不存在的。

    模型的存储

    对于度量模型的存储,图数据库可能是最好的选择,没有之一。

    相比结构化的SQL数据库和文档型的NoSQL数据库,图数据库属于比较小众的一种偏门奇术,主要用在知识图谱和基于关系的信息搜索领域。从基本特征而言,图数据库通常具备NoSQL的非结构化KV存储能力,允许同一类实体具有不同属性项的实例,这对于处理来自多种数据源或多个子类型的实体信息带来很大便利。同时,图数据库通常能像SQL数据库那样支持事务和多实体关联查询。不仅如此,图数据库对复杂关系的检索性能远高于SQL数据库,对于判断、循环查询的支持也比SQL存储过程更加优雅。

    然而这些基础能力上的差异,并非我推荐将图数据库用于效能度量的主要原因。

    好的技术选型应该能够充分适应潜在的业务需求变动,避免过早将技术实现耦合到局部的应用场景。在基于SQL表的开发模式里,“表结构设计”是在软件详细设计阶段里非常重要的一个环节,因为它不仅是对整体业务领域的建模,还关系着未来数据查询的效率和便利性。熟悉SQL表设计的同学应该知道,1对1、1对N、N对N关系,数据表的处理方法是完全不同的:N对N关系需要额外设计关联表,1对N关系通常是在后者的实体上设计外键,而1对1关系的外键设计就更有讲究了,要根据实际场景来决定该在哪个实体上放另一者的外键,然后在使用的时候顺着这个关联方向来查询。对于聚合的设计也是如此,需要事先在被聚合表上提前设计好用于聚合的外键,因此会有“事实表”、“维度表”的区分。数据的查询规则,在数据库表结构设定的时候就被确定下来了。

    对业务模式比较固定的场景而言,提前考虑好数据的使用方法并做针对性优化显得合情合理,然而效能度量业务并不属于此类。在度量领域里,关联、级联、聚合都是十分常见的指标计算操作,由于指标的作用在于发现潜藏于表面之下的问题,事先不应当提前规定只能从哪一类实体作为关联查询的起点,或者必须以哪些维度做聚合观察。

    就图数据库的存储模型来说,所有业务实体都是平等的,任何类型的关系都由实体间的关联来表示。这就像是在SQL表设计时,不论是1对1还是N对N关系,总是额外增加一张关联表,却无需顾虑多表JOIN带来的性能影响。这样一来,相当于将查询和聚合方式的决策推迟到实际使用的时候再做,从而有效解耦建模和查询时的相互制约,不再需要为优化查询而返工改表。

    此外,由于关联直接建立于实体之间,当删除实体的时候,实体间的关联也将自动断开。这就像有垃圾回收机制的Java语言不用自己管理内存指针一样。图数据库绝不会产生由于关系修改时的不对称清除而导致的数据不一致情况。

    那图数据库会不会有坑?肯定有。不过在我们目前有限的探索里,遇到比较大的麻烦主要来自它不够完善的周边工具配套、阿里云图数据库服务的某些配置限制,以及市场上稀缺具备相关技能的专业工程师。

    专家经验

    在研发效能领域,度量的终极目标是DevOps文化所提倡的识别和消除系统性瓶颈。

    通过各式各样的过程数据,经验丰富的项目经理和管理教练往往能够准确判断出项目的潜在问题和交付风险。

    在经济学领域有个十分有趣的“古德哈特定律”,即“当决策者试图以一个事物的客观测度指标作为指针来施行政策时,这一指标就再也不能有效测度事物了”。

    然而效能度量并不是玄学,价值生产活动中的风险应当是有章可循的。古德哈特式的此消彼长现象其实来源于经济领域的范围太过宽广,任何实用指标往往只能是局部度量的结果。效能透视镜产品的提出者嵩华老师曾经分享过一种识别研发项目系统性风险的思路,即有的放矢的关注四种典型的全局现象:

    • 流动阻滞
    • 返工
    • 落后的工程能力
    • 技术债务

    这几种现象不太容易在局部进行遮掩,且在一定条件下能够相互叠加,成为“烂项目”的标配。

    透过整个研发过程中的种种现象,找到反映这些全局性问题的蛛丝马迹,不仅能在一定程度上让“专家经验”产品化、标准化,也有助于将效能数据的使用方法从当前普遍的“事后复盘”式向以全局流动速率和质量作为关注点的“风险管控”式发展,从而在可靠性和时效性两个方面都得到提升。

    总结

    数据不会骗人,但数据的呈现和解读依然有很大的空间值得探索。现实事物复杂而多面,度量正是为描述和对比这些具象事实而采取的抽象和量化措施,从某种意义上来说,度量的结果一定是片面的,反映部分事实。没有银弹,也没有完美的效能度量。

    对于企业研发效能的提升,开发者工具、效能方法理论、效能度量指标都是缺一不可、环环相扣的几个重要板块,相信随着数据价值被越来越多的挖掘,我们终将实现更有效的反馈和更精确的赋能,让研发协作真正变得透明、简单、高效。

    最后

    分享十条前人总结的经验观点。

    • 任何指标一旦用于管控,就不再可靠(古德哈特定律)。
    • 测量的对象与人越近,越不可靠。
    • “凡可度量,皆可改造”是错的。
    • 变化趋势的价值高于指标绝对值。
    • 选择适当的而非“标准的”指标,若发现指标没用,果断舍弃。
    • 务必了解指标的获取成本,明确指标意图和针对的企业目标。
    • 设计“北极星指标”,指标数量越多,边际收益递减。
    • 不要将指标对所有人透明。
    • 让一线人员参与指标制定。
    • 如果可能,合理缩短度量周期。
    ]]>
    ARMS助力「掌游科技」系统重构-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 武汉掌游科技有限公司隶属于盛趣游戏(原盛大游戏)旗下,是一家经营手游发行、深度运营及综合买量的互联网游戏公司。自2014年成立至今,已成功运营超过1000款手游产品,拥有超过1亿游戏用户,活跃用户突破千万。

    系统重构后产生新的需求

    掌游科技有SaaS游戏发行运营平台,帮助游戏厂商通过大数据分析更好的运营游戏。随着业务量的不断上涨,之前单数据库的系统架构逐渐出现了性能瓶颈。

    为了能更好的支撑业务,掌游科技将单库按业务拆分为了四个数据库,整个系统也因为分库而进行了重构。但是重构后的系统经过测试发现有很多问题,几次上线后都出现了不稳定的情况,并且由于业务复杂,开发人员众多,很难快速、全面的发现系统Bug和性能约束点,所以急需通过APM工具来发现系统中存在的各个性能约束点。

    掌游科技期望APM工具能具备以下五点特性:

    • 快速无侵入的接入方式:期望最大限度的不改动系统代码,以无侵入、无感知的方式将监控系统接入现有系统;

    • 系统性能低损耗:接入的监控系统不对能宿主系统产生过高的性能损耗,期望不超过5%;

    • 可视化的配置操作方式:不期望繁琐的、通过命令形式的配置。期望可以通过Web控制台的方式方便的进行配置,比如采样率、SQL提取规则、业务监控配置等;

    • 全方位的应用监控能力:期望从应用层面、节点层面、接口层面、主机层面多维度监控系统。比如应用的整体健康度,接口的调用次数、响应时间、慢SQL分析、异常分析、JVM分析、内存快照分析、CPU/内存/IO分析等;

    • 支持PHP语言:客户主要使用PHP语言进行开发,希望监控系统可以全面支持PHP语言的各个组件和框架。比如CURL、PDO、Mysqli、Yar Client、GRPC Client、Predis Client、Memcache Extension等。

    解决方案

    阿里云自研的应用实时监控服务ARMS完美的契合了客户的诸多痛点,通过Agent的方式无侵入的、快速的接入客户系统,通过白屏化的方式进行设置,提供各种丰富完善的视图协助客户全方位监控系统,并且ARMS结合众多客户场景和专家经验,提供智能诊断功能。帮助客户快速、准确的发现和定位到了系统重构后的很多性能约束点和隐患,让客户有的放矢的对系统进行优化。

    1. 性能瓶颈和Bug一目了然:无论从CPU、内存、磁盘、网络、JVM GC、JVM堆内存、内存快照分析的主机层面还是从接口响应时间、请求数、错误数、异常分析、上下游接口、接口快照、调用链路、线程剖析的接口层面,亦或是慢SQL分析、数据库连接数、CPU/内存/磁盘使用率、网络流入/出流量监控的存储层面,以及NoSQL、MQ监控等。将系统360度无死角的监控起来,所有性能问题都无所遁形。

    2. 提前预知系统问题:ARMS提供了完善的预警通知功能,可以基于主机监控、JVM监控、异常接口调用、应用调用统计、数据库指标等多个指标类型下几十钟触发条件来灵活的设置预警规则。同时提供多样化的通知方式以满足不同客户的通知需求。

    3. 支持PHP:目前开源的APM工具对PHP支持的都不够完善,无论在无侵入接入方面,还是支持的组件方面,面对PHP语言构建的系统,都不能很好的支撑形成监控链路闭环。ARMS在对PHP语言系统的监控方面已经沉淀多年,绝大多数PHP的框架和组件都已支持,有很完善的问题分析定位的链路闭环和最佳实践。

    ]]>
    Spring 5 中文解析数据存储篇-DAO支持-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 Spring核心篇章:

    Spring 5 中文解析之核心篇-IoC容器

    Spring 5 中文解析核心篇-IoC容器之依赖关系

    Spring 5 中文解析核心篇-IoC容器之Bean作用域

    Spring 5 中文解析核心篇-IoC容器之自定义Bean性质

    Spring 5 中文解析核心篇-IoC容器之BeanDefinition继承与容器拓展点

    Spring 5 中文解析核心篇-IoC容器之基于注解的容器配置

    Spring 5 中文解析核心篇-IoC容器之类路径扫描和组件管理

    Spring 5 中文解析核心篇-IoC容器之JSR330标准注解

    Spring 5 中文解析核心篇-IoC容器之基于Java容器配置

    Spring 5 中文解析核心篇-IoC容器之Environment抽象

    Spring 5 中文解析核心篇-IoC容器之ApplicationContext与BeanFactory

    Spring 5 中文解析核心篇-IoC容器之Resources

    Spring 5 中文解析核心篇-IoC容器之数据校验、数据绑定和类型转换

    Spring 5 中文解析核心篇-IoC容器之SpEL表达式

    Spring 5 中文解析核心篇-IoC容器之AOP编程(上)")

    Spring 5 中文解析核心篇-IoC容器之AOP编程(下)")

    Spring 5 中文解析核心篇-IoC容器之Spring AOP API

    Spring测试篇章:

    Spring 5 中文解析测试篇-Spring测试

    Spring 5 中文解析核心篇-集成测试之概要和集成测试注解

    Spring 5 中文解析核心篇-集成测试之TestContext(上)")

    Spring 5 中文解析核心篇-集成测试之TestContext(中)")

    Spring 5 中文解析测试篇-集成测试之TestContext(下)")

    Spring 5 中文解析测试篇-Spring MVC测试框架

    Spring 5 中文解析测试篇-WebTestClient

    Spring存储篇章:

    Spring 5 中文解析数据存储篇-Spring框架的事物支持模型的优势

    [Spring 5 中文解析数据存储篇-事务同步和声明式事物管理
    ](https://mp.weixin.qq.com/s?__biz=MzA3NDgzODYzNg==&tempkey=MTA3OV91TU8vcGlxSXdvTGNhZ2o0a3p2RXZvSGpJeXNCMmNCUkszbU9OZzVSc09rT19Zejl6b3JCWHZHU0JfN3ZrVDhhbzZUV3BfS2s3aHFEakhPb3V4dXVkMVp4ajFfZllOcnM2N3huU2d1ZUJZZlN6T1lZNVVKWHJjOWRkdEg3Uzg3RmpFRzZXbHMzQ3lFUUEwd1JqTl9JOGZzWGxMYWh6N1lhY05DYnFRfn4%3D&chksm=1f7b0caa280c85bcce8c4ffe9fb21629f683d5d9127116dae91dc9b9cbd2f367a19514fef76f#rd)

    [Spring 5 中文解析数据存储篇-@Transactional使用
    ](https://mp.weixin.qq.com/s?__biz=MzA3NDgzODYzNg==&tempkey=MTA3OV9RNU1VNnhsa0ZkRlhBb3Fla3p2RXZvSGpJeXNCMmNCUkszbU9OZzVSc09rT19Zejl6b3JCWHZHU0JfNTZ4dWhENjFrNUV6dlpieWYxVndQRlBNNkFRZVBFWlVyZHdiQlhTMmZMM0g0TnppT040Nk5QUU1rcEpNY2FDN09nZnNPeG5WTU8wajZCNUowaHZnTHhZcGpYdVRlNXQzWTZUSV8yOEpJNl9nfn4%3D&chksm=1f7b0cb3280c85a5682b1c9ea3cf7d2a69abdd6fe9147ed4335a5d5cfbef7c04ed314bd389de#rd)

    Spring 5 中文解析数据存储篇-编程式事物管理

    完整电子书地址

    Spring对数据访问对象(DAO)的支持旨在使以一致的方式轻松使用数据访问技术(例如JDBCHibernateJPA)。这使你可以轻松地在上述持久性技术之间进行切换,并且还使你无需担心捕获每种技术特有的异常即可进行编码。

    2.1 一致的异常层次结构

    Spring提供了从特定于技术的异常(例如SQLException)到其自己的异常类层次结构的便捷转换,该异常类层次结构以DataAccessException作为根异常。这些异常包装了原始异常,因此你永远不会丢失任何有关可能出错的信息。

    除了JDBC异常,Spring还可以包装JPAHibernate特定的异常,将它们转换为一组集中的运行时异常。这样,你就可以仅在适当的层中处理大多数不可恢复的持久性异常,而不必在DAO中使用烦人的样板捕获和抛出块以及异常声明。(尽管如此,你仍然可以在任何需要的地方捕获和处理异常。)如上所述,JDBC异常(包括特定于数据库的方言)也被转换为相同的层次结构,这意味着你可以在一致的编程模型中使用JDBC执行某些操作。

    在Spring对各种ORM框架的支持中,上述讨论对于各种模板类均适用。如果使用基于拦截器的类,应用程序必须关心处理HibernateExceptionsPersistenceExceptions本身,最好是通过分别委托给SessionFactoryUtilsconvertHibernateAccessException(..)convertJpaAccessException()方法。这些方法将异常转换为与org.springframework.dao异常层次结构中的异常兼容的异常。由于未选中PersistenceException,因此它们也可能被抛出(不过,在异常方面牺牲了通用的DAO抽象)。

    下图显示了Spring提供的异常层次结构。(请注意,图像中详细说明的类层次结构仅显示整个DataAccessException层次结构的子集。)

    DataAccessException

    2.2 用于配置DAO或存储类的注解

    确保你的数据访问对象(DAO)或存储库提供异常转换的最佳方法是使用@Repository注解。此注解还使组件扫描支持可以查找和配置DAO和存储库,而不必为其提供XML配置。以下示例显示了如何使用@Repository注解:

    @Repository //1
    public class SomeMovieFinder implements MovieFinder {
        // ...
    }
    1. @Repository注解

    任何DAO或存储库实现都需要访问持久性资源,具体取决于所使用的持久性技术。例如,基于JDBC的存储库需要访问JDBC数据源,而基于JPA的存储库需要访问EntityManager。完成此操作的最简单方法是使用@Autowired@Inject@Resource@PersistenceContext注解之一注入此资源依赖项。以下示例适用于JPA存储库:

    @Repository
    public class JpaMovieFinder implements MovieFinder {
    
        @PersistenceContext
        private EntityManager entityManager;
    
        // ...
    }

    如果使用经典的Hibernate API,则可以注入SessionFactory,如以下示例所示:

    @Repository
    public class HibernateMovieFinder implements MovieFinder {
    
        private SessionFactory sessionFactory;
    
        @Autowired
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
    
        // ...
    }

    我们在此显示的最后一个示例是对典型JDBC支持的。你可以将DataSource注入初始化方法或构造函数中,在此方法中,你可以使用此DataSource创建JdbcTemplate和其他数据访问支持类(例如SimpleJdbcCall等)。以下示例自动装配数据源:

    @Repository
    public class JdbcMovieFinder implements MovieFinder {
    
        private JdbcTemplate jdbcTemplate;
    
        @Autowired
        public void init(DataSource dataSource) {
            this.jdbcTemplate = new JdbcTemplate(dataSource);
        }
    
        // ...
    }

    有关如何配置应用程序上下文以利用这些注解的详细信息,请参见每种持久性技术的特定介绍。

    作者

    个人从事金融行业,就职过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就职于某银行负责统一支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。同时也热衷于技术分享创立公众号和博客站点对知识体系进行分享。关注公众号:青年IT男 获取最新技术文章推送!

    博客地址: http://youngitman.tech

    CSDN: https://blog.csdn.net/liyong1028826685

    微信公众号:

    技术交流群:

    ]]>
    【其他】9月21日阿里云域名交易平台未实名认证.cc/.tv域名下架通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【域名】【域名交易平台】【未实名.cc/.tv域名下架】

    维护时间:北京时间2020年9月21日 00:00

    维护内容:未完成实名认证的.cc/.tv域名将被系统下架一口价(万网)、域名竞价等出售信息。

    维护影响:自北京时间2020年8月10日 10:00起,.cc/.tv域名的注册、转入、持有者信息修改(过户)等操作将要求进行域名实名认证(包括命名审核和实名资料审核)。

    阿里云域名交易平台出售中的.cc/.tv域名若未完成实名认证,一口价(万网)、域名竞价等类型将无法被正常下单购买。请尽快完成.cc/.tv域名实名认证!

    出售中的.cc/.tv域名,若未能在9月21日00:00前完成域名实名认证,相关出售信息将被系统自动下架,您须待域名实名认证完成后,重新操作域名上架。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    关于2020国庆假期的安排-米姆-阿里云服务 Thu, 29 Oct 2020 12:16:15 +0800        根据国务院办公厅关于2020年部分节假日安排的通知,10月1日至8日国庆节,中秋节放假调休,共8天。9月27日(星期日)、10月10日(星期六)上班


           在此节假日期间亲爱的各位老铁,我们依然为您安排了值班工作人员哦!

           阿里云售前、售后:尹先生-13246463538

           阿里云技术支持:陈先生-14737363737

           其他服务需求与咨询:高先生-15869041323


         我们友好的小伙伴会一直陪在您身边,有问题速速联系我们吧!也可以移步至官网智慧表单提交您的需求或问题哦,我们会在第一时间处理。


         感谢大家在2020年对我们的支持,因为你们的信任,我们才能在激烈的市场竞争中不断进步与发展。未来我们不负年华,提升服务质量与体验。也祝您节日快乐。


                                                                                                             广州米姆信息科技有限公司

                                                                                                              2020年9月

    ]]>
    阿里云SAE支持「禾连健康」低门槛微服务化,弹性降本20%以上 Thu, 29 Oct 2020 12:16:15 +0800 166.jpg

    作者:黛忻

    浙江禾连网络科技有限公司(简称:禾连健康)成立于2014年,多年来专注医疗互联网产业,致力于通过互联网技术,建立服务患者、医生、医院的大平台。

    业务范围从医院Wi-Fi、患者端App、医护端App,拓展到提供一站式医院物联网应用解决方案。目前医院Wi-Fi已签约全网245个城市1700多家医院,成为中国最大的医院Wi-Fi服务商。禾健康、禾连保、禾医助几个App提供一站式家庭健康管理服务,服务1亿用户。

    客户需求:

    禾连是聚石塔的最早一批用户,采用ECS + Docker模式部署应用。因聚石塔定位的变化,没有持续维护相关业务;再加上禾连业务的不断发展,而聚石塔在弹性、服务治理上的能力不满足预期,禾连不得不考虑重新做技术选型。

    在架构优化初期,公司基于ECS自建整套微服务架构,过程中暴露了很多问题:

    (1)产品迭代跟不上业务变化:传统开发模式无法支撑公司业务的快速发展,研发既要忙于业务,又要Cover底层组件开发和运维,效率非常低;

    (2)硬件闲置成本高:云上按业务峰值保有大量的包年ECS,逐台购买安骑士服务。但业务具有潮汐特性,峰谷时闲置浪费高。而且业务瞬息万变,一旦发展不符合预期,购买的ECS会长期处于闲置状态。

    (3)系统维护成本高,无运维人员:公司无专职运维人员,系统相对复杂,微服务架构 + APM工具等均采用开源自研,开发&维护成本高。聚石塔上ECS + Docker高密部署的降本方案,集群初始化非常繁琐且耗时较长,需给每台ECS安装探针,运行一系列初始化脚本。研发精力严重分散,疲于奔命。

    (4)效率&稳定性:系统的扩缩容困难,流量高峰时效率得不到保证。且服务发布和重启的时候偶尔会影响线上业务稳定。

    使用Serverless技术构建新型互联网医疗应用

    基于Serverless应用引擎(SAE),提供了一个零改造、开箱即用的Serverless PaaS,最大程度帮助用户屏蔽底层IaaS、K8s运维、以及常用微服务组件的学习成本,解决了禾连长期以来运维成本高、开发迭代和弹性效率低,硬件闲置成本高等痛点问题。

    image.png

    降成本:节省自建微服务架构+APM的ECS成本,无需购买ECS安全骑士服务;基于秒级弹性能力,按需自动弹、同时通过一键启停开发测试环境,极大的提升了资源利用率,比ECS方案节省20%以上的硬件成本。

    提效率:提供了开箱即用的微服务治理、应用监控的能力,零运维零改造直接使用,支撑新业务快速上线;提升定位诊断效率,让企业专注于业务本身。

    极致弹性,发布无感知:基于SAE 的定时弹性和监控指标弹性(CPU、Memory等),无须容量规划,秒级弹性,便可轻松应对流量暴增,保障SLA。通过配置健康检查探针,系统自动检测,做到服务发布和扩缩容时业务无感知。

    一站式体验:自动集成阿里云基础设施类产品:SLB、SLS、NAS等和微服务生态产品:ACM、ARMS、AHAS,对接DevOps产品云效,提供一站式的上云体验。

    ]]>
    消息队列在线迁移实战 | 最佳实践 Thu, 29 Oct 2020 12:16:15 +0800 前言

    消息队列(Message Queue,下文简称MQ)是分布式互联网架构中必不可少的核心组件,包括RocketMQ、Kafka、RabbitMQ等在业界广泛使用的产品,在消息分发、异步解耦、削峰填谷、广播通知等领域发挥着巨大的作用。

    在MQ的使用过程中,在线对MQ组件进行迁移是一个非常普遍的需求,在如下的几个场景中,都会涉及到MQ的在线迁移:

    (1)规格升级。比如将3 Broker的Kafka集群替换成6 Broker的Kafka集群。

    (2)更换另一种MQ产品。比如将RabbitMQ替换为性能和扩展性更强的RocketMQ。

    (3)使用云服务替换自建MQ集群。比如将自建的RocketMQ集群替换为云上商业版RocketMQ服务。

    在MQ迁移的过程中,存在3个非常重要的需求:

    • 操作简单。
    • 风险可控。
    • 不影响业务系统的正常运行。

    如何让MQ的在线迁移同时满足这3个重要的需求呢?本文将对几种可行的方式进行深入探讨。

    理论基础

    在涉及到MQ在线迁移的所有方案中,都存有一个很重要的原则:对于发往MQ的每一条消息,如果已经被它的消费者成功接收并得到处理,这条消息就不再具有业务含义。已经被成功接收并得到处理的消息,只体现出统计方面的价值,并不需要随着MQ本身的迁移而进行数据迁移。

    在数据库迁移的场景中,新旧DB之间的数据迁移是非常重要的工作,这是因为DB中的数据是持久化的数据,需要伴随着数据库的生命周期而长期存在。

    而对于MQ而言,消息一旦被消息者接收并得到处理,就不再是持久化的数据,可以直接删除或归档。因此在MQ在线迁移的场景中,对已经处理过的消息,是没有数据迁移必要的。这样就将问题简化为:如何在迁移的过程中确保每一条消息被成功接收并得到处理。

    在系统维护期停业务迁移

    我们先从一个最简单方案开始体验MQ在线迁移是如何进行的。对于不要求7*24小时连续运行的业务系统,可以利用系统维护期的时间窗口,通过停业务的方式来实现消息队列的迁移。这种迁移方式因为不需要保证业务的连续性,操作起来就非常简单。

    (1)初始状态

    image.png

    进入维护窗口期后,关闭生产者应用,这个时候不会再有的新的消息写入MQ:

    image.png

    在这个状态下保持一段时间,当MQ上的所有消息都被消费者接收并成功处理后,就可以对消费者进行版本发布,使其从新的MQ上接收消息:

    image.png

    接下来再启动生产者,使其指向新的MQ,整个操作就已经完成。当系统运行稳定后,可以对原MQ实例进行相关数据归档后直接下线:

    image.png

    在停业务迁移方案中,最关键一步,在于如何在系统维护窗口期之内,确保原MQ上的所有消息被消费者接收并成功处理。因为生产者关闭之后,不会有新的消息写入原MQ,只要预留足够长的时间,原MQ上堆积的消息一定会被消费者取走。在这个方案中,新MQ和原MQ也可以是不同的产品,比如从RabbitMQ迁移到RocketMQ也是可以支持的,因为生产者和消费者都经过了版本发布的动作,只需要在新版本中对API和收发逻辑进行修改就可以实现。

    双订阅方案

    在互联网领域,能够容忍维护期将业务暂停的系统越来越少了,7*24不间断服务是行业的趋势,上述的停业务迁移方案就不再适用了,如何在MQ迁移的过程中确保业务持续运行呢?

    有一个非常棒的idea是让消费者同时具有从原MQ和新MQ接收消息的能力,这样不管生产方往哪一个MQ发送消息,都能够确保消息得到及时的处理。这是一种不需要暂停业务的方案,我们来看一下具体的步骤。

    首先对消费者进行改造,使其同时连上新老两个MQ,具备同时从新老MQ接收消息的能力,这就是所谓的“双订阅”:

    image.png

    接下来对生产者进行发布,使其往新MQ发送消息,等原MQ上堆积的所有消息被消费者接收并成功处理后,就可以对原MQ下线:

    image.png

    在对原MQ下线的时候,因为消费者还保持着双订阅的状态,所以最好先切断消费者与原MQ的连接,再关闭原MQ,否则会造成一些异常(取决于SDK的实现)。如果消费者的订阅逻辑实现的足够优雅,可以在不重启消费者的情况下,通过一个指令在线切断消费者与原MQ的连接。

    这个方案看似可以用一种对业务无损的方式在线迁移MQ,在实际操作中可行性却很低,其根本原因在于:同时从两个MQ接收消息的改造工作量极大。一般情况下,每一个消费者都在引入MQ产品对应的SDK,并通过MQ提供接入点与MQ建立连接后,接下来就只需要围绕业务逻辑完成所需要的消息订阅操作。这个时候要想同时从一个新的MQ接入消息,需要在代码层面对所有的订阅逻辑进行改造,这是一项非常复杂的工作。

    在新MQ和原MQ是不同消息队列产品的情况下,消费者需要同时引入两套不同的SDK,改造难度会变得更大。基于双订阅方案完成MQ的迁移后,还需要考虑将来清理掉消费者从原MQ接收处理消息的遗留代码,这也是需要一定工作量的。

    如果在MQ和消费者中间,能有一个中间件来实现双订阅的逻辑,是不是消费者的代码就不需要改造呢?答案是肯定的。但引入这样的中间件本身就是一项非常有挑战的工作,还增加了整个系统的复杂度,如果仅仅是为了MQ的在线迁移而引入一个新的组件,是得不偿失的。

    基于工作量和风险的考虑,尽量不要使用双订阅方案。

    最优方案

    双订阅的本质,在于存在一个消费者可以同时接收新旧两个MQ消息的中间状态,在这个状态下,不管生产者往哪个MQ发送消息,消息都可以得到及时的处理。能不能有一种更简单的方式让消费者可以同时接收新旧两个MQ的消息呢?当然有,而且实现方式更加的简单。

    在一个可靠的分布式微服务系统中,应用都可以通过增加节点的方式而进行水平扩容,为了确保整套系统的高可用性,每一个应用都不应该长期处于单实例运行状态,而是通过多个无状态的应用实例组成一个应用集群。因此,在真实环境下,不管是消息的生产者还是消费者,都至少有2个实例在运行。在迁移MQ的过程中,“消费者可以同时接收新旧两个MQ的消息”的中间状态,并不一定要让消费者的每一个实例都通过双订阅来实现,其实只要让一部分实例从原MQ接收消息,另一部分实例从新MQ接收消息就能满足了。通过这样的思路,能极大程度上简化MQ迁移的工作量,而且在迁移的过程中确保业务不受任何影响。

    在迁移之前,需要先把元数据信息从原MQ复制到新MQ集群,不同的消息队列产品之前元数据的格式不一样,需要根据业务场景进行元数据的转换,元数据包括Topic、Queue、消费组、基础配置等信息。

    image.png

    首先,通过灰度发布机制,让一部分消费实例连上新的MQ。如果之前的消费者是单实例,这个时候也可以增加一个新的消费实例来完成这个步骤:

    image.png

    接下来,让生产者往新的MQ发送消息,这个操作并不一定需要采取一刀切的方式,也可以通过灰度发布的方式让消息的转向逐步转移到新的MQ上来。最终,原MQ将不再接收新的消息,它上面堆积的消息总将会被成功接收处理,这个时候可以继续通过灰度发布的方式解除消费者与原MQ的连接,连接全部解除完之后,原MQ就可以关闭了。

    image.png

    在这个方案中,对于单个的生产者和消费者,都不存在同时连接新旧两个MQ的情况,因此在改造工作量非常小。而且迁移的过程通过灰度的方式实现,既不会影响业务,又可以进一步的降低风险,是消息队列在线迁移的通用方案。

    常见问题

    问: 为什么不在新旧MQ之间进行消息数据的同步?

    答:对于MQ而言,消息一旦被消息者接收并得到处理,就不再是持久化的数据,可以直接删除或归档。在迁移的过程中,新旧MQ之间消息数据同步是没有必要的,反而会增加迁移的难度,并导致消息被重复接收。

    问:迁移过程中需要验证消息幂等性吗?

    答: RocketMQ、Kafka等大多数消息队列产品都没有从消息队列服务端本身确保消息只投递一次,需要消费者自行实现对幂等性的保证。因此,不管在消息队列的迁移过程中,还是正常使用中,都应该借助数据库、Redis等外部系统确保消息的幂等性,否则会造成业务逻辑重复处理。

    ]]>
    构建在线教育弹性高可用视频处理架构实战 Thu, 29 Oct 2020 12:16:15 +0800 前言

    近些年,在线教育行业飞速发展,为整个社会的知识传播提供了前所未有的便利性。通过多种形式的在线教育平台,学员与教师即使相隔万里也可以开展教学活动。借助丰富的网络课件,学员还可以随时随地的进行学习,真正打破了时间和空间的限制。在各种形式的网络课件中,视频课件自然是最直观表现力最丰富的形式,因此视频课件的市场占有率也在逐年提升。

    视频处理需求分析

    对于在线教育领域的视频课件出品方而言,每天都要对大量视频内容进行处理,下图展示了一个比较典型的场景:

    image.png

    (1)用户上传一个视频到平台后,会先在对象存储中对视频源文件进行暂存。

    (2)平台对视频进行预处理,并打上水印。

    (3)平台将视频文件转换为其他格式,并对分辨率进行调整,以适配各种不同的终端设备的要求。

    (4)将处理好的视频文件保存回对象存储,并同步到CDN进行加速。

    虽然从流程上来讲,这个场景比较简单,但在技术上的挑战其实是非常大的。视频课件的原作者来自于在线教育平台的广大用户,可能是平台负责内容输出的内部用户,也有可能是签约的教师,或者是平台认证过的分享型用户。用户上传视频的操作并没有固定的频率,往往集中在几个时间段,存在明显的波峰波谷。在业务高峰期,视频处理的需求量非常大,有的在线教育企业每天要完成数万个视频的转码工作。对于负责建设视频处理系统的技术团队而言,这样的业务场景就留给了他们一系列的挑战:

    (1)如何确保这套系统在业务高峰期的高可用性?

    (2)如何让每一个上传的视频尽可能快的处理完?

    (3)如何尽可能的降低资源成本?

    (4)如何高效率的应对需求的频繁变更?

    基于这几个诉求,我们结合云计算的特点,来分析一下可行的解决方案。

    使用SaaS化的云服务完成视频处理

    随着各大云计算厂商产品线的不断丰富,我们可以很轻松的寻找到开箱即用的方案来解决这类典型的视频处理需求。以阿里云为例,视频点播类产品提供了视频采集、编辑、上传、媒体资源管理、转码处理、视频审核分析、分发加速于一体的一站式解决方案。

    877.jpg

    对于技术团队而言,采用这样的方案不用预先准备任何计算资源,甚至不用编写任何代码,就能够从无到有拥有一整套视频处理系统,完全不用考虑资源规划的问题。这样的方案非常适合在业务发展初级需要让系统快速上线的场景。

    但随着业务的不断发展,开箱即用的SaaS化方案还是存在不少的局限性,基于如下的原因,大多数的技术团队还是会选择自己建设视频处理系统:

    (1)对于之前已经通过FFmpeg技术实现的视频处理服务,因为涉及到复杂的业务逻辑,很难直接迁移到SaaS化方案上来。

    (2)高阶的视频处理需求必须使用代码来实现:比如音频降噪、插入动态Gif水印、按固定频率截帧等等。

    (3)使用高分辨率的大视频是行业趋势,对于超大视频的处理,比如10G以上的1080P视频,往往需要通过自定义的手段进行计算优化,才能保证处理的及时性。

    (4)在很多种场景下,自建视频处理系统都会带来明显的成本优势。

    (5)频繁的业务需求变更需要对整套系统进行更精细粒度的迭代管理,比如采用金丝雀策略降低新版本发布所带来的风险。

    那么如何建设一套同时具备高性能、高可用性、高灵活性、低成本特点的视频处理系统呢?

    基于分布式集群

    最典型的方案是申请一组云虚拟机,在每台虚拟机上部署视频处理应用,组建成一个可以水平伸缩的服务集服。当有新的上频上传的时候,可以触发一个处理任务,并通过负载均衡或消息队列对任务进行分发,接到任务的应用节点负责完成对应的任务。

    image.png

    通过这个架构,在业务高峰期,用户上传视频行为比较密集,可以增加服务集群的实例数量,来提升处理能力。在业务低峰期,可以减少服务集群的实例数量,来减少资源成本。

    此方案可以通过定制化的代码逻辑实现各种高阶的视频处理需求,灵活度非常高,配合可以水平伸缩的计算集群以及负载均衡机制,能同时满足性能和成本方面的需求,是一套被广泛采纳的方案。但在生产环境大规模运行的情况下,这套方案还是会暴露出很多问题:

    (1)维护工作量大。

    整套系统的维护工作量涵盖了虚拟机、网络、负载均衡组件、操作系统、应用等多个层面,需要投入大量的时间和精力来保障系统的高可用性与稳定性。举一个最简单的例子,当某个应用实例出现故障的时候,如何第一时间定位故障并尽可能迅速的将其从计算集群中摘除,摘除之后又如何保证之前没有完成的任务能够重新得到处理呢?这些都需要再配合完整的监控机制、故障隔离恢复机制来实现,甚至涉及到代码层的业务逻辑优化。

    (2)弹性伸缩能力滞后。

    有两种方式实现计算集群的弹性伸缩:通过定时任务触发,或者通过指标阈值(CPU利用率,内存使用率等)触发。不管采用哪种方式,都没有办法基于用户行为精细化管理,在遇到任务密度大幅度起伏的时候,会面临弹性伸缩能力滞后的问题。当来自用户的视频上传请求突增的时候,新增一个应用实例需要经过申请云资源>初始化>部署应用镜像>应用启动>加入负载均衡列表等多个阶段,即便通过Kubernetes+预留资源池等技术优化,也往往需要10分钟以上。

    (3)资源利用率低。

    滞后的弹性伸缩能力会导致伸缩策略制定的相对保守,造成计算资源的大量浪费,增加了使用成本,如下图所示:

    image.png

    有没有一种方案能能帮助技术团队专注于业务逻辑的实现,并可以根据用户的实际上传请求进行精细化的资源分配,实现资源利用最大化呢?随着云计算的飞速发展,各大云厂商都在积极探索新的方案,用更加“云原生”的方式来解决成本和效率的问题,阿里云提供的函数计算 + Serverless工作流就是这个领域非常具有代表性的方案。

    函数计算

    阿里云函数计算是事件驱动的全托管计算服务。通过函数计算,开发者无需管理服务器等基础设施,只需编写代码并上传。函数计算会为自动准备好计算资源,以弹性、可靠的方式运行代码,并提供日志查询、性能监控、报警等功能,确保系统的稳定运行。

    相比传统的应用服务器保持运行状态并对外提供服务的方式,函数计算最大的区别是按需拉起计算资源对任务进行处理,在任务完成以后自动的回收计算资源,这是一种真正符合Serverless理念的方案,能最大化的提升资源利用率,减少系统系统维护工作量和使用成本。因为不需要预先申请计算资源,使用者完全不需要考虑容量评估和弹性伸缩的问题,只需要根据资源的实际使用量来进行付费。

    下图展示了函数计算的工作方式:

    image.png

    对于使用者而言,把实现关键业务逻辑的代码上传到函数计算平台,就能以事件驱动的方式触发函数执行。函数计算已经支持各种主流的编程语言,对于即有的代码,可以通过几个非常简单的步骤部署到函数计算。函数支持的所有开发语言请参考开发语言列表。

    每一次计算资源的分配,都基于事件的触发,一个事件往往对应着业务上的一个任务。函数计算支持多种多样的触发器,比如HTTP触发器的事件源就是HTTP请求,函数计算接收到一次HTTP请求后,会按照预设的规格,分配相应的计算资源来处理这个HTTP请求,请求处理完成之后,函数计算会根据用户的设置决定是否立即回收这一次拉起的计算资源。而OSS触发器,能够监控发生在对象存储OSS上的各种事件,当有用户上传新文件或者对文件进行修改的时候,自动触发函数执行,这种方式就刚好适合视频处理的业务场景。更多支持的函数触发器请参考触发器列表。

    在计算资源的调度上,函数计算进行了大量优化,面对用户请求的突增,可以在毫秒级拉起大量的计算资源来并行工作,确保用户体验。

    通过函数计算进行视频处理

    基于函数计算的特性,搭建一套视频处理系统就非常简单,只需要配置一个OSS触发器,并将视频处理的核心代码上传到函数计算,就大功告成:

    image.png

    通过这套方案,使用者不再需要考虑资源管理、负载均衡、系统高可用、弹性伸缩、系统监控等一系列复杂的问题,函数计算平台会按最优的方式根据用户的上传行为调度计算资源,低成本高效率的完成视频处理任务。具体的操作步骤和代码实现可以参考视频处理Python实现Demo,在这个Demo中,演示了如何基于函数计算将用户上传的视频统一转为640 * 480分辨率的mp4格式视频。

    代码开发

    每一个创建好的函数都会对应一个指定的入口,函数计算会从这个函数入口开始执行,类似于本地开发中的Main()函数。以Python语言为列,一个简单的入口函数如下:

    def handler(event, context):
        return 'hello world'

    当有事件触发的时候,就会从入口函数开始执行,其中event参数携带了事件源相关的信息,比如在视频处理场景中,event参数携带了上传到OSS的Bucket以及文件名等信息。而context参数携带了函数的运行信息,包括函数名、超时时间、访问凭证等。通过这些信息,就能让执行代码完成预定义的各种操作。

    函数计算支持各种主流的编程语言,在这个编程语言当中,Node.js和Python等脚本型语言含了丰富的类库,开发效率很高,而且运算实例启动的速度很快,能够支持对延迟特别敏感的任务,是函数计算最匹配的语言。Java和Go等语言不能像脚本型语言一样直接上传代码就能创建一个函数,需要预先进行编译,使用起来会稍微复杂一些,但配合函数计算提供的Funcraft等工具,也可以大幅度提升开发和部署的效率。不管使用哪种开发语言,都建议使用者下载官方提供的Funcraft工具,更轻松进行开发、构建、部署操作,请参考Funcraft。

    像Java这样的语言,在虚拟机启动的时候需要加载比较多的类库,不能够像实现运算实例毫秒级启动并进入执行状态,不能直接使用在一些对于延迟特别敏感的业务场景。但配合函数计算提供的预留实例以及单实例多并发新功能,能够消除冷启动对业务的影响,并降低等待下游服务响应的影响,让函数计算上运行的Java语言也能实现API网关等对延时要求特别高业务场景。请参考预留实例和单实例多并发。

    Serverless工作流

    通过前面介绍的方案,可以轻松完成对短视频的各种定制化处理。但每一个函数计算实例,在资源规格上和总运行时长都不是无限的,目前函数计算实例可以拥有3G的内存资源和10分钟的执行时间,这也就说明,当一个视频处理任务需要占用3G以上的系统内存,或者总执行时长超过10分钟的情况下,处理任务是会失败的。

    在5G时代,超大视频课件是非常普遍的需求,如何通过函数计算处理这样的大视频呢?这个时候就要出动另一个武器---Serverless工作流,来配合函数计算一起完成这个任务。

    Serverless 工作流是一个用来协调多个分布式任务执行的全托管云服务。您可以用顺序、选择、并行等方式来编排分布式任务,Serverless 工作流会按照设定好的步骤可靠地协调任务执行,跟踪每个步骤的状态转换,并在必要时执行用户定义的重试逻辑,以确保工作流顺利完成。Serverless 工作流通过提供日志记录和审计来监视工作流的执行,方便您轻松地诊断和调试应用。

    image.png

    您可以使用 Serverless 工作流编排一系列的函数资源,同时定义流程中每一步的输入和输出,使用内置控制步骤编排复杂逻辑、发起并行执行、管理超时或终止流程。另外通过控制台能够使用图形界面显示出执行任务状态和执行顺序,同时控制台会显示每个步骤的实时状态,并提供每次执行的详细历史记录。通过Serverless工作流 + 函数计算的组合,我们可以突破时间和空间的限制,对任意大小的视频文件进行复杂的处理。

    大视频处理

    简单来讲,处理一个大视频的基本思路是:

    (1)将视频先进行切片处理,把每一个分片的大小控制在合理的大小,以便单个函数计算实例可以对其进行快速处理。

    (2)拉起多个函数计算实例对每一个分片进行并行处理。

    (3)对处理结果进行合并。

    通过Serverless工作流 + 函数计算进行视频处理的流程如下:

    image.png

    通过Serverless工作流提供的可视界面,我们能在工作流执行的过程当中,方便的查看到每一个步骤运行的信息,并配合自定义的Dashboard实现对整套视频处理系统的全面监控:

    image.png

    方案对比22.png

    总结

    基于函数计算和Serverless工作流的弹性高可用视频处理架构,充分体现了云原生时代Serverless化思想,以事件驱动的形式触发函数执行,真实计算资源真正意义上的按需使用。

    对于使用而言,这套方案在保证业务灵活度的同时,可以显著降低维护成本与资源成本,并大幅度的缩短项目交付时间。

    在线教育领域对于视频处理的需求量非常大,而且对于处理速度、并发吞吐量、资源利用率等方面都有极高的要求,函数计算 + Serverless工作流方案组合帮助用户轻松建设弹性高可用的视频处理架构,是实现这些复杂需求的最优解。随着云原生的不断发展,Serverless相关技术还将深入更多的业务场景,有未来有无限可能!

    ]]>
    阿里云资深技术专家姬风:Serverless 引领云的下一个十年 Thu, 29 Oct 2020 12:16:15 +0800 十年前通过推出云服务器,云计算拿下了第一桶金。这种基于服务器的云服务,帮助客户节省了对 IDC 的机器采购和运维成本,同时也保持了传统服务器运维的习惯。但服务器里面运行的操作系统、应用软件,以及整个分布式架构的运维复杂度,依然没法得到彻底解决,企业为此也投入了大量成本。

    事实上,基于服务器的云服务并不是云时代的终态。

    试想一下,如果服务器的概念被进一步抽象,那么与服务器有关的维护工作都会变成由云来承担。这就是我们常说的Serverless。过去十年,云正在逐步向 Serverless 演进。阿里云最初发布的 ECS 是服务器抽象,随着云原生技术的发展,Docker 容器让应用运行变得简单,Kubernetes 让集群运维变得简单。

    2016 年,阿里云发布的函数计算提供了函数级抽象,2019 年发布的 SAE 提供了应用级抽象,这些产品都抹去了服务器的概念,让用云方式得到极大的简化,并逐渐成为趋势。Serverless 已经不仅仅只有函数一种形态,它应该有不同的抽象级别。

    阿里云有4种不同的 Serverless 产品,分别提供了容器实例、容器编排、应用、函数的抽象。抽象级别低的产品,客户会拥有更大的管理灵活度;抽象级别高的产品,由云承担的工作会越多,客户的研发和运维的效率也会越高。

    这些 Serverless 产品可以给客户、给开发者带来什么样的价值呢?

    Serverless有三大核心价值:

    一是快速的交付:Serverless 通过进行大量的端对端整合以及云服务之间的集成,为应用开发提供了最大化的便利性,让开发者无需关注底层的 IaaS 资源,而更专注于业务逻辑开发,聚焦于业务创新,大大缩短业务的上市时间。

    二是极致的弹性:在 Serverless 之前,一旦遇到突发流量,可能会直接导致各种超时异常,甚至是系统崩溃的问题。即使有限流保护以及提前扩容等手段,依然会出现评估不准的情况,进而引发灾难性的后果。有了 Serverless 之后,由于具备毫秒级的弹性能力,应对突发流量会变得更加从容。

    三是更低的成本:就跟生活中用水电煤一样,我们只为实际消耗的资源买单,而无需为闲置的资源付费。Serverless 提供的端到端的整合能力,极大地降低运维的成本与压力,使 NoOps 成为可能。

    基于快速交付、智能弹性、更低成本的三大核心价值,Serverless 被认为是云时代的全新计算范式,引领云在下一个十年乘风破浪。 那么下一个十年的 Serverless 将会有什么趋势呢?

    第一,标准开放。通过支持开源的工具链和研发框架,Serverless 能够在多云环境下使用,无厂商锁定,免除客户后顾之忧。

    第二,云原生结合。与业界认为容器和 Serverless 有对立关系不同,阿里云 Serverless 将借助容器出色的可移植性和灵活性,实现应用交付模式统一;通过复用云原生生态,Serverless 在存储、网络、安全、可观测等方面更加标准、强大。

    第三,事件驱动。通过采用统一的事件标准,如 CloudEvent来建立云上的事件枢纽,让 Serverless 开发集成云服务、云边端应用更简单。

    第四,解锁更多业务类型。Serverless 早已不再局限在代码片段、短任务、简单逻辑,长时间运行、大内存的任务,有状态的应用,以及 GPU/TPU 的异构计算任务都会在 Serverless 产品上得到支持。

    第五,更低成本。在使用成本方面,采用 Serverless 产品的 TCO 会比基于服务器自建更低,一方面是引入预付费等计费模式,比按量节省 30% 以上;另一方面,随着 Serverless 不断演进,更大的资源池、更高的资源利用率,成本会进一步压低。在迁移成本方面,可以通过选择不同形态的 Serverless 产品,采用迁移工具,甚至一行代码不改,存量应用就能迁上 Serverless,享受 Serverless 红利。

    阿里巴巴的 Serverless 实践在业内处于领先地位,不仅淘宝、支付宝、钉钉、闲鱼等已经将 Serverless 应用于生产,Serverless 产品更为新浪微博、石墨文档、跟谁学、Timing 等各行各业的企业提供服务,助力企业快速数字化。而能够做到这些,离不开阿里云在 Serverless 战略上的坚持与技术投入。

    Serverless如何开启云的下一个十年,闲鱼是如何布局Serverless?一个没有服务器的世界是什么样子的?所有关于Serverless的热点话题,我们将在9月18日13:00 云栖大会「Serverless,引领云的下一个十年」全面揭秘!

    serverless海报.png

    扫码或点击预约直播,获取Serverless 实践与趋势解读。

    ]]>
    2020年容器应用的新思考 Thu, 29 Oct 2020 12:16:15 +0800 阿里云容器服务自从2016年5月正式推出,已经走过4年的旅程,服务了全球上万家企业客户。过去几年,阿里云和业界各位共同见证了容器技术的快速发展。

    容器镜像已经成为了分布式应用交付的标准,Kubernetes已经成为了分布式资源调度的标准:向下封装资源,向上支撑应用,已经成为了云应用操作系统,帮助应用以一致的方式运行在公共云、边缘计算和专有云环境中。在Kubernetes之上,也浮现出服务网格等新技术,进一步简化分布式应用架构开发和运维。

    阿里云提供了经典的云原生容器产品,包括:

    • Kubernetes服务 ACK,提供云端最佳容器运行环境
    • 镜像服务 ACR,管理各种云原生应用资产
    • 托管服务网格 ASM,加速新一代云原生应用架构落地

    容器已经无处不在了。越来越多的应用,通过容器方式进行管理、交付,从Web应用、数据库、消息等中间件,再到数据化、智能化应用。

    基于容器技术构建的新架构,会催生新的应用业务价值。其中,云原生 AI 是非常重要的应用场景,快速搭建 AI 环境,高效利用底层资源,无缝配合深度学习的全生命周期。好未来的AI中台基于容器服务搭建, 不仅帮助AI服务应对各种资源的急剧增长,而且解决了5个9的SLA需求。好未来AI中台技术负责人刘东东将会在18日的分享中详细讲述更多技术落地细节。

    作为容器服务的提供者,容器技术会继续发展,被应用于“新的计算形态”、“新的应用负载”和“新的物理边界”。云原生技术理念使企业用户及开发者只需要关注应用开发,无需关注基础设施及基础服务。

    因此除了上述的三款经典产品,阿里云还推出了 Serverless容器服务(ASK)和边缘容器服务(ACK@Edge)两款产品。

    Serverless容器服务(ASK)遵循Serverless 理念,将应用服务资源化并以 API 接口的方式提供出来,使用者只需从客户端发起调用请求即可,更重要的是,pay as you go 能够真正为用户节省成本。18日的分论坛演讲中,微博架构师胡春林先生将分享微博如何基于Serverless容器应对突发热点。

    此外,容器最被熟知的基础环境是数据中心,在业务流量高峰与低谷之时,凭借容器极致弹性可以实现应用与资源伸缩,有效地保证高利用率与高性价比。随着 5G 和物联网时代的到来,传统云计算中心集中存储、计算的模式已经无法满足终端设备对于时效、容量、算力的需求。将云计算的能力下沉到边缘侧、设备侧,并通过中心进行统一交付、运维、管控,将是云计算的重要发展趋势。以 Kubernetes 为基础的云原生技术,在任何基础设施上提供与云一致的功能和体验,实现云 - 边 - 端一体化的应用分发, 支持不同系统架构和网络状况下,应用的分发和生命周期管理,并且针对边缘及设备进行如访问协议、同步机制、安全机制的种种优化。

    容器可以适用于多种基础环境,比如数据中心、边缘云、和多云 / 混合云,使得开发者关注回归到应用本身。今年,阿里云容器服务也将迎来一系列新产品特性,并在9月18日「企业云原生创新与实践」分论坛上重磅发布。我们提前揭秘其中一部分新产品。

    第一个是容器服务ACK Pro版。它是针对金融、大型互联网、政企客户对安全、稳定、规模的更高需求,推出的高度优化的K8s运行环境。它具备几个关键优势:

    (1)基于神龙架构,软硬一体化优化设计,提供卓越性能;
    (2)提供高效调度能力,可以有效优化计算成本;
    (3)为企业提供全面安全防护,国内首批通过可信云容器安全先进性认证。

    ACK Pro正式商用后将提供可赔付的SLA。

    第二个是基于ACK的云原生AI加速器。Gartner预测到2023年,70% AI应用构建在容器和Serverless环境中。在过往的几年,阿里云帮助众多企业和阿里云计算平台等内部团队基于云原生技术构建AI平台。通过容器服务Kubernetes,可以对多种异构计算资源进行统一管理,提升资源利用率,降低计算成本。通过GPU共享等技术可以实现资源利用率2~4倍提升。

    通过K8s调度优化和分布式缓存等技术,可以提升AI计算效率。在模型训练场景,计算效率提升20%。此外,通过对AI任务提供统一流程管理,构建可重现、可移植、可组装的的AI流水线,AI工程效率可以提升50%。在此基础上,容器服务ACK推出云原生AI加速器,将把异构计算资源管理、调度优化,AI任务流水线,和上层AI算法引擎等全栈优化能力有机整合在一起。 它面向企业AI平台建设者,可以让客户自由组合各层能力,构建符合自己需求的AI平台, 加速算力的释放。

    以好未来为例,它是K12在线学习的领头羊,基于ACK的云原生AI加速器,提供了上百个AI服务。峰值请求量达每天8000万次。通过GPU共享调度,节省了近50%的资源成本。

    第三个是容器镜像服务企业版 ACR EE。它为众多跨国企业、互联网、在线教育、游戏等公司提供企业级云原生应用管理和分发能力。ACR EE支持容器镜像和所有符合OCI标准的应用制品管理,比如Helm Chart。以欢聚时代为例,它作为互联网出海的代表企业,其容器化应用需要在全球多地域、多 IDC 部署。使用 ACR EE,全球应用分发效率提高 85% ,成本仅为自建 1/3。

    第四个是阿里云托管服务网格ASM。Gartner预测,81%的企业将采用多云/混合云战略,混合云架构已经成为企业上云的新常态。在云原生时代,以Kubernetes为代表的技术屏蔽了基础设施的差异性,可以帮助企业在混合云环境下,进行统一资源调度和应用生命周期管理。

    阿里云托管服务网格ASM,是业内首个全托管,与Istio全兼容的服务网格产品。 服务网格的控制平面的组件托管在阿里云侧,用户集群只包含数据平面组件。这个架构解耦了服务网格与K8s集群的生命周期,简化升级和问题诊断;提升了系统的可伸缩性和稳定性。此外ASM全面整合阿里云可观测性、安全等能力,大大简化了服务网格生产环境的运维管理。

    9月,ASM正式商用,阿里云容器服务负责人易立将在9月18日云栖大会「企业云原生创新与实践」分论坛详细介绍ASM的新特性。

    去年阿里云发布边缘容器服务ACK@Edge。帮助企业将云计算能力延展到边缘,降低应用网络延时,简化海量设备的分布式管理。短短一年,已经广泛应用于音视频直播、云游戏、工业互联网、交通、物流、能源、城市大脑等应用场景中。

    这一次,ACK@Edge 与阿里云智能接入网关服务 SAG 共同推出多链路、云边协同的网络方案,具备安全加密、就近接入、即插即用等多种能力,使能边缘资源、业务一站式接入上云。在边缘计算领域,阿里巴巴云原生边缘计算平台 OpenYurt 在9月9日正式成为 CNCF 沙箱级别项目(Sandbox Level Project),标志着 OpenYurt 在边缘计算场景中构建云原生基础设施的能力受到了行业的广泛认可。

    此外,在本次云栖大会上,阿里云原生还将发布沙箱容器 2.0等重磅产品,通过核心技术解读与案例分享,帮助企业获得更加敏捷、高效的容器实现。

    更多精彩内容,敬请期待9月18日13:00 「企业云原生创新与实践」分论坛。

    18 企业云原生-商圭.png

    预约直播:https://yunqi.aliyun.com/2020/session88

    ]]>
    首届云原生编程挑战赛精彩盘点:他们如何从10000多支团队中脱颖而出? Thu, 29 Oct 2020 12:16:15 +0800

    云原生编程挑战赛,是“中间件性能挑战赛”的升级,赛题升级、赛道升级、报名团队数超过10000支,创下同类大赛报名新高。

    9月14日,阿里云原生编程挑战赛决赛答辩线上直播完美落幕,10支进入决赛的团队用精彩的答辩,为历时4个月的大赛画下了圆满的句号。其中,greydog团队以出色的方案、创新的优化思路、过硬的技术实力斩获冠军。

    大赛专家评审团认为,greydog团队的方案思路清晰,提出的7个技术优化点具有可落地性,在冷启动处理、OOM处理和大压力请求或超多函数场景下的解决思路具有很高的借鉴意义,能深入到赛题核心,勇于创新,具有较高的技术价值和应用价值。

    冠军.jpg

    ONE PIECE团队、睡衣小英雄团队并列亚军,四字成语团队、afkbrb团队、穿山甲团队获得季军。另外四支团队:井底虾蟆笔尖蛙Errr、hello,靓仔、亚洲王子王云轩、hehehlin获得优秀奖。

    阿里云研究员、本次云原生编程挑战赛的决赛评委之一的叔同,在决赛答辩结束后,跟在场的选手们分享了他对于云原生的理解。

    “过去我们常以虚拟化作为云平台和与客户交互的界面,为企业带来灵活性的同时也带来一定的管理复杂度;容器的出现,在虚拟化的基础上向上封装了一层,逐步成为云平台和与客户交互的新界面之一,应用的构建、分发和交付得以在这个层面上实现标准化,大幅降低了企业 IT 实施和运维成本,提升了业务创新的效率。

    从技术发展的维度看,开源让云计算变得越来越标准化,容器已经成为应用分发和交付的标准,可以将应用与底层运行环境解耦;Kubernetes 成为资源调度和编排的标准,屏蔽了底层架构的差异性,帮助应用平滑运行在不同的基础设施上;在此基础上建立的上层应用抽象如微服务和服务网格,逐步形成应用架构现代化演进的标准,开发者只需要关注自身的业务逻辑,无需关注底层实现,云原生正在通过方法论、工具集和理念重塑整个软件技术栈和生命周期。

    以容器为代表的云原生技术,用开放、标准的技术体系,帮助企业和开发者在云上构建和运行可弹性扩展、容错性好、易于管理、便于观察的系统,已经成为释放云价值的最短路径。最早创造和应用容器技术的是互联网公司,今天有了开放标准的云原生生态,使得容器技术得到迅速普及,越来越多的企业和开发者使用容器构建应用,共同享受这一技术红利。”

    一、为什么决赛选择了Serverless这一技术方向?

    十年前通过推出云服务器,云计算拿下了第一桶金。这种基于服务器的云服务,帮助客户节省了对 IDC 的机器采购和运维成本,同时也保持了传统服务器运维的习惯。但服务器里面运行的操作系统、应用软件,以及整个分布式架构的运维复杂度,依然没法得到彻底解决,企业为此也投入了大量成本。

    事实上,基于服务器的云服务并不是云时代的终态。
    试想一下,如果服务器的概念被进一步抽象,那么与服务器有关的维护工作都会变成由云来承担。这就是我们常说的Serverless。过去十年,云正在逐步向 Serverless 演进。阿里云最初发布的 ECS 是服务器抽象,随着云原生技术的发展,Docker 容器让应用运行变得简单,Kubernetes 让集群运维变得简单。

    阿里云Serverless负责人、本次云原生编程挑战赛决赛评委之一的不瞋在分享中提到,2016 年,阿里云发布的函数计算提供了函数级抽象,2019 年发布的 SAE 提供了应用级抽象,这些产品都抹去了服务器的概念,让用云方式得到极大的简化,并逐渐成为趋势。Serverless 已经不仅仅只有函数一种形态,它应该有不同的抽象级别。

    总的来看,Serverless有三大核心价值:

    一是快速的交付:Serverless 通过进行大量的端对端整合以及云服务之间的集成,为应用开发提供了最大化的便利性,让开发者无需关注底层的 IaaS 资源,而更专注于业务逻辑开发,聚焦于业务创新,大大缩短业务的上市时间。

    二是极致的弹性:在 Serverless 之前,一旦遇到突发流量,可能会直接导致各种超时异常,甚至是系统崩溃的问题。即使有限流保护以及提前扩容等手段,依然会出现评估不准的情况,进而引发灾难性的后果。有了 Serverless 之后,由于具备毫秒级的弹性能力,应对突发流量会变得更加从容。

    三是更低的成本:就跟生活中用水电煤一样,我们只为实际消耗的资源买单,而无需为闲置的资源付费。Serverless 提供的端到端的整合能力,极大地降低运维的成本与压力,使 NoOps 成为可能。

    基于快速交付、智能弹性、更低成本的三大核心价值,Serverless 被认为是云时代的全新计算范式,引领云在下一个十年乘风破浪。

    二、他们凭什么赢得阿里云众多技术专家的认可?

    今年是云原生编程挑战赛的第一年,是过去5年“中间件性能挑战赛”的升级。大赛一经发布,就吸引了众多开发者和高校学生的注意力。据统计,本次云原生编程挑战赛总计报名团队11060支,初赛分为三大并行赛道:【赛道1】实现一个分布式统计和过滤的链路追踪;【赛道2】实现规模化容器静态布局和动态迁移;【赛道3】服务网格控制面分治体系构建。

    通过三大赛道,为参赛团队更多的选择,从而让更多的开发者能够加入到比赛中来。

    正如云原生编程挑战赛负责人天北所说,“为了让这么庞大的参赛团队有充足的时间备战,同时也给评委更多的时间从这么多优秀的团队和作品中做出合理公正的选择,我们将大赛的赛程设置为4个月的长期赛,对于每个坚持到最后的参赛团队而言,都是一场脑力与耐力的比拼。在大赛结束之后,我们也会把优秀的作品分享出来,让大家了解这次大赛的技术方案和参赛团队的一些创新的想法,从而赋能更多的开发者。”

    本次大赛与其他编程类大赛最大的不同在于,云原生是未来十年最热的技术趋势之一,对于每一个参赛团队而言,所要处理的技术问题和挑战,都是未来大家真正深入到工作中会用到的方法和技能。每个赛题都来自于阿里云技术专家多年的实践思考,从技术痛点出发,真正能帮助选手了解Serverless、Service Mesh、Kubernetes等当下热门技术的核心。在这段比赛旅程中,阿里云的技术专家全程在钉钉群中为选手答疑解惑,启发大家从技术本身出发了解云原生是什么,解决什么问题,未来还有哪些想象力。

    能从10000多支团队中脱颖而出,这十支战队有何“秘密武器”?

    在赛后对这些参赛团队采访时,我们发现,他们对于新技术和新趋势抱有极大的学习热情,对于不懂的知识点会抽出时间来学习,对于已完成的方案仍然十分挑剔,每一处优化都希望尽可能达成更极致的效果。经历了4个月的磨砺,对于坚持到最后的这10支队伍而言,不仅结交到了一群热爱技术的朋友,更拓展了视野,接触到了最前沿的技术趋势。

    而这4个月,对于选手的考察不仅是脑力的比拼,更是耐力的考验。在答辩现场,面对众多阿里云技术专家的“灵魂拷问”,这些选手们能够从容不迫地阐述方案、讲解技术优化思路,并在与专家们的交流中收获经验。

    900.png

    三、云原生在未来十年将进一步释放技术红利

    云的技术发展会领先于企业落地的速度。尽管云原生技术已经被广泛接受,其在企业技术栈的落地仍然需要时间,也面临不少挑战。如容器化过程中改变传统虚拟机模式下的运维习惯,企业传统应用分布式微服务化的改造涉及 re-architecturing 等因素。

    云原生被企业接受之后,落地的过程需要解决这些挑战。运维管理含有丰富组件并快速演进的云原生的基础设施也对企业 IT 人员的技术技能提出了更高的要求。但是我们坚信,云原生技术带来的资源成本降低,研发运维效率提升等巨大价值,会驱动企业迎接这些挑战。

    在这个过程中,使用云原生上云,基于容器和服务网格等标准界面和混合云方案,将极大的降低迁云复杂度,使企业可以更快迁移到云上标准服务。**通过云原生上云最大化使用云的能力,高效的社会分工,使企业聚焦于自身业务发展,相信将成为企业的共识。
    **

    在企业迈入云原生的历程中,阿里云原生也将提供最大的助力。阿里云拥有国内最丰富的的云原生产品家族,最全面的云原生开源贡献,最大规模的云原生应用实践,最广泛的云原生客户群体,助力企业数字化转型。全链路压测、极速弹性扩缩容以及云原生的全栈技术已广泛服务于互联网、金融、零售、制造、政务等领域企业和机构,大幅降低了应用开发的门槛,让企业轻松享受云的技术红利。

    对于云原生从业者来说,最大的挑战之一就是兑现新技术给业务带去的价值。站在新的一个十年起点,云原生从业者应当坚定自己对于新技术价值的理解和洞察,沉下心去将云原生的基础能力建设好,创造行业趋势,为云计算的发展做出自己的贡献。

    今年是云原生编程挑战赛的第一年,是一个非常好的开始。我们看到越来越多年轻的技术力量融入到云原生的技术浪潮里,因为相信,所以看见。这些跳动的思考、新鲜的血液、创新的方案也将成为中国云原生技术发展生生不息的动力源泉。

    决赛答辩方案介绍:
    https://tianchi.aliyun.com/forum/?spm=5176.12282029.0.0.72d86fdcIExKCw#raceId=231793

    点击决赛答辩,观看云原生编程挑战赛决赛答辩盛况。

    ]]>
    技术与业务同行:我是如何在业务中成长的? Thu, 29 Oct 2020 12:16:15 +0800 作者:慕扉

    应用实时监控服务ARMS(Application Real-Time Monitoring Service)是一款应用性能管理(APM)产品,包含应用监控、Prometheus监控和前端监控三大子产品,涵盖分布式应用、容器环境、浏览器、小程序、App 等领域的性能管理,能帮助用户实现全栈式性能监控和端到端全链路追踪诊断,让应用运维从未如此轻松高效。

    我主要负责阿里云ARMS前端监控平台,该业务更偏向于技术类产品。我想聊聊如何在业务中成长,期间也有困惑和迷茫,希望我的经历或者方式方法能给有类似情况的前端同学有所帮助。

    我个人的成长主要分为三个阶段,分别是:

    (1)监控领域初接触,建立自身监控知识体系
    (2)业务痛点跟进,打造监控平台核心能力
    (3)业务场景不断拓展,建立保障业务稳定体系

    监控领域初接触,建立自身监控知识体系

    最初业务面临的问题:业务上线之后,用户在实际访问时遇到错误,业务方无法快速感知;发生线上故障后,很多场景无法快速复现和排查原因等。基于业务的这些痛点,团队决定搭建前端监控平台来解决这些问题。

    我是从Retcode2.0正式开始接触前端监控领域,面对一个新的领域,需要快速从0-1建立自身监控知识体系。这个过程是非常充实且充满挑战的,但当你完成这个阶段后会非常有成就感。面对未知和挑战,这里总结一下我认为比较重要的经验。

    勇于打破自己的边界,拓展自己的技术栈

    前端监控的整个体系简单总结一下:采集、日志存储、日志切分&计算、数据分析、告警,也就是工作不再局限于前端业务的开发工作,需要有Nginx服务运维能力、实时/离线分析能力、Node应用开发运维能力等等,所以我迈出了第一步,从前端->全栈的转变,让我整体熟悉并能把控前端监控从采集到最后告警诊断整个流程,在这个基础上让我后续能Cover整个监控平台。

    Owner意识

    对于负责的产品需要具备较强的Owner意识,把工作做大做强,服务好客户。每一个功能的开发、迭代、优化及创新,认真对待,保障每个环节做到最好。在这个过程中,我的角色也发生了改变,从最初的功能实现落地者到产品能力的主导技术方案的选型拍板者,这段时间的复盘让我不经意间意识到自己的这些变化。

    以我自己的一个经历为例:最初日志服务器的部署是运维同学直接在机器上配置好,再提供服务。我接手后就遇到了一个比较大的问题:扩容。正常应用扩容是很简单的事情,通过PSP提交扩容申请单,可快速完成扩容。但当前Nginx日志服务没有基线配置,无法直接PSP扩容,只能手动配置。

    对于扩容来说,当前的方案存在2个问题:

    (1)手动配置扩容时间成本高
    (2)无法有效保证所有机器上各类包的版本号一致。

    为了解决这些问题,就需要了解Nginx日志服务的能力及运维相关的能力,通过与PE、后端同学讨论,最终决定采用Dokcer的形式解决当时扩容的问题,不仅提升了运维效率,也为后续海外业务支持打好了基础。
    所以给到大家的建议是,不要单纯的完成产品的一个个功能,而是要有Owner意识,认真审视业务面临的问题,能够主动去跟进和改变,慢慢积累后续会产生质变。

    业务痛点跟进,打造监控核心能力

    平台从0-1搭建完成后,为了服务更多的业务,打磨产品能力,正式上云升级为阿里云ARMS前端监控平台。监控的基础能力已全部上线,后续如何发展是我需要思考的问题。如果后续在这个基础上一直做迭代优化,产品和个人都没有明显的突破与成长。

    针对技术类产品,大部分是技术同学主导,在产品发展到一个阶段后,就会面临如何做后续的突破问题。我有两点建议:

    (1)深入业务面临的问题,制定技术解决方案。

    首先问自己几个问题:
    • 业务方是谁?
    • 现在业务在用自己的产品的时候都有哪些问题?
    • 业务的诉求是什么?
    • 自己的产品存在哪些问题?

    深入挖掘这些问题,列出TOP5的答案,会发现有很多值得去做和突破的事情。

    在最初的前端监控领域,产品都集中在针对采集上报的数据做统计展示阶段,通过数据指标的波动情况发现异常,然后接下来异常的定位则直接依赖于原始日志,原始日志如果覆盖不到信息,则只能靠业务同学自己复现和排查了。更多时候统计的数据无法解释,直接导致业务同学对数据的准确性产生质疑。所以监控产品要从最初的数据统计演进为问题定位。在这个阶段,主导并补齐相应的问题诊断链路。

    (2)拓展视野 (技术&业务)

    在主导一个产品方案/制定技术方案前,需要提前调研,辅助做出决策。调研的目的是拓展自己的技术&业务视野,其中对应的途径可以有:

    • 竞品分析:当前成熟的产品听云、dynatrace、oneAPM等;

    • 相关联领域同学输入/讨论:产品、后端应用监控同学等。

    一个线上问题的排查,不是独立的前端监控或者应用监控就直接给到原因的,拓展自己认知的领域后,与后端中间件同学讨论,最终制定提供全链路监控的方案,来满足业务排查问题的诉求。通过这个案例可以看到,如果不跨出一步,是看不到也无法给出方案的。

    业务场景不断拓展,建立保障业务稳定体系

    在产品能力整体趋于稳定后,如何寻找自己的突破口?我也曾经走过误区,希望自己在技术上能有突破,所以出发点是现在有哪些技术可以在我的产品上体现出深度,直接导致越考虑越迷茫。其实,正确的出发点仍然是第二部分提到的:从业务痛点出发来制定解决方案。在这一部分不再是单点解决问题,而是体系化的考虑方案。

    我有几点经验可以分享下:

    开放的心态,合作共赢

    技术类产品会收到各个业务方的诉求,在人力有限的情况下要支持各类诉求难度很大。这时候摆正心态,可以拉诉求方同学合作共建,更好的满足业务方诉求,同时让产品也不断拓展支持场景。

    前端技术发展非常迅速,在最初小程序迅猛发展的时候,小程序的监控诉求也随之而来。但当时团队对于小程序的技术架构等并不熟悉,在此基础上做监控成本较大。其中钉钉有较多的访问量级较大的小程序,对于监控有较强的的诉求,在综合考虑业务诉求和产品拓展后,与钉钉同学合作共建支持各类小程序的监控诉求。在这次合作中,让我深刻体会到优势互补、事半功倍的效果。

    体系化建设

    在前期完成对于整个体系的了解,后续可以从这个体系涉及的各个环节来综合考虑解决方案。

    随着业务的不断接入,监控所需的计算资源、存储资源等问题不断暴露出来,这时候我的工作不仅要保障业务稳定,更要保障平台稳定,所以在采集阶段、上报阶段、存储阶段、计算阶段考量制定保障方案。完成体系化稳定性建设后,不仅可以在大促前1分钟发现风险,也可以保障平台稳定支持大促中各类站点的监控诉求,并且在大促后沉淀赋能于日常的稳定性运维工作。

    结束语

    每个人的经历与负责的工作各不相同,无法直接照搬别人成功的经验,同时很多总结的点都是知易行难,但可以从优秀同学的经验及总结中找到自己认可的内容,坚持并不断在自己身上实践,只有不断实践才能慢慢转化为自己的能力。

    推荐文档:
    阿里云业务实时监控服务ARMS:https://www.aliyun.com/product/arms
    阿里云业务实时监控服务ARMS前端监控:https://arms.console.aliyun.com/#/retcode
    阿里云业务实时监控服务ARMS前端监控文档:https://help.aliyun.com/document_detail/58652.html

    ARMS是阿里云原生团队非常重要的一款产品。目前已经服务了如人人视频、完美日记、畅捷通等众多客户,云原生中间件的技术和产品体系,如何帮助企业降低业务的运行成本和技术风险?如何提升业务的迭代速度?针对云原生场景下常见的技术挑战和痛点,阿里云、人人视频、畅捷通技术专家有哪些技术经验和思考?我们将在9月18日13:00 云栖大会「云原生中间件」全面揭秘!

    中间件分论坛(二维码).jpg

    扫码或点击阅读原文预约直播,获取云原生中间件的实战经验和落地思考。
    阅读原文:https://yunqi.aliyun.com/2020/session91

    ]]>
    解构云原生,从概念到落地:阿里云、声网、微博、好未来、CNCF的专家们怎么看? Thu, 29 Oct 2020 12:16:15 +0800

    钉钉2小时内扩容1万台云主机支撑2亿上班族在线开工,申通快递核心系统云原生化上云,日均处理订单3000万,IT成本降低50%,中国联通建成最大云上BSS系统支持3.6亿用户无缝覆盖,完美日记采用容器服务ACK,节省服务器成本50%以上,轻松应对大促……

    这些案例的背后正是云原生的普及,推动全社会加速享受技术红利。 从2009年首次上线核心中间件系统,到2011年淘宝天猫开始使用容器调度技术,再到推出自研云原生硬件神龙服务器、云原生数据库PolarDB,阿里已经在云原生领域深耕数十年。2019年双11之前,阿里核心系统完成100%上云,这也是全球规模最大的云原生实践。

    目前,阿里云已将基础设施全面升级云原生。关于云原生,我们曾在年初发布了:2020 云原生7大趋势预测。对于云原生从业者而言,2020年最大的挑战就是兑现新技术给业务带去的价值,那么过去一年,阿里云原生取得了哪些成果?又有哪些企业接受了云原生的技术理念从而加速业务升级?

    让我们在云栖大会做一次整体的汇报。作为今年云栖大会的重磅热点之一,云原生有哪些新玩法?

    四大分论坛,拆解云原生技术实践

    分论坛一:企业云原生创新与实践

    以前一家企业想使用云原生的技术或产品,需要花费大量的精力研究一些开源项目,自己做运维和管理,还需要考虑集成、稳定性保障等问题,这样才能建立一个云原生平台。今天,为了方便企业和开发者更容易地使用云原生的技术和产品,更好地接受云原生的理念,并解决企业担忧的可靠性、性能、连续性等问题,阿里云为大家提供了一整套云原生产品家族,提供了非常强的 SLA 保障。

    18 企业云原生-商圭.png

    在企业云原生创新与实践分论坛,不仅有阿里云技术专家分享容器技术、Serverless容器、云原生基础设施、底层系统等产品升级和发展演进,还邀请了来自好未来、声网、新浪微博、CNCF的技术专家分享云原生实践的历程、开源项目和经验思考。

    分论坛二:云原生中间件

    如果把企业内部的业务比喻为一个城市系统,这个城市中的IT机构就是像水、电、煤一样的基础设施,那么中间件就类似于输水管道,推动着数据从一个应用流向另一个应用。而在云计算时代,中间件又被赋予了新的定义,那就是对云原生的支持。

    中间件海报.png

    本论坛将全面解读如何利用阿里云原生中间件的技术和产品体系,帮助企业降低业务的运行成本和技术风险,提升业务的迭代速度。同时,针对云原生场景下常见的技术挑战和痛点,分享技术经验和思考,并深入探讨云原生中间件如何加速企业数字化转型等热点话题。

    分论坛三:Serverless,引领云的下一个十年
    试想一下,如果服务器的概念被进一步抽象,那么与服务器有关的维护工作都会变成由云来承担。这就是我们常说的Serverless。过去十年,云正在逐步向 Serverless 演进。阿里云最初发布的 ECS 是服务器抽象,随着云原生技术的发展,Docker 容器让应用运行变得简单,Kubernetes 让集群运维变得简单。

    serverless海报.png

    Serverless将开发人员从繁重的手动资源管理和性能优化中解放出来,就像数十年前汇编语言演变到高级语言的过程一样,云计算生产力再一次发生变革。与其说Serverless是云计算的升华,不如说Serverless重新定义了云计算,将成为云时代新的计算范式,引领云的下一个十年。对于Serverless的热点话题,我们在Serverless分论坛邀请众多大咖一起来碰撞新思考。

    分论坛四:企业数字化转型最佳实践

    云原生,是云计算的再升级,也是企业数字化转型的最短路径。阿里巴巴作为中台概念提出者和践行者,积极推动中台发展,并完整提出从理论到实践的企业数字化转型最佳路径。本论坛将介绍业务中台技术解决方案产品为基础,围绕服务能力的标准化、可复用、可扩展、可视化、可管控等要素提供新方法和新工具,帮助业务中台实施落地。

    业务中台海报.png

    一场Serverless重磅新品发布

    在云栖大会新品发布会上,阿里云智能研究员丁宇将重磅发布4个Serverless生态产品,助力阿里云Serverless的快速发展。

    • 沙箱容器2.0:阿里云Serverless产品的基石,更稳定、更安全、更弹性。
    • EventBridge:云上事件枢纽,原生支持CloudEvents,更标准、更规范。
    • Serverless工作流:提供简单灵活、可视化的函数编排,更直观、更便捷。
    • 函数计算2.0Plus:携手开发者工具+应用中心,引领开发者体验全面升级。

    叔同海报22.jpg

    在9月18日13:00 云栖大会上,丁宇将详细讲解四大产品的特性和应用实践,扫码订阅直播,第一时间获得直播开始通知。

    一场面向生态合作伙伴的分享

    随着阿里云在云原生领域的探索和实践,阿里云逐渐成为云原生领域的定义者,领导者,对云原生技术发展做了一些预判:

    • 我们相信,云原生技术成为了云计算的新界面;
    • 我们相信,云原生技术能够重塑软件研发全生命周期;
    • 我们相信,云原生技术能够推动了信息产业的转型与升级;

    因此说云原生是释放云计算技术红利的最短路径;这次阿里云正式发布的云原生联盟,是阿里云云原生合作伙伴计划的重要载体。以解决方案伙伴为驱动,带动分销伙伴、服务伙伴,实现三位一体,帮助伙伴在销售能力、产品和解决方案能力、服务能力的全面成长。坚持定位云原生基础设施,“练好内功、做好被集成,帮助伙伴构建自身核心竞争力,共同服务企业数字化转型”。

    宁晓民.jpg

    9月17日13:00,阿里云智能资深解决方案架构师宁晓民将分享云原生合作伙伴计划的发展与目标。

    附上云栖大会云原生参会指南,一图解锁云原生重要热点和重大发布。

    参会秘籍.jpg

    敬请期待 9.18云栖大会-云原生四大分论坛精彩内容。点击 订阅 提前订阅直播。

    ]]>
    ARMS在APM工具选型中的实践 Thu, 29 Oct 2020 12:16:15 +0800 前言

    当前的系统在数字化转型需求以及互联网架构实施的影响下,越来越普遍地使用了微服务架构,我们在享受微服务带来的好处(开发效率高, 独立部署, 水平扩展, 故障与资源隔离等等)外,也带来测试,事务,应用监控等各方面的困难。

    image.png
    从上图可以看出,在以分布式为主的互联网架构下,应用间的调用变得越来越复杂,我们传统使用的开发工程师主动埋点,运维人员到主机上查日志,组合调用链,监控应用的运行情况,显得越来越力不从心。

    为了更好地做到应用层面的监控,包括应用运行环境的基础设施数据,系统业务调用情况,性能消耗分析,在发生性能,异常与故障问题时,能够快速定位和解决问题,诞生了很多优秀的APM(Application Performance Management)工具。

    这些APM工具都提供了包括指标统计信息与调用链路跟踪信息。

    常见的APM工具

    APM工具包括指标收集与调用链收集。指标收集例如在某一段时间的请求数,异常数,错误数,响应时间RT, IAAS层的资源使用情况(例如cpu, memory, IO, load, 网络), 也包括JVM的各种运行参数(例如 各内存分区情况,gc情况)。调用链收集包括业务请求中访问过的各应用,类,方式,在每个运行节点/方法上的时间消耗情况。
    常见的APM工具有:
    1、ARMS:由阿里巴巴自研开发的一款APM工具。由于分布式微服务框架以阿里为主体的企业很早就开始探索,阿里集团内很早就有配套的鹰眼系统做相关的应用监控,为适应产品上云输出,阿里在2016-08-04的时间就以ARMS的产品形式正式对外提供应用监控服务。
    2、开源系的APM
    u Pinpoint:基于java编写的开源APM工具,由韩国人开发贡献,功能完善,发展快,影响了很多其它的APM工具实现,在国内外使用比较广泛。
    u Skywalking:支持open tracing标准,由我国的吴晟主导开发的分布式追踪,分析,告警的开源工具,当前是Apache旗下的开源项目,发展非常迅速,在各类开源APM工具里国内的使用比较广泛。
    u ZipKin:支持open tracing标准,由Twitter公司开发贡献,于2012年的时候就开始开源发展,是比较成熟的开源APM工具。
    u Jaeger:支持open tracing标准,由Uber公司开发贡献,是比较成熟的开源APM工具。

    APM工具原理

    尽管这些APM工具功能与实现各有不同,但基本上原理都是一样的,这个原理基于google dapper的分布式追踪技术论文,把APM工具实现总体上分为两大部分:
    1、对应用运行节点上进行应用埋点,在业务运行期间进行埋点数据的生成;

    image.png
    2、通过APM的后端服务日志收集,数据清洗与聚合,把相应的处理结果持久化,并且提供丰富的可视化控制台。
    image.png

    在这个调用链追踪技术里,还原调用链的功能主要依赖于两个ID.

    第一个ID是TraceID, 这个代表一个业务调用,就好像在电商系统里发起的一个下单结算; 在线教育里的一个选课流程; 物流系统里的揽收; 这些业务从客户触发到获得响应结果就是一个完整的请求,就是一次业务调用,它每一次的业务请求的都会获得维一的TraceID;

    第二个ID是RpcID (或者称为SpanID), 在一次业务请求中,可能经过的应用会有多过,以一个电商下单业务为例: 它需要经过订单系统创建订单; 支付系统接受支付;库存系统扣减产品库存;会员系统给买家进行积分处理; 购物车系统会清理购物清单。这样对于业务流经的每一个应用,都有一个有层次的RpcID, 这个RpcID可以认为是使用目录层级记录的,从这个RpcID来看,那怕它在同一个业务中被调用了多次,它的每一次进入的RpcID都是一样的。

    依赖于TraceID & RpcID,我们可以很方便地还原整个调用链。
    image.png

    ARMS功能上的优势:

    客观来说, 优秀的APM工具发展到现在,基础功能上的差异都不大。例如以前开源APM比较薄弱的自动埋点功能也跟进了ARMS这些先发的产品; 在异步产品如各类MQ的支持上也慢慢拉平;SQL/API参数抓取的功能方面也是补足。我们再来列一下ARMS的优点:

    1、指标数据的准确性
    ARMS的agent把指标数据与调用链数据是分开两种类型来采集统计的, 相应的指标数据不受调用链的采样率的影响,会在具体的运行节点进行完完全全的统计后,精准到上传加载到ARMS后端。(而有些优秀的APM工具是通过采样上来的调用链进行加工处理,再来产出相应的指标,这在准确性上会有一定的丢失。)
    2、线程栈捕获
    因为是JAVA自动埋点的原理是对已知的框架进行字节码加强,当某框架不在已支持的范围内,那么这段访问的信息就不会被记录下来。ARMS可以通过设定调用超过一定时长后,可以通把整个线程栈捕获下来,这样我们就可以通过线程栈的分析进行补充定位。
    3、线程分析
    ARMS可以通过线程分析页签,清淅地看到各类线程的资源占用情况。例如可以知道当前的某线程池线程数是多少, 占用cpu最多的线程是那个, 占用的百分比情况,并且可以看到线程的运行状态。
    4、业务关联日志
    ARMS这边可以通过给合传统的log4j等技术,在输出业务日志上可以把相应的TraceID 就像线程ID那样通过方便的配置就可以与业务日志同时输出。另外,ARMS与阿里云的SLS进行整合,可以通过ARMS的页面方便地根据调用链的TraceID查找到关联的业务日志,这样需要结合业务日志定位时,更方便实用。
    5、智能合并能力
    ARMS对于相同的调用,例如递当,循环会进行智能合并,显示循环的次数,执行的最大时长,最小时长,平均时长。
    image.png
    6、主动诊断能力
    ARMS提供了主动诊断能力,可以通过选定具体的时间,执行主动诊断,ARMS会分析这一段时间内的应用运行情况,自动总结这一段时间内的问题,并且结合阿里的经验,产出具体的报表。我们依据这个报表,可以加速我们的定位与优化。
    7、丰富的报警能力
    完善报警体系,ARMS提供了丰富的报警规则,我们可以对相应的规则进行开启/关停,编辑,这样可以快速搭建报警体系。在报警通道方面,可以直接发对接钉钉/WebHook/Email/短信网关等。

    运维能力上的优势

    1、 按需监控启停管理
    通过ARMS的管理控制台,我们可以批量在管理应用的启停,可以一键停止所有的ARMS监控,也可以一键启动相关应用的监控。非常符合上云的按需要使用观念。
    2、动态采样率变更
    在面对特殊的时间点或者异常出现机率的时候,我们希望动态调整采样率,例如通过调大采样率来捕获这些概率极少的调用链,借助ARMS的配置管理,我们可以非常方便地把更齐全的调用链收集起来;通过调小采样率来保证存储空间的合理使用(其它的APM工具在做采样率的变更时,需要应用的重新配置,启动,这不但处理起来麻烦,并且影响业务的边续性,在实际操作上很难下定决心去在运行期间中断业务去做改变采样率的变更。)
    3、 绑定参数的开关
    虽然很多APM工具都可以提供绑定参数的功能。但很多时候,如果对于业务数据敏感的系统,并不希望这类APM工具在非必要的时候采集SQL/API的运行参数。所以ARMS在它的配置管理里提供这么一个功能非常有意义,也就是当需要收集这些运行的业务参数进行问题定位分析的时候,那么只要打开就可以了,使用完毕后,再通过把这些开关关上,那么就可以保护我们的业务数据不外泄漏出去了。
    4、接入简易
    可通过更简易的方式如阿里容器ACK/EDAS/SAE等各种非常便捷的接入方式,只需要简单的YAML注解或按钮即可完成接入。
    5、 组件稳定免运维
    因为ARMS是商业化的产品,所以所有的组件都是不需要我们使用方运维的。如果使用开源自建,那么我们就需要对日志收集,计算清洗服务,存储产品本身进行运维,包括相应的集群规模,清理处理,扩容处理,如果在峰值过后,不进行资源回收,也会产生额外的使用浪费。

    成本使用上的优势

    1、 ARMS是按接入节点,接入的小时(时长)计费的,这样可以充分发挥云上产品的优势。按需要使用,按需要的应用节点付费。另外ARMS单纯地按照节点数来计算,并不受采样率的变动而产生变化,这样对于大采样率的应用是有一定的优势。
    2、 ARMS有相应的资源包,可以通过购买资源包的方式进一步节省费用。
    3、 因为产品的组合因素,ARMS如果搭配阿里云的容器(ACK)使用,计费会自动5折。

    最后,这里列一下开源与ARMS的一个成本的比较供大家参考:
    image.png

    备注

    1、开源的按照统一统计数据存15天,全量明细数据存3天计算(ARMS的数据是全天24小时使用,存储60天,在非容器下按年包折下来的月费用。)
    2、人力成本以具有开发能力的运维人员月薪3万计算。人力成本,主要参数变动带来的发布,后端系统的不稳定带来的效率损失,后端系统的维护操作。中大型的会做一些定制的开发(例如采样的动态配置化生效)

    综述

    在阿里云上,ARMS在APM层面提供了足够丰富的功能;可以友好地运维操作;另外通过合理地按需使用,结合资源包,以及容器的方式运行,使用起来还高效与节省。作为基础设施的实用监控,不重复发明轮子,不重人力资源投入,综合考虑各方面因素,最终选择使用ARMS。

    ]]>
    【升级】9月4日Afilias注册局维护通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【域名】【Afilias注册局维护通知】

    维护时间:北京时间 2020年9月4日 22:00 - 23:00

    维护内容:接到注册局的通知,注册局将于上述时间对后台系统进行维护升级。

    维护影响:届时 .Red/.Kim/.Pro/.Asia/.Info/.Mobi/.ORG域名的注册、续费、信息修改和查询域名注册信息等操作,将会无法使用,在此期间会对您造成的影响如下:

    1、您提交的注册(购买)、续费、转入、赎回、一口价域名业务在支付费用后状态为“处理中”,待维护结束后将变为正常的“成功”状态;

    2、维护过程中您无法对域名注册信息进行修改,将提示修改失败。

    如果您需要注册或管理以上业务操作,建议您避开该时间段,以免给您的业务造成影响。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    【升级】9月11日消息队列AMQP升级通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【消息队列AMQP】【升级通知】

    升级窗口:北京时间2020年9月11日 00:00 - 03:00
    升级内容:华东1(杭州)、北京、深圳、上海、内蒙古、张家口、香港、青岛等全部区域(铂金版)服务升级。
    升级影响:升级期间消息队列AMQP相关服务访问可能会出现多次闪断或者拒绝连接现象,每次闪断或拒绝连接不会超过 5 分钟,请在客户端中做好重连重试机制。如需在控制台进行管理操作,请避开维护时间段。

    给您带来的不便敬请谅解,有任何问题,可点击联系我们进行咨询反馈。

    ]]>
    权威认可!蚂蚁分布式金融核心套件bPaaS成金融核心系统的最佳实践-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 日前,由国家金融与发展实验室金融科技研究中心与神州信息共同发起,由金融科技50人论坛具体推动和落实的 “首届NIFD-DCITS全球金融科技创新案例”征集活动在“金融科技创新应用与发展”研讨会上公布成果。

    经过为期一年的征集评选,蚂蚁分布式金融核心套件bPaaS从112个来自国内外金融机构、科技企业的参选案例中脱颖而出,正式入选 “2020全球金融科技创新案例库”,并收录于《“新基建+数字金融”全球金融科技创新实践(2020)》一书中,已由中国金融出版社发行。

    0.jpg

    分布式金融核心套件bPaaS(Business Platform As a Service)是凝结了蚂蚁多年“大中台、小前台”架构实践沉淀的分布式金融核心能力,它依托蚂蚁集团的金融领域建模和微服务应用架构实践,可以帮助金融机构快速建立数字化对客服务和数字化运营能力,支撑其快速业务创新, 促进业务发展。

    以网商银行为例,作为中国第一家核心系统基于云计算架构的商业银行,网商银行基于分布式金融核心套件bPaaS的金融基础服务和基础组件,提供产品业务创新迭代所需要的整套技术服务,同时保障底层基础设施具备更高的稳定性、可用性及性能。在没有一个网点的情况下,截至目前,网商银行已为超过2000万家小微企业及个体经营者提供了金融服务。

    实际上,bPaaS的精髓就在于,以非常强大的可编排、可组合、可配置、可扩展的技术服务能力,来支撑业务的快速敏捷和灵活多变,让金融机构“复制蚂蚁的核心技术能力”成为现实。当前,bPaaS 已从对内提供服务开放给对外提供服务,将自带支付宝10余年来的技术发展和业务创新能力赋能金融机构,是分布式架构下金融核心系统的最佳实践。

    据悉,包括蚂蚁企业级分布式关系数据库OceanBase、金融级分布式架构SOFAStack、移动开发平台mPaaS和分布式金融核心套件bPaaS等在内的数十个系列、上百款产品和解决方案正通过阿里云新金融统一对外输出,服务各种类型的金融机构。未来,还会有越来越多的蚂蚁金融科技产品和解决方案通过阿里云新金融对外输出,全力助推金融客户完成数字化转型。

    ]]>
    论程序的健壮性——就看Redis-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    “众里寻他千百度,蓦然回首,那人却在,灯火阑珊处”。多年的IT生涯,一直希望自己写的程序能够有很强的健壮性,也一直希望能找到一个高可用的标杆程序去借鉴学习,不畏惧内存溢出、磁盘满了、断网、断电、机器重启等等情况。但意想不到的是,这个标杆程序竟然就是从一开始就在使用的分布式缓存——Redis。


    Redis(Remote Dictionary Server ),即远程字典服务,是 C 语言开发的一个开源的高性能键值对(key-value)的内存数据库。由于它是基于内存的所以它要比基于磁盘读写的数据库效率更快。因此Redis也就成了大家解决数据库高并发访问、分布式读写和分布式锁等首选解决方案。

    那么既然它是基于内存的,如果内存满了怎么办?程序会不会崩溃?既然它是基于内存的,如果服务器宕机了怎么办?数据是不是就丢失了?既然它是分布式的,这台Redis服务器断网了怎么办?

    今天我们就一起来看看Redis的设计者,一名来自意大利的小伙,是如何打造出一个超强健壮性和高可用性的程序,从而不惧怕这些情况。

    一、 Redis的内存管理策略——内存永不溢出

    Redis主要有两种策略机制来保障存储的key-value数据不会把内存塞满,它们是:过期策略和淘汰策略。

    1、 过期策略

    用过Redis的人都知道,我们往Redis里添加key-value的数据时,会有个选填参数——过期时间。如果设置了这个参数的值,Redis到过期时间后会自行把过期的数据给清除掉。“过期策略”指的就是Redis内部是如何实现将过期的key对应的缓存数据清除的。

    在Redis源码中有三个核心的对象结构:redisObject、redisDb和serverCron。

    • redisObject:Redis 内部使用redisObject 对象来抽象表示所有的 key-value。简单地说,redisObject就是string、hash、list、set、zset的父类。为了便于操作,Redis采用redisObject结构来统一这五种不同的数据类型。

    • redisDb:Redis是一个键值对数据库服务器,这个数据库就是用redisDb抽象表示的。redisDb结构中有很多dict字典保存了数据库中的所有键值对,这些字典就叫做键空间。如下图所示其中有个“expires”的字典就保存了设置过期时间的键值对。而Redis的过期策略也是围绕它来进行的。

    • serverCron:Redis 将serverCron作为时间事件来运行,从而确保它每隔一段时间就会自动运行一次。因此redis中所有定时执行的事件任务都在serverCron中执行。

    了解完Redis的三大核心结构后,咱们回到“过期策略”的具体实现上,其实Redis主要是靠两种机制来处理过期的数据被清除:定期过期(主动清除)和惰性过期(被动清除)。

    • 惰性过期(被动清除):就是每次访问的时候都去判断一下该key是否过期,如果过期了就删除掉。该策略就可以最大化地节省CPU资源,但是却对内存非常不友好。因为不实时过期了,原本该过期删除的就可能一直堆积在内存里面!极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
    • 定期过期(主动清除):每隔一定的时间,会扫描Redis数据库的expires字典中一定数量的key,并清除其中已过期的 key。Redis默认配置会每100毫秒进行1次(redis.conf 中通过 hz 配置)过期扫描,扫描并不是遍历过期字典中的所有键,而是采用了如下方法:

    (1)从过期字典中随机取出20个键;
    (server.h文件下ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP配置20)

    (2)删除这20个键中过期的键;

    (3)如果过期键的比例超过 25% ,重复步骤 1 和 2;

    具体逻辑如下图:

    因为Redis中同时使用了惰性过期和定期过期两种过期策略,所以在不同情况下使得 CPU 和内存资源达到最优的平衡效果的同时,保证过期的数据会被及时清除掉。

    2、淘汰策略

    在Redis可能没有需要过期的数据的情况下,还是会把我们的内存都占满。比如每个key设置的过期时间都很长或不过期,一直添加就有可能把内存给塞满。那么Redis又是怎么解决这个问题的呢?——那就是“淘汰策略”。

    官网地址:https://redis.io/topics/lru-cache
    Reids官网上面列出的淘汰策略一共有8种,但从实质算法来看只有两种实现算法,分别是LRU和LFU。

    LRU(Least Recently Used):翻译过来是最久未使用,根据时间轴来走,淘汰那些距离上一次使用时间最久远的数据。
    LRU的简单原理如下图:

    从上图我们可以看出,在容器满了的情况下,距离上次读写时间最久远的E被淘汰掉了。那么数据每次读取或者插入都需要获取一下当前系统时间,以及每次淘汰的时候都需要拿当前系统时间和各个数据的最后操作时间做对比,这么干势必会增加CPU的负荷从而影响Redis的性能。Redis的设计者为了解决这一问题,做了一定的改善,整体的LRU思路如下:

    (1)、Redis里设置了一个全局变量 server.lruclock 用来存放系统当前的时间戳。这个全局变量通过serverCron 每100毫秒调用一次updateCachedTime()更新一次值。

    (2)、每当redisObject数据被读或写的时候,将当前的 server.lruclock值赋值给 redisObject 的lru属性,记录这个数据最后的lru值。

    (3)、触发淘汰策略时,随机从数据库中选择采样值配置个数key, 淘汰其中热度最低的key对应的缓存数据。

    注:热度就是拿当前的全局server.lruclock 值与各个数据的lru属性做对比,相差最久远的就是热度最低的。

    Redis中所有对象结构都有一个lru字段, 且使用了unsigned的低24位,这个字段就是用来记录对象的热度。

    LFU(Least Frequently Used):翻译成中文就是最不常用。是按着使用频次来算的,淘汰那些使用频次最低的数据。说白了就是“末尾淘汰制”!
    刚才讲过的LRU按照最久未使用虽然能达到淘汰数据释放空间的目的,但是它有一个比较大的弊端,如下图:

    如图所示A在10秒内被访问了5次,而B在10秒内被访问了3 次。因为 B 最后一次被访问的时间比A要晚,在同等的情况下,A反而先被回收。那么它就是不合理的。LFU就完美解决了LRU的这个弊端,具体原理如下:

    上图是末尾淘汰的原理示意图,仅是按次数这个维度做的末尾淘汰,但如果Redis仅按使用次数,也会有一个问题,就是某个数据之前被访问过很多次比如上万次,但后续就一直不用了,它本身按使用频次来讲是应该被淘汰的。因此Redis在实现LFU时,用两部分数据来标记这个数据:使用频率和上次访问时间。整体思路就是:有读写我就增加热度,一段时间内没有读写我就减少相应热度。

    不管是LRU还是LFU淘汰策略,Redis都是用lru这个字段实现的具体逻辑,如果配置的淘汰策略是LFU时,lru的低8位代表的是频率,高16位就是记录上次访问时间。整体的LRU思路如下:

    (1)每当数据被写或读的时候都会调用LFULogIncr(counter)方法,增加lru低8位的访问频率数值;具体每次增加的数值在redis.conf中配置默认是10(# lfu-log-factor 10)

    (2)还有另外一个配置lfu-decay-time 默认是1分钟,来控制每隔多久没人访问则热度会递减相应数值。这样就规避了一个超大访问次数的数据很久都不被淘汰的漏洞。

    小结:“过期策略” 保证过期的key对应的数据会被及时清除;“淘汰策略”保证内存满的时候会自动释放相应空间,因此Redis的内存可以自运行保证不会产生溢出异常。

    二、 Redis的数据持久化策略——宕机可立即恢复数据到内存

    有了内存不会溢出保障后,我们再来看看Redis是如何保障服务器宕机或重启,原来缓存在内存中的数据是不会丢失的。也就是Redis的持久化机制。

    Redis 的持久化策略有两种:RDB(快照全量持久化)和AOF(增量日志持久化)

    1、 RDB

    RDB 是 Redis 默认的持久化方案。RDB快照(Redis DataBase),当触发一定条件的时候,会把当前内存中的数据写入磁盘,生成一个快照文件dump.rdb。Redis重启会通过dump.rdb文件恢复数据。那那个一定的条件是啥呢?到底什么时候写入rdb 文件?

    触发Redis执行rdb的方式有两类:自动触发和手动触发
    “自动触发”的情况有三种:达到配置文件触发规则时触发、执行shutdown命令时触发、执行flushall命令时触发。

    注:在redis.conf中有个 SNAPSHOTTING配置,其中定义了触发把数据保存到磁盘触发频率。

    “手动触发”的方式有两种:执行save 或 bgsave命令。执行save命令在生成快照的时候会阻塞当前Redis服务器,Redis不能处理其他命令。如果内存中的数据比较多,会造成Redis长时间的阻塞。生产环境不建议使用这个命令。

    为了解决这个问题,Redis 提供了第二种方式bgsave命令进行数据备份,执行bgsave时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。

    具体操作是Redis进程执行fork(创建进程函数)操作创建子进程(copy-on-write),RDB持久化过程由子进程负责,完成后自动结束。它不会记录 fork 之后后续的命令。阻塞只发生在fork阶段,一般时间很短。手动触发的场景一般仅用在迁移数据时才会用到。

    我们知道了RDB的实现的原理逻辑,那么我们就来分析下RDB到底有什么优劣势。

    优势:

    (1)RDB是一个非常紧凑(compact类型)的文件,它保存了redis在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复。

    (2)生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。

    (3)RDB在恢复大数据集时的速度比AOF的恢复速度要快。

    劣势:

    RDB方式数据没办法做到实时持久化/秒级持久化。在一定间隔时间做一次备份,所以如果Redis意外down掉的话,就会丢失最后一次快照之后的所有修改

    2、 AOF(Append Only File)

    AOF采用日志的形式来记录每个写操作的命令,并追加到文件中。开启后,执行更改 Redis数据的命令时,就会把命令写入到AOF文件中。Redis重启时会根据日志文件的内容把写指令从前到后执行一次以完成数据的恢复工作。

    其实AOF也不一定是完全实时的备份操作命令,在redis.conf 我们可以配置选择 AOF的执行方式,主要有三种:always、everysec和no

    AOF是追加更改命令文件,那么大家想下一直追加追加,就是会导致文件过大,那么Redis是怎么解决这个问题的呢?
    Redis解决这个问题的方法是AOF下面有个机制叫做bgrewriteaof重写机制,我们来看下它是个啥

    注:AOF文件重写并不是对原文件进行重新整理,而是直接读取服务器现有的键值对,然后用一条命令去代替之前记录这个键值对的多条命令,生成一个新的文件后去替换原来的AOF文件。

    我们知道了AOF的实现原理,我们来分析下它的优缺点。

    优点:

    能最大限度的保证数据安全,就算用默认的配置everysec,也最多只会造成1s的数据丢失。

    缺点:

    数据量比RDB要大很多,所以性能没有RDB好!

    小结:因为有了持久化机制,因此Redis即使服务器宕机或重启了,也可以最大限度的恢复数据到内存中,提供给client继续使用。

    三、Redis的哨兵模式——可战到最后一兵一卒的高可用集群

    内存满了不会挂,服务器宕机重启也没问题。足见Redis的程序健壮性已经足够强大。但Redis的设计者,在面向高可用面前,仍继续向前迈进了一步,那就是Redis的高可用集群方案——哨兵模式。

    所谓的“哨兵模式”就是有一群哨兵(Sentinel)在Redis服务器前面帮我们监控这Redis集群各个机器的运行情况,并且哨兵间相互通告通知,并指引我们使用那些健康的服务。

    Sentinel工作原理:

    1、 Sentinel 默认以每秒钟1次的频率向Redis所有服务节点发送 PING 命令。如果在down-after-milliseconds 内都没有收到有效回复,Sentinel会将该服务器标记为下线(主观下线)。

    2、 这个时候Sentinel节点会继续询问其他的Sentinel节点,确认这个节点是否下线, 如果多数 Sentinel节点都认为master下线,master才真正确认被下线(客观下线),这个时候就需要重新选举master。

    Sentinel的作用:

    1、监控:Sentinel 会不断检查主服务器和从服务器是否正常运行

    2、故障处理:如果主服务器发生故障,Sentinel可以启动故障转移过程。把某台服务器升级为主服务器,并发出通知

    3、配置管理:客户端连接到 Sentinel,获取当前的 Redis 主服务器的地址。我们不是直接去获取Redis主服务的地址,而是根据sentinel去自动获取谁是主机,即使主机发生故障后我们也不用改代码的连接!

    小结:有了“哨兵模式”只要集群中有一个Redis服务器还健康存活,哨兵就能把这个健康的Redis服务器提供给我们(如上图的1、2两步),那么我们客户端的链接就不会出错。因此,Redis集群可以战斗至最后一兵一卒。

    这就是Redis,一个“高可用、强健壮性”的标杆程序!

    作者:宜信技术学院 谭文涛

    ]]>
    阿里云多账号网络互通最佳实践-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 前言

    在企业起步阶段,规模较小,一般采用单账号模式。随着企业的发展,单账号的缺陷越来越明显,多账号相对于单账号有众多优点:
    • 多账号间的资源默认隔离,减少了单账号因为一个资源或服务问题导致其它资源和服务也出现问题的可能性;
    • 多账号减少了单帐户过于宽泛的 RAM 权限带来的风险;
    • 多账号便于成本结算、独立管理、环境隔离等。

    因此中大型企业上云时通常选择多账号,但是多账号间往往存在着大量的网络互通场景,如何解决多账号的网络互通问题呢?
    VPC 作为云上最常用的网络环境,不同账号的 VPC 之间默认是无法互通的,多账号网络互通常用的解决方案是 CEN(云企业网)和 VPN 网关。

    基于 VPN 的网络架构

    VPN 网关是一款基于 Internet 的网络连接服务,通过加密通道的方式实现企业数据中心、企业办公网络或 Internet 终端与 VPC 安全可靠的连接。VPN 网关可以实现跨地域、跨账号的 VPC 互通,在需要连接的 VPC 上创建 VPN 网关,网关之间通过基于 Internet 的 IPSec 加密隧道来传输私网数据,以实现安全可靠的多账号 VPC 间通信。

    图1.png

    图1

    如上图所示:服务分别部署在账号1、2、3的 VPC 网络环境中,每个服务基于多可用区和 SLB 实现同城双活,前端 VPC 部署前端服务,后端 VPC 部署后端应用,前端服务处理 Web 请求时需调用部署在账号2、账号 3 的后端应用,分别为每个 VPC 创建 VPN网关,VPN 之间配置 IPSEC、路由,以此来实现多账号网络互通。

    基于 CEN 的网络架构

    云企业网(Cloud Enterprise Network)是承载在阿里云提供的高性能、低延迟的私有全球网络上的一张高可用网络,可以在跨地域、跨账号的 VPC 间搭建私网通道,通过自动路由分发及学习,提高网络的快速收敛和跨网络通信的质量和安全性,实现全网资源的互通,打造一张具有企业级规模和通信能力的互联网络。

    图2.png

    图2

    如上图所示:首先创建 CEN 实例,将要互通的网络实例(专有网络和边界路由器)加载到 CEN 中,再购买一个带宽包(同 Region 无需购买带宽包),配置路由、跨账号授权等,即可实现服务在不同账号的 VPC 间互通。

    VPN 和 CEN 网络架构比较

    VPN 和 CEN 都可实现多账号网络互通,两者有何区别呢?
    • VPN 需要为每个 VPC 配置 VPN 网关,创建 IPsec 连接、配置 VPN 网关路由等,随着 VPC 数量的增加,人工配置成本成倍增加;同时 VPN 连接使用共享的公网资源进行通信,网络延时和丢包率等都无法保证,其网络带宽受限于公网 IP 的带宽。在实际使用中 VPN 网关很少用于多账号网络互通,多用于本地数据中心与 VPC 互通以构建混合云。
    • CEN 专线连接在网络质量、安全性和传输速度等方面都优于 VPN,但是 CEN 在跨账号连接时需要配置跨账号授权、路由等,存在一定的配置成本;跨 Region 通信时需要购买带宽,存在一定的费用成本;每个 CEN 实例在每个 Region 可加载的网络实例数量有限。

    由此可见,VPN 和 CEN 都能解决多账号网络互通问题,但是不一定适合所有的场景,还有其他的方案吗?

    ResourceSharing 介绍

    不同于 VPN 和 CEN,资源共享服务(ResourceSharing)通过在账号间共享 VSwitch 来实现多账号网络互通。
    如下图所示:企业账号 A、B、C、D 加入 ResourceDirectory(资源目录)后,资源所有者账号 A 把虚拟交换机共享给账号 B、C、D,这样账号 A、B、C、D 都能使用该虚拟交换机,并在该交换机上挂载 ECS/RDS/SLB 等资源,以此来实现不同账号的资源共享同一个子网。

    图3.png

    图3

    相对于 CEN 和 VPN,ResourceSharing 极大地简化了配置,在网络规模较复杂的场景下尤为明显。

    基于 ResourceSharing 的网络架构

    如下图所示为基于 ResourceSharing 的网络架构:账号 1 所在的 VPC 使用两个 VSwitch 作为多可用区以实现同城双活,用于部署前端服务;再共享三个 VSwitch 给账号 2 和账号 3 用于部署后端服务:“Shared VSwitch For AZ1 ECS” 用于挂截账号 2 和账号 3 在 AZ1 的 ECS 资源,“Shared VSwitch For AZ2 ECS” 用于挂截账号 2 和账号 3 在 AZ2 的 ECS 资源,“Shared VSwitch For SLB” 用于挂截账号 2 和账号 3 的 SLB 资源;这样基于资源共享的方式,前端服务与后端服务均在同一个 VPC 下,所有服务天然支持网络互通。

    图4.png

    图4

    由于每个账号仍然独立管控自己的资源,所以服务之间既实现了多账号间网络互通,又保证了相关资源在账号间的隔离,此外,相对于 CEN 和 VPN,ResourceSharing 有一定的优势:
    • 整个体系在一个 VPC 中,因此不需要网关、路由、IPSEC、跨账号授权等相关配置,极大地简化了工作量。
    • 服务在 VPC 内部通信,不依赖公网带宽,减少了网络延时和丢包率带来的风险。
    • ResourceSharing 是完全免费的,能为用户节省不少成本。

    总结

    ResourceSharing 有众多优势,是否能取代 VPN 和 CEN 满足所有的应用场景呢?
    • 由于 VPC 是地域级别的资源,因此 ResourceSharing 是不能跨 Region 共享 VSwitch 的,而 CEN 则没有这个限制,所以跨 Region 间 VPC 通信时通常选择 CEN 的方式。如下图所示 Region A 和 Region B 的 VPC 通过 CEN 互通。
    • 当用户需要将本地数据中心与 VPC 互通以构建混合云时,ResourceSharing 显然无法满足需求。如下图所示通过 VPN 的方式将本地数据中心与安全登陆 VPC 快速连接起来。
    • 当企业对安全有更高要求时,往往需要通过 VPC 将网络划分成多个安全域,ResourceSharing 由于共享 VSwitch 所在的实例都在同一个 VPC,无法满足需求。如下图所示:根据安全级别的不同,将整个网络分隔成多个 VPC,通过 CEN 实现不同安全域 VPC 的网络互通,利用 ResourceSharing 实现多账号同安全域 VPC 的网络互通。

    图5.jpeg

    图5

    VPN 网关、CEN 和 ResourceSharing 分别适用于不同的场景,如上图所示为集团化的大型企业,网络架构较为复杂,同时用到了三种方案,用户在实际使用时,需要根据自己的需求和网络规模选择最合适的方案。

    ]]>
    来了!2020云栖大会:蚂蚁金融科技产品能力再升级-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 当前,全球正在经历一场数字化变革,给各行各业带来了前所未有的影响。尤其在金融行业,以云计算、大数据以及移动互联网等为代表的科技已经开始广泛的运用到金融服务各个领域中,传统金融行业迎来了技术全面赋能的未来金融时代,金融科技正在为金融行业的业务场景创新与技术应用创新提供助力。

    但科技与金融的融合并非一蹴而就,金融行业的数字化转型客观上还面临着如何快速搭建线上业务,如何利用互联网获客、扩大业务规模和覆盖范围,如何基于互联网用户群体的特性开发新的产品等诸多问题。

    对于传统的金融机构而言,该如何构建深度融合的技术创新体系,更好推动数字化转型?在9月17日下午13点云栖大会数字金融源动力专场分论坛中,蚂蚁金融科技将发布“三驾马车”企业级分布式关系数据库OceanBase、移动开发平台mPaaS和金融级分布式架构SOFAStack的全新能力。

    OceanBase 2.2 版本和全新一体机产品发布

    OceanBase是蚂蚁集团完全自研的企业级分布式关系数据库,作为底层的基础设施,在为金融客户持续提供安全稳定的服务的同时,能够承载上层千变万化的业务需求和各种不同的使用场景。

    据了解,OceanBase已服务大量金融、电信等行业企业,在南京银行、西安银行、天津银行、苏州银行、东莞银行、常熟农商行、广东农信、中国人保、招商证券、浙江移动等多家银行、保险、证券及运营商机构上线。

    此次云栖大会,OceanBase聚焦客户需求,将发布完整的平台能力,混合负载引擎,多种容灾方式,以及全新的OceanBase一体机。

    mPaaS:全新视频云营业厅方案发布

    作为国内领先的移动开发平台,mPaaS能够为金融服务机构提供移动开发、测试、发布、分析、智能化运营各个方面的云到端的一体化解决方案,并将在本次云栖大会中推出全新的视频云营业厅解决方案,包括视频柜员、智能远程定损理赔、金融直播、智能双录等新的业务构想。

    mPaaS已经服务了中国农业银行、广发银行,华夏银行,西安银行、国寿保险等众多B端客户,助力企业在数字时代赢得先机。例如,常熟农商银行引入mPaaS打造新一代移动金融中心,大幅提升App启动速度,有效降低闪退率和崩溃率,用户服务质量显著提升。而视频云营业厅的推出,则将金融行业更多业务场景搬到了“云上”,构建起了广域办事通道,将业务半径限制彻底“松绑”,极大改善了业务办理效率和用户体验,为企业的“全渠道数字化运营”提供了坚强后盾。

    SOFAStack:金融级应用PaaS - 高可用管理解决方案发布

    蚂蚁金融级分布式架构SOFAStack,能够提供从服务构建、应用开发、部署发布、服务治理、监控运维、容灾高可用等全生命周期、全栈式解决方案,不仅支撑着蚂蚁的丰富复杂业务,而且已全面对外开放,其中包括中国人保、南京银行、浙商证券、上海华瑞银行、四川农信银行等数十家金融机构。

    其中,作为首期国家发改委的数字化转型伙伴行动的金融机构,四川农信借助阿里金融云平台、蚂蚁金融级分布式架构SOFAStack、mPaaS技术框架、数据中台等技术支撑,推动其IT架构由集中式向分布式的架构转型。

    此次云栖大会,SOFAStack再次深入金融级PAAS运维领域,并发布金融级应用PaaS - 高可用管理解决方案,服务各类型的金融服务机构,助力其打造更好地服务大量用户的能力。

    事实上,这些产品能力升级的重磅发布,都是基于蚂蚁金融科技的定位——不断加强金融数字化基础设施的能力。“蚂蚁金融科技和阿里云共同的使命,就是成为金融行业数字化的基础设施,为金融机构的数字化转型按下‘加速按钮’”,蚂蚁集团OceanBase CEO、金融云总经理杨冰表示。

    未来,蚂蚁集团将继续坚持开放的战略依托多年沉淀下来的技术和经验,对外输出更多优质的金融科技产品和解决方案,助力金融机构建立基于云计算、数据智能、分布式业务系统等金融新基建,打造全新的金融服务体验和用户连接渠道,实现客户、场景、产品、服务等的全面数字化升级转型。

    掌握基础设施技术脉搏,搭载数字化转型发展列车,更多精彩内容,赶快“阅读原文”来云栖大会“数字金融源动力”专场参加吧~~

    640.png

    直达云栖会场:https://yunqi.aliyun.com/2020/session152


    上阿里云搜索“mPaaS”.jpg

    动态-logo.gif

    ]]>
    智能语音组件适配指南 | 《无需从0开发 1天上手智能语音离在线方案》第七章-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 智能语音终端调试指南

    1. 使用串口调试

    1.1 用内置串口命令调试

    YoC支持丰富的串口命令,通过串口命令可以完成很多调试操作。系统支持串口命令介绍如下:

    help

    > help
    help            : show commands
    ping            : ping command.
    ifconfig        : network config
    date            : date command.
    ps              : show tasks
    free            : show memory info
    sys             : sys comand
    log             : log contrtol
    iperf           : network performance test
    kv              : kv tools

    输入 help 命令,可以查看当前所有支持命令:

    image.png
    image.png
    image.png

    ps 命令可以打印出当前系统所有的线程状态,每项含义介绍如下:
    image.png

    部分信息详细说明如下:

    • 线程状态有ready、pend、suspend、sleep、deleted
    – ready:表示当前线程已经等待被调度,系统的调度原则是:若优先级不同则高优先级线程运行,优先级相同则各个线程时间片轮转运行
    – pend:表示当前线程被挂起,挂起原因是线程在等待信号量、互斥锁、消息队列等,例如调用:aos_sem_wait,aos_mutex_lock 等接口,线程就会被挂起并置成pend状态。如果是信号量等待时间是forever,则left tick 的值为 0;如果有超时时间,则 left tick 的值就是超时时间,单位为毫秒
    – suspend:表示当前线程被主动挂起,就是程序主动调用了 task_suspend 函数
    – sleep:表示当前线程被主动挂起,就是调用了 aos_sleep 等睡眠函数, left tick 的值即表示 睡眠的时间
    – deleted:当前线程已经被主动删除,也就是调用 krhino_task_del函数

    • %CPU 状态只有在 k_config.h 文件中 RHINO_CONFIG_HW_COUNT和RHINO_CONFIG_TASK_SCHED_STATS宏被设置 1 的时候才会出现。
    • 第一行 CPU USAGE: 640/10000 表示,当前系统的整体负载,如上示例,系统的CPU占有率是 0.64%

    free

    > free
                       total      used      free      peak 
    memory usage:    5652536    605316   5047220   1093576
    

    free 命令可以使用输出当前系统的堆状态,其中:

    • total 为 总的堆的大小
    • used 为 系统使用的 堆大小
    • free 为 系统空余的 堆大小
    • peak 为 系统使用的 堆最大空间

    单位为 byte

    >free mem
    
    ------------------------------- all memory blocks --------------------------------- 
    g_kmm_head = 1829bfc8
    ALL BLOCKS
    address,  stat   size     dye     caller   pre-stat    point
    0x1829cb20  used       8  fefefefe  0x0        pre-used;
    0x1829cb38  used    4128  fefefefe  0xbfffffff pre-used;
    0x1829db68  used    1216  fefefefe  0x180190b6 pre-used;
    0x1829e038  used    2240  fefefefe  0x180190b6 pre-used;
    0x1829e908  used    4288  fefefefe  0x180190b6 pre-used;
    0x1829f9d8  free     592  abababab  0x180aaa6d pre-used; free[     0x0,     0x0] 
    0x1829fc38  used      40  fefefefe  0x180cb836 pre-free [0x1829f9d8];
    0x1829fc70  used      40  fefefefe  0x180cb836 pre-used;
    0x1829fca8  used   18436  fefefefe  0x1810448d pre-used;
    0x182a44bc  used      40  fefefefe  0x180cb836 pre-used;
    ...
    0x183a5ce0  used      16  fefefefe  0x1801d477 pre-used;
    0x183a5d00  used      40  fefefefe  0x1801d477 pre-used;
    0x183a5d38  used      12  fefefefe  0x1801a911 pre-used;
    0x183a5d54  used      32  fefefefe  0x18010d40 pre-used;
    0x183a5d84  used    4288  fefefefe  0x180190b6 pre-used;
    0x183a6e54  free  4559244  abababab  0x18027fd9 pre-used; free[     0x0,     0x0] 
    0x187ffff0  used  sentinel  fefefefe  0x0        pre-free [0x183a6e54];
    
    ----------------------------- all free memory blocks ------------------------------- 
    address,  stat   size     dye     caller   pre-stat    point
    FL bitmap: 0x10f4b
    SL bitmap 0x84
    -> [0][2]
    0x18349b88  free       8  abababab  0x1802a1b1 pre-used; free[     0x0,     0x0] 
    -> [0][7]
    0x182df2f8  free      28  abababab  0x0        pre-used; free[     0x0,     0x0] 
    -> [0][25]
    
    0x182df3c8  free     100  abababab  0x18010ea5 pre-used; free[     0x0,     0x0] 
    ...
    0x182b5704  free  160204  abababab  0x1804fe55 pre-used; free[     0x0,     0x0] 
    SL bitmap 0x4
    -> [16][2]
    0x183a6e54  free  4559244  abababab  0x18027fd9 pre-used; free[     0x0,     0x0] 
    
    ------------------------- memory allocation statistic ------------------------------ 
         free     |     used     |     maxused
         5047040  |      605496  |     1093576
    
    -----------------alloc size statistic:-----------------
    [2^02] bytes:     0   |[2^03] bytes:  1350   |[2^04] bytes: 398770   |[2^05] bytes: 29121   |
    [2^06] bytes: 408344   |[2^07] bytes: 396962   |[2^08] bytes:   350   |[2^09] bytes:   231   |
    [2^10] bytes:    55   |[2^11] bytes:    38   |[2^12] bytes: 396677   |[2^13] bytes:  1410   |
    [2^14] bytes:    14   |[2^15] bytes:    16   |[2^16] bytes:     0   |[2^17] bytes:     4   |
    [2^18] bytes:    17   |[2^19] bytes:     0   |[2^20] bytes:     0   |[2^21] bytes:     0   |
    [2^22] bytes:     0   |[2^23] bytes:     0   |[2^24] bytes:     0   |[2^25] bytes:     0   |
    [2^26] bytes:     0   |[2^27] bytes:     0   |
    

    free mem 命令可以打印出堆内各个节点的细节信息 整个打印信息被分成 4个部分

    • 第一部分为 系统所有 堆节点,包含了 节点的地址、大小、占用状态、调用malloc的程序地址等
    • 第二部分为 当前系统 空置的 堆节点,信息与第一部分相同,只是单独列出了free的节点,可以观察系统的内存碎片情况
    • 第三部分为 系统的总体堆内存使用情况,和 free 命令打印出的信息相同
    • 第四部分为 堆节点的大小统计,与2的次方为单位进行划分

     >free list
                                    total      used      free      peak 
    memory usage:    5652536    605316   5047220   1093576
    
      0: caller=0xbffffffe, count= 1, total size=4128
      1: caller=0x180190b6, count=25, total size=85696
      2: caller=0x180aaa6c, count= 1, total size=592
      3: caller=0x180cb836, count= 3, total size=120
      4: caller=0x1810448c, count= 1, total size=18436
      5: caller=0x18010a68, count=39, total size=1716
      6: caller=0x18014548, count= 8, total size=580
      7: caller=0x18054dda, count= 1, total size=1028
    ...
     52: caller=0x18010d40, count= 2, total size=64
     53: caller=0x1801d5b8, count= 3, total size=72
     54: caller=0x1801d476, count= 6, total size=196
     55: caller=0x1801d5ac, count= 3, total size=48092
     56: caller=0x1801a910, count= 1, total size=12
     57: caller=0x18027fd8, count= 1, total size=4559244
    

    free list 是另一种形式的堆内存使用统计,统计了程序内各个malloc的调用并且还没有free的次数。 这个统计信息对于查找内存泄露非常有帮助。多次输出该命令,若 count 的值出现了增长,则可能有内存泄露的情况出现。

    以上命令的 caller 信息,我们可以通过 在 yoc.asm 反汇编文件查找函数来确认具体的调用函数。

    注意:free mem和free list只有在开启CONFIG_DEBUG_MM和CONFIG_DEBUG时才能使用,因为它需要占用一些内存空间用于存放这些调试信息。

    sys

    image.png

    具体显示的信息如下:

    其中 sys app 和sys id 两个命令是在需要FOTA升级的时候才会使用到,一般是OCC网站颁发的信息,不可更改,如果没有走过FOTA流程一般为空。其余的版本号信息,是代码宏定义,可以在代码中修改。

    date

    data命令是用于查询和设置当前系统时间,一般系统连上网络以后会定期调用ntp,来和服务器同步时间,这个命令可以查询同步时间和设置系统时间

    > date
        TZ(08):Tue Aug 11 18:03:14 2020 1597168994
           UTC:Tue Aug 11 10:03:14 2020 1597140194
           date -s "2001-01-01 12:13:14"
    > date -s "2020-08-11 18:15:38"
    set date to: 2020-08-11 18:15:38
        TZ(08):Wed Aug 12 02:15:38 2020 1597198538
           UTC:Tue Aug 11 18:15:38 2020 1597169738
           date -s "2001-01-01 12:13:14"

    log

    log命令可以用于控制打印等级和打印的模块

    > log
    Usage:
        set level: log level 0~5
            0:disable 1:F 2:E 3:W 4:I 5:D
        add ignore tag: log ignore tag
        clear ignore tag: log ignore
    > log level 0
    > log ignore fota
    log tag ignore list:
    fota
    > log ignore RTC
    log tag ignore list:
    fota
    RTC
    >

    log level num 用于控制打印等级
    0:关闭日志打印;
    1:打印F级别的日志;
    2:打印E级别及以上的日志;
    3:打印W级别及以上的日志;
    4:打印I级别及以上的日志;
    5:打印D级别及以上的日志,也是就日志全开

    log ignore tag 用于控制各个模块的打印
    例如log ignore RTC 表示关闭 RTC 模块的日志打印

    需要注意的是:log 命令只能控制通过 LOG 模块打印出来的日志,直接通过 printf 接口打印的日志 不能被拦截。所以推荐用 LOG 模块去打印日志。

    kv

    kv是一个小型的存储系统,通过key-value 的方式存储在flash中

    > kv
    Usage:  
        kv set key value
        kv get key
        kv setint key value
        kv getint key
        kv del key
    >

    kv set key value 是设置字符串类型的value kv setint key value 是设置整形的value

    例如:

    kv set wifi_ssid my_ssid
    kv set wifi_psk my_psk
    

    如上两条命令是用于设置wifi的 ssid和psk,重启后系统会去通过kv接口获取flash的kv value值,从而进行联网。

    ifconfig

    > ifconfig
    
    wifi0   Link encap:WiFi  HWaddr 18:bc:5a:60:d6:04
            inet addr:192.168.43.167
        GWaddr:192.168.43.1
        Mask:255.255.255.0
        DNS SERVER 0: 192.168.43.1
    
    WiFi Connected to b0:e2:35:c0:c0:ac (on wifi0)
        SSID: yocdemo
        channel: 11
        signal: -58 dBm
    

    ifconfig命令可以查看当前 网络连接的状态,其中:

    • 第一部分是 本机的网络状态,包括本机mac地址,本机IP,网关地址、掩码、DNS Server地址
    • 第二部分是 连接的路由器信息,包括wifi的名称,mac地址,连接的信道、信号质量

    1.2 创建自己的串口命令

    上一节介绍了系统内置的串口命令,本节介绍如何创建自定义串口命令用于调试。 YoC中,串口命令代码模块为cli,其代码头文件为cli.h。自定义串口命令时,需要包含这个头文件。

    代码示例如下:

    /*
     * Copyright (C) 2019-2020 Alibaba Group Holding Limited
     */
    #include <string.h>
    #include <aos/cli.h>
    
    #define HELP_INFO 
        "Usage:ntmycmd testn"
    
    static void cmd_mycmd_ctrl_func(char *wbuf, int wbuf_len, int argc, char **argv)
    {
            int i;
        
        for (i = 0; i < argc; i ++) {
            printf("argv %d: %sn", i, argv[i]);
        }
     
        printf(HELP_INFO);
    }
    
    void cli_reg_cmd_my_cmd(void)
    {
        static const struct cli_command cmd_info = {
            "my_cmd",
            "my_cmd test",
            cmd_mycmd_ctrl_func,
        };
    
        aos_cli_register_command(&cmd_info);
    }

    其中,
    • 需要定义一个被cli回调的函数,当串口输入这个命令时就会触发这个回调,本例为cmd_mycmd_ctrl_func;
    • 需要定义一个命令字符串,用于cli比较用于输入字符串来触发回调,本例为my_cmd;
    • 需要定义帮助信息,用于串口输入help命令时打印出来,本例为my_cmd test;
    • 最后在系统初始化时把这个命令注册到cli里面,本例为cli_reg_cmd_my_cmd;

    这样就可以拥有自己的串口调试命令了,效果如下:

    > my_cmd first cmd test
    argv 0: my_cmd
    argv 1: first
    argv 2: cmd
    argv 3: test
    Usage:
        mycmd test

    2. 使用GDB调试

    GDB是C/C++ 程序员的程序调试利器,很多问题使用GDB调试都可以大大提高效率。GDB在查看变量、跟踪函数跳转流程、查看内存内容、查看线程栈等方面都非常方便。

    同时,GDB也是深入理解程序运行细节最有效的方式之一,GDB 对于学习了解C语言代码、全局变量、栈、堆等内存区域的分布都有一定的帮助。

    下面我们来介绍GDB在基于玄铁内核的嵌入式芯片上的调试方法。

    2.1 建立GDB连接

    这一小节讲解一些嵌入式GDB调试使用的基础知识,和在PC上直接使用GDB调试PC上的程序会有一些区别。

    CK GDB是运行在PC上的GDB程序,通过仿真器和JTAG协议与开发板相连接,可以调试基于玄铁CPU内核的芯片。其中DebugServer为作为连接GDB和CKLink仿真器的桥梁和翻译官,一端通过网络与GDB连接,另一端通过USB线与仿真器连接。

    由于GDB与DebugServer通过网络通讯,他们可运行在同一个或不同的PC上。仿真器CKLink与开发板通过20PIN的JTAG排线连接。

    image.png

    CKLink

    CKLink 实物如下图所示。可以通过淘宝购买 。其使用方法可以查看:CKLink设备使用指南

    image.png

    DebugServer

    DebugServer有Windows 版本和Linux版本,下载和安装过程请参考:《Windows调试环境安装》,《Linux调试环境安装》。

    以Windows版本的DebugServer为例,安装完成以后,打开程序有如下界面:

    image.png

    点击连接按钮,如果连接成功会有CPU和GDB的信息打印,告知当前连接的CPU信息和开启的GDB服务信息。具体使用可以参考OCC资源下载页面下的文档:《DebugServer User Guide_v5.10》。

    2.2 启动GDB及配置

    GDB工具包含在整体的编译调试工具链里面,也可以通过OCC下载。GDB的使用都需要通过命令行完成,通过在终端敲入命令来完成交互 启动GDB通过如下命令进行:

    csky-abiv2-elf-gdb xxx.elf
    

    其中 xxx.elf 为当前板子上运行的程序,它包含了所有的程序调试信息,如果缺少elf文件则无法进行调试。

    启动GDB后输入如下命令连接DebugServer。这条命令在DebugServer的界面会有打印,可以直接复制。

    target remote [ip]:[port]
    

    需要注意的是:运行GDB程序对应的PC需要能够通过网络访问DebugServer开启的对应的IP
    连上以后就可以通过GDB 访问调试开发板上的芯片了。

    .gdbinit 文件

    .gdbinit 文件为GDB启动时默认运行的脚本文件,我们可以在.gdbinit 文件里面添加启动默认需要执行的命令,例如:target remote [ip]:[port],那么在启动GDB的时候,会直接连接DebugServer,提高调试效率。

    2.3 常用GDB命令

    这一小节介绍一些常用的GDB命令及使用方法。
    加载程序

    • 命令全名: load
    • 简化 :lo
    • 说明 :将 elf 文件 加载到 芯片中,这个命令对代码在flash运行的芯片无效。

    举例:

    (cskygdb) lo
    Loading section .text, size 0x291a00 lma 0x18600000
            section progress: 100.0%, total progress: 69.01% 
    Loading section .ram.code, size 0x228 lma 0x18891a00
            section progress: 100.0%, total progress: 69.02% 
    Loading section .gcc_except_table, size 0x8f8 lma 0x18891c28
            section progress: 100.0%, total progress: 69.08% 
    Loading section .rodata, size 0xeeac4 lma 0x18892520
            section progress: 100.0%, total progress: 94.12% 
    Loading section .FSymTab, size 0x9c lma 0x18980fe4
            section progress: 100.0%, total progress: 94.13% 
    Loading section .data, size 0x2e3c4 lma 0x18981400
            section progress: 100.0%, total progress: 98.98% 
    Loading section ._itcm_code, size 0x9b70 lma 0x189af7c4
            section progress: 100.0%, total progress: 100.00% 
    Start address 0x18600014, load size 3903412
    Transfer rate: 238 KB/sec, 4003 bytes/write.

    继续执行

    • 命令全名:continue
    • 简化 :c
    • 说明 :继续执行被调试程序,直至下一个断点或程序结束。

    举例:

    (cskygdb)c
    

    当DebugServer连接上开发板,程序会自动停止运行。等GDB挂进去以后,用c就可以继续运行程序。

    当程序在运行的时候,GDB直接挂入也会使程序停止运行,同样用c 命令可以继续运行程序。

    同样,当 load完成后,也可以使用c运行程序。

    暂停运行

    使用组件按键 ctrl + c 可以停止正在运行的程序。

    停止运行程序后就可以进行各种命令操作,如打印变量,打断点,查看栈信息,查看内存等。

    当操作完成以后,使用c 继续运行,或者使用 n/s 单步执行调试。

    打印变量

    • 命令全名: print
    • 简化 : p

    打印变量可以打印各种形式

    • 变量
    • 变量地址
    • 变量内容
    • 函数
    • 计算公式

    举例:

    (cskygdb)p g_tick_count
    (cskygdb)p &g_tick_count
    (cskygdb)p *g_tick_count
    (cskygdb)p main
    (cskygdb)p 3 * 5

    可以指定打印格式 按照特定格式打印变量

    • x 按十六进制格式显示变量。
    • d 按十进制格式显示变量。
    • o 按八进制格式显示变量。
    • t 按二进制格式显示变量。
    • c 按字符格式显示变量。

    通过这个功能,还可以进行简单的 各种进制转换

    举例:

    (cskygdb)p /x g_tick_count
    (cskygdb)p /x 1000
    (cskygdb)p /t 1000

    注意:有些局部变量会被编译器优化掉,可能无法查看。 p 命令是万能的,可以 p 变量地址,可以p 变量内容,可以p 函数地址;基本上所有符号,都可以通过p查看内容。

    设置断点

    • 命令全名: breakpoint
    • 简化 :b

    设置断电可以让程序自动停止在你希望停止的地方,断点可以以下面多种方式设置

    • 行号
    • 函数名
    • 文件名:行号
    • 汇编地址

    举例:

    (cskygdb)b 88
    (cskygdb)b main
    (cskygdb)b main.c:88
    (cskygdb)b *0x18600010

    硬件断点

    嵌入式芯片一般都有硬件断点可以设置,它相对于普通断点的不同是,该断点信息保存在cpu 调试寄存器里面,由cpu通过运行时的比较来实现断点功能,而普通断点则是通过修改该处代码的内容,替换成特定的汇编代码来实现断点功能的。 需要注意的是:硬件断点的设置会影响cpu的运行速度,但是对于一些微型的嵌入式芯片,代码放在flash这种无法写入,只能读取介质上时,就只能通过设置硬件断点才能实现断点功能,普通的断点设置将不会生效。 设置硬件断点通过另外一个命令设置,举例:

    (cskygdb)hb main
    

    设置内存断点

    • 命令全名: watchpoint
    • 简化 :watch

    设置内存断电可以在内存的内容发生变化的时候 自动停止运行。可以通过设置变量、内存断点

    举例:

    (cskygdb)watch g_tick_count
    (cskygdb)watch *0x18600010
    

    内存断点和硬件断点是相同的原理,只要是cpu运行导致的内存修改都会自动停止运行。内存断点和硬件断点都会都会占用cpu的调试断点数,每个芯片都由固定有限的个数可供设置,一般为4个或者8个等。

    查看断点

    • 命令全名:info breakpoint
    • 简化 :i b

    举例:

    (cskygdb) i b
    Num     Type           Disp Enb Address    What
    1       breakpoint     keep y   0x18704f9c in main 
                                               at vendor/tg6100n/aos/aos.c:110
    2       breakpoint     keep y   0x1871ca9c in cpu_pwr_node_init_static 
                                               at kernel/kernel/pwrmgmt/cpu_pwr_hal_lib.c:88

    使能断点

    • 命令全名:enable
    • 简化 :en

    举例:

    (cskygdb)en 1
    

    禁止断点

    • 命令全名:disable
    • 简化 :dis

    举例:

    (cskygdb)dis 1
    

    查看栈信息

    • 命令全名: backtrace
    • 简化 : bt

    例如:

    (cskygdb) bt
    #0  board_cpu_c_state_set (cpuCState=1, master=1)
        at vendor/tg6100n/board/pwrmgmt_hal/board_cpu_pwr.c:103
    #1  0x1871cb98 in cpu_pwr_c_state_set_ (
        all_cores_need_sync=<optimized out>, master=<optimized out>, 
        cpu_c_state=CPU_CSTATE_C1, 
        p_cpu_node=0x189d2100 <cpu_pwr_node_core_0>)
        at kernel/kernel/pwrmgmt/cpu_pwr_hal_lib.c:275
    #2  _cpu_pwr_c_state_set (target_c_state=CPU_CSTATE_C1)
        at kernel/kernel/pwrmgmt/cpu_pwr_hal_lib.c:495
    #3  cpu_pwr_c_state_set (target_c_state=CPU_CSTATE_C1)
        at kernel/kernel/pwrmgmt/cpu_pwr_hal_lib.c:524
    #4  0x1871d20c in tickless_enter ()
        at kernel/kernel/pwrmgmt/cpu_tickless.c:381
    #5  0x1871ce74 in cpu_pwr_down ()
        at kernel/kernel/pwrmgmt/cpu_pwr_lib.c:70
    #6  0x187095a4 in idle_task (arg=<optimized out>)
        at kernel/kernel/rhino/k_idle.c:48
    #7  0x1870bf44 in krhino_task_info_get (task=<optimized out>, 
        idx=<optimized out>, info=0x8000000)
        at kernel/kernel/rhino/k_task.c:1081
    Backtrace stopped: frame did not save the PC
    

    选择栈帧

    • 命令全名: frame
    • 简化 :f

    举例:

    (cskygdb) f 2
    #2  _cpu_pwr_c_state_set (target_c_state=CPU_CSTATE_C1)
        at kernel/kernel/pwrmgmt/cpu_pwr_hal_lib.c:495
    495                 ret = cpu_pwr_c_state_set_(p_cpu_node, target_c_state, master, FALSE);

    选择了栈帧就可以通过 p 命令查看该栈函数内的局部变量了。(函数内的局部变量是存放在栈空间中的)

    单步执行

    • 命令全名: next
    • 简化 :n

    举例:

    (cskygdb) n
    

    单步执行进入函数

    • 命令全名: step
    • 简化 :s

    举例:

    (cskygdb) s
    

    单步执行(汇编)

    • 命令全名: nexti
    • 简化 :ni

    举例:

    (cskygdb) ni
    

    单步执行进入函数(汇编)

    • 命令全名: stepi
    • 简化 :si

    举例:

    (cskygdb) si
    

    相对于s 的单步执行,si的单步执行精确到了汇编级别,每一个命令执行一条汇编指令。对于优化比较严重的函数,s 的按行 单步执行 流程往往会比较混乱,按汇编的单步执行则会比较符合芯片底层的逻辑。当然使用si单步调试程序,也需要程序员对于汇编指令有比较好的了解,调试难度也比较大。但是对于嵌入式程序,编译器必然会对程序进行各种优化,s 的单步调试往往不是很好的选择。

    完成当前函数

    • 命令全名: finish
    • 简化 :fin

    举例:

    (cskygdb) fin
    

    当想跳出该函数调试时,使用该命令会相当方便。但是该命令有一个限制,当在不会支持普通断点的设备上调试时(代码放在flash上执行),这个命令需要配合 另一条命令才能生效

    (cskygdb) set debug-in-rom
    

    这条命令的意思是,告诉gdb这个代码是放在flash上的,需要使用硬件断点才能使用fin命令,这条命令只需要执行一次。

    设置变量

    • 命令格式:

    set [variable] = [value]
    

    举例:

    (cskygdb) set g_tick_count = 100
    (cskygdb) set *0x186000010 = 0x10
    

    在调试一些程序逻辑时,通过设置变量数值可以让程序走期望的流程,来方便调试。

    查看内存

    • 命令格式

    x /[n][f][u] [address]
    

    其中:
    • n 表示显示内存长度,默认值为1
    • f 表示显示格式,如同上面打印变量定义
    • u 表示每次读取的字节数,默认是4bytes
    – b 表示单字节
    – h 表示双字节
    – w 表示四字节
    – g 表示八字节

    举例:

    (cskygdb) x /20x 0x18950000
    0x18950000:     0x6f445f6c      0x72652077      0x21726f72      0x6c43000a
    0x18950010:     0x546b636f      0x72656d69      0x5f6c633a      0x61746164
    0x18950020:     0x6c633e2d      0x6365535f      0x74696220      0x2070616d
    0x18950030:     0x61207369      0x30206c6c      0x21212120      0x6c43000a
    0x18950040:     0x546b636f      0x72656d69      0x5f6c633a      0x61746164

    这条命令对于调试踩内存,栈溢出等大量内存变化的场景非常有帮助。

    2.4 快速上手调试

    接下来,你可以找一块开发板,按照下面步骤体验GDB调试过程:

    • 如前面介绍,下载并安装DebugServer
    • GDB 连上DebugServer
    • lo //灌入编译好的 elf
    • b main //打断点到 main函数入口
    • c //运行程序
    • 如果顺利,这时程序应该自动停在main函数入口
    • n //单步执行下一行程序,可以多执行几次
    • 找几个全局变量, p 查看结果

    大部分开发板上电都自动会运行程序,连上DegbuServer就会停止运行。

    注意事项

    • 调试的时候 elf 文件 一定要和运行程序对应上,不然没法调试,使用一个错误的elf文件调试程序,会出现各种乱七八糟的现象。而且同一份代码,不同的编译器,不同的主机编译出来的elf都可能不相同。所以保存好编译出来的elf相当重要
    • 对于一些代码运行在 flash的芯片方案,GDB调试的时候要注意转换,和在ram上GDB调试命令有一些不一样。
    • watch 只能观察到CPU的内存更改行为,如果是外设(DMA等)运行导致的内存变化,不能被watch到
    • CKLink 连接开发板可能存在各种问题连接不上,要仔细检查,包括:开发板是否上电,芯片是否上电,芯片是否在运行,JTAG排线是否插反等等。

    3. CPU异常分析及调试

    3.1 CPU异常案例

    在开发板运行过程中,有时会突然出现如下打印,进而程序停止运行,开发板也没有任何响应:

    CPU Exception: NO.2
    r0: 0x00000014  r1: 0x18a70124  r2: 0x00001111  r3: 0x10020000  
    r4: 0x00000000  r5: 0x00000001  r6: 0x00000002  r7: 0x07070707  
    r8: 0x00000000  r9: 0x09090909  r10: 0x10101010 r11: 0x11111111 
    r12: 0x40000000 r13: 0x00000000 r14: 0x18b166a8 r15: 0x186d9c0a 
    r16: 0x16161616 r17: 0x47000000 r18: 0x3f800000 r19: 0x00000000 
    r20: 0xc0000000 r21: 0x40000000 r22: 0x00000000 r23: 0x00000000 
    r24: 0x40400000 r25: 0x12345678 r26: 0x12345678 r27: 0x12345678 
    r28: 0x12345678 r29: 0x12345678 r30: 0x12345678 r31: 0x12345678 
    vr0: 0x12345678 vr1: 0x00000000 vr2: 0x00000000 vr3: 0x00000000 
    vr4: 0x00000000 vr5: 0x00000000 vr6: 0x00000000 vr7: 0x00000000 
    vr8: 0x00000000 vr9: 0x00000000 vr10: 0x00000000    vr11: 0x00000000    
    vr12: 0x00000000    vr13: 0x00000000    vr14: 0x00000000    vr15: 0x00000000    
    vr16: 0x00000000    vr17: 0x00000000    vr18: 0x00000000    vr19: 0x00000000    
    vr20: 0x00000000    vr21: 0x00000000    vr22: 0x00000000    vr23: 0x00000000    
    vr24: 0x00000000    vr25: 0x00000000    vr26: 0x00000000    vr27: 0x00000000    
    vr28: 0x00000000    vr29: 0x00000000    vr30: 0x00000000    vr31: 0x00000000    
    vr32: 0x00000000    vr33: 0x00000000    vr34: 0x00000000    vr35: 0x00000000    
    vr36: 0x00000000    vr37: 0x00000000    vr38: 0x00000000    vr39: 0x00000000    
    vr40: 0x00000000    vr41: 0x00000000    vr42: 0x00000000    vr43: 0x00000000    
    vr44: 0x00000000    vr45: 0x00000000    vr46: 0x00000000    vr47: 0x00000000    
    vr48: 0x00000000    vr49: 0x00000000    vr50: 0x00000000    vr51: 0x00000000    
    vr52: 0x00000000    vr53: 0x00000000    vr54: 0x00000000    vr55: 0x00000000    
    vr56: 0x00000000    vr57: 0x00000000    vr58: 0x00000000    vr59: 0x00000000    
    vr60: 0x00000000    vr61: 0x00000000    vr62: 0x00000000    vr63: 0x00000000    
    
    epsr: 0xe4000341
    epc : 0x186d9c12

    这段打印表明程序已经崩溃。接下来以它为例,来一步一步分析如何调试和解决。

    3.2 基础知识介绍

    3.2.1 关键寄存器说明

    • pc:程序计数器,它是一个地址指针,指向了程序执行到的位置
    • sp:栈指针,它是一个地址指针,指向了当前任务的栈顶部,它的下面存了这个任务的函数调用顺序和这些被调用函数里面的局部变量。在玄铁CPU框架里,它对应了 R14 寄存器
    • lr:连接寄存器,它也是一个地址指针,指向子程序返回地址,也就是说当前程序执行返回后,执行的第一个指令就是lr寄存器指向的指令,在玄铁CPU框架里,它对对应了 R15 寄存器
    • epc:异常保留程序计数器,它是一个地址指针,指向了异常时的程序位置,这个寄存器比较重要,出现异常后,我们就需要通过这个寄存器来恢复出现异常时候的程序位置。
    • epsr:异常保留处理器状态寄存器,它是一个状态寄存器,保存了出异常前的系统状态。
    这几个重要的寄存器都在上面的异常打印中打印出来了。

    3.2.2 关键文件说明

    • yoc.elf:保存了程序的所有调试信息,GDB调试时必须用到该文件,编译完程序后务必保留该文件。
    • yoc.map:保存了程序全局变量,静态变量,代码的存放位置及大小。
    • yoc.asm:反汇编文件,保存了程序的所有反汇编信息。这些文件都保存在每个solutions目录中。如果使用CDK开发,则位于项目的Obj目录中。
    其中:
    • yoc.map 文件必须在编译链接的时候通过编译选项生成,例如:CK的工具链的编译选项为-Wl,-ckmap='yoc.map'
    • yoc.asm 文件可以通过elf 文件生成,具体命令为csky-abiv2-objdump -d yoc.elf > yoc.asm

    3.2.3 异常号说明

    在XT CPU架构里,不同的cpu异常会有不同的异常号,我们往往需要通过异常号来判断可能出现的问题。

    image.png
    image.png

    这些异常中,出现最多的是 1、2 号异常,4、7 偶尔也会被触发,3号异常比较好确认。

    3.3 异常分析过程

    GDB准备及连接
    参考上节:《2. 使用GDB调试》。

    恢复现场

    在GDB 使用 set 命令 将异常的现场的通用寄存器和 PC 寄存器设置回CPU中,便可以看到崩溃异常的程序位置了

    (cskygdb)set $r0=0x00000014
    (cskygdb)set $r1=0x18a70124
    (cskygdb)set $r2=0x00001111
    (cskygdb)set $r3=0x10020000 
    ...
    (cskygdb)set $r14=0x18b166a8
    (cskygdb)set $r15=0x186d9c0a
    ...
    (cskygdb)set $r30=0x12345678
    (cskygdb)set $r31=0x12345678
    (cskygdb)set $pc=$epc

    不同的CPU 通用寄存器的个数有可能不相同,一般有 16个通用寄存器、32个通用寄存器两种版本,我们只需要把通用寄存器,即 r 开头的寄存器,设置回CPU即可。 pc,r14,r15 三个寄存器是找回现场的关键寄存器,其中r14,r15分别是 sp 寄存器和 lr寄存器,pc寄存器需要设置成epc。其余的通用寄存器是一些函数传参和函数内的局部变量。

    设置完成以后,通过 bt命令可以查看异常现场的栈:

    (cskygdb) bt
    #0  0x186d9c12 in board_yoc_init () at vendor/tg6100n/board/init.c:202
    #1  0x186d9684 in sys_init_func () at vendor/tg6100n/aos/aos.c:102
    #2  0x186dfc14 in krhino_task_info_get (task=<optimized out>, idx=<optimized out>, info=0x11)
        at kernel/kernel/rhino/k_task.c:1081
    Backtrace stopped: frame did not save the PC
    
    
    
    从 bt 命令打印出来的栈信息,我们可以看到 异常点在 init.c 的 202 行上,位于board_yoc_init函数内。 到这里,对于一些比较简单的错误,基本能判断出了什么问题。 如果没法一眼看出问题点,那我们就需要通过异常号来对应找BUG了。

    3.4 通过异常号找BUG

    程序崩溃后,异常打印的第一行就是CPU异常号。

    CPU Exception: NO.2
    

    如上,我们示例中的打印是2号异常。 2号异常是最为常见的异常,1号异常也较为常见。4号、7号一般是程序跑飞了,运行到了一个不是程序段的地方。3号异常就是除法除零了,比较好确认。其余的异常基本不会出现,出现了大概率也是芯片问题或者某个驱动问题,不是应用程序问题。

    CPU Exception: NO.1

    一号异常是访问未对齐异常,一般是一个多字节的变量从一个没有对齐的地址赋值或者被赋值。 例如:

    uint32_t temp;
    uint8_t data[12];
    temp = *((uint32_t*)&data[1]);

    如上代码,一个 4字节的变量 temp从 一个单字节的数组中取4个字节内容,这种代码就容易出现地址未对齐异常。这种操作在一些流数据的拆包组包过程比较常见,这个时候就需要谨慎小心了。

    有些CPU 可以开启不对齐访问设置,让CPU可以支持从不对齐的地址去取多字节,这样就不会出现一号异常。但是为了平台兼容性,我们还是尽量不要出现这样的代码。

    CPU Exception: NO.2

    二号异常是访问错误异常,一般是访问了一个不存在的地址空间。 例如:

    uint32_t *temp;
    *temp = 1;
    

    如上代码,temp指针未初始化,如果直接给 temp指针指向的地址赋值,有可能导致二号异常,因为temp指向的地址是个随机值,该地址可能并不存在,或者不可以被写入。 二号异常也是最经常出现的异常,例如常见的错误有:

    • 内存访问越界
    • 线程栈溢出
    • 野指针赋值
    • 重复释放指针(free)

    请注意你代码里的 memset、memcpy、malloc、free 、strcpy等调用。

    大部分2号异常和1号异常的问题,异常的时候都不是第一现场了,也就是说异常点之前就已经出问题了。

    比如之前就出现了 memcpy的 内存访问越界,内存拷贝超出变量区域了。memcpy的时候是不会异常的,只有当程序使用了这些被memcpy 踩了内存时,才会出现一号或二号异常。

    这个时候异常点已经不是那个坑的地方了,属于“前人埋坑,后人遭殃”型问题。

    如果是一些很快就复现的问题,我们可以通过GDB watch命令,watch那些被踩的内存或变量来快速的定位是哪段代码踩了内存。

    如果是一些压测出现的问题,压测了2天,出了一个2号异常,恭喜你,碰到大坑了。类似这种,比较难复现的问题,watch已经不现实了。

    结合异常现场GDB查看变量、内存信息和review代码逻辑,倒推出内存踩踏点,是比较正确的途径。

    再有,就是在可疑的代码中加 log日志,增加压测的机器,构造缩短复现时间的case等一些技巧来加快BUG解决的速度。

    CPU Exception: NO.4/NO.7

    四号异常是指令非法,即这个地址上的内容并不是一条CPU机器指令,不能被执行。 七号异常是断点异常,也就是这个指令是断点指令,即 bktp 指令,这是调试指令,一般代码不会编译生成这种指令。 这两种异常大概率是 指针函数没有赋值就直接跳转了,或者是代码段被踩了

    例如:

    typedef void (*func_t)(void *argv);
    
    func_t f;
    void *priv = NULL;
    
    if (f != NULL) {
        f(priv);
    }

    如上代码,f是一个 函数指针,没有被赋值,是一个随机值。直接进行跳转,程序就肯定跑飞了。 这种异常,一般epc地址,都不在反汇编文件 yoc.asm 中。

    CPU Exception: NO.3

    3号异常是除零异常,也是最简单、最直接的一种异常。 例如:

    int a = 100;
    int b = 0;
    
    int c = a / b; 

    如上代码,b 变量位 0,除零就会出现 三号异常。

    3.5 不用GDB找到异常点

    有些时候无法使用GDB去查看异常点,或者搭环境不是很方便怎么办? 这个时候我们可以通过反汇编文件和epc地址来查看产生异常的函数。 打开yoc.asm 反汇编文件,在文件内搜索epc地址,就可以找到对应的函数,只是找不到对应的行号。

    例如:

    186d9b14 <board_yoc_init>:
    186d9b14:   14d3        push        r4-r6, r15
    186d9b16:   1430        subi        r14, r14, 64
    186d9b18:   e3ffffc6    bsr         0x186d9aa4  // 186d9aa4 <speaker_init>
    186d9b1c:   3001        movi        r0, 1
    186d9b1e:   e3fe3221    bsr         0x1869ff60  // 1869ff60 <av_ao_diff_enable>
    186d9b22:   e3fe4ca9    bsr         0x186a3474  // 186a3474 <booab_init>
    186d9b26:   e3fffe7d    bsr         0x186d9820  // 186d9820 <firmware_init>
    ...
    186d9bfc:   1010        lrw         r0, 0x188d1a50  // 186d9c3c <board_yoc_init+0x128>
    186d9bfe:   e00c6aeb    bsr         0x188671d4  // 188671d4 <printf>
    186d9c02:   ea231002    movih       r3, 4098
    186d9c06:   ea021111    movi        r2, 4369
    186d9c0a:   b340        st.w        r2, (r3, 0x0)
    186d9c0c:   1410        addi        r14, r14, 64
    186d9c0e:   1493        pop         r4-r6, r15
    186d9c12:   9821        ld.w        r1, (r14, 0x4)
    186d9c14:   07a4        br          0x186d9b5a  // 186d9b5a <board_yoc_init+0x46>
    186d9c14:   188d19c0    .long   0x188d19c0

    如上的汇编代码,根据异常的epc地址0x186d9c12,我们可以确认异常发生在board_yoc_init函数内。

    ]]>
    浅谈基于 Git 的版本控制工作流-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    博主说:本文借鉴了很多「 DRPrincess」博主的文章内容,在此对其表示感谢。

    为了更好的理解基于 Git 的版本控制工作流,我们不妨先来回答几个问题?

    • 什么是版本控制?
    • 什么是版本控制系统?
    • 为什么要做版本控制?
    • 为什么选择基于 Git 的版本控制?

    要回答这些问题,最好的方法,莫过于回顾一下版本控制的发展历史。

    因此,在本文中,我们就从「[版本控制简史」出发,揭开「基于 Git 的版本控制工作流」的神秘面纱。

    版本控制简史

    版本控制,是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理。版本控制最主要的目的就是追踪文件的变更。它将什么时候、什么人更改了文件的什么内容等信息忠实地了记录下来。每一次文件的改变,文件的版本号都将增加。

    除了记录版本变更外,版本控制的另一个重要功能是并行开发。软件开发往往是多人协同作业,版本控制可以有效地解决版本的同步以及不同开发者之间的开发通信问题,提高协同开发的效率。并行开发中最常见的不同版本软件的错误修正问题也可以通过版本控制中分支与合并的方法有效地解决。

    但版本控制是目的而不是实现的工具,所以我们还需要通过某种工具来实现版本控制的目的,我们将这样的工具称之为 Version Controll System,缩写为 VCS,即版本控制系统。我们可以把一个版本控制系统简单的理解为一个“数据库”,在需要的时候,它可以帮我们完整地保存一个项目的快照。当我们需要查看一个之前的快照(称之为“版本”)时,版本控制系统可以显示出当前版本与上一个版本之间的所有改动的细节。

    早在 1986 年 12 月,Dick Grune 就以 shell 脚本的形式发布了第一个流行的版本控制系统 CVS 的雏形。1989 年 4 月,Brian Berliner 设计了 CVS 并编写了代码。CVS 是一个 C/S 系统,其设计思路为,在一台服务器上建立一个源代码库,库里可以存放许多不同项目的源程序,由源代码库管理员统一管理这些源程序。每个用户在使用源代码库之前,首先要把源代码库里的项目文件下载到本地,然后用户可以在本地任意修改,最后用 CVS 命令进行提交,由 CVS 源代码库统一管理修改。这样,就好像只有一个人在修改文件一样,既避免了冲突,又可以做到跟踪文件变化等。

    2000 年,CollabNet Inc 开发了 Subversion,缩写为 SVN,是一个开放源代码的版本控制系统,现已发展成了 Apache 基金会的项目。相对于 CVS,SVN 采用了分支管理系统,它的设计目标就是取代 CVS,但与 CVS 相同的是,SVN 也采用了 C/S 体系,项目的各种版本都存储在服务器上,程序开发人员首先将从服务器上获得一份项目的最新版本,并将其复制到本机,然后在此基础上,每个开发人员可以在自己的客户端进行独立的开发工作,并且可以随时将新代码提交给服务器。当然也可以通过更新操作获取服务器上的最新代码,从而保持与其他开发者所使用版本的一致性。

    2005 年,Linux 之父 Linus Torvalds 为了帮助管理 Linux 内核开发而开发了一个开放源码的版本控制软件 Git。说起来,Git 的诞生还有一些戏剧性,Linus 最初使用 BitKeeper 作为版本控制系统,但在 2005 年,Andrew Tridgell 写了一个程序,可以连接 BitKeeper 的存储库,BitKeeper 著作权拥有者 Larry McVoy 认为 Andrew Tridgell 对 BitKeeper 内部使用的协议进行逆向工程,决定收回无偿使用 BitKeeper 的许可。Linux 内核开发团队与 BitMover 公司进行磋商,但无法解决他们之间的歧见。最终,Linus Torvalds 决定自行开发版本控制系统替代 BitKeeper,就用十天的时间编写出了 Git 的第一个版本。

    如上所述,从 CVS、到 SVN、再到 Git 的变化,也是版本控制系统演进的过程。我们可以将 CVS、SVN 和 Git 大致分为两类:

    • 集中式版本控制系统:CVS 和 SVN 属于这一类。它们用集中管理的单一服务器,来保存所有文件修订版本,而协同工作的人们都通过客户端连到这台服务器,下载最新的代码或者是更新提交。但是如果中央服务器宕机了,那宕机的这一段时间,大家都无法更新提交更新,没法协同工作;更糟糕的情况下,如果中央服务器的数据没有做备份而且损坏,那么所有记录就都丢失了。
    • 分布式版本控制系统:Git 属于这一类。分布式版本控制系统最大的特点就是客户端并不只是提取最新版本的文件快照,而是把代码仓库完整地镜像下来,每个客户端其实都可以当做是中央服务器,当中央服务器数据损坏了,从任何一个本地客户端都可以重新恢复。而且我们可以随时随地提交代码,因为我们提交代码是提交到本地的服务器,所以效率大大提高。

    现如今,Git 应该算是最受欢迎的版本控制工具了。例如现在世界上最大的两个代码托管平台 GitHub 和 GitLab,都是基于 Git 进行版本控制的;在国内,大家使用较多的中文代码托管平台 Gitee,也是基于 Git 进行版本控制的。由此可见,Git 作为版本控制工具,其速度快、分布式等特性,深受大家喜爱的。因此,了解基于 Git 的版本控制工作流,还是与我们有益的!

    什么是工作流?

    工作流,即工作流程。在项目开发过程中,多人协作是很常见的现象,每个人拉取自己分支、实现自己的业务逻辑,虽然各自在分支上互不干扰,但是我们总归需要把分支合并到一起,而且真实项目中涉及到很多问题,例如版本迭代,版本发布,bug 修复等,为了更好的管理代码,需要制定一个工作流程,这就是我们说的工作流,也有人叫它分支管理策略。

    工作流不涉及任何命令,因为它就是一个规则,完全由开发者自定义,并且自行遵守,正所谓无规矩不成方圆,就是这个道理。其中,Git Flow 出现的最早,GitHub Flow 在 Git Flow 的基础上,做了一些优化,适用于持续版本的发布,而 GitLab Flow 出现的时间比较晚,所以综合了前面两种工作流的优点,制定而成的一种工作流。接下来,我们就详细了解这三个工作流。

    Git Flow

    Git Flow 是 Vincent Driessen 2010 年发布出来的他自己的分支管理模型,到现在为止,使用度非常高,可以说是一个非常成熟的 Git 工作流。Git Flow 的分支结构,按功能来说,可以分为 5 种分支,从 5 种分支的生命周期上,又可以分为长期分支和短期分支,或者更贴切的描述为,主要分支和辅助分支。

    主要分支

    在采用 Git Flow 工作流的项目中,代码的中央仓库会一直存在以下两个长期分支:

    • master
    • develop

    其中,origin/master分支上的最新代码永远是版本发布状态,origin/develop分支则是最新的开发进度。当develop上的代码达到一个稳定的状态,可以发布版本的时候,develop上这些修改会以某种特别方式被合并到master分支上,然后标记上对应的版本标签。

    辅助分支

    除了主要分支,Git Flow 的开发模式还需要一系列的辅助分支,来帮助更好的并行开发,简化功能开发和问题修复。辅助分支不需要一直存在,仅当我们需要的时候,创建辅助分支就可以,当我们不需要的时候,也可以删除辅助分支。辅助分支分为以下几类:

    • Feature Branch
    • Release Branch
    • Hotfix Branch

    Feature 分支用来做分模块功能开发,命名看开发者喜好,不要和其他类型的分支命名弄混淆就好,举个坏例子,命名为master就是一个非常不妥当的举动。模块完成之后,会合并到develop分支,然后删除自己。

    Release 分支用来做版本发布的预发布分支,建议命名为release-xxx。例如在软件1.0.0版本的功能全部开发完成,提交测试之后,从develop检出release-1.0.0,测试中出现的小问题,在release分支进行修改提交,测试完毕准备发布的时候,代码会合并到masterdevelopmaster分支合并后会打上对应版本标签v1.0.0,合并后删除自己,这样做的好处是,在测试的时候,不影响下一个版本功能并行开发。

    Hotfix 分支是用来做线上的紧急 bug 修复的分支,建议命名为hotfix-xxx。当线上某个版本出现了问题,将检出对应版本的代码,创建 Hotfix 分支,问题修复后,合并回masterdevelop,然后删除自己。这里注意,合并到master的时候,也要打上修复后的版本标签。

    Merge 加上 --no-ff 参数

    需要说明的是,Git Flow 的作者 Vincent Driessen 非常建议,合并分支的时候,加上--no-ff参数,这个参数的意思是不要选择 Fast-Forward 合并方式,而是策略合并,策略合并会让我们多一个合并提交。这样做的好处是保证一个非常清晰的提交历史,可以看到被合并分支的存在。下面是对比图,左侧是加上参数的,后者是普通的提交:

    git-merge

    示意图

    git-flow

    如上图所示,这是 Vincent Driessen 于 2010 年给出的 Git Flow 示意图,也是我们所有想要学习 Git Flow 的人都应该了解的一张图。图中画了 Git Flow 的五种分支,masterdevelopfeaturereleasehoxfixes,其中masterdevelop字体被加粗代表主要分支。master分支每合并一个分支,无论是hotfix还是release,都会打一个版本标签。通过箭头可以清楚的看到分支的开始和结束走向,例如feature分支从develop开始,最终合并回develophoxfixesmaster检出创建,最后合并回developmastermaster也打上了标签。

    GitHub Flow

    GitHub Flow 是世界上最大的代码托管平台,也称为“世界上最大的同性交友网站” GitHub 制定并使用的工作流,其是一个轻量级,基于分支的工作流,支持团队和项目的定期部署,由 Scott Chacon 在 2011 年 8月 31 号正式发布。

    模型说明

    在 GitHub Flow 中,只有一个长期分支master,而且master分支上的代码永远是可发布状态。一般来说,master会设置为受保护状态,只有有权限的人才能推送代码到master分支。以 GitHub 官方教程为准,遵循 GitHub Flow 需要经历以下几个步骤:

    • 创建分支
    • 添加提交
    • 提出 PR 请求
    • 讨论和评估你的代码
    • 部署
    • 合并

    简单解释一下,其大致流程为:如果有新功能开发、版本迭代或者 bug 修复等需求,我们就从master分支上检出新的分支;将检出的新分支代码拉取到本地,在本地环境中进行编码,完成后,向远程新分支仓库推送代码;当我们需要反馈问题、取得帮助,或者想合并分支代码时,可以发起一个 Pull Request,常简称为 PR;当我们的代码通过项目维护者(有权限向master分支合并代码的人)讨论和评估后,就可以部署代码;待部署完成、验证通过后,代码就应该被合并到目标分支。

    示意图

    github-flow

    与 Git Flow 的示意图相比,GitHub Flow 的示意图可以称得上简单明了,因为 GitHub Flow 推荐做法就是只有一个主分支master,团队成员们的分支代码通过 PR 来合并到主分支上。实际上,上面的图仅是创建分支的示意图,但无论是创建分支还是添加提交、提出 PR 请求等,都不过是围绕着主分支按照上述的流程推进而已,如果大家感兴趣,可以通过「 深入理解 GitHub Flow」查看全部示意图。

    特色功能

    因为 GItHub Flow 的初衷就是用于在 GitHub 上进行团队协作,所以借助于 GitHub 平台的功能,GItHub Flow 中也引入了一些比较实用的工作流程,其中最出色的两个功能莫过于 PR 与问题追踪了。

    PR

    在工作流中引入 PR,是 GItHub Flow 的一个特色,它的用处并不仅仅是合并分支,还有以下功能:

    • 控制分支合并权限
    • 问题讨论或者寻求其他小伙伴们的帮助
    • Code Review

    有了 PR 功能之后,相信我们再提交代码的时候,就得慎之又慎了。否则的话,代码写的太烂,就等着被喷吧!

    问题追踪

    在日常开发中,我们可能会用到很多第三方的开源库,如果使用过程中遇到了问题,我们可以去其 GitHub 仓库上搜索一下 Issue 列表,看看有没有人遇到过、项目维护者修复了没有,一般未解决的 Issue 是Open状态,已解决的 Issue 是Closed状态,这就是问题追踪。

    如果你是一个项目维护者,除了标记 Issue 的开启和关闭,还可以给它标记上不同的标签。当提交的时候,如果提交信息中有fix #1等字段,可以自动关闭对应编号的 Issue。

    GitLab Flow

    这个工作流十分地年轻,是 GitLab 的 CEO Sytse Sijbrandij 在 2014 年 9月 29 正式发布出来的。因为出现的比前面两种工作流稍微晚一些,所以它有个非常大的优势,集百家之长,补百家之短。GitLab 既支持 Git Flow 的分支策略,也支持 GitHub Flow 的 PR 和问题追踪。

    Git Flow & GitHub Flow 的瑕疵

    当 Git Flow 出现后,它解决了之前项目管理的很让人头疼的分支管理,但是实际使用过程中,也暴露了很多问题:

    • 默认工作分支是develop,但是大部分版本管理工具默认分支都是master,开始的时候总是需要切换很麻烦。
    • Hotfix 和 Release 分支在需要版本快速迭代的项目中,几乎用不到,因为刚开发完就直接合并到master发版,出现问题develop就直接修复发布下个版本了。
    • Hotfix 和 Release 分支,一个从master创建,一个从develop创建,使用完毕,需要合并回developmaster。而且在实际项目管理中,很多开发者会忘记合并回develop或者master

    GitHub Flow 的出现,非常大程度上简化了 Git Flow ,因为只有一个长期分支master,并且提供 GUI 操作工具,一定程度上避免了上述的几个问题,然而在一些实际问题面前,仅仅使用master分支显然有点力不从心,例如:

    • 版本的延迟发布(例如 iOS 应用审核到通过中间,可能也要在master上推送代码)
    • 不同环境的部署 (例如:测试环境,预发环境,正式环境)
    • 不同版本发布与修复 (是的,只有一个master分支真的不够用)

    GitLab Flow 解决方案

    为了解决上面提到的那些问题,GitLab Flow 给出了以下的解决方法。

    版本的延迟发布 Prodution Branch

    master分支不够,于是添加了一个prodution分支,专门用来发布版本。

    master-production

    不同环境的部署 Environment Branches & Upstream First

    每个环境,都对应一个分支,例如下图中的pre-productionprodution分支都对应不同的环境,这个工作流模型比较适用服务端,测试环境,预发环境,正式环境,一个环境建一个分支。

    这里要注意,代码合并的顺序,要按环境依次推送,确保代码被充分测试过,才会从上游分支合并到下游分支。除非是很紧急的情况,才允许跳过上游分支,直接合并到下游分支。这个被定义为一个规则,名字叫 “upstream first”,翻译过来是 “上游优先”。

    master-pre-production

    版本发布分支 Release Branches & Upstream First

    只有当对外发布软件的时候,才需要创建release分支。对外发布版本的记录是非常重要的,如果线上出现了一个问题,需要拿到问题出现对应版本的代码,才能准确定位问题。

    在 Git Flow 中,版本记录是通过master上的tag来记录的。发现问题,创建hotfix分支,完成之后合并到masterdevelop

    在 GitLab Flow 中,建议的做法是每一个稳定版本,都要从master分支拉出一个分支,比如2-3-stable2-4-stable等等。发现问题,就从对应版本分支创建修复分支,完成之后,先合并到master,然后才能再合并到release分支,遵循 “上游优先” 原则。

    master-stable

    分支命名实践

    现如今,越来越多的公司都会利用 GitLab 来搭建自己的代码托管平台,因此就以 GitLab Flow 为例,给出一个较好的分支命名实践。

    如果存在多个环境,则为每个环境建立一个长期分支,可以命名为:

    • master,表示主分支,用于生产环境;
    • beta,表示内测分支,用于内测环境;
    • test,表示测试分支,用于测试环境。

    在此,着重解释一下“内测环境”吧,实际上,内测环境应该是生产环境的一部分,是从生产环境隔离出来一部分用于内测,以保证线上回归测试时不影响真实的用户,因此两者共用一套生产数据库,仅是通过流量入口做区分。

    接下来,根据不同的目的,为新拉取的分支取不同的名称:

    • 如果是开发需求,则从master拉取新分支,命名为feature-1xx-2xx-3xx,其中每一部分都有不同的含义,如

      • feature为固定词,表示这是一个新特性分支;
      • 1xx表示新特性的描述,为防止分支名过长,可以用缩写;
      • 2xx表示新分支创建的时间,格式为YYYYMMDD
      • 3xx表示新分支的创建者,姓名拼音或者英文名均可。

    给出一个开发需求的分支命名示例,feature-SupportIM-20200711-chariesgavin,整个分支名称的含义就是,“某人在某时创建了某个功能的新特性分支”。开发、测试及代码合并的流程,大致如下:

    1. master分支拉取新的开发分支,进行编码,自测;
    2. 自测完成后,将代码合并到test分支,并且在test环境进行测试;
    3. test环境测试通过后,将代码合并到beta分支,并且在beta环境进行线上回归测试;
    4. beta环境测试通过后,将代码合并到master分支,并且将代码同步到生产环境;
    5. 生产环境上线后,就再从master分支打一个tag,其作用和稳定分支stable、发布分支release一样,用于回滚代码,命名为tag-xxx,其中xxx自定义即可,如版本号。

    如果线上的代码一直没问题,自然是万事大吉,但难免会遇到各种各样的问题。这时,我们就遇到了另一种场景,即 BUG 修复。

    • 如果是 BUG 修复,则从master拉取新分支,命名为hotfix-1xx-2xx-3xx,其中每一部分都有不同的含义,如

      • hotfix为固定词,表示这是一个修复 BUG 的分支;
      • 1xx表示 BUG 的描述,为防止分支名过长,可以用缩写;
      • 2xx表示新分支创建的时间,格式为YYYYMMDD
      • 3xx表示新分支的创建者,姓名拼音或者英文名均可。

    给出一个 BUG 修复分支命名示例,hotfix-messageRepeat-20200711-chariesgavin,整个分支名称的含义就是,“某人在某时创建了修复某个 BUG 的新分支”。理论上来说,BUG 修复的开发、测试及代码合并的流程应该和上述的开发需求是一致的,毕竟如果生产环境出现了问题,其他前置环境肯定也是跑不掉的,修复已知问题终归是值得提倡的;但在比较紧急的情况下,没有足够的时间让我们在不同的环境进行测试,该流程也是可以简化的,大致如下:

    1. master分支拉取新的开发分支,进行编码,自测;
    2. 自测完成后,将代码直接合并到beta分支,上线到内测环境进行测试;
    3. 内测环境通过后,再将代码合并到master分支,同步到生产环境,并从master分支打一个tag,备份稳定代码;
    4. 最后,再将修复 BUG 的代码同步到不同环境的稳定分支。

    在这里,有一点可能让我们诟病,那就是分支名称太长了。确实,当我们想把更多的信息都揉进一个名称的时候,难免会遇到这样的问题!但如果是feature-1.0或者hotfix-20200710这类名称,可能开发周期稍微长一些的时候,大家都容易忘了这样的分支到底是谁创建的、实现了什么功能吧?因此,与之相比,我感觉分支名称稍微长一些还是可以接受的。

    当然,就如 Git Flow 一样,任何工作流想要起作用,都需要我们认同它、打心里接受它,然后才能自觉的遵守其规范,毕竟,公司总不至于因为我们不遵守分支命名规范而开除我们吧?公司采取硬性规定的另算。但这些工作流之所以能得到大家广泛的认同,并且流传之广,自然还是尤其魅力的,或多或少还是能够提高团队协作效率的。采取与否,您来决定!


    参考资料

    ]]>
    电商行业业务及数据库上云-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    阿里云最佳实践频道:【点击查看更多上云最佳实践
    这里有丰富的企业上云最佳实践,从典型场景入门,提供一系列项目实践方案,降低企业上云门槛的同时满足您的需求!

    场景描述

    该方案适用于新零售领域的电商行业,包括电商公司初创,满足快速搭建平台;以及中型企业应对发展阶段,满足业务快速占领市场。对于头部客户搬站,方案借鉴参考。本文重点解决阿里云资源的开通配置,以及其他云厂商或自建的MySQL搬迁到阿里云RDS。

    方案优势

    • 通过SLB流量分发,快速扩展应用对外服务能力
    • 通过Redis缓解高并发的数据读写,QPS支持万级到千万级
    • 提供高可用的数据库架构,保障数据的可用性和可靠性
    • 将电商静态资源存储在oss,通过cdn分发,提升用户
      访问体验
    • 云产品,支持随时弹性升级、扩容配置

    产品列表

    • 云服务器 ECS
    • 数据库 RDS
    • 数据传输 DTS
    • 负载均衡 SLB
    • 专有络 VPC

    bp-8.png

    直达最佳实践 》》


    bp-8.png

    ]]>
    容器Swarm集群向ACK集群灰度迁移-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    阿里云最佳实践频道:【点击查看更多上云最佳实践
    这里有丰富的企业上云最佳实践,从典型场景入门,提供一系列项目实践方案,降低企业上云门槛的同时满足您的需求!

    场景描述

    随着K8S生态的完善,越来越多的客户需要从Swarm集群迁移向ACK集群,本实践向您介绍阿里云上的容器Swarm集群向ACK集群灰度迁移。

    解决问题

    • 迁移过程中维持业务的延续性
    • 迁移过程业务高可用
    • 迁移过程可灰度
    • 迁移过程可回滚
    • 迁移进度可把控

    产品列表

    • 专有网络 VPC
    • 云数据库 RDS MySQL
    • 容器服务 ACK
    • 云服务器 ECS

    bp-27.png

    直达最佳实践 》》


    bp-27.png

    ]]>
    金融行业从经典网络向VPC容器化改造-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    阿里云最佳实践频道:【点击查看更多上云最佳实践
    这里有丰富的企业上云最佳实践,从典型场景入门,提供一系列项目实践方案,降低企业上云门槛的同时满足您的需求!

    场景描述

    本实践介绍经典网络向VPC容器化改造实践以及配置步骤,可适用于金融等行业。

    解决问题

    • 经典网络管理困难
    • 应用发布不灵活
    • 运维效率低

    产品列表

    • 专有网络 VPC
    • 容器服务 Kubernetes版
    • 日志服务 SLS
    • 云数据库 RDS版
    • NAT网关
    • 容器镜像服务 ACR

    bp-43.png

    直达最佳实践 》》

    bp-43.png

    ]]>
    弹性裸金属自建ORACLE数据库单机版-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    阿里云最佳实践频道:【点击查看更多上云最佳实践
    这里有丰富的企业上云最佳实践,从典型场景入门,提供一系列项目实践方案,降低企业上云门槛的同时满足您的需求!

    场景描述

    本文重点解决在弹性裸金属(神龙)服务器上自建ORACLE数据库单机的问题,通过ESSD和神龙的搭配使用为业务系统提供强大的数据库性能支撑,展示云上数据库在备份和恢复上的优势。

    解决问题

    • 如何利用云上强劲资源,如神龙服务器、ESSD存储,支撑数据库高效稳健运行。
    • 如何利用云上资源和产品优势兼顾单机数据库的可用性。
    • 如何快速备份和恢复数据库数据,保证云上数据的安全性。

    产品列表

    • 专有网络 VPC
    • 弹性公网IP
    • 弹性裸金属服务器
    • 块存储

    bp-49.png

    直达最佳实践 》》

    bp-49.png

    ]]>
    Spring 5 中文解析数据存储篇-理解Spring事物抽象-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 Spring核心篇章:

    Spring 5 中文解析之核心篇-IoC容器

    Spring 5 中文解析核心篇-IoC容器之依赖关系

    Spring 5 中文解析核心篇-IoC容器之Bean作用域

    Spring 5 中文解析核心篇-IoC容器之自定义Bean性质

    Spring 5 中文解析核心篇-IoC容器之BeanDefinition继承与容器拓展点

    Spring 5 中文解析核心篇-IoC容器之基于注解的容器配置

    Spring 5 中文解析核心篇-IoC容器之类路径扫描和组件管理

    Spring 5 中文解析核心篇-IoC容器之JSR330标准注解

    Spring 5 中文解析核心篇-IoC容器之基于Java容器配置

    Spring 5 中文解析核心篇-IoC容器之Environment抽象

    Spring 5 中文解析核心篇-IoC容器之ApplicationContext与BeanFactory

    Spring 5 中文解析核心篇-IoC容器之Resources

    Spring 5 中文解析核心篇-IoC容器之数据校验、数据绑定和类型转换

    Spring 5 中文解析核心篇-IoC容器之SpEL表达式

    Spring 5 中文解析核心篇-IoC容器之AOP编程(上)")

    Spring 5 中文解析核心篇-IoC容器之AOP编程(下)")

    Spring 5 中文解析核心篇-IoC容器之Spring AOP API

    Spring测试篇章:

    Spring 5 中文解析测试篇-Spring测试

    Spring 5 中文解析核心篇-集成测试之概要和集成测试注解

    Spring 5 中文解析核心篇-集成测试之TestContext(上)")

    Spring 5 中文解析核心篇-集成测试之TestContext(中)")

    Spring 5 中文解析测试篇-集成测试之TestContext(下)")

    Spring 5 中文解析测试篇-Spring MVC测试框架

    Spring 5 中文解析测试篇-WebTestClient

    Spring存储篇章:

    Spring 5 中文解析数据存储篇-Spring框架的事物支持模型的优势

    完整电子书地址

    1.2 理解Spring框架事物抽象

    Spring事务抽象的关键是事务策略的概念。事务策略由TransactionManager定义,特别是用于命令式事务管理的org.springframework.transaction.PlatformTransactionManager接口和用于响应式事务管理的org.springframework.transaction.ReactiveTransactionManager接口。以下清单显示了PlatformTransactionManager API的定义:

    public interface PlatformTransactionManager extends TransactionManager {
    
        TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    
        void commit(TransactionStatus status) throws TransactionException;
    
        void rollback(TransactionStatus status) throws TransactionException;
    }

    尽管你可以从应用程序代码中以编程方式使用它,但它主要是一个服务提供接口(SPI)。由于PlatformTransactionManager是接口,因此可以根据需要轻松对其进行模拟或存根。它与JNDI之类的查找策略无关。与Spring框架IoC容器中的任何其他对象(或bean)一样,定义了PlatformTransactionManager实现。这一优点使Spring框架事务成为值得抽象的,即使在使用JTA时也是如此。与直接使用JTA相比,你可以更轻松地测试事务代码。

    同样,为了与Spring的理念保持一致,可以由任何PlatformTransactionManager接口方法抛出的TransactionException未检查异常(也就是说,它扩展了java.lang.RuntimeException类)。事物基础架构故障几乎总是致命的。在极少数情况下,应用程序代码实际上可以从事务失败中恢复,应用程序开发人员仍然可以选择捕获和处理TransactionException。实际一点是,开发人员没有被迫这样做。

    getTransaction(..)方法根据TransactionDefinition参数返回TransactionStatus对象。如果当前调用堆栈中存在匹配的事务,则返回的TransactionStatus可能表示一个新事务或一个现有事务。后一种情况的含义是,与Java EE事务上下文一样,TransactionStatus与执行线程相关联。

    从Spring框架5.2开始,Spring还为使用响应式类型或Kotlin协程的响应式应用程序提供了事务管理抽象。以下清单显示了由org.springframework.transaction.ReactiveTransactionManager定义的事务策略:

    public interface ReactiveTransactionManager extends TransactionManager {
    
        Mono<ReactiveTransaction> getReactiveTransaction(TransactionDefinition definition) throws TransactionException;
    
        Mono<Void> commit(ReactiveTransaction status) throws TransactionException;
    
        Mono<Void> rollback(ReactiveTransaction status) throws TransactionException;
    }

    响应式事务管理器主要是服务提供接口(SPI),尽管你可以从应用程序代码中以编程方式使用它。由于ReactiveTransactionManager是接口,因此可以根据需要轻松对其进行模拟或存根。

    TransactionDefinition接口指定:

    • 传播:通常,事务范围内的所有代码都在该事务中运行。但是,如果在已存在事务上下文的情况下运行事务方法,则可以指定行为。例如,代码可以在现有事务中继续运行(常见情况),或者可以暂停现有事务并创建新事务。Spring提供了EJB CMT熟悉的所有事务传播选项。要了解有关Spring中事务传播的语义的信息,请参阅事务传播
    • 隔离:此事务与其他事务的工作隔离的程度。例如,此事务能否看到其他事务未提交的写入?
    • 超时:该事务在超时之前将运行多长时间,并由基础事务基础结构自动回滚。
    • 只读状态:当代码读取但不修改数据时,可以使用只读事务。在某些情况下,例如使用Hibernate时,只读事务可能是有用的优化。

    这些设置反映了标准的事物概念。如有必要,请参考讨论事务隔离级别和其他核心事务概念的资源。了解这些概念对于使用Spring框架或任何事务管理解决方案至关重要。

    TransactionStatus接口为事务代码提供了一种控制事务执行和查询事务状态的简单方法。这些概念应该很熟悉,因为它们对于所有事务API都是通用的。以下清单显示了TransactionStatus接口:

    public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
    
        @Override
        boolean isNewTransaction();
    
        boolean hasSavepoint();
    
        @Override
        void setRollbackOnly();
    
        @Override
        boolean isRollbackOnly();
    
        void flush();
    
        @Override
        boolean isCompleted();
    }

    无论你在Spring中选择声明式还是编程式事务管理,定义正确的TransactionManager实现都是绝对必要的。通常,你可以通过依赖注入来定义此实现。TransactionManager实现通常需要了解其工作环境:JDBCJTAHibernate等。

    TransactionManager实现通常需要了解其工作环境:JDBCJTAHibernate等。以下示例显示了如何定义本地PlatformTransactionManager实现(在这种情况下,使用纯JDBC)。

    你可以通过创建类似于以下内容的bean来定义JDBC数据源:

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

    然后,相关的PlatformTransactionManager Bean定义将引用DataSource定义。它应类似于以下示例:

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    如果你在Java EE容器中使用JTA,则可以使用通过JNDI获得的容器DataSource以及Spring的JtaTransactionManager。以下示例显示了JTAJNDI查找:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jee="http://www.springframework.org/schema/jee"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/jee
            https://www.springframework.org/schema/jee/spring-jee.xsd">
    
        <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
    
        <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
    
        <!-- other <bean/> definitions here -->
    
    </beans>

    JtaTransactionManager不需要了解数据源(或任何其他特定资源),因为它使用了容器的全局事务管理基础结构。

    dataSource bean的先前定义使用jee名称空间中的标记。有关更多信息,参考JEE Schema

    你还可以轻松使用Hibernate本地事务,如以下示例所示。在这种情况下,你需要定义一个Hibernate LocalSessionFactoryBean,你的应用程序代码可使用该Hibernate LocalSessionFactoryBean获取Hibernate Session实例。

    DataSource bean定义与先前显示的本地JDBC示例相似,因此在以下示例中未显示。

    如果通过JNDI查找数据源(由任何非JTA事务管理器使用)并由Java EE容器管理,则该数据源应该是非事务性的,因为Spring框架(而不是Java EE容器)管理事务。

    在这种情况下,txManager bean是HibernateTransactionManager类型。就像DataSourceTransactionManager需要引用数据源一样,HibernateTransactionManager需要引用SessionFactory。以下示例声明了sessionFactorytxManager bean:

    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingResources">
            <list>
                <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=${hibernate.dialect}
            </value>
        </property>
    </bean>
    
    <bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    如果使用Hibernate和Java EE容器管理的JTA事务,则应使用与前面的JDBC JTA示例相同的JtaTransactionManager,如以下示例所示:

    <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

    如果使用JTA,则无论使用哪种数据访问技术(无论是JDBCHibernate JPA或任何其他受支持的技术),事务管理器定义都应该相同。这是由于JTA事务是全局事务,它可以征用任何事务资源。

    在所有这些情况下,无需更改应用程序代码。你可以仅通过更改配置来更改事务的管理方式,即使更改意味着从本地事务转移到全局事务,反之亦然。

    作者

    个人从事金融行业,就职过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就职于某银行负责统一支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。同时也热衷于技术分享创立公众号和博客站点对知识体系进行分享。关注公众号:青年IT男 获取最新技术文章推送!

    博客地址: http://youngitman.tech

    CSDN: https://blog.csdn.net/liyong1028826685

    微信公众号:

    技术交流群:

    ]]>
    如何在Joomla中删除组件菜单链接-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 有时,Joomla用户已删除组件,但仍在其管理区域中看到该组件的菜单项。

    在本教程中,您将学习如何摆脱不必要的菜单项。Akeeba订阅将用作示例组件。

    您可以在下图中看到以语言字符串形式渲染的不需要的菜单项:

    deleted-components-menu-01.png

    要彻底删除它,请打开您站点的数据库。

    找到#__menu表,其中#__是您的数据库前缀。单击此数据库表。

    deleted-components-menu-02.png

    浏览表记录,直到找到由不需要的组件创建的记录。

    单击删除。

    deleted-components-menu-03.png

    您将看到“确认”框,提示您确认您确实要删除数据库表记录。

    单击确定。

    deleted-components-menu-04.png

    您将看到您的组件记录不再在表中列出:

    deleted-components-menu-05.png

    在您的Joomla控制面板中,转到“组件”菜单。您将看到那里也没有列出不需要的菜单项:

    deleted-components-menu-06.png

    ]]>
    架构设计 | 分布式体系下,服务分层监控策略-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 一、分布式故障

    分布式系统的架构,业务开发,这些在良好的思路和设计文档规范之下,是相对来说好处理的,这里的相对是指比较分布式架构下生产环境的突然故障。

    在实际的开发中,有这样一个很妖娆的情况:越是核心复杂的业务,越是担心出问题,越容易出问题。

    13-1.png

    所以当核心服务的链路出现故障时,如何快速定位问题就是一件很头疼的事情,尤其是一些特殊情况下,问题很模糊很难复现,外加客户或者领导催促,这种场景心里阴影是大部分开发都有的。更有甚者,可能问题发生的切入点的开发是某人负责的,实际问题是发生在请求链路的其他服务上,这种情况遇多了,甩锅水平会直线上升。

    越是复杂的系统,越是经验丰富的开发或者运维,对监控系统就越是有执念,尤其是全链路的监控,底层,网络,中间件,服务链路,日志观察预警等,用来快速定位问题,省时省心。

    二、全链路监控

    1、监控层次

    在分布式系统中,需要监控的体系和层次极其复杂,通常整体上划分为三个层次:应用服务,软件服务,硬件服务。

    13-2.png

    通常情况,运维管理硬件服务,开发管理应用和软件服务。

    2、应用服务

    应用层为开发的业务逻辑服务,也是最容易突发问题的一个层面,当在一家公司待久了,因为开发过多个业务线,就会感觉自己不是开发,是个打杂的,每天都要分出大量时间处理各种问题。应用层监控涉及下面几个核心模块:

    请求流量

    任何服务,高并发的流量都会暴露各种服务问题,尤其核心接口的流量更是监控的重点。

    服务链路

    一次请求发生问题,快速判断问题所在的服务,或者哪些服务之间,这对快速处理问题是至关重要的。

    日志体系

    核心接口日志记录也是必备的功能,通常情况下基于日志体系的分析结果,可以明确系统的异常点,重点优化。

    3、软件服务

    为了解决分布式系统的各种复杂业务场景,通常会引入各种中间软件来做支撑,例如必备的数据库,缓存,消息MQ等,通常这些中间件都会有自带的监控管理端口。

    数据库:较多使用Druid监控分析;

    消息队列:常用RocketMQ和控制台;

    Redis缓存:提供命令获取相关监控数据;

    还有一些公司甚至直接在中间件层开发一套管理运维和监控的聚合平台,这样更容易从整体上分析问题。

    4、硬件服务

    硬件层面,运维最关注的三大核心内容:CPU、内存、网络。底层硬件资源爆发的故障,来自上层的应用服务或者中间件服务触发的可能性偏高。

    硬件层面的监控有许多成熟的框架,例如zabbix,grafana等,当然这些组件功能很丰富,不仅仅在硬件层应用。

    5、雪崩效应

    有些故障导致大面积服务瘫痪,也称为雪崩效应,可能故障源没有快速处理,也没有熔断机制,导致整个服务链路全部垮掉,这是常见的问题,所以在处理故障时,要学会基于全栈监控信息,全局关联分析核心故障点,快速切断单点服务的故障,保证整个系统的可用性。

    三、注意事项

    监控系统虽然作用很大,但是实际搭建的时候难度还是很大,需要有较好的意识,不是业务开发那种感觉,方方面面需求都需要处理,做监控系统的基本策略如下。

    1、选择性

    不是所有服务的所有环境,和所有接口都需要监控,通常都是监控核心链路,核心中间件,和服务所在环境。

    例如:交易链路,交易库,和部署的环境;或者大客户高并发业务,一旦出问题需要及时响应,立即处理。说的直接点,带来收益的服务是需要重点关注的。

    非关键服务即使出现问题,是有缓冲时间的,所以不需要花费精力添加监控,在做监控系统的时候存在这样一句话:简单的链路添加监控,复杂了容易出错;复杂链路添加监控,更复杂更容易出错,然而这样却是为了更好的解决故障。

    2、独立性

    监控系统的本身发生故障,不能影响正常业务流程,即使在一定情况下没有监控信息,也不能因为监控服务影响正常业务服务。

    3、整体性

    聚合的监控系统可以观察监控链路的全局状态,这样可以快速定位故障坐标,可以关联性分析问题原因。

    4、预警性

    例如CPU突然升高,某个中间件服务突然停止,内存占用过高,这些可以基于监控系统做预警通知,然后邮件或者消息通知到相关负责人,达到快速响应的目的,这个场景大部分开发都熟悉,且有心理阴影。

    ]]>
    大数据简介,技术体系分类整理-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 一、大数据简介

    1、基础概念

    大数据是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。大数据技术则主要用来解决海量数据的存储和分析。

    2、特点分析

    大数据的5V特点(IBM提出):Volume(大量)、Velocity(高速)、Variety(多样)、Value(低价值密度)、Veracity(真实性)。

    3、发展过程

    Google在2004年前后发表的三篇论文,分别是文件系统GFS、计算框架MapReduce、NoSQL数据库系统BigTable。海量数据文件,分析计算,并存储,确立了大数据的基本原理和思路。

    天才程序员DougCutting,也是Lucene、Nutch项目发起人。根据Google论文原理初步实现类似GFS和MapReduce的功能,后来发展成为大名鼎鼎的Hadoop。

    再后来,Hadoop经过高速的发展,已经形成一个生态体系,基于Hadoop之上,有实时计算,离线计算,NoSQL存储,数据分析,机器学习等一系列内容。

    从这一系列事情发展看技术规律:Google业务实践中创造性的提出论文作为基础,业务的成长和需求,迫使技术不断更新换代。所以业务是技术不断发展的关键。

    二、Hadoop框架

    1、Hadoop简介

    注意这里基于Hadoop2.X版本描述。后续如果没有特别说明,都是2.7版本。

    01-1.png

    Hadoop是一个由Apache基金会所开发的分布式系统基础架构;

    提供海量的数据存储能力,和分析计算能力;

    作为Apache的顶级项目,包含众多子项目是一个生态圈;

    2、框架特点

    可靠性:Hadoop按位存储和存储多个数据副本,提供可靠服务;

    扩展性:Hadoop利用计算机集群分配数据并完成计算任务,可以方便地扩展到数以千计的节点中;

    高效性:基于MapReduce思想,为海量的数据提供高效的并行计算;

    容错性:自动保存数据的多个副本,并且能够自动将失败的任务重新分配;

    3、组成结构

    HDFS存储

    • NameNode

    存储文件相关的元数据,例如:文件名,文件目录,创建时间,权限副本数等。

    • DataNode

    文件系统存储文件块数据,以及和数据块ID的映射关系。

    Yarn调度

    负责资源管理和作业调度,将系统资源分配给在Hadoop集群中运行的各种应用程序,并调度要在不同集群节点上执行的任务。

    MapReduce计算

    MapReduce将计算过程分为两个阶段:Map阶段并行处理输入数据,Reduce阶段对Map结果进行汇总。

    三、大数据技术栈

    01-2.png

    1、Kafka中间件

    开源组织: Apache软件

    应用场景:

    Kafka是一种高吞吐量的分布式发布订阅消息系统,通过磁盘数据结构提供消息的持久化,这种结构对于即使数以TB的消息存储也能够保持长时间的稳定性能。高吞吐量:即使是非常普通的硬件Kafka也可以支持每秒数百万的消息。支持通过Kafka服务器和消费机集群来分区消息。支持Hadoop并行数据加载。

    2、Flume日志系统

    开源组织: Cloudera公司

    应用场景:

    Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制)的能力。

    3、Sqoop同步工具

    开源组织: Apache软件

    应用场景:

    Sqoop是一款开源的工具,主要用于在Hadoop、Hive与传统的数据库例如:MySql间进行数据的传递,可以将一个关系型数据库(例如:MySQL,Oracle 等)中的数据导进到Hadoop的HDFS中,也可以将HDFS的数据导进到关系型数据库中。

    4、HBase数据库

    开源组织: Apache软件

    应用场景:

    HBase是一个分布式的、面向列的开源数据库,HBase在Hadoop之上提供了类似于Bigtable的能力。HBase是Apache的Hadoop项目的子项目。HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库,并且基于列的而不是基于行的存储模式。

    5、Storm实时计算

    开源组织: Apache软件

    应用场景:

    Storm用于实时计算,对数据流做连续查询,在计算时就将结果以流的形式输出给用户。Storm相对简单,可以与任何编程语言一起使用。

    6、Spark计算引擎

    开源组织: Apache软件

    应用场景:

    Spark是专为大规模数据处理而设计的快速通用的计算引擎,拥有Hadoop的MapReduce所具有的优点;但不同于MapReduce的是——Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapReduce的算法。Spark是在Scala 语言中实现的,它将Scala用作其应用程序框架。

    7、R语言

    开源组织: 微软公司

    应用场景:

    R是用于统计分析、绘图的语言和操作环境。R是属于GNU系统的一个自由、免费、源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具。

    8、Hive数仓工具

    开源组织: 脸书公司

    应用场景:

    hive是基于Hadoop的一个数据仓库工具,用来进行数据提取、转化、加载,这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。hive数据仓库工具能将结构化的数据文件映射为一张数据库表,并提供SQL查询功能,能将SQL语句转变成MapReduce任务来执行。

    9、Oozie组件

    开源组织: Apache软件

    应用场景:

    Oozie是一个管理Hdoop作业(job)的工作流程调度管理系统。

    10、Azkaban组件

    开源组织: Linkedin公司

    应用场景:

    批量工作流任务调度器。用于在一个工作流内以一个特定的顺序运行一组工作和流程。Azkaban定义了一种KV文件格式来建立任务之间的依赖关系,并提供一个易于使用的web用户界面维护和跟踪的工作流。

    11、Mahout组件

    开源组织: Apache软件

    应用场景:

    Mahout提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序。Mahout包含许多实现,包括聚类、分类、推荐过滤、频繁子项挖掘。

    12、ZooKeeper组件

    开源组织: Apache软件

    应用场景:

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    四、技术栈分类

    存储体系:Hadoop-HDFS、HBase、MongoDB、Cassandra

    计算体系:Hadoop-MapReduce、Spark、Storm、Flink

    数据同步:Sqoop、DataX

    资源调度:YARN、Oozie、Zookeeper

    日志收集:Flume、Logstash、Kibana

    分析引擎:Hive、Impala、Presto、Phoenix、SparkSQL

    集群监控:Ambari、Ganglia、Zabbix

    五、源代码地址

    GitHub·地址
    https://github.com/cicadasmile/big-data-parent
    GitEE·地址
    https://gitee.com/cicadasmile/big-data-parent
    ]]>
    穿越数据的变迁(数据闪回PR)-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 在当下数据为王的时代,客户的业务数据是一个企业的核心资产,各个行业客户都在不断追求在其使用的数据库上有更为强大、细粒度的数据备份恢复功能,以应对各样的数据丢失、业务逻辑错误带来的商业风险。例如,在游戏行业里,有大量客户存在“游戏回档”的实际需求,以应对运营或故障风险。再例如,2020年某上市公司出现删库跑路事件,公司市值遭到严重打击。对于上述情况,传统的定时或手动备份的数据由于存在备份时间点与黑天鹅事件之间的时间差,因此均不是理想完备的解决方案。对于防范上述数据风险,最理想的功能是,数据能够以秒级颗粒度恢复至黑天鹅事件发生的瞬时时间点上。

    在传统关系型数据库中(如Oracle)提供了数据闪回功能,帮助客户完成数据的按时间恢复。而在主流的高速缓存产品Redis、Memcached上却鲜有类似的功能,个中原因主要是考虑到作为缓存产品,其中的数据可以丢失,而通过背后配备的持久化、事务性的关系型数据库可以对缓存进行重新加载。但是,随着大量客户对于低延迟的业务应用性能要求不断的提高,对于一些对延迟要求极高的场景下,例如游戏行业,越来越多的客户选择化简架构,将Redis直接作为内存数据库来使用,这便对Redis的数据安全可恢复提出了更大的挑战。阿里云Redis作为行业内的领军产品,拥有国内最强大的Redis产品系列,在托管社区Redis版本的同时大力发展自主研发、兼容Redis协议增强型键值存储产品Tair(阿里云Redis企业版)。其中“更安全”是阿里云Redis向广大客户提供服务的重要部分,针对上述客户诉求,阿里云在Tair中的性能增强版上特别推出了数据闪回功能,帮助客户实现在其指定时间点上恢复指定Redis实例数据的能力,提前为客户可能出现的风险准备好一剂“后悔药”。功能示意如下图所示:
    使用这个能够帮助用户穿越数据变迁的黑科技只需简单几步。
    • 开通阿里云Redis企业版性能增强版实例
    • 开启数据闪回功能
    • 正常读写Redis数据库
    • 一旦发生即时数据恢复要求,选择对应实例和欲恢复的时间点,产生新实例
    • 切换应用连接的实例地址
    下面以一个简单的示例演示:

    首先,我们先对一个阿里云Tair实例写入一些数据,写入脚本如下:
    % cat preparerepldata.sh

    !/bin/bash

    echo "started at: date +%m%d%H%M%S"
    for i in seq -f "%010g" 1 $1
    do

    namerand=$[ $RANDOM % 3 ]
    timerand=`date +%m%d%H%M%S`
    nationrand=$[ $RANDOM % 3 ]
    redis-cli -h   r-t4nq2viog3z4rshoxxpd.redis.singapore.rds.aliyuncs.com -a 'gnuhpc:Pa$$w0rd'   hset userprofile foo$timerand $namerand
    sleep 0.75 #consider the   latency for connection establish

    done

    echo "ended at: date +%m%d%H%M%S"

    我们运行上述脚本以大约一秒的速率写入带时间戳的KV到一个叫做userprofile的hash结构中,一共写入120个Key,代表业务写入。

    % bash preparerepldata.sh 120
    OK
    OK

    % redis-cli -h hosts -a 'username:password' hkeys userprofile | wc -l

     120

    % redis-cli -h hosts -a 'username:password' hkeys userprofile | sort -n
    foo0803202709

    foo0803202909

    如命令执行所示,我们是在08月03日20:27:09 –08月03日 20:29:09 写入了120条数据。

    随后在业务运行中,发现08月03日20:28:10之后,上述业务运行中发生数据风险,我们需要将新创建一个数据库,将原数据库在此时间点之前的数据恢复到这个新的数据库实例中。

    我们到阿里云Redis控制台的备份恢复功能,选择数据闪回功能,点击“马上闪回”按钮,选择克隆源类型是“过去时间点”,然后选择要恢复的时间点:

    新建的实例就是我们要将指定时间点数据恢复到的目标实例,这里值得一提的数据闪回只要求目标实例容量大于等于源实例,而架构则可以与源实例不同,也就是说用户可以自由选择目标实例为标准主从、集群或者读写分离架构的任何一个。

    点击支付后等待片刻后实例创建完毕并完成数据恢复。

    我们连接新创建的实例,看看究竟数据恢复的情况如何?

    % redis-cli -h hosts -a 'username:password' hkeys userprofile | wc -l
    62

    % redis-cli -h hosts -a 'username:password' hkeys userprofile | sort -n
    foo0803202709

    foo0803202810
    可以看到,我们已经成功的恢复数据到了08月03日 20:28:10的数据,在此时间点之后的数据修改均没有生效,用户完美地规避了指定的时间点之后发生的数据风险。

    作为全球数据库领域最领先的企业之一,阿里云数据库的核心理念是更快、更稳、更安全(Faster, Stronger, Securer)的数据库,致力于为用户提供拥有极致性能、高稳定性和更加安全可靠的数据库产品。作为“更安全”的践行,阿里云Redis团队在Redis企业版(Tair)中提供的数据闪回功能,具备了用户指定秒级时间点的数据恢复功能,通过此功能为企业的高贵数据资产做最高级别的保驾护航,客户可以更加放心的将Redis作为内存数据库使用以简化架构与业务的快速迭代。另外,我们云数据库专属集群MyBase还支持Redis,这是阿里云专为大中型企业用户定制优化的解决方案,填补了市场空白,具有资源独享、自主可运维、多数据库混合部署等特点,让用户既享受到云数据库的灵活性,又满足企业对数据库合规性、高性能和安全性要求。
    ========微博消息版========
    让您不再有“从删库到跑路”的噩梦!阿里云Redis企业版性能增强版特别推出数据闪回功能,帮助客户实现在其指定时间点上恢复指定Redis实例数据的能力,详见https://help.aliyun.com/document_detail/148479.html

    ]]>
    2020云栖大会来了!阿里云数据库6大专场重磅发布技术突破-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 6个分论坛预热广告.png

    ]]>
    SpringCloud 应用在 Kubernetes 上的最佳实践 — 线上发布(优雅上下线)-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 头图.png

    作者 | 骄龙

    导读:本篇是《SpringCloud 应用在 Kubernetes 上的最佳实践》系列文章的第八篇,主要介绍了如何做到流量的无损上/下线。更多相关文章阅读可查看文末。

    前言

    上篇我们讲的是发布回滚过程,尤其是在 Kubernetes 的回滚过程中,原生有提供 Rollout 到上一个版本的能力,能保证我们在发布过程中遇到问题时快速回退的能力。然而在每一次上线的过程中,我们最难处理的就是正在运行中的流量,如何做到流量的无损上/下线,是一个系统能保证 SLA 的关键。

    介绍

    什么是优雅上线?就如下面这个房子一样,未建好的房子,人住进去会有危险,房子应该建好,装修好,人才能住进去。

    1.jpeg

    那么如何做到优雅上线呢?我们先来看一个 WEB 应用的加载过程,就像上面造房子一样,是个漫长的过程:

    2.png

    应用的加载是漫长的,在加载过程,服务是不可预期的;如过早地打开 Socket 监听,则客户端可能感受到漫长的等待;如果数据库、消息队列、REDIS 客户端未完成初始化,则服务可能因缺少关键的底层服务而异常。

    所以在应用准备完成后,才接入服务,即做到优雅上线。当然应用上线后,也可能因如数据库断连等情况引起服务不可用;或是准备完成了,但在上线前又发生数据库断连,导致服务异常。为了简化问题,后面两种情况作为一个应用自愈的问题来看待。

    什么是优雅下线?与建房子相反就像下面的危房一样,人住在里面很危险,人应该先从房子出来,然后推掉房子。

    3.jpeg

    那么如何做到优雅下线呢?我们先来看一个 WEB 应用的停止过程:

    4.png

    所以关闭服务接入(转移服务接入),完成正在处理的服务,清理自身占用的资源后退出即做到优雅下线。

    如何实现优雅下线

    从上面介绍看,似乎不难,但事实上,很少有系统真正实现了优雅上下线。因为软件本身由无数各种各样相互依赖的结构组成,每个结构都使用一些资源,污染一些资源;通常在设计之初优雅上下线也不被作为优先考虑的需求,所以对于下线的过程,通常都没被充分考虑,在设计上通常要求:

    • 结构(组件)应形成层次关系;
    • 用户线程需能收到停止信号并响应退出;否则使用 daemon 线程;
    • 结构应按依赖关系自下向上构建:就像建房子一样,自内向外构建而成;
    • 结构应按依赖关系自上向下销毁:就像拆房子一样,自外向内拆解。

    优雅下线实现路径

    大致分为一个完整的过程,需要经历一下四个关键的节点,如下图:

    5.png

    • 接收信号:停止信号可能从进程内部触发(比如 Crash 场景),如果自退出的话基本上无法保证优雅下线;所以能保证优雅下线的前提就是需要正确处理来自进程外部的信号;
    • 停止流量接收:由于在停止之前,我们会有一些正在处理的请求,贸然退出会对这些请求产生损耗。但是在这段时间之内我们绝不能再接收新的业务请求,如果这是一个后台任务型(消息消费型或任务调度型)的程序,也要停止接收新的消息和任务。对于一个普通的 WEB 场景,这一块不同的场景实现的方式也会不一样,下面的 Srping Cloud 应用的下线流程会详细讲解;
    • 销毁资源:常见的是一些系统资源,也包括一些缓存、锁的清理、同时也包括线程池、关闭阻塞中的的 IO 操作,等到我们这些服务器资源销毁之后,就可以通知主线程退出。

    Spring Cloud 应用

    一个 Spring boot 应用通常由应用本身和一系列的 Starter 组成,对于 Spring boot 体系,需要了解如下核心概念:

    • Starter:提供一系列的模块,由 Spring boot 核心通过 auto-configuration 机制加载;
    • Bean:一切皆 Bean,starter 模块的加载产生各种 Bean;
    • Context:Bean 的容器,容器拥有生命周期,Bean 需要感知生命周期事件;
    • LifeCycle:生命周期管理接口;
    • ApplicationEvent:模块之间,模块与容器之间,通过发送或监听事件来达到互相通讯的目的。

    所以对于应用上下线这个主题,我们应尽可能利用其丰富的原生事件机制,Spring Cloud 中内置的 Starter 机制针对整个生命周期管理的过程有了很好的封装。

    Spring Cloud 应用的优雅上线

    Spring Cloud 启动过程触发回调及事件如下,详细介绍见 application-events-and-listeners,简单罗列如下:

    6.png

    Spring 自身及其组件大量基于这些事件构建,如响应 WebServerInitializedEvent 事件向服务注册中心注册服务,对于应用一般可利用:

    • InitializingBean or @PostConstruct:在 Bean 装配完后,被回调,如完成数据源初始化连接;
    • ApplicationReadyEvent、ApplicationRunner、CommandLineRunner:如开始监听消息队列,处理消息;注册到SLB等;先通过配置禁用服务的自动注册,在这里做手动服务注册。

    Spring Cloud 应用的优雅下线

    Spring Cloud 本身可以作为一个应用单独存在,也可以是依附在一个微服务集群中,同时还能作为反向代理架构中的一个网关。不同的场景,需要用到的方法也不一样,我们就常用的三种场景针对性的加以说明。

    场景一:直接访问 WEB 服务

    7.png

    客户端直接访问 WEB 应用,在这个用例下,优雅下线需要做的事情有:

    • 正在处理的请求完成处理
    • 应用自身完成安全下线并正常退出
    • 客户端感知到连接异常

    Spring-boot 从 2.3 开始内置了 WEB 应用优雅下线的能力,需配置如下,具体介绍参见 graceful-shutdown

    server.shutdown=graceful
    spring.lifecycle.timeout-per-shutdown-phase=20s

    其实现方式:

    • 首先关闭 socket 监听,等待正在处理的所有请求完成:具体可见 WebServerGracefulShutdownLifecycle,通过 getPhase 返回最大值,达到早于 WEB 容器关闭执行的目的;
    • 然后触发 WEB 容器关闭:具体可见 WebServerStartStopLifecycle。

    但其实,对于未被 WEB 容器完全接收的请求,客户端仍会收到连接被重置的异常,只是这个时间窗口极小。该需求从提出到实现的时间跨度较长,感兴趣的可参见 github 上的讨论

    场景二:经由反向代理的服务优雅下线

    8.jpeg

    因为实例前面还有反向代理,相比上个场景,需要新增“反向代理下线”这个处理流程。即若应用已经下线,但反向代理未摘除该应用实例时客户端将感知到失败。一般采取的策略有:

    • 反向代理支持失败转移到其它应用实例;
    • 在关闭应用前,如将健康探测接口返回不健康以及等待足够的超时,让反向代理感知并摘除实例的路由信息。

    对于仍在使用 2.3 以前版本的 Spring Cloud 应用,可参见一个方案,实现方式:

    • 使用自身的 shutdownHook 替换 Spring 的 shutdownHook;
    • 先改变 health 状态,等待一段时间,让反向代理感知并摘除实例的路由信息。

    场景三:在微服务集群中下线单个服务

    9.jpeg

    在优雅关闭 Spring Cloud 应用自身之前,我们除了完成场景一之中的目标之外,还需要将自身节点从注册中心中下线。目前在 Spring Cloud 中针对注册中心下线的场景暂未提供开箱即用的方法,下面介绍两种可能的实现方案:

    方案 1:先通过脚本、或通过监听 ContextClosedEvent 反注册服务摘除流量;等待足够时间,如使用 ribbon 负载均衡器,需要长于配置的刷新时间;对于基于 HTTP 的服务,若 Spring Cloud 版本小于 2.3,则时间需加上预期的请求处理时间;

    方案 2:客户端支持连接感知重试,如重试,实现方案可参考Spring-retry,针对连接异常 RemoteConnectFailureException 做重试。

    针对 Eureka 中的场景,有一个很好的参考的例子,请参见:https://home1-oss.github.io/home1-oss-gitbook/release/docs/oss-eureka/GRACEFUL_SHUTDOWN.html

    Kubernetes 下的机制

    Kubernetes 中针对应用的的管控提供了丰富的手段,正常的情况它提供了应用生命周期中的灵活扩展点,同时也支持自己扩展它的 Operator 自定义上下线的流程。

    10.jpeg

    抛开实现成本,以下线的情况来说,一个 Kubernetes 应用实例下线之前,管控程序会向 POD 发送一个 SIGTERM 的信号,应用响应时除了额外响应这一个信号之外,还能触发一段自定义的 PreStop 的挂在脚本,代码样例如下:

    yaml
    lifecycle:                   
          preStop:                   
            exec:                    
              command:               
              - sh
              - -c
              - "sleep 5"

    上面的例子一点特殊说明:因服务控制面刷新与 POD 收到 SIGTERM 同时发生,所以这里通过 sleep 5 让服务控制面先完成刷新,应用进程再响应 SIGTERM 信号。

    Spring Cloud 与 Kubernetes 的结合

    Kubernetes 会根据健康检查的情况来更新服务(Service)列表,其中如果 Liveness 失败,则会触发容器重建,这是一个相对很重的操作;若 Readiness 失败,则 Kubenetes 则默认不会将路由服务流量到相应的容器;基于这一机理,Spring Cloud 2.3 开始,也做了原生的的支持,具体参见 liveness-and-readiness-probes-with-Spring-boot,这些健康检查端点可对接 Kubnetes 相应的 probe:

    • /actuator/health/liveness
    • /actuator/health/readiness

    同时,Spring Boot 内置了相应的 API、事件、Health Check 监控,部分代码/配置片段如下:

    java
    // Available as a component in the application context
    ApplicationAvailability availability;
    LivenessState livenessState = availabilityProvider.getLivenessState();
    ReadinessState readinessState = availabilityProvider.getReadinessState();
    ....
    // 对于应用,也可以通过API,发布相应的事件,来改变应用的状态
    AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
    // 同时,应用监控也可影响这健康状态,将监控与健康关联,在K8S体系下,可以实现如离群摘除,应用自愈的能力
    // application.properties
    management.endpoint.health.group.liveness.include=livenessProbe,cacheCheck

    回到 Spring Cloud 应用 在微服务集群中下线单个服务 的章节中,我们的应用如果跑在 Kuberntes 中,如果我们使用了原生的 Kubernetes 机制去管理应用生命周期的话,只需要发布一个应用事件 (LivenessState.BROKEN) 即可实现优雅下线的能力。

    EDAS提供内置的优雅上下线能力

    通过上面两部分了解了 Spring Cloud 和 K8s 中的机制,EDAS 基于原生的机制,衍生出来了自己的方法,除了最大化利用这些能力:主动更新 Liveness、Readiness、Ribbon 服务列表之外,我们还提供了无代码侵入的开箱即用的能力,列举如下:

    后续

    这一章节之后,和发布相关的内容都已经更新完毕,下一章节我们要开始高可用部分的能力,高可用也是系统保障 SLA 的关键部分,简单的理解是流量洪峰到来如何保证系统不会受到影响?当然我们还有一部分要达成的是洪峰退去之后资源是否存在浪费?敬请期待 ...

    相关文章推荐:

    阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

    ]]>
    数据湖构建服务搭配Delta Lake玩转CDC实时入湖-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 什么是CDC

    Change Data Capture(CDC)用来跟踪捕获数据源的数据变化,并将这些变化同步到目标存储(如数据湖或数据仓库),用于数据备份或后续分析,同步过程可以是分钟/小时/天等粒度,也可以是实时同步。CDC方案分为侵入式(intrusive manner)和非倾入性(non-intrusive manner)两种。

    1.png

    侵入式

    侵入式方案直接请求数据源系统(如通过JDBC读取数据),会给数据源系统带来性能压力。常见的方案如下:

    • 最后更新时间(Last Modified)

    源表需要有修改时间列,同步作业需要指定最后修改时间参数,表明同步某个时间点之后变更的数据。该方法不能同步删除记录的变更,同一条记录多次变更只能记录最后一次。

    • 自增id列

    源表需要有一个自增id列,同步作业需要指定上次同步的最大id值,同步上次之后新增的记录行。该方法也不能同步删除记录的变更,而且老记录的变更也无法感知。

    非侵入式

    非侵入性一般通过日志的方式记录数据源的数据变化(如数据库的binlog),源库需要开启binlog的功能。数据源的每次操作都会被记录到binlog中(如insert/update/delete等),能够实时跟踪数据插入/删除/数据多次更新/DDL操作等。

    示例:

    insert into table testdb.test values("hangzhou",1);
    update testdb.test set b=2 where a="hangzhou";
    update testdb.test set b=3 where a="hangzhou";
    delete from testdb.test where a="hangzhou";

    2.png

    通过将binlog日志有序的回放到目标存储中,从而实现对数据源的数据导出同步功能。

    常见的CDC方案实现

    开源常见的CDC方案实现主要有两种:

    Sqoop离线同步

    sqoop是一个开源的数据同步工具,它可以将数据库的数据同步到HDFS/Hive中,支持全量同步和增量同步,用户可以配置小时/天的调度作业来定时同步数据。

    sqoop增量同步是一种侵入式的CDC方案,支持Last Modified和Append模式。
    3.png

    缺点:

    • 直接jdbc请求源库拉取数据,影响源库性能
    • 小时/天调度,实时性不高
    • 无法同步源库的删除操作,Append模式还不支持数据更新操作

    binlog实时同步

    binlog日志可以通过一些工具实时同步到kafka等消息中间件中,然后通过Spark/Flink等流引擎实时的回放binlog到目标存储(如Kudu/HBase等)。

    4.png

    缺点:

    • Kudu/HBase运维成本高
    • Kudu在数据量大的有稳定性问题, HBase不支持高吞吐的分析
    • Spark Streaming实现回放binlog逻辑复杂,使用java/scala代码具有一定门槛

    Streaming SQL+Delta Lake实时入湖方案

    前面介绍了两种常见的CDC方案,各自都有一些缺点。阿里云E-MapReduce团队提供了一种新的CDC解决方案,利用自研的Streaming SQL搭配Delta Lake可以轻松实现CDC实时入湖。这套解决方案同时通过阿里云最新发布的数据湖构建(Data Lake Formation,DLF)服务提供一站式的入湖体验。

    5.png

    Streaming SQL

    Spark Streaming SQL在Spark Structured Streaming之上提供了SQL能力,降低了实时业务开发的门槛,使得离线业务实时化更简单方便。

    Spark Streaming SQL支持的语法如下:
    截屏2020-09-14 下午10.22.51.png

    下面以实时消费SLS为例:

    # 创建loghub源表
    spark-sql> CREATE TABLE loghub_intput_tbl(content string)
             > USING loghub
             > OPTIONS
             > (...) 
    # 创建delta目标表
    spark-sql> CREATE TABLE delta_output_tbl(content string)
             > USING delta
             > OPTIONS
             > (...);
    # 创建流式SCAN
    spark-sql> CREATE SCAN loghub_table_intput_test_stream
             > ON loghub_intput_tbl
             > USING STREAM;
    # 将loghub源表数据插入delta目标表         
    spark-sql> INSERT INTO delta_output_tbl SELECT content FROM loghub_table_intput_test_stream;

    Delta Lake

    Delta Lake是Databricks开源的一种数据湖格式,它在parquet格式之上,提供了ACID事务/元数据管理等能力,同时相比parquet具有更好的性能,能够支持更丰富的数据应用场景(如数据更新/schema演化等)。

    5.png

    E-MapReduce团队在开源Delta Lake基础上做了很多功能和性能的优化,如小文件合并Optimize/DataSkipping/Zorder,SparkSQL/Streaming SQL/Hive/Presto深度集成Delta等。

    15.png

    Streaming SQL+Delta Lake CDC实时入湖

    Spark Streaming SQL提供了Merge Into 的语法,搭配Delta Lake的实时写入能力,可以很方便的实现CDC实时入湖方案。

    17.png

    如上图所示,只需要SQL就能完成CDC实时入湖,细节步骤详见E-MapReduce文档

    阿里云最新发布的数据湖构建(Data Lake Formation,DLF)服务,提供了完整的一站式入湖解决方案

    ----

    更多数据湖技术相关的文章请点击:阿里云重磅发布云原生数据湖体系


    更多数据湖相关信息交流请加入阿里巴巴数据湖技术钉钉群
    数据湖钉群.JPG

    ]]>
    如何基于 Flink 生成在线机器学习的样本?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 作者:曹富强(微博)

    在线机器学习与离线相比,在模型更新的时效性,模型的迭代周期,业务实验效果等方面有更好的表现。所以将机器学习从离线迁移到在线已经成为提升业务指标的一个有效的手段。

    在线机器学习中,样本是关键的一环。本文将给大家详细的介绍微博是如何用 Flink 来实现在线样本生成的。

    为何选择 Flink 来做在线的样本生成?

    在线样本生成对样本的时效性和准确性都有极高的要求。同样对作业的稳定性及是否容灾也都有严格的指标要求。基于这个前提,我们对目前较为流行的几种实时计算框架(Storm 0.10, Spark 2.11, Flink 1.10)进行了分析比较,结论如下:

    1.jpg

    因此,我们决定使用 Flink 来作为在线样本生成的实时流计算框架。

    如何实现?

    在线样本生成,简单描述一个业务场景:对用户的曝光数据和点击数据实时的做关联,关联后将数据输出到 Kafka 中,给下游的在线训练作业用。

    首先我们要确定两个数据流关联的时间窗口。这一步一般建议先离线对两个数据流的日志做关联,通过离线的方式对两份数据在不同的时间范围内做 join,来判断在线需要的时间窗口。比如业务接受的最低关联比例是 85%,并且通过离线测试确认 20 分钟内两个数据流可以关联 85%的数据,那么就可以采用 20 分钟作为时间窗口。这里的关联比例和窗口时间实际上是在准确性和实时性之间的一个 trade-off。

    确定时间窗口后,我们并没有使用 Flink 的 time window 来实现多个数据流的 join,而是选择采用 union + timer 方式来实现。这里主要考虑两点:第一、Flink 自带的 join 操作不支持多个数据流。第二、使用 timer+state 来实现,自定义程度更高,限制更少,也更方便。

    接下来,我们把样本生成过程细分为:

    ① 输入数据流

    一般我们的数据源包括 Kafka,Trigger,MQ 等。Flink 需要从数据源中实时的读取日志。

    ② 输入数据流的格式化和过滤

    读取日志后,对数据做格式化,并且过滤掉不需要的字段和数据。
    指定样本 join 的 key。例如:用户 id 和 内容 id 作 key。
    输出的数据格式一般为 tuple2(K,V),K:参与 join 的 key。V:样本用到的字段。

    ③ 输入数据流的 union

    使用 Flink 的 union 操作,将多个输入流叠加到一起,形成一个 DataStream。
    为每个输入流指定一个可以区分的别名或者增加一个可以区分的字段。

    ④ 输入数据流的聚合:keyby 操作

    对 join 的 key 做 keyby 操作。接上例,表示按照用户 id 和内容 id 对多个数据流做 join。
    如果 key 存在数据倾斜的情况,建议对 key 加随机数后先聚合,去掉随机数后再次聚合。

    ⑤ 数据存储 state + timer

    1. 定义一个Value State。
    2. keyby后的process方法中,我们会重写processElement方法,在processElement方法中判断,如果value state为空,则new 一个新的state,并将数据写到value state中,并且为这条数据注册一个timer(timer会由Flink按key+timestamp自动去重),另外此处我们使用的是ProcessingTime(表示onTimer()在系统时间戳达到Timer设定的时间戳时触发)。如果不为空则按照拼接的策略,更新已经存在的结果。比如:时间窗口内 用户id1,内容id1的第一条日志数据没有点击行为,则这个字段为0,第二条点击数据进入后,将这个字段更新为1。当然除了更新操作,还有计数、累加、均值等各种操作。如何在process里区分数据是来自曝光还是点击呢,使用上面步骤③定义的别名。
    3. 重写onTimer方法,在onTimer方法中主要是定义定时器触发时执行的逻辑:从value state里获取到存入的数据,并将数据输出。然后执行state.clear。
    4. 样本从窗口输出的条件有2个:第一,timer到期。第二,业务需要的样本都拼接上了。

    此处参考伪代码:

    public class StateSampleFunction extends KeyedProcessFunction<String, Tuple2, ReturnSample> {
        /**
         * 这个状态是通过过程函数来维护,使用ValueState
         */
        private ValueState state;
    
        private Long timer = null;
    
        public StateSampleFunction (String time){
            timer = Long.valueOf(time);
        }
    
        @Override
        public void open(Configuration parameters) throws Exception {
            // 获取state
            state = getRuntimeContext().getState(new ValueStateDescriptor<>("state", TypeInformation.of(new TypeHint< ReturnSample >() {})));
        }
    
        @Override
        public void processElement(Tuple2value, Context context, Collector< ReturnSample > collector) throws Exception {
            if (value.f0 == null){
                return;
            }
    
            Object sampleValue = value.f1;
            Long time = context.timerService().currentProcessingTime();
            ReturnSample returnSample = state.value();
            if (returnSample == null) {
                returnSample = new ReturnSample();
                returnSample.setKey(value.f0);
                returnSample.setTime(time);
                context.timerService().registerProcessingTimeTimer(time +timer);
            }
    
            // 更新点击数据到state里
            if (sampleValue instanceof ClickLog){
                ClickLog clickLog = (ClickLog)values;
                returnSample =(ReturnSample) clickLog.setSample(returnSample);
            }
            state.update(returnSample);
        }
    
        /**
         * @param timestamp
         * @param ctx
         * @param out
         * @throws Exception
         */
        @Override
        public void onTimer(long timestamp, OnTimerContext ctx, Collector< ReturnSample > out) throws Exception {
            ReturnSample value = state.value();
            state.clear();
            out.collect(value);
        }
    }

    ⑥ 拼接后的日志格式化和过滤

    拼接后的数据需要按照在线训练作业的要求对数据做格式化,比如 json、CSV 等格式。
    过滤:决定什么样的数据是合格的样本。例如:有真正阅读的内容才算是可用的样本。

    ⑦ 输出

    样本最终输出到实时的数据队列中。下面是实际的作业拓扑和运行时状态:

    1-2.jpg
    1-3.jpg

    整个样本拼接过程的流程图:

    1-4.jpg

    StateBackend 的选取

    使用 RocksDB/Gemini 作为 state 的 Backend 的优势和建议:

    我们用大数据对 memory 和 RocksDB,Gemini 做了实验对比,结果显示 RocksDB 和 Gemin 在数据处理,作业稳定性和资源使用等方面比 memory 更合理。其中 Gemini 的优势最为明显。

    此外,如果是大数据量的 state,建议使用 Gemini + SSD 固态硬盘。

    样本的监控

    1. Flink 作业的异常监控

    • 作业失败监控
    • Failover 监控
    • Checkpoint 失败的监控
    • RocksDB 使用情况的监控
    • 作业消费 Kafka 的 Comsumer Lag 的监控
    • 作业反压的监控

    2. 样本输入端 Kafka 的消费延迟监控

    3. 样本输出端 Kafka 的写入量的监控

    4. 样本监控

    • 拼接率监控
    • 正样本监控
    • 输出样本格式的监控
    • 输出标签对应的值是否在正常范围
    • 输入标签对应的值是否为 null
    • 输出标签对应的值是否为空

    样本的校验

    样本生成后,如何验证数据是否准确

    1. 在线和离线的相互校验

      将在线样本从输出的 Kafka 中接入到 HDFS 上离线存储。并按照在线 join 的时间窗口来分区。
    2. 用同等条件下生成的离线样本和在线样本做对比
    3. 白名单用户的全流程校验

      将白名单用户的日志和样本结果存入 ES 等实时数仓中,来做校验。
      

    故障的处理

    样本异常对线上模型训练的影响非常大。当发现异常报警时,首先要做的是向在线模型训练作业发送样本异常的报警。收到报警信息后,模型停止更新。从而避免影响模型线上效果。

    普通意义的业务故障解决后,丢弃原来的数据,所有输入日志流从最新的时间点开始消费并生成新的样本即可。重要业务需要重置输入日志流的 Kafka offset 从故障时间点开始重新生成样本数据。

    平台化

    通过平台化对样本生成的流程做出严格的规范非常重要。在平台化的过程中,需要提供简单通用的开发模板以提高作业开发效率;提供平台化的作业监控和样本指标监控框架,避免重复造车;提供通用的样本输出落地策略,和在线/离线校验策略,更便捷的为业务方服务。

    微博基于 Flink 搭建的在线样本生成平台架构,如图:

    1-5.jpg

    UI 页面,如图:

    1-6.jpg
    1-61.jpg

    基于平台化开发,用户只需要关心业务逻辑部分即可。需要用户开发的有:

    1. 对应输入数据的数据清洗逻辑
    2. 样本输出前的数据清洗逻辑

    其余的在 UI 上配置即可实现,具体有:

    1. 输入 Kafka 的配置信息及对应数据清洗的 UDF 类
    2. 样本拼接的时间窗口
    3. 窗口内对字段的聚合操作
    4. 样本输出的 Kafka 配置信息及输出前数据清洗和格式化的 UDF 类

    资源情况由平台方审核并配置。完成后,自动生成并提交作业。

    1-7.jpg

    作业提交后:

    1. 平台会提供如前所述的作业相关监控,如下:

    ■ Flink 作业的异常监控

    作业失败监控
    Failover 监控
    Checkpoint 失败的监控
    RocksDB 使用情况的监控
    作业消费 Kafka 的 Comsumer Lag 的监控
    作业反压的监控

    ■ 样本监控

    拼接率监控
    正样本监控
    输出样本格式的监控
    输出标签对应的值是否在正常范围
    输入标签对应的值是否为 null
    输出标签对应的值是否为空

    2. 平台会自动将数据落盘,存储到HDFS上。方便离线验证或者离线训练。

    3. 用户只需将精力放到样本的验证上即可,由平台方保证作业的稳定性。

    作者介绍:

    曹富强,微博机器学习研发中心-高级系统工程师。现负责微博机器学习平台数据计算/数据存储模块,主要涉及实时计算 Flink、Storm、Spark Streaming,数据存储Kafka、Redis,离线计算 Hive、Spark 等。目前专注于 Flink/Kafka/Redis 在微博机器学习场景的应用,为机器学习提供框架,技术,应用层面的支持。

    ]]>
    【其他】阿里云SCDN改版通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【SCDN】【产品改版通知】

    安全加速SCDN产品将于2020年10月1日起进行产品改版,老版本SCDN将停止续费,阿里云提供了优惠或免费的迁移方案,建议您迁移到新版SCDN。新版SCDN产品详情点此查看。

    新老版本差异:

    老版SCDN主要提供CDN分发+DDoS高防的产品能力,最高提供联通,电信双线300G DDoS防护能力。

    新版SCDN将主要提供安全CDN带宽,独享资源,并提供全网100W QPS,单点6W QPS能力,同时支持频次控制和流量管理等功能。

    老用户迁移方案,详情请参考

    如有任何疑问欢迎加入 SCDN产品改版钉钉群 34125539 咨询

    ]]>
    【其他】9月11日ECS第七代高主频实例公测通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【ECS第七代高主频实例】【公测通知】

    公测时间:2020年9月11日至10月31日

    公测内容:阿里云中国站(www.aliyun.com)ECS将开放新增第七代高主频实例产品公测,首次开放地域包括杭州、广州、乌兰、河源,后续会有更多地域开放。

    七代高主频实例产品是依托第三代神龙架构,采用intel最新一代cooper lake处理器,可以提供3.8Ghz的全核睿频,为用户提供稳定可靠的超高性能。实例的规格名称为hfg7/hfc7/hfr7系列,具体的产品规格参数及使用场景请详见官方文档介绍。购买方式及售卖价格请参考相关售卖地域页面高主频产品。

    ]]>
    【其他】Flink全托管版商业化通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【Flink全托管服务】【商业化通知】

    Flink全托管服务将于2020.9.15号开始结束公测进行商业化收费,为了保证您业务平稳过渡,请各位用户评估业务影响。针对在公测期间申请公测时间过长的用户,我们将免费服务期限统一限制为2020.9.30 23:59:59,特此通知,如有其他问题,请通过工单联系我们

    ]]>
    【其他】9月16日数据湖分析产品更名通知 Thu, 29 Oct 2020 12:16:15 +0800 【阿里云】【数据湖分析】【产品名称变更通知】

     变更时间:2020年9月16日

     变更内容:自2020年9月16日0时起,阿里云产品“数据湖分析”名称正式变更为“云原生数据湖分析”。如有任何问题,可点击联系我们进行咨询反馈

    ]]>
    助力企业数字化转型 | 斑羚在线、环宇数通、乘云科技入选阿里云原生合作伙伴计划 Thu, 29 Oct 2020 12:16:15 +0800 近日,北京三家重量级伙伴“斑羚在线、环宇数通、乘云科技”喜获阿里云正式授牌认证。自从2019年加入“云原生合作计划”以来,在云原生技术方面,双方开展了深度合作,推进企业进行数字化转型,达成生态共赢。而在此之前,这三家企业与阿里云已经建立了深厚的合作基础,在“新基建”的战略背景下,基于阿里云丰富全面的云原生产品、成熟的云计算技术及平台支撑能力,斑羚在线、环宇数通、乘云科技将为华为区域的企业级用户提供快速可靠、个性化的云原生技术解决方案,造福华北区的广大阿里云客户。

    这么优秀的伙伴,是怎样快速发展起来的呢?让我们逐一为大家揭示。

    01 斑羚在线:一站式全方位服务

    北京斑羚在线网络科技有限公司提供基于阿里云的专业软件开发服务,响应及时、服务精细、团队稳定,深耕IT服务行业10余年,是客户认可的“软件开发明星企业”,更是值得依赖的云服务合作伙伴。作为新零售行业的践行者,斑羚在线独立开发运营的校园新零售项目“零食盒子”,已覆盖全国26省市,超300所高校,触达500万人次高校人群,每日消费笔数达4万以上。除新零售行业,直播领域也是近年来斑羚在线的主攻方向,公司先后向用户提供了“LiveMall电商直播” “螃蟹横屏演艺直播”等解决方案,助力企业创建属于自己的直播+购物平台,转型线上逆市增长。

    此次加入阿里云原生合作伙伴计划,斑羚在线将专注于以阿里云产品和先进技术为核心,向客户提供专属定制开发,按需定制,集群部署,以及领先的技术、完备的解决方案、完善的服务及成熟的渠道等一站式全方位服务。

    112.png

    斑羚在线获得“云原生合作计划伙伴”授牌

    02 环宇数通:助力企业轻松不如云时代

    北京环宇数通科技有限公司成立于2009年,核心成员来自于国内顶尖安全厂商与集成商。2013年研发出自主知识产权数通云产品,2015年环宇数通正式进入阿里云生态体系大家庭,通过3年时间的努力奋斗、群策群力共同打造了一支优秀的云计算、大数据服务团队。2016年成为阿里云全国授权服务中心,2018年获得ISO27001国际安全资质,2019年成为国信安全合作伙伴。

    image.png

    基于阿里云原生全面的技术和产品,环宇数通为客户提供电商解决方案、App解决方案、金融解决方案、游戏解决方案。以某互联网金融公司为例,得益于微消息队列 MQTT 的多协议、多语言和多平台的支持能力,目前 MQTT 广泛应用于移动互联网以及物联网领域,覆盖移动直播、车联网、金融支付、智能餐饮、即时聊天等多种应用场景。相比使用HTTP等其他协议,客户使用消息队列RocketMQ + 微消息队列 for MQTT的组成方案能节省至少2人月的开发成本,还能通过这套方案支撑起对于安全和可靠性要求极高的金融级业务场景,并轻松扩展到百万组别的客户端。

    244.png

    环宇数通获得“云原生合作计划伙伴”授牌

    03 乘云科技:成立6年,营收破亿

    乘云科技成立于2014年,是基于阿里云生态的专业的云计算业务供应商,为泛行业客户提供云计算资源转售、云服务技术支持、云产品渠道生态共创以及云业务IT咨询等。成立六年来,发展迅速,2019年营业收入突破一亿元。

    image.png

    乘云总部设立在北京,在沈阳、成都、武汉、深圳分别设有分公司。在河北的邢台设有50多人的外呼中心。乘云的理念就是用普惠的云计算、云服务、服务于全国的云计算用户。针对云上技术服务和上云的技术服务,乘云有一系列的解决方案,基于阿里云完善的基础设施,整合云上PaaS层的调配资源,完善客户的技术架构的同时,协助客户提供优质的云上管理方案。

    image.png

    乘云科技获得“云原生合作伙伴计划”授牌

    乘云作为阿里云优质的服务商,提供全站的上云解决方案,全流程的技术协助、云上便捷的运维管理能力,上云企业的技术培训指导,面对客户新需求的定制化的架构服务,以及面对中大型企业主流的混合云架构的落地都是具备成熟的闭环能力的。

    随着云计算的全面到来,普通的创业者也能拥有和500强企业一样的计算资源。创业公司像飞机,速度够快才能起飞,通过现有的云端资源才能更快的让产品落地。通过阿里云,普通的创业者也能和大企业同台竞争,让创业进入快消时代。

    在企业数字化转型加速的浪潮下,越来越多的企业开始探索云原生架构如何落地。通过云原生,企业可以最大化使用云的能力。阿里云将与合作伙伴携手,通过全面丰富的云原生技术和产品,激发更多企业在云原生时代的生命力。

    点击:云原生合作伙伴计划,了解更多云原生合作伙伴计划细节和加入详情。

    ]]>
    阿里云 SAE 携手云效助力「石家庄掌讯」持续交付、降本提效 Thu, 29 Oct 2020 12:16:15 +0800 背景

    石家庄掌讯信息技术有限公司创立于2009年,是一家提供企业信息化咨询、创新型软件产品、电商代运营服务,标准化管理、快速发展的高新技术企业。当前公司正处于企业互联网市场突破转型重要阶段,希望将更多精力转移到业务创新,提升开发和交付效率,低成本试错。因此选择一套低门槛开箱即用的持续交付、快速部署&运维平台尤为重要。

    面对的挑战

    • 组织、人员权限管理复杂:
      Jenkins的权限管理独立一套,与其它系统不能很好的对接,维护成本非常高。
    • 好的工程实践、流程规范不容易复用,质量更无法保证:
      代码开发过程中加入了阿里巴巴P3C规范,与集成工作流无打通,不得不依赖人工介入的效果,当项目的时间紧,任务重,往往执行不到位,效果无法保证,形同虚设。代码质量很难保证。
    • FTP手工发布效率慢,Jenkins需要编写大量的脚本,降本提升效率成为了瓶颈:
      公司在很长一段时间在使用Jenkins作为自动化部署工具,Jenkins易用的插件化模式和灵活的流水线脚本编写能力是我们一直使用他的原因。不过对于我们这种0运维人员的小团队来说,一些平台细小的不便性也会团队效率带来很大的负面影响。Jenkins的流水线脚本编写维护的繁琐性以及第三方平台(服务)与Jenkins整合的复杂度都给我们带来不小的麻烦。
    • 缺少专职运维人员和微服务改造实战经验,研发运维效率不高:
      公司未设置专职运维人员,在做业务创新同时,微服务架构同步改造进行中。采用自建微服务架构+APM,技术门槛和人力不足很难在短时间成功落地。急切需要一条快速上手的平台支撑,需要最大限度屏蔽底层IaaS, 容器,以及常用微服务套件的学习成本。
    • 测试开发环境和生产环境的闲置计算资源较高:
      长期保有固定的IaaS资源,单台ECS单部署应用,导致资源利用率很低,存在较多的闲置浪费。

    1597802958345-20d3d343-c3f4-49ee-99bd-4805d7a901e6.png

    架构图

    解决效果

    总体上来说,掌讯信息公司在与云效&SAE共建之后,通过Codeup自动化代码检查提升了代码质量,降低了生产的故障,FLow自动化流水线、SAE的接入不但降低了成本,同时提升了交付效率。

    1. 降成本:

    零成本投入提高质量管理能力和持续交付能力
    免费使用的codeup代码库让我们节省了自建git代码库的成本,codeup中集成的代码审查和安全审查模块又让我们节省了质量管理的投入成本。免费的流水线flow让我们节省了原本在jenkins中投入的环境成本。这些还只是节省的有形成本,对于平台整合后效率的提升所节省的成本更是不可估量。

    低成本高质量玩转微服务架构
    对于我们这样的小团队想要玩转微服务架构一直是一个可望不可即的事情,直到发现了阿里云的SAE(Serverless应用引擎)产品,SAE(Serverless应用引擎)节省了自建微服务架构的ECS成本。基于秒级弹性能力,无需长期保有固定资源,按需启停和自动弹性、按分钟计费,极大的提升了资源利用率。使用SAE(Serverless应用引擎)后,公司单从硬件成本上就节省了50%。

    2. 提效率:

    SAE,从0到1的高效体验
    SAE 提供了应用托管和应用监控的开箱即用的体验,帮助我们关注业务开发而非底层资源的运维,节省了大量的人力成本。目前,我们通过 SAE 上线了 5 个核心业务:商品中心、用户中心、销售中心、采购中心和库存中心。

    SAE,0改造使用Serverless技术
    SAE实现了微服务应用的无缝迁移,WAR/JAR无需容器化改造直接部署,这也是SAE区别其它Serveless产品的重要优势,平滑迁移企业在线应用。

    云效codeup代码库,加速你的code review
    在codeup代码库中code review是在每一次commit后自动进行审查,和我们之前的集中时间,集中人力做code review工作相比,分散在commit后的自动审查模式更节约时间,并且自动化的触发模式减少了人为参与产生误判的可能性。

    云效flow,高易用性,高集成性
    使用云效flow产品后很多问题迎刃而解,可视化的流水线配置让之前繁琐的脚本编写工作一去不复返。flow高度集成阿里云产品线,在流水线flow中轻松集成我们在阿里云使用的SAE环境。我们曾尝试让一名有3年工作经验的普通的开发人员在flow中构建一个java测试应用部署的流水线,结果他在没有查看任何文档的情况下很快的完成了流水线的配置工作。这些体验都让我们切身感受到flow产品的高易用性和高集成性。

    3. 提升质量,减少故障:

    一提到流量增长,大家第一时间可能想到的就是加机器加带宽,但往往这个时候加机器已经来不及了。以往我们都是提前预估峰值,按峰值保有ECS资源,但经常出现容量预估不准的情况(比如资源浪费或资源不足),更严重的是会影响系统的SLA。通过SAE的秒级自动弹性,我们可以轻松的动态扩容应对峰值大考,峰谷时按需自动缩容。

    以前团队中的code review工作只能指定专人在合并代码后执行审查任务,并根据生成的审查报告统一对问题进行修订,在使用云效codeup代码库后,代码审查工作被分配在每次commit后自动执行,以前统一的审核时间被分配在团队中每个人commit代码后自动执行,不但减少了人员参与的人力成本而且减少了code review工作执行的时间成本,大大提高了工作效率。由于整个code review工作提前到了代码commit阶段,将发现并解决代码潜在问题的阶段提前到了代码合并之前,这样就减少了在后续环节中出现遗漏问题的可能性,这里不得不提一下codeup审查代码阶段包含的敏感信息和依赖包漏洞扫描功能,这两个在codeup中自带的安全扫描功能,不但调高了代码质量的安全性,而且潜移默化的提高了团队的安全意识。

    对比 原来 现在
    代码规范评审 代码评审环节滞后,人为控制环节多。 commit自动化评审
    代码安全评审 缺失安全评审工作 commit自动化安全评审
    发布方式 Jenkins手工编写流水线脚本 高度可视化操作--简单
    Jenkins通过API方式集成阿里云产品(SAE) 高度集成阿里云产品(SAE)--便捷
    分布式环境建设 购买ECS设备构建环境 SAE无需购买ECS,按资源使用量弹性付费
    分布式环境运维 自建运维环境,集成多种运维工具 SAE提供统一运维平台,高度集成阿里云运维相关产品。

    结语

    企业创新要做的是成长速度快于消费者需求变化的速度,所以「掌讯信息」深感依靠自身摸索固然也可以持续提升能力,但面临的挑战要求能力的提升也必须更快、更好。在寻求提升开发和交付效率,低成本试错中,「掌讯信息」发现阿里经过数年互联网研发实战,已经总结出了一套高效能的研发思想、流程及工具,那就是阿里云SAE+云效。

    持续交付、降本提效是一个很大的主题,一篇文章要讲透是不够的,只是简单分享了我们在这个过程中遇到的几个关键问题。「掌讯信息」在实践中其实都在摸着石头过河。希望大家可以多交流,共同探索互联网交付效率的成功模式。

    最后,感谢 「SAE + 云效」 这两款工具及官方团队给予我们的支持,希望在未来更加深度的合作中,「掌讯信息」和 「SAE + 云效」 都能为更多团队的交付效率提供更多更好的经验。

    作者介绍
    乔亚浩,2009年加入石家庄掌讯信息技术有限公司,从业务开发至产品管理,现任职「掌讯企业智能服务部主管」。先后承担多次技术攻坚及推动技术演进:前端混合开发技术落地,产品后端微服务化改造、服务自动化构建及容器化部署、云效CI/CD落地等。

    ]]>
    SpringCloud 应用在 Kubernetes 上的最佳实践 — 高可用(熔断) Thu, 29 Oct 2020 12:16:15 +0800 前言

    阿里巴巴十多年的双十一,锤炼出来了一套业界领先的高可用技术,有一些已经商业化(云产品 PTS、AHAS),也有的开源了如:Sentinel、ChaosBlade。我们这一系列的高可用章节也主要介绍这方面的内容。今天介绍熔断部分,即开源产品 Sentinel 的核心能力。

    问题定义

    在一个常见的分布式应用中,一个请求先通过终端到达 Gateway,再经过防火墙和网络负载均衡,其中还包括调用下游的其它服务和第三方应用,才能到达前端网络服务;如下图所示。

    1.png

    和这样一个架构一样,大家可能也会遇到如下的一些熟悉的 Case :

    • 瞬间洪峰流量导致系统超出最大负载,load 飙高,系统崩溃导致无法正常提供服务。
    • “黑马”热点数据击穿缓存,DB 被打垮,挤占正常流量。
    • 调用端被不稳定服务拖垮,线程池被占满,导致整个调用链路卡死甚至系统雪崩
    • ......

    这些不稳定的场景可能会导致严重后果。大家可能想问:如何做到均匀平滑的用户访问?如何预防流量过大或服务不稳定带来的影响?这时候我们就要请出微服务稳定性的法宝 —— 高可用流量防护,其中重要的手段就是流量控制和熔断降级,它们是保障整个系统稳定性重要的一环。

    流量控制

    流量是非常随机性的、不可预测的。前一秒可能还风平浪静,后一秒可能就出现流量洪峰了(例如双十一零点的场景)。然而我们系统的容量总是有限的,如果突然而来的流量超过了系统的承受能力,就可能会导致请求处理不过来,堆积的请求处理缓慢,CPU/Load 飙高,最后导致系统崩溃。因此,我们需要针对这种突发的流量来进行限制,在尽可能处理请求的同时来保障服务不被打垮,这就是流量控制。

    2.png

    熔断降级

    一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。

    3.png

    Spring Cloud 中如何做熔断?

    在原来的 Spring Cloud 产品族中,有自带的熔断组件 Hystrix ,是 Netflix 公司提供的一个开源的组件,提供了熔断、隔离、降级的这些特性,不过 Hystrix 在 2018 年 11 月份开始,就不再迭代开发,进入维护的模式。不过好消息是也就是这一年开源了 Spring Cloud for Alibaba 产品族,其中的 Sentinel 完美的对 Hystrix 做了补充,下面针对 Sentinel 做一些基本介绍。

    Sentinel 工作原理?

    Sentinel 以资源流量(URL、线程、本地函数、Dubbo服务等)为切入点,根据用户输入的规则,自适应的做到流量控制、熔断降级、系统负载保护等多个维度,全方位的保障系统的稳定性。并提供了一套具备丰富的应用场景、完备的实时监控、广泛的开源生态、完善灵活的 SPI 扩展点的完美的高可用解决方案产品,一个基本的原理介绍图如下,详细介绍请参考官方文档

    4.png

    在使用上,针对主流框架默认提供自动适配的能力来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析。同时,Sentinel 也提供开放的接口,方便您自定义并改变规则。

    快速使用 Sentinel 的方式

    除了在开源提供的方案之外,Sentinel 已经以多种形态进入到了各种云产品的组合解决方案中,列举如下:

    一、在 AHAS 中使用

    Sentinel 现在已经是阿里云云产品 AHAS 的重要能力,使用方式请参考官方文档,相比开源的方式接入,云产品主要省去了繁琐的配置,提供了更快的接入方式,以及更友好的产品管控界面,以及更强大的能力;当然除此之外,最重要的是在接入和运行的过程中,都可以获得原厂同学的直接的支持。

    二、在容器服务 Kubernetes 集群中使用

    在容器服务中我们目前做到了纯白屏和云原生的方式进行安装,使用方式请参考官方文档来安装所需的 pilot,在集群中安装完 pilot 之后,会自动选择集群中打上了相应 AHAS 注解的 POD 进行 Sentinel Agent 的挂载,配置如下:

    annotations:
      # 是否开启 AHAS 应用流控插件, on、true 表示开启, off、false表示关闭
      ahasPilotAutoEnable: "on"
      # 服务名称,会显示在 AHAS 控制台上
      ahasAppName: "<your-service-name>"

    三、在 EDAS 中使用

    在 EDAS 中,如果选择的是部署在容器服务K8s集群或 Serverless K8s 集群中的应用支持通过重新部署来接入AHAS,并可在EDAS内嵌的监控页面中实时监控流量规则,所有的配置能力都能通过一个控制台白屏化操作完成,全面可视化地保障您的应用可用性,使用方式可以参考文档

    结尾

    本文简单介绍了高可用流量防护的背景和手段,在熔断的场景下,我们理解十年的积累打磨了高可用产品 AHAS 来为 Kubernetes Spring Cloud 应用保驾护航。除此之外,AHAS 高可用防护还提供以下能力:

    • 针对不稳定弱依赖的熔断降级能力,支持慢调用比例/异常比例策略,支持渐进式恢复策略。
    • 机器维度的系统自适应保护,智能化调配系统流量
    • 全自动托管、高可用的集群流量控制
    • 针对 Nginx 网关及 Spring Cloud Gateway、Zuul 等 API Gateway 的网关流控
    • 针对 Istio/Envoy 集群的 Mesh 高可用防护

      需要注意的是,流控降级的配置是需要结合容量规划、依赖梳理来做的。我们可以借助阿里云 PTS 等压测工具对我们的服务进行全链路压测,了解每个服务的最大承受能力,来确定流控和熔断降级的阈值。同时,业务系统需要具备实时监控的能力,以便实时地根据流量情况做出相应的限流降级策略调整,我们下面的章节中将介绍这一利器。
    ]]>
    闲鱼靠什么支撑起万亿的交易规模?| 云原生Talk Thu, 29 Oct 2020 12:16:15 +0800 image.png
    造梦者 | 王树彬,阿里巴巴闲鱼架构负责人

    2014年6月28日,阿里即将赴美上市的这一年,西溪园区的一个茶水间里,28个人日夜赶工了三个月后,上线了一个闲置交易平台——闲鱼。今年5月份,在阿里巴巴的年报中对外公布了闲鱼的数据:GMV2000亿元,同比增长100%,每天在线卖家数超过3000万人。 闲鱼已经从一个茶水间创业的内部小产品,变成了在C2C领域的领先平台。

    据艾媒数据估计,2020年全年的二手物品交易市场的规模将达到万亿以上。线上交易的繁荣亟需技术架构做相应的调整、演进才能支撑业务的快速发展。闲鱼对于阿里而言,有比营收更重要的意义,那就是创新。创新不只体现在业务模式上,闲鱼的技术架构也在探索最新的方向——向Flutter化、云原生/Serverless化发展。

    2009年,从浙江大学毕业的王树彬,在UT斯康达工作了三年后,加入阿里巴巴。2017年,王树彬首次将Flutter引入到闲鱼,从2018年开始,王树彬带领闲鱼技术团队在下一盘更大的棋:布局Serverless。颠覆性创新往往是从边缘性的地方出现,而向云原生化/Serverless化升级,对于闲鱼是一条全新的路,但趟出了这条路,对于很多做线上交易的公司有着巨大的借鉴意义。

    今天,我们就一起聊聊闲鱼的云原生故事。

    01 为什么要做Serverless?

    闲鱼是依托阿里电商体系的前台型业务,有非常独特的业务特点和用户诉求,在底层依托阿里系统的同时,在表现层和业务层需要探索适合闲鱼的、并且更加快速灵活的研发体系。

    按照传统的开发方式,闲鱼原有的 IT 系统会面临很多痛点,比如:

    1、客户端交互层、服务端业务胶水层、领域层边界划分不清晰,这就导致很小的业务需求就需要整条链路的同学参与,协同成本高,开发调试周期长。

    2、服务端存在巨型应用,研发耦合、发布耦合、运维耦合严重,甚至系统稳定性也受到很大挑战,单个业务问题往往会影响整个应用。

    3、运维成本极高。为了保障业务的稳定性和可用性,阿里对每一个应用上线都有相应的规范和规则。哪怕是一个很小的内部应用,一天可能只有一两个访问量,上线也需要遵守既有的规范,这势必会消耗一些固定资源。单个应用消耗的资源可能很有限,但所有应用消耗的资源累积起来也是一个不小的数字。而对于巨型应用,由于影响面巨大,发布时要有更加严格的流程和步骤,一次发布至少要耗时6小时,导致运维成本极高。

    Serverless 的出现,一方面使云端一体化研发成为可能,很多小业务需求的协同成本可以大大降低。另一方面,Serverless 使业务胶水层的巨型应用,有了比微服务更加合理的拆分方式。

    传统巨型应用的成本(速度)、稳定、质量相互制约的瓶颈,可以用下面这个三角形来直观的表示。
    image.png
    云原生/Serverless 这些新技术的出现,可以使应用运维能力下沉,传统巨型应用的成本(速度)、稳定、质量相互制约的瓶颈才有可能被打破。闲鱼在落地新技术的过程中,先围绕 Flutter 重点攻坚了 Flutter 混合工程体系、高性能组件库。然后围绕Serverless 重点攻坚云端一体化研发体系、服务端业务组装层架构体系。

    闲鱼客户端基于 Flutter 进行架构演进与创新,通过 Flutter 统一 Android 和 iOS 双端提升研发效能之后,希望通过 Flutter+Serverless 解决各角色间存在的大量的协同问题,正是这些问题导致整体研发效率低,移动端离业务越来越远,服务端没有时间做底层领域沉淀。通过 Serverless 的引入,闲鱼会明显看到整体研发效率的提升。

    02 一边探索,一边实践

    2018年,闲鱼技术团队开始探索 Serverless,整体分为四个阶段:自建Dart Server、依托FaaS平台、云端一体化、传统巨型应用Serverless化。

    2018年5月,以 Serverless 思路构建了2s内冷启动的 Dart Server 应用框架,用于服务端业务胶水层的轻量化开发。

    2018年底到2019年初,闲鱼启动与Gaia团队协同共建基于Gaia平台的Dart 运行时,并上线了部分业务。注:Gaia是基于阿里云的面向淘宝业务特点封装的、用于淘宝业务的FaaS平台。

    2019年,闲鱼基于Gaia的Dart Runtime标准化,探索 Flutter+FaaS 云端编程一体化,领域接口元数据化,最终诞生了 Nexus 等胶水层业务框架,并在闲鱼20多个业务落地。

    2020年,闲鱼开始进行云端的工程&工具一体化,目标是实现一个工程、多端部署。现在,王树彬正带着技术团队攻坚业务胶水层的传统巨型应用治理,使传统应用向Serverless化迁移,“最快3个月,最晚6个月,我们就会交出一份漂亮的答卷。”

    具体来看过去这两年的时间里,闲鱼在Serverless上的实践成果,主要分为5个方面:

    1、云端编程模型一体化框架(Nexus API)
    这个框架的目标是使Flutter、FaaS的编程模型统一,打通UI、交互、数据、逻辑。王树彬提到,一开始说要做Flutter + FaaS一体化的时候,我们对“一体化“这三个字的认知相对比较模糊,只是知道端侧的同学可以用 Dart 这门语言来写FaaS函数,这其实还停留在语言上的一体化。对于FaaS所能做的事,也仅仅停留在前端实施已久的BFF层面。

    我们花了很长时间来讨论,基于Dart生态下,前端的 FaaS 在研发交付其实并不高效,研发阶段主要面临的问题是:

    编程语言不统一:编程语言本身虽然不是最大的障碍,但这也确实给前端开发者增加不少门槛,而且更重要的是语言背后的生态、环境与体系更是一道高高的墙。

    开发模式与架构割裂,环境复杂:端侧一个工程,FaaS侧也有一个独立的工程,它们背后有自己的一套构建、调试、集成/发布的工具链;除此之外,FaaS 还有自己配套的环境、Runtime、框架作为支撑。开发者面对这样复杂的 FaaS 研发环境与双重的研发工作流是无法做到高效交付的。

    最终,我们对一体化有了一个比较清晰的共识,那就是要实现两个核心的一体化:

    • 语言一体化
    • 开发模式与架构一体化

    编程语言的一体化可以为开发者提供一种熟悉的技术栈,开发模式与架构一体化能帮助开发者解决工程割裂以及背后复杂的 FaaS 本地运行环境问题,带来与原研发模式基本一致的研发体验。

    通过这两个层面的一体化,最终达到开发 Flutter 页面和开发 FaaS 无明显Gap。例如,闲鱼客户端Flutter以往是用Redux框架开发,在Nexus API框架下,可以使Redux与FaaS调用无缝集成。
    image.png
    2、CLI 开发工具标准化

    云端一体化开发时,通过 CLI(命令行工具)屏蔽 FaaS 开发的一些细节,使客户端开发 FaaS 时的开发体验标准化,符合客户端同学的本地开发习惯。

    image.png

    3、基础服务 BaaS 化

    过去两年,我们在逐渐简化基础服务能力,如对象存储、消息、搜索。同时,建设业务领域层服务的元数据中心,这些简化的基础服务能力,再加上已有的业务领域层服务,使客户端同学可以快速组装业务。

    4、云端工程一体化

    闲鱼在成功引入 Flutter 后,在端侧形成了以 Flutter 为主、H5为辅的跨端研发体系,使传统的 Android 和 iOS 的两端研发,合并成一端。在端上的生产力得到释放时,我们发现端的同学有机会向下层走一点,使服务端面向简单的数据组装逻辑,由端的同学一人闭环完成,这套模式尤其适用于一些小业务的需求。类似的尝试业界其实早就有了,例如 GraphQL 框架的流行,前端的BFF层的形成。但有了Serverless,服务端轻量代码的开发可以极大地简化,所以闲鱼选择这个时机推进云端一体化。
    云端一体化涉及到云端编程框架、工具链、工程体系、基础服务BaaS化、领域服务下沉,同时,也涉及人员上的组织保障、分工重塑、安全生产培训等。

    5、传统巨型应用的Serverless化改造

    Serverless不是银弹,但与业务胶水层的特点很匹配,非常适用于解决胶水层的传统巨型应用的拆分,这也是闲鱼正在攻坚的下一个难题。
    image.png

    03 难题与破局

    闲鱼落地 Serverless 的过程中并非一帆风顺。王树彬提到,在Serverless云端一体化过程中,遇到了一些技术难题,比如Java富客户端的异构语言访问、开放环境如何统一以及客户端同学对领域接口不熟悉等问题。

    在闲鱼的Java系统中,存在大量的Java富客户端应用。针对Java富客户端的异构语言访问,闲鱼以Sidecar的模式,建立Java的Proxy来解决这类问题。

    紧接着,为了让开发环境统一,闲鱼开发了自己的CLI工具(GCLI)。GCLI是一个基于支撑 FaaS 研发生命周期的命令行工具,它定义了闲鱼 FaaS 开发闭环,统一了 FaaS 的研发环境,是提升FaaS研发效率的利器。GCLI 将研发闭环拆解成适合Serverless 研发习惯的开发指令。为了让用户继承其研发习惯和工具,闲鱼优先选择了基于本地的开发方案;使用Docker技术统一开发环境,在 Dcoker 内声明Dart FaaS技术栈依赖的运行环境(软件+配置)。借助容器技术,FaaS 的软件环境可以移植到任何支持Linux运行的操作系统,从而解决了环境统一的问题;GCLI 通过 FaaS Open API 实现本地和函数平台实现互操作,形成完整的研发闭环。

    最后,针对客户端同学对领域接口不熟悉的问题,闲鱼开发了领域层的元数据中心。

    云端一体化重塑了传统的云、端边界,减少了协同,也给人员的分工带来了更大的灵活性,技术上的研发效率、研发质量也明显提升。而这些改变对于业务带来的直接好处,就是可以让业务有更快的迭代速度、更快地适应市场和用户需求的变化。

    云端一体化目前应用在闲鱼的重交互场景以及轻量业务场景中,其带来的技术效率、质量提升更容易以量化的数据形式呈现。例如,以典型的中大型业务需求抽样统计,开发人日降低了30%,千行代码Bug率降低了20%。如果以零散需求统计,数据提升会更加明显。以往的小需求由于多个同学参与,往往排期需要几周,而云端一体化后,资源的灵活性明显提高,使需求响应速度大大提升。
    image.png
    “但是,还有一些问题没有解决”,王树彬说,在 Serverless 的巨型应用拆分方面,闲鱼遇到的问题更加严峻,比如:

    • 微服务和 Serverless 的选型
      在 Functions 之间代码复用

    对函数的依赖做统一升级

    这几个问题的方案,闲鱼还在逐步验证中,待经验成熟后再向大家详细分享,欢迎持续关注。

    04 借鉴与思考

    什么样的公司、应用或场景应该选用 Serverless 的架构模式?目前没有具体的定义,关键在于想清楚。想清楚,就需要平衡好收益、成本、效率和应对市场的能力。其中,成本是企业更为关注的因素,这其中包括基础设施搭建的成本、运维成本、扩容成本、安全成本等。

    Netflix是落地 Serverless 的一个成功的典型,Netflix 在产品设计上一直都有创新的基因,除了不间断的 A/B 测试之外,每周都会发布很多新功能。为了确保这样高强度的工作成果,就需要一个 API 服务平台来帮助客户端工程师快速而有效地将更改的需求部署到服务层。FaaS 通过把那些与服务相关的所有平台组件抽象为业务逻辑本身来实现这一目标,而 Serverless 模式能够为Netflix提供一个平台,即使没有服务器和运营经验的工程师也可以开发高可用的服务。

    采用 FaaS 模式,本质上是对交易速度和可能性的定制化。有些应用程序的 FaaS 服务表现得很好——Netflix API 的情况就是如此,Netflix 运行的是相对统一的微服务,只需要访问和改变下游服务的数据。然而,如果服务需要定制化,例如需要改变服务平台的各个组成部分,像 RPC、数据访问、缓存、认证等,那么 FaaS 模式可能无法为这些服务提供足够的灵活性。

    自建 Serverless 平台对企业IT人员的要求比较高,同时建设成本也很高。另外,实施Serverless 需要一个成熟的生态。绝大多数情况下,已经上云的企业应该优先考虑云厂商的Serverless产品,而没有上云的企业,需要考虑现有系统的生态情况是否能与云厂商的Serverless产品兼容。

    对于 Serverless 产品的选型,应该综合几个方面来看:生态的成熟度,支持的开发语言,功能丰富度,收费标准等,关键是结合企业自身业务发展的需求。

    05 关于未来

    O'Reilly 曾对 Serverless 的应用情况进行了过一次调查,发现软件行业的开发者关注和应用 Serverless 非常多,这在意料之中,但是金融和银行业也在高度关注Serverless,原因之一是越来越多的金融科技初创企业的诞生,它们承担了传统基础架构的责任,并且以更开放的心态,接纳和拥抱 Serverless 。

    对于拒绝 Serverless 的理由,60% 的受访者表示是安全问题。因为很多行业对于 IT 环境的安全性要求很高,而采用任何新技术都可能会带来安全风险。

    此外,开发者另外一层顾虑主要是担心被厂商绑定,这就导致具备一定规模的组织会基于开源方案,如 Knative,搭建自己的 Serverless 平台。而一旦某个开源方案成为主流,云厂商就会主动去兼容开源标准并增大社区投入。

    Serverless 除了对技术和业务产生影响外,对于企业组织架构和技术人员也提出了新的要求。

    首先,Serverless 改变了沟通结构。按照康威定律,组织架构需要适应新的沟通结构,才是最好的匹配。闲鱼以前负责客户端和服务端的同学是分开的,在全新的 Flutter+Serverless 的背景下,组织结构也需要做相应的调整。经过讨论,闲鱼最终决定按照业务线划分,将客户端、服务端的同学按业务线重新组合到一起。

    其次,Serverless 使客户端的同学有机会更多的了解业务,这就要求客户端同学更加具有业务敏感度。Serverless 促使客户端同学扩大了技术边界,也需要了解一定的服务端开发概念。

    最后,Serverless 要求原有的服务端同学有更好的数据建模、领域建模能力,从而有助于底层接口复用度更好。

    从最开始不被外界看好,甚至被调侃为“咸鱼”,到如今实现了千万DAU,盘活了一个万亿级市场,闲鱼的出现,无论是对前端的电商生态,还是用户在互联网上的生活形式,都产生了重要的影响。

    为了支撑起闲鱼万亿的交易规模,王树彬和技术团队正在紧锣密鼓地进行传统巨型应用的 Serverless 化改造,“闯过了 Serverless 的这一关,才是我比较满意的状态。”

    云栖大会预告:

    在9月17-18日云栖大会上,王树彬将在「Serverless分论坛 — 2020 Serverless 新浪潮」分享《闲鱼Serverless架构实践》的话题,敬请期待。

    ]]>
    阿里云原生十年磨剑:让企业在数字经济时代焕发生命力 Thu, 29 Oct 2020 12:16:15 +0800 15.jpg

    日前,国际知名咨询机构 Gartner 发布了最新云厂商产品评估报告,作为亚洲唯一入选的云厂商,阿里云在计算大类中,以 92.3% 的高得分率拿下全球第一,并且刷新了该项目的历史最佳成绩。本次报告,Gartner 更多关注云原生领域,比如在软件基础设施层面,Gartner 重点评测了中间件等领域,阿里云得分位列全球第二。

    以计算项为例,本次测试选取了 Large-scale provisioning of VMs、Scheduled autoscaling、Workload migration service 等 33 条评估细项,涉及容器服务能力(ACK)在内的多项领域,在必备能力和推荐能力的评估项目中,阿里云全部拿到满分,并获得分析师的一致好评。

    在软件基础设施服务领域的 21 条评估细项中,涵盖各类数据库服务、服务网格 ASM 、 FaaS 、消息队列等领域,阿里云得分率 82.2% ,位居第二。同计算、存储一样,数据库与中间件产品能力也是分析师认可阿里云的优势领域。

    从 2011 年率先在国内布局容器技术开始,阿里在云原生领域已经深耕了十余年。在这期间涌现了众多云原生技术和产品,并在开源领域贡献了多款深受开发者欢迎的开源项目,如 Dubbo、RocketMQ、Sentinel、Spring Cloud Alibaba、OpenYurt 等。

    在 2020 阿里云线上峰会上,阿里云智能总裁张建锋表示,阿里云将做深基础,做厚中台,做强生态,有信心真正做好数字经济时代的基础设施。经实践证明,云原生是企业实现数字化转型的最短路径。

    云原生产品全面升级

    目前,阿里云拥有国内最丰富的云原生产品家族,覆盖八大类别 20 余款产品,涵盖底层基础设施、数据智能、分布式应用等,可以满足不同行业场景的需求。同时,阿里拥有最全面的云原生开源贡献。截至目前,阿里拥有 400 多个开源项目,3600 多位贡献者参与了阿里开源项目,在开源社区获得 30 多万个 Star。
    image.png
    除了支持集团内部应用规模化运维,阿里云云原生技术还向全社会输出。阿里云拥有国内最大的容器集群和客户群体,其容器服务(ACK)已在中国及海外 19 个公有云可用区开服,同时也支持客户在自有机房和边缘端的部署使用 Kubernetes。同时,阿里云还提供了丰富的差异化产品:兼容 Istio 的托管版服务网格、基于弹性容器实例的无服务器 Kubernetes(ASK)、提供镜像扫描的独享版容器镜像服务 (ACR),还有基于轻量虚拟机技术的安全沙箱容器运行时和托管服务网格(ASM),它是业内首个全托管Istio兼容的服务网格产品,为容器化的微服务应用提供一致的流量控制和观测能力。

    在中间件领域,阿里云原生拥有全球最大规模的软负载集群,消息处理量日均万亿条,双十一峰值可以达到亿级 TPS ;RPC 调用量日均万亿次,双十一峰值可以达到亿级 QPS 。通过阿里云全面的云原生产品,企业相当于站在巨人的肩膀上,即使是普通的中小企业业务系统也能具备阿里电商的敏捷、弹性、稳定性。
    image.png
    过去十年,云逐步向 Serverless 演进。2016 年阿里云发布的函数计算提供了函数级抽象,2019 年发布的 SAE 提供了应用级抽象,这些产品都抹去了服务器的概念,让用云方式得到极大的简化,并逐渐成为趋势。阿里巴巴不仅在淘宝、支付宝、钉钉、闲鱼上将 Serverless 应用于生产,新浪微博、石墨文档、跟谁学、Timing 等企业也通过阿里云 Serverless 产品,免去了维护复杂机器状态的工作,大幅降低了 IT 成本。

    云原生服务升级,从服务技术到服务业务

    阿里云拥有国内最大规模的云原生应用实践。疫情驱动企业线下业务转到线上,架构互联网化渐成趋势。全链路压测、极速弹性扩缩容以及云原生的全栈技术已广泛服务于互联网、金融、零售、制造、政务等领域企业和机构,大幅降低了应用开发的门槛,加速企业数字化转型的进程。

    利用 PTS 压测,实现资源规划可视化

    根据 Amazon 统计,每慢 100 毫秒,交易额下降 1% 。这些事件和统计数据为大家敲响了警钟,也说明了性能压测对于企业应用的重要性。性能测试服务 PTS 是一个 SaaS 性能测试平台,提供场景 API 编排功能。结合阿里巴巴的自研平台和引擎,支持按需设定压测模式、压测量级、压测时间,快速发起压测,监控压测过程并生成报告等功能,同时也兼容开源工具 JMeter 。

    作为电商行业的独角兽,完美日记通过性能测试服务 PTS 和应用高可用服务 AHAS,第一次参加双十一就成为 2019 年美妆行业第一,第一个破亿。通过大促之前反复压测,完美日记把可能出现的问题都在大促前暴露出来,大大小小提前发现并解决了20多个问题,最终把不确定性变成了确定性。

    快速扩容,容器服务秒级扩容千个 Pod 的能力,平滑应对突发流量高峰

    阿里云是连续两年国内唯一进入 Gartner 《公有云容器服务竞争格局》报告的云厂商;在 Forrester 首个企业级公共云容器平台报告中,阿里云容器服务位列Strong Performer ,中国第一。

    容器镜像服务可自动执行并优化基本镜像分发流程,支持通过 P2P 大规模分发到 1 万个节点,效率高达以前的 4 倍。企业可在数分钟内扩展到 1000 个节点,而阿里云 Serverless Kubernetes 版 (ASK) 和弹性容器实例 ECI 可在 30 秒内启动 500 个容器组。

    新一代容器服务 ACK,可以将最新神龙弹性裸金属实例的强大性能发挥得淋漓尽致,具备极致性能、高效调度、全面安全的特点:

    • 新一代神龙架构具备业界第一的 I/O 转发能力,提供最高 100G 网络带宽;阿里云高速 Terway 容器网络通过网卡直通和数据平面加速,延迟下降 30%。
      第 7 代实例最大支持 192 个 vCPU。ACK 智能 CPU 调度可以轻松释放强大算力,无需应用调整可以实现 QPS 20~30% 提升;结合 ENI 网卡密度提升,可以缩减 50% 的计算成本。

    弹性裸金属实例支持阿里云安全容器,提升端到端安全隔离能力,与开源方案相比性能提升 30%。也支持阿里云首发机密计算容器,基于软硬一体技术有效保护数据隐私。

    云原生正在打通数字化落地的“最后一公里”。疫情期间,阿里云 2 小时内支撑了复工第一天钉钉业务 1 万台云主机的扩容需求。基于云服务器和容器化的应用部署方案,让应用发布扩容效率大大提升,为全国用户提供线上工作的流畅体验。

    面对指数级增长的流量,希沃课堂通过容器服务 ACK 高效管理神龙裸金属服务器和 Serverless 弹性容器实例,顺利积累超过 30 万教师开设 200 万节课程,助力希沃课堂整体业务性能提升 30%,运维成本降低 50%。

    基于阿里云边缘容器服务 ACK@Edge 底座,盒马全程保障疫情期间居民日常供应。结合了云原生技术体系良好的资源调度和应用管理能力,与边缘计算就近访问,实时处理的优势,轻松实现全方位的降本提效,门店计算资源成本节省 50%,新店开服效率提升 70%。

    云原生中间件助力应用架构向互联网化演进

    应用架构向互联网化演进是保障业务稳定和持续创新的根本,应用容器化、微服务化、异步化是实现架构演进的三步曲。应用容器化:通过将应用和环境打包,以容器化的方式实现快速部署,快速交付。微服务化:将一个单体多模块的大应用分解为具有一些原子业务能力的微服务,通过微服务化实现业务快速迭代和变更上线。异步化:引入消息队列中间件,将应用之间的通信异步化,提升应用系统的可用性,减少响应时间。

    云上消息的准确和不丢失对于业务可靠和稳定至关重要。以出行领域为例,如果数据丢失,不仅会导致运行轨迹出现错误,后续应用在自动驾驶上还会带来安全的问题。汽车产业互联网平台大搜车通过云上消息队列 Kafka 的优化版本减少了数据的丢失情况,保证了业务的可靠性和稳定性。

    Timing App是一款提供在线学习的教育社交类应用,目前已有用户700万人。该企业无专职运维人员,之前采用单体PHP架构,无法满足快速增长的业务需求。通过阿里云Serverless应用引擎 SAE 来管理底层 IaaS 资源,解决了客户长期以来代码耦合度高、运维复杂、开发迭代效率低、资源利用率不高等问题。

    EDAS 3.0 无侵入构建云原生应用,提供更多维度自动监控

    EDAS3.0 除了在微服务治理和容器纳管上提供了差异化的产品竞争力外,还将阿里巴巴应用应用安全三板斧,即可观测、可灰度、可回滚融合其中,并实现了 K8s 集群的监管控一体化,提供了更多维度的自动监控、智能诊断和报告输出等功能。中国邮政、安利、福特汽车、红岭创投等来自政企、新零售、制造、新金融等行业的客户正通过 EDAS 来构建云上的容器应用。

    为提振消费,刺激经济快速复苏,成都市政府通过“消费券”项目,第一次活动就吸引 2000 多万市民报名。为支撑大流量高并发的报名场景,在与阿里云技术专家深入讨论后,成都信通决定采用阿里云企业级分布式应用服务 EDAS 。EDAS 的动态扩缩容、灰度发布等能力,为成都信通提供了一整套的应用生命周期的管理,真正做到一键部署、一键发布。同时 EDAS 平台对应用快速扩缩容以及对流量控制、熔断、降级等功能的支持,很好地帮助成都信通在面对大流量、高并发场景时,业务系统依旧能够持续平稳的运行。

    十年磨一剑!面向未来,阿里云将继续与企业并肩前行,激发更多企业在数字化转型浪潮下的生命力,迎接云原生的下一个十年。

    9月18日云栖大会《企业云原生实践》分论坛,敬请期待。

    升级.jpg

    ]]>
    云原生:重新定义信息产业生态体系 Thu, 29 Oct 2020 12:16:15 +0800

    作者:宁晓民(灭道),阿里云原生生态负责人

    信息产业竞争的核心是技术生态体系的竞争

    半个世纪以来,信息产业的生态竞争从微型机、服务器到PC互联网,到移动互联网,再到云计算时代,以操作系统为核心的产业生态系统的竞争愈演愈烈。

    1.png

    1、基于Wintel体系的计算机产业生态
    在PC时代,以微软和Intel推动软硬件功能的深度适配,协同创新和持续升级,Wintel体系以操作系统为核心,构建了PC计算机软硬件的生态体系,形成了数百个各类基于Windows的软件开发工具,在全球范围内建立了上千万名研发人员参与的开发者社区,每年培训了数以亿计的各类应用软件开发人员,基于Window的各类应用软件数以百万计,拥有超过10亿以上的用户。Wintel体系通过整合软硬件,开发者,软件商,用户等资源,形成了全球个人计算机市场难以撼动的产业生态

    2、基于Android/iOS体系的智能设备产业生态
    从苹果公司推出IPhone智能手机为标志,代表着从原来的PC互联网时代进入到了移动互联网时代,从而全球移动智能设备形成了以Android/iOS为核心的产业生态。苹果公司以软硬件结合为重点,以iOS操作系统为纽带,构建起以“CPU(ARM)+操作系统+开发工具+应用商店+各类应用”为核心的产业生态。同样Google公司以开源为手段,构建与之相配的Android体系产业生态

    3、基于云原生(Cloud Native)体系的云计算产业生态
    从2006年第一次提出“云计算”的概念起,云计算、大数据、物联网、人工智能等相关的技术及产业发展势如破竹,不断渗透当代信息产业,从而实现信息产业升级。应用迁云、上云的过程越来越快,从原来的云托管(Cloud Hosting)到云原生(Cloud Native),生于云长于云,最大化的运用云的能力,从而最大化的释放云计算的技术红利。以容器、微服务、服务网格、不可变基础设施及声明式API等技术为主的云原生技术,能够实现应用系统与基础设施解耦,从而让开发者聚焦于业务而不是底层基础设施,云原生进而成为云计算时代的新“操作系统”。以云原生技术为核心,构建起以“云厂商+异构软硬件+云边端+Serverless化+软件全生命周期+开发者+企业客户”为核心的新一代信息产业生态。

    云原生是释放云计算技术红利的最短路径

    2013年一个名叫“Docker”的开源项目发布,以“应用封装+容器镜像”,直接将一个应用运行所需的完整环境,实现了“一次发布,随处运行”,彻底解决了PaaS用户一致性的问题,进而通过Kubernetes开源项目,采用了一整套容器化设计模式和对应的控制模型,从而明确了如何以容器为核心构建真正能够跟开发者对接起来的应用交付和开发范式。容器+Kubernetes技术的逐步成熟与发展,以“云原生(Cloud Native)”为关键词的技术生态雏形基本确立。
    经过6~7年的技术发展,云原生的概念逐渐被广大的客户和合作伙伴所熟知,云原生技术、云原生产品、云原生架构的概念逐步定义出来。
    云原生技术:让系统更加弹性可靠容错、松耦合、易管理、可观察;代表技术是容器、微服务、服务网格、不可变基础设施和声明式API。
    云原生产品:云计算平台提供的数据库、大数据、中间件、函数技术、容器服务等开放标准的原生产品服务。
    云原生架构:生于云长于云,最大化运用云的能力,依赖云产品构建的IT架构,让开发者聚焦于业务而不是底层技术。
    生产力决定生产关系,以云原生为代表的先进生产力,改变整个信息产业格局,从而重新定义新的信息产业生态。

    2.png

    (1)云原生会成为云计算的新界面

    以容器、Kubernetes技术为主,向下封装底层基础设施差异性,如异构环境,异构硬件,向上支撑多样性的工作负载,如新型计算等,覆盖云、边、端,赋能无边界计算、分布式云,云原生逐步成为云计算的新界面,新一代的操作系统。

    (2)云原生重塑软件的全生命周期

    云原生通过底层基础设施与应用的解耦,在软件研发、交付、运维的全生命周期层面的效率提升,从而对软件行业上下游产业链都会带来变革。在微服务领域,在应对系统复杂性的同时,对可观测性、易测试、环境适应性的层面实现更大解耦,让开发人员聚焦于业务开发。在Mesh化层面,实现网络和流量下沉基础设施,方便软件基础设施和业务解耦,独立演进,实现全链路精准流量控制和资源动态隔离,从而带来效率的提升。以全托管、免运维、极致弹性、按需部署、按需计费、强安全为特点的Serverless无服务器架构也推动着软件研发运维模式重大升级

    (3)云原生加速信息产业转型升级

    随着云原生应用的越来越多,软件厂商从基础设施的资源需求,向精细化管理、更优成本、极致弹性、以及研发效能、交付优化的全生命周期的转化。而底层基础设施的变革,带来的“降维打击”,从而推动整个信息产业的重构。从ISV(独立软件提供商)的软件全生命周期,到硬件厂商、云厂商、ISV、企业客户之间的新一轮的软硬件的供需体系,再到云计算技术、社区、ISV、开发者之间的技术互动体系中,云原生技术作为新一代云技术操作系统,加速推动整个信息产业的快速升级。

    云原生合作伙伴计划是阿里云原生生态体系的重要载体

    “开放、被集成、共赢”是阿里云的一贯追求,今年阿里云智能总裁行癫升级了阿里云公司战略“做深基础、做厚中台、做强生态”,生态建设成为阿里云战略的重之之重。在6月份阿里云生态大会上,阿里云智能基础产品事业部高级研究员蒋江伟宣布阿里云启动“云原生合作伙伴计划“,重点扶持100个头部伙伴,赋能10000家合作伙伴,50万开发者,帮助伙伴云原生技术升级,助力企业数字化转型。

    信息产业竞争的核心是技术生态体系,从以Wintel体系的PC时代到Android/iOS的移动互联网,再到云原生体系云计算时代,对于企业和伙伴来讲,抓住技术发展趋势,提前布局是企业长盛不衰的根本。

    “阿里云原生合作伙伴计划”是阿里云原生生态体系的重要载体,生态竞争的核心。“阿里云原生合作伙伴计划”具有合作模式多样化、合作对象强强化、合作范围立体化的特点,采用“集成/被集成”的方法,从而帮助阿里云生态伙伴优化资源配置,降低交易费用,实现规模化经济。
    3.png
    “阿里云原生合作伙伴计划”主要是从市场合作、产研合作、产业链合作、技术标准4个维度,采用多维度、松耦合、立体式的合作模式,助力阿里云原生伙伴销售能力、产品/解决方案能力、服务能力的全方位能力成长。

    (1)市场合作

    阿里云原生合作伙伴计划,在传统电销、分销(代理、reseller、总代、虚商)的基础上,发展解决方案伙伴,以产品和解决方案集成的方式进行产品销售。同时在商机、品牌等市场合作之上,帮助伙伴从原来线上线下拜客模式,走向产品和解决方案推广模式,在以云原生体系为核心的云计算生态中,助力伙伴实现向高附加值的产品型公司进行转型,帮助伙伴成长与成功。

    (2)产研合作

    阿里云原生合作伙伴计划,以集成/被集成为手段,实现产品双向互动,帮助伙伴与阿里云各自产品线布局。在以云原生体系为核心的云计算生态体系中,采用OEM、OBM、ODM等方式共创、共建新产品,实现三方伙伴产品一方化,通过阿里云直销、云市场、生态等多渠道,帮助伙伴产品推广,实现更大的规模经济效益。

    (3)产业链合作

    阿里云原生合作伙伴计划,以云原生产品售前、售中、售后的全链路,以产品研发、测试、交付的全周期,全面和伙伴进行服务合作,通过培训赋能,实现服务伙伴云原生能力认定,通过能力中心、交付伙伴、外包(委外)等方式进行产品、服务的合作。

    (4)技术标准

    技术是第一生产力,以云原生体系为核心的云计算生态体系,技术发展与成熟是根本。当前云原生技术发展趋势是,以容器、Kubernetes为核心的云原生技术逐渐稳定与成熟,后期将发展为以服务治理、云边端一体化、Serverless等上层技术栈为创新发展的核心。阿里云原生合作伙伴计划,愿和业界同行一起在国际、国家、行业技术标准,以及一些自组织产业联盟共建、共同定义一些技术标准,共同发展云原生生态体系。一个典型的案例就是在2019年,阿里云和微软共同发布全球首个云原生应用标准定义与架构模型OAM,它是一个专注于描述应用的标准规范。有了这个规范,应用描述就可以彻底与基础设施部署和管理应用的细节分开。

    回顾信息产业的历次变革,每次都伴随着新技术的发展,进而推动整个生态体系的再平衡而形成的。从2013年Docker开源、容器技术快速发展开始,2014年Kubernetes开源项目大幅度提高了调度和资源管理能力。无数实践已经证明,云原生成为了云计算的新一代操作系统,以云原生体系为核心的新的信息产业生态已经形成。

    阿里云原生助力企业数字化转型

    随着对云原生技术的探索、实践和积累,阿里云原生形成了业界“四个最”:阿里云拥有国内最丰富的云原生产品家族,最全面的云原生开源贡献,最大规模的云原生应用实践,最大的容器集群和客户群体,致力于帮助客户最大化利用云的价值。

    2019年、2020年阿里云容器服务两次成为国内唯一入选Gartner公共云容器报告,“与去年相比,阿里云在产品丰富度上更进一步,与AWS并列成为全球容器产品最完善的云服务厂商。”2019年全球知名市场调研机构 Forrester 发布首个企业级公共云容器平台报告。报告显示:阿里云容器服务创造了中国企业最好成绩,与谷歌云位于同一水平线,进入强劲表现者象限。“阿里云容器服务提供了广泛的开发和应用服务支持能力,并且具备丰富的市场生态和合作伙伴体系,是企业在中国寻求最完备云服务能力的首要选择。”

    据IDC报告,全球前1000的大企业中,67%的企业已将数字化转型变成企业级战略,企业数字化转型也正成为许多中国企业的核心战略。随着企业上云成为业界趋势,全面使用开源技术和云产品构建软件服务的时代已经到来。如何更好地拥抱云计算、拥抱云原生、用技术加速创新,将成为企业数字化转型升级成功的关键。
    云时代下,企业需要新技术架构,使之更好地利用云计算优势,让业务更敏捷、成本更低、可伸缩性更强。而云原生架构的应用意义正在于此。数据显示,2020 年,超过 50% 的全球组织在生产环境中运行容器化应用程序,到 2022 年将超过 75% 。云原生正逐步成为企业数字化转型的“最短路径”。

    阿里云根据自身积累多年的云原生技术、产品和上云实践,提出完整云原生架构的设计原则、解决方案以及最佳实践,帮助企业找到数字化转型“最短路径”,完成从“压迫感”到“掌控感”的主被动力量转变,加速实现 IT 能力提升,打好降本增效组合拳。

    阿里云坚信以云原生为核心的新一代操作系统,会成为云计算时代新界面,会重塑软件行业的全生命周期,推动信息产业的转型升级。阿里云原生生态体系是云计算、大数据、物联网、人工智能的信息产业竞争的核心。“万物生长,合作共赢”是阿里云原生生态的愿景,帮助伙伴成长是阿里云原生生态的使命,阿里云愿意和广大伙伴一起,在新的信息产业生态中,互利共赢,共同成长!

    ]]>
    Spring Cloud 应用在 Kubernetes 上的最佳实践 — 高可用(混沌工程) Thu, 29 Oct 2020 12:16:15 +0800 前言

    从上篇开始,我们进入到了高可用的章节,上篇提到的熔断能力,是历年保障大促当天晚上整个系统不被洪峰流量打垮的法宝,本篇介绍的措施与熔断有不一样的地方,一个是线上洪峰来临时的保护措施,他更多的是流量低峰或者在专门的演练环境中,针对可能遇见的各类故障,采取演练的手段,来窥探对业务的影响。他的主要目的是让我们自己更加了解自己业务系统的薄弱环节,以便来对症下药增强系统的高可用能力。本文重点介绍为什么要做混沌工程以及如何使用 ChaosBlade 工具和 AHAS 平台快速实施混沌工程。

    为什么需要混沌工程

    任何一个系统都会有未曾可知的故障出现,拿现代工艺已经很好的磁盘来说,有统计数据的磁盘最低的年故障率都可达到 0.39% 。即便是这么底层基础设施,也会有这么高的不确定性。尤其当下大部分的服务形态都是分布式架构,在分布式系统架构下,服务间的依赖日益复杂,更很难评估单个服务故障对整个系统的影响;并且请求链路长,监控告警的不完善导致发现问题、定位问题难度增大;同时业务和技术迭代快,如何持续保障系统的稳定性和高可用性受到很大的挑战。

    云原生系统挑战更大

    谈到云原生,可以说云原生是一个理念,主要包含的技术有云设施、容器、微服务、服务网格、Serverless等技术。云设施指公有云、专有云和混合云等,是云原生系统的基础设施,基础实施的故障可能对整个上层业务系统造成很大影响,所以说云设施的稳定性是非常重要的。
    容器服务的挑战可以分两大类,一类是面向 k8s 服务提供商,服务是否稳定,另一类是面向用户,配置的扩缩容规则是否有效,实现的 CRD 是否正确,容器编排是否合理等问题。
    分布式服务的挑战主要是复杂性,单个服务的故障很难判断对整个系统的影响;service mesh,sidecar 的服务路由、负载均衡等功能的有效性,还有 sidecar 容器本身的可用性。
    一些新兴的部署模式的挑战 如 serverless,现在基本上都是函数加事件的形式,资源调度是否有效,而且 serverless 服务提供商屏蔽了一些中间件,你能掌控的是函数这些服务,那么你可以通过混沌工程去验证你函数调用的一些配置,比如超时配置,还有相关的一些降级策略,这些是否合理。
    以上技术都有相同的共性,比如弹性可扩展、松耦合、容错性高、还有一些易于管理,便于观察这些特性。所以说在云原生时代,通过混沌工程可以更有效的推进系统的“云原生”化。

    每个职位都需要懂混沌工程

    混沌工程是一种思想,他让系统中的每个参与者都学会去考虑一件事情:如果所依赖的某服务中断了服务该怎么办?对于以下四类人群而言,意义尤显突出:

    • 对于架构师来说,可以验证系统架构的容错能力,我们需要面向失败设计的系统,混沌工程的思想就是践行这一原则的方式。
    • 对于开发和运维,可以提高故障的应急效率,实现故障告警、定位、恢复的有效和高效性。
    • 对于测试来说,可以弥补传统测试方法留下的空白,之前的测试方法基本上是从用户的角度去做,而混沌工程是从系统的角度进行测试,降低故障复发率。
    • 对于产品和设计,通过混沌事件查看产品的表现,提升客户使用体验。所以说混沌工程面向的不仅仅是开发、测试,拥有最好的客户体验是每个人的目标 所以实施混沌工程,可以提早发现生产环境上的问题,并且可以以战养战,提升故障应急效率和可以使用体验,逐渐建设高可用的韧性系统。



    混沌工程实操

    在一次完整的演练流程中,需要先做好计划,对相关的演练计划有一个行为预期;演练相关计划的同时,我们推荐的最佳实践是需要配合有业务的自动化测试,每演练一次需要全方位的跑完自动化测试用例,这样才能全面的了解真正的业务产生时对业务造成的影响:
    1.png

    在上面的图中描述了一次完整的故障演练需要经过的步骤,其中的最重要的一步的实践是如何“执行预制混沌实验”?因为这一步需要一个专业的工具,在业内目前最流行的工具是 Netflix 的 Chaos Monkey 和阿里巴巴开源的 ChaosBlade ,我们接下来主要是介绍如何使用 ChaosBlade 来完成一次演练。

    使用 ChaosBlade 去做

    ChaosBlade 是阿里巴巴一款遵循混沌实验模型的混沌实验执行工具,具有场景丰富度高,简单易用等特点,而且扩展场景也特别方便,开源不久就被加入到 CNCF Landspace 中,成为主流的一款混沌工具。目前包含的场景有基础资源、应用服务、容器服务、云资源等。ChaosBlade 下载解压即用,可以通过执行 blade 命令来执行云原生下微服务的演练场景,下面是模拟 Kubernetes 下微服务中数据库调用延迟故障。
    2.jpeg

    使用 AHAS 故障演练平台去做

    AHAS 故障演练平台是阿里云对外部用户开放的云产品,使用方式可参考官方文档。其底层的故障注入能力大部分来源于 ChaosBlade 实现,另一部分使用自身小程序扩展实现。AHAS 相比于 ChaosBlade,除了简单易用的白屏操作之外,还实现了上层的演练编排、权限控制、场景管理等,而且还针对微服务新增应用维度演练,简化演练成本,优化演练体验。

    3.png

    结尾

    混沌工程是一种主动防御的稳定性手段,体现的是反脆弱的思想,实施混沌工程不能只是把故障制造出来,需要有明确的驱动目标。我们要选择合适的工具和平台,控制演练风险,实现常态化演练。阿里巴巴内部从最早引入混沌工程解决微服务的依赖问题,到业务服务、云服务稳态验证,进一步升级到公共云、专有云的业务连续性保障,以及在验证云原生系统的稳定性等方面积累了比较丰富的场景和实践经验;这一些经验沉淀我们都通过开源产品以及云产品 AHAS 一一对外输出。

    ]]>
    【升级】9月1日阿里云华南1、华南2地域网络升级通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【网络】【升级通知】
    升级窗口:北京时间2020年9月1日 00:00-01:00
    升级内容:由于华南地区运营商相关服务存在一定风险,可能导致网络拥塞,为预防对云上客户产生影响,阿里云计划在9月1日凌晨对华南地域网络做预防性调整,将部分移动流量调整至华东出口。
    升级影响:升级过程中通过南方部分省份移动线路访问阿里云华南1(深圳)、华南2(河源)地域的云资源可能会出现1次不超过30s的间断性网络丢包,应用重连即可恢复正常。升级后,大部分省份延时不会有变化,南方部分省份(如四川、福建)移动用户访问阿里云华南1(深圳)、华南2(河源)地域的云资源延时会有部分增加。

    给您带来的不便敬请谅解,有任何问题,可点击联系我们进行咨询反馈。

    ]]>
    【升级】8月27日至9月2日Centralnic注册局维护通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【域名】【Centralnic注册局维护通知】

    维护时间:北京时间2020年8月27日 - 9月2日 

    维护内容:接到注册局的通知,注册局将于上述时间对后台系统进行不间断地维护升级。

    维护影响:届时.xyz/.art/.love/.icu/.site/.online/.website/.host/.store/.fun/.press/.space/.tech/.ink/.wiki/.design域名的注册、续费、信息修改和查询域名注册信息等操作,将会无法使用,在此期间会对您造成的影响如下:

    1、您提交的注册(购买)、续费、转入、赎回、一口价域名业务在支付费用后状态为“处理中”,待维护结束后将变为正常的“成功”状态;

    2、维护过程中您无法对域名注册信息进行修改,将提示修改失败。

    如果您需要注册或管理以上业务操作,建议您避开该时间段,以免给您的业务造成影响。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    【升级】8月30日.COM/.NET注册局系统维护公告 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【域名】【注册局维护通知】

    维护时间:北京时间2020年8月30日 09:00 - 09:45

    维护内容:接到注册局的通知,注册局将于上述时间对后台系统进行维护升级。

    维护影响:届时 .com/.net 域名的注册、续费、信息修改和查询域名注册信息等操作,将会无法使用,在此期间会对您造成的影响如下:

    1、您提交的注册(购买)、续费、转入、赎回、一口价域名业务在支付费用后状态为“处理中”,待维护结束后将变为正常的“成功”状态;

    2、维护过程中您无法对域名注册信息进行修改,将提示修改失败。

    如果您需要注册或管理以上业务操作,建议您避开该时间段,以免给您的业务造成影响。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    【升级】9月1日消息队列AMQP升级通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【消息队列AMQP】【升级通知】

    升级窗口:北京时间2020年9月1日15:00 - 18:00

    升级内容:华北5(呼和浩特)、华北2(北京)、华东1(杭州)、华东2(上海)、华南1(深圳)、香港、青岛等地域的服务升级。

    升级影响:升级期间消息队列AMQP相关服务访问可能会出现多次闪断或者拒绝连接现象,每次闪断或拒绝连接不会超过 5 分钟,请在客户端中做好重连重试机制。如需在控制台进行管理操作,请避开维护时间段。

    给您带来的不便敬请谅解,有任何问题,可点击联系我们进行咨询反馈。

    ]]>
    【升级】9月消息队列MQ升级计划通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【消息队列MQ】【升级通知】

    升级窗口:

    北京时间2020年8月31日 22:00 - 2020年9月1日 04:00

    北京时间2020年9月3日 22:00 - 2020年9月4日 04:00

    北京时间2020年9月7日 22:00 - 2020年9月8日 04:00

    北京时间2020年9月9日 22:00 - 2020年9月10日 04:00

    北京时间2020年9月14日 22:00 - 2020年9月15日 04:00

    北京时间2020年9月16日 22:00 - 2020年9月17日 04:00

    北京时间2020年9月21日 22:00 - 2020年9月22日 04:00

    北京时间2020年9月23日 22:00 - 2020年9月24日 04:00

    北京时间2020年9月25日 22:00 - 2020年9月29日 04:00

    升级内容:所有地域的MQ服务(包含TCP、MQTT、HTTP接入方式)。

    升级影响:升级期间MQ控制台和集群中每个服务节点可能出现秒级闪断(闪断时间和集群规模正相关),客户端会自动重试机制,一般不会影响业务,但会有异常日志。

    升级期间,消息可能会有重复,应用应该按最值实践,做好消息的幂等;同时可能会有消息延迟的现象。如需在控制台进行管理操作,请避开维护时间段。HTTP接入可能会出现闪断或者拒绝连接现象,每次闪断或拒绝连接不会超过1分钟,请在客户端中做好重连重试机制。同时,您可使用监控管理功能对重要业务进行监控,具体设置方法请点击MQ控制台左侧监控报警菜单。

    给您带来的不便敬请谅解,有任何问题,可点击联系我们进行咨询反馈。

    ]]>
    【升级】9月3日消息队列AMQP华东1(杭州)地域升级通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【消息队列AMQP】【升级通知】

    升级窗口:北京时间2020年9月3日15:00 - 18:00
    升级内容:华东1(杭州)地域的服务升级。
    升级影响:升级期间消息队列AMQP相关服务访问可能会出现多次闪断或者拒绝连接现象,每次闪断或拒绝连接不会超过 5 分钟,请在客户端中做好重连重试机制。如需在控制台进行管理操作,请避开维护时间段。

    给您带来的不便敬请谅解,有任何问题,可点击联系我们进行咨询反馈。

    ]]>
    滴滴基于 Flink 的实时数仓建设实践-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 随着滴滴业务的高速发展,业务对于数据时效性的需求越来越高,而伴随着实时技术的不断发展和成熟,滴滴也对实时建设做了大量的尝试和实践。本文主要以顺风车这个业务为引子,从引擎侧、平台侧和业务侧各个不同方面,来阐述滴滴所做的工作,分享在建设过程中的经验。

    1.实时数仓建设目的

    随着互联网的发展进入下半场,数据的时效性对企业的精细化运营越来越重要,商场如战场,在每天产生的海量数据中,如何能实时有效的挖掘出有价值的信息, 对企业的决策运营策略调整有很大帮助。

    其次从智能商业的角度来讲,数据的结果代表了用户的反馈,获取结果的及时性就显得尤为重要,快速的获取数据反馈能够帮助公司更快的做出决策,更好的进行产品迭代,实时数仓在这一过程中起到了不可替代的作用。

    1.1 解决传统数仓的问题

    从目前数仓建设的现状来看,实时数仓是一个容易让人产生混淆的概念,根据传统经验分析,数仓有一个重要的功能,即能够记录历史。通常,数仓都是希望从业务上线的第一天开始有数据,然后一直记录到现在。但实时流处理技术,又是强调当前处理状态的一个技术,结合当前一线大厂的建设经验和滴滴在该领域的建设现状,我们尝试把公司内实时数仓建设的目的定位为,以数仓建设理论和实时技术,解决由于当前离线数仓数据时效性低解决不了的问题。

    现阶段我们要建设实时数仓的主要原因是:

    • 公司业务对于数据的实时性越来越迫切,需要有实时数据来辅助完成决策
    • 实时数据建设没有规范,数据可用性较差,无法形成数仓体系,资源大量浪费
    • 数据平台工具对整体实时开发的支持也日渐趋于成熟,开发成本降低

    1.2 实时数仓的应用场景

    • 实时 OLAP 分析:OLAP 分析本身就是数仓领域重点解决的问题,基于公司大数据架构团队提供的基于 Flink 计算引擎的 stream sql 工具,Kafka 和 ddmq (滴滴自研)等消息中间件,druid 和 ClickHouse 等 OLAP 数据库,提升数仓的时效性能力,使其具有较优的实时数据分析能力。
    • 实时数据看板:这类场景是目前公司实时侧主要需求场景,例如“全民拼车日”订单和券花销实时大屏曲线展示,顺风车新开城当日分钟级订单侧核心指标数据展示,增长类项目资源投入和收益实时效果展示等。
    • 实时业务监控:滴滴出行大量核心业务指标需要具备实时监控能力,比如安全指标监控,财务指标监控,投诉进线指标监控等。
    • 实时数据接口服务:由于各业务线之间存在很多业务壁垒,导致数仓开发很难熟悉公司内全部业务线,需要与各业务线相关部门在数据加工和数据获取方面进行协作,数仓通过提供实时数据接口服务的方式,向业务方提供数据支持。

    640 1.png

    2. 滴滴顺风车实时数仓建设举例

    在公司内部,我们数据团队有幸与顺风车业务线深入合作,在满足业务方实时数据需求的同时,不断完善实时数仓内容,通过多次迭代,基本满足了顺风车业务方在实时侧的各类业务需求,初步建立起顺风车实时数仓,完成了整体数据分层,包含明细数据和汇总数据,统一了 DWD 层,降低了大数据资源消耗,提高了数据复用性,可对外输出丰富的数据服务。

    数仓具体架构如下图所示:

    640 2.png

    从数据架构图来看,顺风车实时数仓和对应的离线数仓有很多类似的地方。例如分层结构;比如 ODS 层,明细层,汇总层,乃至应用层,他们命名的模式可能都是一样的。但仔细比较不难发现,两者有很多区别:

    • 与离线数仓相比,实时数仓的层次更少一些
    • 从目前建设离线数仓的经验来看,数仓的数据明细层内容会非常丰富,处理明细数据外一般还会包含轻度汇总层的概念,另外离线数仓中应用层数据在数仓内部,但实时数仓中,app 应用层数据已经落入应用系统的存储介质中,可以把该层与数仓的表分离。
    • 应用层少建设的好处:实时处理数据的时候,每建一个层次,数据必然会产生一定的延迟。
    • 汇总层少建的好处:在汇总统计的时候,往往为了容忍一部分数据的延迟,可能会人为的制造一些延迟来保证数据的准确。举例,在统计跨天相关的订单事件中的数据时,可能会等到 00:00:05 或者 00:00:10 再统计,确保 00:00 前的数据已经全部接受到位了,再进行统计。所以,汇总层的层次太多的话,就会更大的加重人为造成的数据延迟。
    • 与离线数仓相比,实时数仓的数据源存储不同
    • 在建设离线数仓的时候,目前滴滴内部整个离线数仓都是建立在 Hive 表之上。但是,在建设实时数仓的时候,同一份表,会使用不同的方式进行存储。比如常见的情况下,明细数据或者汇总数据都会存在 Kafka 里面,但是像城市、渠道等维度信息需要借助 Hbase,MySQL 或者其他 KV 存储等数据库来进行存储。

    接下来,根据顺风车实时数仓架构图,对每一层建设做具体展开:

    2.1 ODS 贴源层建设

    根据顺风车具体场景,目前顺风车数据源主要包括订单相关的 binlog 日志,冒泡和安全相关的 public 日志,流量相关的埋点日志等。这些数据部分已采集写入 Kafka 或 ddmq 等数据通道中,部分数据需要借助内部自研同步工具完成采集,最终基于顺风车数仓ods层建设规范分主题统一写入 Kafka 存储介质中。

    命名规范:ODS 层实时数据源主要包括两种。

    • 一种是在离线采集时已经自动生产的 DDMQ 或者是 Kafka topic,这类型的数据命名方式为采集系统自动生成规范为:cn-binlog-数据库名-数据库名 eg:cn-binlog-ihap_fangyuan-ihap_fangyuan
    • 一种是需要自己进行采集同步到 kafka topic 中,生产的topic命名规范同离线类似:ODS 层采用:realtime_ods_binlog_{源系统库/表名}/ods_log_{日志名} eg: realtime_ods_binlog_ihap_fangyuan

    2.2 DWD 明细层建设

    根据顺风车业务过程作为建模驱动,基于每个具体的业务过程特点,构建最细粒度的明细层事实表;结合顺风车分析师在离线侧的数据使用特点,将明细事实表的某些重要维度属性字段做适当冗余,完成宽表化处理,之后基于当前顺风车业务方对实时数据的需求重点,重点建设交易、财务、体验、安全、流量等几大模块;该层的数据来源于 ODS 层,通过大数据架构提供的 Stream SQL 完成 ETL 工作,对于 binlog 日志的处理主要进行简单的数据清洗、处理数据漂移和数据乱序,以及可能对多个 ODS 表进行 Stream Join,对于流量日志主要是做通用的 ETL 处理和针对顺风车场景的数据过滤,完成非结构化数据的结构化处理和数据的分流;该层的数据除了存储在消息队列 Kafka 中,通常也会把数据实时写入 Druid 数据库中,供查询明细数据和作为简单汇总数据的加工数据源。

    命名规范:DWD 层的表命名使用英文小写字母,单词之间用下划线分开,总长度不能超过 40 个字符,并且应遵循下述规则:realtime_dwd_{业务/pub}_{数据域缩写}_[{业务过程缩写}]_[{自定义表命名标签缩写}]

    • {业务/pub}:参考业务命名
    • {数据域缩写}:参考数据域划分部分
    • {自定义表命名标签缩写}:实体名称可以根据数据仓库转换整合后做一定的业务抽象的名称,该名称应该准确表述实体所代表的业务含义
      样例:realtime_dwd_trip_trd_order_base

    2.3 DIM 层

    • 公共维度层,基于维度建模理念思想,建立整个业务过程的一致性维度,降低数据计算口径和算法不统一风险;
    • DIM 层数据来源于两部分:一部分是 Flink 程序实时处理ODS层数据得到,另外一部分是通过离线任务出仓得到;
    • DIM 层维度数据主要使用 MySQL、Hbase、fusion(滴滴自研KV存储) 三种存储引擎,对于维表数据比较少的情况可以使用 MySQL,对于单条数据大小比较小,查询 QPS 比较高的情况,可以使用 fusion 存储,降低机器内存资源占用,对于数据量比较大,对维表数据变化不是特别敏感的场景,可以使用HBase 存储。

    命名规范:DIM 层的表命名使用英文小写字母,单词之间用下划线分开,总长度不能超过 30 个字符,并且应遵循下述规则:dim_{业务/pub}_{维度定义}[_{自定义命名标签}]:

    • {业务/pub}:参考业务命名
    • {维度定义}:参考维度命名
    • {自定义表命名标签缩写}:实体名称可以根据数据仓库转换整合后做一定的业务抽象的名称,该名称应该准确表述实体所代表的业务含义
      样例:dim_trip_dri_base

    2.4 DWM 汇总层建设

    在建设顺风车实时数仓的汇总层的时候,跟顺风车离线数仓有很多一样的地方,但其具体技术实现会存在很大不同。

    第一:对于一些共性指标的加工,比如 pv,uv,订单业务过程指标等,我们会在汇总层进行统一的运算,确保关于指标的口径是统一在一个固定的模型中完成。对于一些个性指标,从指标复用性的角度出发,确定唯一的时间字段,同时该字段尽可能与其他指标在时间维度上完成拉齐,例如行中异常订单数需要与交易域指标在事件时间上做到拉齐。

    第二:在顺风车汇总层建设中,需要进行多维的主题汇总,因为实时数仓本身是面向主题的,可能每个主题会关心的维度都不一样,所以需要在不同的主题下,按照这个主题关心的维度对数据进行汇总,最后来算业务方需要的汇总指标。在具体操作中,对于 pv 类指标使用 Stream SQL 实现 1 分钟汇总指标作为最小汇总单位指标,在此基础上进行时间维度上的指标累加;对于 uv 类指标直接使用 druid 数据库作为指标汇总容器,根据业务方对汇总指标的及时性和准确性的要求,实现相应的精确去重和非精确去重。

    第三:汇总层建设过程中,还会涉及到衍生维度的加工。在顺风车券相关的汇总指标加工中我们使用 Hbase 的版本机制来构建一个衍生维度的拉链表,通过事件流和 Hbase 维表关联的方式得到实时数据当时的准确维度

    命名规范:DWM 层的表命名使用英文小写字母,单词之间用下划线分开,总长度不能超过 40 个字符,并且应遵循下述规则:realtime_dwm_{业务/pub}_{数据域缩写}_{数据主粒度缩写}_[{自定义表命名标签缩写}]_{统计时间周期范围缩写}:

    • {业务/pub}:参考业务命名
    • {数据域缩写}:参考数据域划分部分
    • {数据主粒度缩写}:指数据主要粒度或数据域的缩写,也是联合主键中的主要维度
    • {自定义表命名标签缩写}:实体名称可以根据数据仓库转换整合后做一定的业务抽象的名称,该名称应该准确表述实体所代表的业务含义
    • {统计时间周期范围缩写}:1d:天增量;td:天累计(全量);1h:小时增量;th:小时累计(全量);1min:分钟增量;tmin:分钟累计(全量)
      样例:realtime_dwm_trip_trd_pas_bus_accum_1min

    2.5 APP 应用层

    该层主要的工作是把实时汇总数据写入应用系统的数据库中,包括用于大屏显示和实时 OLAP 的 Druid 数据库(该数据库除了写入应用数据,也可以写入明细数据完成汇总指标的计算)中,用于实时数据接口服务的 Hbase 数据库,用于实时数据产品的 MySQL 或者 Redis 数据库中。

    命名规范:基于实时数仓的特殊性不做硬性要求。

    3. 顺风车实时数仓建设成果

    截止目前,一共为顺风车业务线建立了增长、交易、体验、安全、财务五大模块,涉及 40+ 的实时看板,涵盖顺风车全部核心业务过程,实时和离线数据误差<0.5%,是顺风车业务线数据分析方面的有利补充,为顺风车当天发券动态策略调整,司乘安全相关监控,实时订单趋势分析等提供了实时数据支持,提高了决策的时效性。

    同时建立在数仓模型之上的实时指标能根据用户需求及时完成口径变更和实时离线数据一致性校验,大大提高了实时指标的开发效率和实时数据的准确性,也为公司内部大范围建设实时数仓提供了有力的理论和实践支持。

    4. 实时数仓建设对数据平台的强依赖

    目前公司内部的实时数仓建设,需要依托数据平台的能力才能真正完成落地,包括 StreamSQL 能力,数据梦工程 StreamSQL IDE 环境和任务运维组件,实时数据源元数据化功能等。

    640 3.png

    4.1 基于StreamSQL的实时数据需求开发

    StreamSQL 是滴滴大数据引擎部在 Flink SQL 基础上完善后形成的一个产品。

    使用 StreamSQL 具有多个优势:

    • 描述性语言:业务方不需要关心底层实现,只需要将业务逻辑描述出来即可。
    • 接口稳定:Flink 版本迭代过程中只要 SQL 语法不发生变化就非常稳定。
    • 问题易排查:逻辑性较强,用户能看懂语法即可调查出错位置。
    • 批流一体化:批处理主要是 HiveSQL 和 Spark SQL,如果 Flink 任务也使用 SQL 的话,批处理任务和流处理任务在语法等方面可以进行共享,最终实现一体化的效果。

    StreamSQL 相对于 Flink SQL (1.9 之前版本)的完善:

    • 完善 DDL:包括上游的消息队列、下游的消息队列和各种存储如 Druid、HBase 都进行了打通,用户方只需要构建一个 source 就可以将上游或者下游描述出来。
    • 内置消息格式解析:消费数据后需要将数据进行提取,但数据格式往往非常复杂,如数据库日志 binlog,每个用户单独实现,难度较大。StreamSQL 将提取库名、表名、提取列等函数内置,用户只需创建 binlog 类型 source,并内置了去重能力。对于 business log 业务日志 StreamSQL 内置了提取日志头,提取业务字段并组装成 Map 的功能。对于 json 数据,用户无需自定义 UDF,只需通过 jsonPath 指定所需字段。
    • 扩展UDX:丰富内置 UDX,如对 JSON、MAP 进行了扩展,这些在滴滴业务使用场景中较多。支持自定义 UDX,用户自定义 UDF 并使用 jar 包即可。兼容 Hive UDX,例如用户原来是一个 Hive SQL 任务,则转换成实时任务不需要较多改动,有助于批流一体化。

    Join 能力扩展:

    • 基于 TTL 的双流 join:在滴滴的流计算业务中有的 join 操作数据对应的跨度比较长,例如顺风车业务发单到接单的时间跨度可能达到一个星期左右,如果这些数据的 join 基于内存操作并不可行,通常将 join 数据放在状态中,窗口通过 TTL 实现,过期自动清理。
    • 维表 join 能力:维表支持 HBase、KVStore、Mysql 等,同时支持 inner、left、right、full join 等多种方式。

    4.2 基于数据梦工厂的 StreamSQL IDE 和任务运维

    StreamSQL IDE:

    • 提供常用的SQL模板:在开发流式 SQL 时不需要从零开始,只需要选择一个 SQL 模板,并在这个模板之上进行修修改改即可达到期望的结果
    • 提供 UDF 的库:相当于一个库如果不知道具有什么含义以及如何使用,用户只需要在 IDE 上搜索到这个库,就能够找到使用说明以及使用案例,提供语法检测与智能提示
    • 提供代码在线DEBUG能力:可以上传本地测试数据或者采样少量 Kafka 等 source 数据 debug,此功能对流计算任务非常重要。提供版本管理功能,可以在业务版本不断升级过程中,提供任务回退功能。

    任务运维:任务运维主要分为四个方面

    • 日志检索:Flink UI 上查询日志体验非常糟糕,滴滴将 Flink 任务日志进行了采集,存储在 ES 中,通过 WEB 化的界面进行检索,方便调查。
    • 指标监控:Flink 指标较多,通过 Flink UI 查看体验糟糕,因此滴滴构建了一个外部的报表平台,可以对指标进行监控。
    • 报警:报警需要做一个平衡,如重启报警有多类如 ( 机器宕机报警、代码错误报警 ),通过设置一天内单个任务报警次数阈值进行平衡,同时也包括存活报警 ( 如 kill、start )、延迟报警、重启报警和 Checkpoint 频繁失败报警 ( 如 checkpoint 周期配置不合理 ) 等。
    • 血缘追踪:实时计算任务链路较长,从采集到消息通道,流计算,再到下游的存储经常包括 4-5个环节,如果无法实现追踪,容易产生灾难性的问题。例如发现某流式任务流量暴涨后,需要先查看其消费的 topic 是否增加,topic 上游采集是否增加,采集的数据库 DB 是否产生不恰当地批量操作或者某个业务在不断增加日志。这类问题需要从下游到上游、从上游到下游多方向的血缘追踪,方便调查原因。

    4.3 基于数据梦工厂的实时数据源元数据化(meta化表)

    将 topic 引入成实时表,metastore 统一管理元数据,实时开发中统一管理 DDL 过程。对实时数仓来说,通过元数据化,可以沉淀实时数仓的建设成果,使数仓建模能更好的落地。

    640 4.png

    目前数据梦工厂支持的元数据化实时数据源包括 Postgre、DDMQ、MySQL、Druid、ClickHouse、Kylin、Kafka。

    5. 面临的挑战和解决方案思考

    虽然目前滴滴在实时数仓建设方面已初具规模,但其面临的问题也不容忽视。

    5.1 实时数仓研发规范

    问题:为了快速响应业务需求,同时满足数仓的需求开发流程,迫切需要建设一套面向实时数据开发的规范白皮书,该白皮书需要涉及需求对接、口径梳理、数据开发、任务发布、任务监控、任务保障。

    目前解决方案:目前由数据 BP 牵头,制定了一套面向实时数据指标的开发规范:

    640 5.png

    常规流程:需求方提出需求,分析师对接需求,提供计算口径,编写需求文档。之后由数仓 BP 和离线数仓同学 check 计算口径,并向实时数仓团队提供离线 Hive 表,实时数仓同学基于离线 Hive 表完成数据探查,基于实时数仓模型完成实时数据需求开发,通过离线口径完成数据自查,最终交付给分析师完成二次校验后指标上线。

    口径变更--业务方发起:业务方发起口径变更,判断是否涉及到实时指标,数仓 BP 对离线和实时口径进行拉齐,向离线数仓团队和实时数仓团队提供更口口径和数据源表,实时数仓团队先上测试看板,验收通过后切换到正式看板

    存在的不足:

    • 当针对某个业务进行新的实时数据建设时,会有一个比较艰难的初始化过程,这个初始化过程中,会和离线有较多耦合,需要确定指标口径,数据源,并进行大量开发测试工作
    • 在指标口径发生变更的时候,需要有一个较好的通知机制,目前还是从人的角度来进行判断。

    5.2 离线和实时数据一致性保证

    目前解决办法:由业务、BP、离线数仓共同保证数据源、计算口径与离线一致,数据加工过程,逐层与离线进行数据比对,并对指标结果进行详细测试,数据校验通过并上线后,根据离线周期进行实时和离线数据的校验。

    640 6.png

    待解决的问题:结合指标管理工具,保证指标口径上的一致性,扩展数据梦工厂功能,在指标加工过程中,增加实时离线比对功能,降低数据比对成本。

    6. 未来展望:批流一体化

    虽然 Flink 具备批流一体化能力,但滴滴目前并没有完全批流一体化,希望先从产品层面实现批流一体化。通过 Meta 化建设,实现整个滴滴只有一个 MetaStore,无论是 Hive、Kafka topic、还是下游的 HBase、ES 都定义到 MetaStore 中,所有的计算引擎包括 Hive、Spark、Presto、Flink 都查询同一个 MetaStore,实现整个 SQL 开发完全一致的效果。根据 SQL 消费的 Source 是表还是流,来区分批处理任务和流处理任务,从产品层面上实现批流一体化效果。

    640 7.png

    更多 Flink 技术交流,可以钉钉扫码加入 Flink 的社区大群~

    最新钉群二维码.jpeg

    ]]>
    蚂蚁架构师郭援非:分布式数据库是金融机构数字化转型的最佳路径-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 ​2020年8月26-28日,在中科软科技举办的中国财险科技应用高峰论坛上,蚂蚁集团高级解决方案架构师郭援非发表了《OceanBase分布式关系数据库助力保险业务创新》的主题演讲,为大家分享了蚂蚁集团企业级分布式关系数据库OceanBase的发展历程、产品价值,以及在保险行业的最佳实践应用。

    以下为演讲整理:

    26CA4DDD-F2FF-48d4-805B-95795AA4E1EE.png

    各位朋友,下午好!

    支付宝在全球有十几亿用户,他们可以同时进行可靠、稳定、高效的支付交易,这背后离不开一个重要的秘密武器——OceanBase。今天我很荣幸向大家介绍OceanBase的发展过程、产品特点,以及在保险行业的最佳实践。

    分布式数据库OceanBase的迭代

    OceanBase数据库立项于2010年,第一个客户是淘宝收藏夹。2013年,OceanBase开始了对SQL的支持。2014年,OceanBase开始支持网商银行的所有业务,成为了全球首个应用在金融核心业务系统的分布式关系数据库。从2014年到2016年,支付宝全部的交易系统和核心账务系统都跑在OceanBase之上。多年来全世界十几亿用户在支付宝上发生的所有交易都是由OceanBase来承载,始终稳若磐石。

    1.png

    2017年,我们开始向更多的外部客户输出我们的技术,我们帮助南京银行打造了“鑫云+”互联网金融业务核心。OceanBase服务过的这些场景里既包括新兴的互联网金融核心业务、传统的金融核心业务,也包括对传统数据库的替换、对MySQL的替换,都非常成功。

    2019年, OceanBase参加了世界数据库范围内最权威的TPC-C认证测试,我们取得了6088万tpmC的成绩,是第二名传统数据库公司甲骨文的两倍。TPC-C绝对不是一个简单的跑分测试,实际上,它是要求被测试的对象必须满足数据库的ACID四个事务特征才能够进行的测试。

    2020年,我们又一次参加了TPC-C测试, 达到了7.07亿tpmC,跑出了接近去年12倍的成绩,再次问鼎TPC-C榜首。今年6月份OceanBase正式独立成公司,我们立志于成为世界领先的企业级数据技术解决方案提供商。

    数据库形态演进

    金融业的核心业务系统,包括保险行业的核心业务系统仍旧大规模使用传统集中式数据库。这种方案带来了两个问题,一是集中式数据库造价非常高,来自于两方面,一方面是软件License很贵;另一方面是硬件很贵,因为它必须使用高端硬件,比如IBM的大机、EMC的高端存储,这些都是非常昂贵的,时间长了再大的企业也很难承受;二是扩展性非常不好,传统集中式数据库都是基于共享存储(shared-storage)的方式做横向扩展,当面临关键业务系统发展需要不断扩容的时候,这种方案有心无力,难以做有效的支撑。

    4.png

    对于上面这种方案业界提了一种补丁方案,十几年前曾有人提出既然传统集中式数据库很贵,那么在单机开源的基础上加一个语法兼容,这样就解决了它昂贵的问题。但是发展到今天,我们在金融领域的核心系统还没有看到广泛使用这种方案。原因很简单,金融业核心系统使用传统集中式数据库主要不是因为它们在语法上的完善和优秀,根本原因在于它们的稳定可靠,而这个补丁方案做不到这些,同时这个方案也没有解决扩展性的问题。

    说到扩展性同样是在十几年以前,最早在互联网企业中提出了这么一种方案,叫做分库分表,一个典型的例子就是在多台单机的MySQL上,用Proxy把MySQL单机集成为MySQL集群,提供很好的算力。这种方案同样具有很大的问题,当计算发生在单个MySQL机器内部的时候一切很好,但是一旦用户的负载跨越MySQL单机边界的时候,你可能会发现分库分表系统的表现并不尽如人意。具体来说,在全局事务、数据强一致性、负载均衡以及复杂SQL方面都不能很好的支持,所以这种方案的使用场景非常受限。截止到今天,在银行、保险、券商行业的核心业务系统中依然没有广泛使用过这种方案。

    那么到底是否存在这样一种数据库系统,它既可以提供传统集中式数据库的高可靠性,又成本可控,同时扩展性良好?在这个基础之上还能够满足事务的ACID、具备强一致性、复杂SQL的处理能力?答案是有,而且可以更好,那就是OceanBase。

    OceanBase的三大独特价值

    首先,OceanBase是一款完全自主研发的分布式关系数据库,代码是百分之百自研的,包括SQL引擎、存储引擎都是我们的工程师自己一行一行代码写出来的。这一点很重要,它意味着当你的数据库出现问题的时候,我们的工程师不需要求助开源社区,我们自己就可以兜底,这对于要求稳定,要求可靠,要求有可预期性的金融领域的核心业务系统是一个刚需,这一点OceanBase可以充分提供。

    2.png

    第二, OceanBase是全世界唯一一款经过长时间复杂金融场景验证的原生分布式数据库。数据库其实是一个非常复杂的系统,它的复杂度甚至不亚于操作系统,对它的各种复杂应用场景的测试不是一个简单的测试程序可以穷尽的。目前,可能唯一有效的方法就是在实践中找到足够复杂、足够多的场景对数据库进行反复的使用,使用到最后没有问题为止大家才会信任它。我们非常高兴的告诉大家,OceanBase做到了。

    第三,OceanBase数据库是全世界范围内唯一一款基于普通的X86云服务器,在TPC-C领域获得第一名的原生分布式数据库。登顶TPC-C榜单意味着OceanBase不但可以提供世界级的性能,而且可以提供单机数据库一样的完整体验,这一点意味着用户可以像使用单机数据库一样使用OceanBase。

    OceanBase核心特性

    在OceanBase数据库中,我们通过“五高一多”的特点定义了分布式数据库的领先标准。

    3.png

    高可用

    我们通过Paxos协议和多副本技术,可以提供很好的高可用性,当出现灾难的时候我们可以做到RPO=0,RTO<30秒,这完全可以满足企业的容灾需求。同时由于我们使用的是Paxos协议, Paxos协议是支持日志空洞的,这就带来一个好处,当在网络出现波动的时候,我们可以给到更好的性能保证。

    OceanBase的高可用性,是完全在通用X86服务器和普通硬件上提供出来的,没有使用任何高端硬件,所以我们的成本会更低一些。

    高扩展

    在实际生产系统中单个OceanBase集群内的服务器可以达到100台以上。而且OceanBase具有很好的线性扩展比。高扩展性还体现在扩容时的自动负载均衡,这意味着当DBA需要扩容的时候,所做的只是增加一台机器到集群里,接下来,我们的OceanBase管理系统会自动的根据系统的负载情况,把数据迁移到新加的机器上。整个扩容缩容过程中,业务没有感知。

    高性能

    我们采用了很多先进的技术来提高数据库的性能。比如LSM Tree、无锁结构、消除磁盘的随机写等等,这些技术帮助我们充分使用硬件的能力,再辅以高扩展性,我们就可以提供一个世界级性能的OceanBase集群。

    在实际的生产系统里,我们可以在峰值的时候提供6100万次每秒,单表最大容量可以到3200亿行。和高性能伴随的是低成本,因为我们采用了LSM Tree结构,所以当数据落盘的时候是更有组织的,可以做到1:3的压缩比。

    高透明

    我们实现了不少关键技术,比如全局一致性快照、全局索引、自动事务两阶段提交。使用OceanBase数据库,应用就像使用一台单机数据库一样,不需要做针对分布式数据库的特别感知和修改。

    高兼容

    我们在一套OceanBase集群上同时为您提供两套生态,一套是Oracle生态,一套是MySQL生态,有效地降低业务迁移改造的成本。同时我们和国内主流的操作系统、芯片也都做了互认的支持,可以有效满足技术供应链安全的需求。

    多租户

    多租户就是在一个OceanBase集群上,可以建立很多个租户,每个租户对应一个Oracle实例或者是MySQL实例。可以用这个特性实现业务大集中,把以前全国一省一套的传统集中式数据库都集中在一个OceanBase数据库集群那里。也可以做不同种类的小业务的集中,之前几十个小的业务现在都集中在一个OceanBase集群里统一管理,这个特性不但可以有效利用集群资源,更可以有效降低 DBA的运维成本。

    OceanBase产品定位与形态

    OceanBase可以提供拥有世界级性能的OLTP引擎,同时也提供一个非常优秀的OLAP引擎,这意味着辅以刚才提到的多租户功能,您可以在一个OceanBase的集群里创建不同的实例,有的专门用于交易,有的专门用于分析,当然也可以创建一个大的实例,既做交易又做分析。OceanBase目前真正做到了一套HTAP引擎,它能够同时支持交易和分析型业务。

    5.png

    OceanBase的容灾架构,既支持经典的主备容灾方式,同时也支持基于Paxos协议的容灾方式,我们支持同机房三副本,也支持同城三机房,甚至是两地三中心,三地五中心,这些不同的容灾级别可以完全满足您的容灾诉求。

    关于部署模式,如果您希望和阿里云其他的优秀产品,比如和金融级分布式中间件SOFA或者对象云存储OSS一起使用,那么OceanBase可以在阿里云的专有云上为您输出。如果您只想使用OceanBase,我们也可以以一个纯License的方式提供给您,就在您的服务器上安装我们的软件,一样可以获得一个高可用、高扩展、高性能的集群。如果您希望只是购买一个公有云的服务,您可以在阿里云的公有云上购买一个OceanBase的RDS。这些不同选项可以无缝适配您各种不同的需求。

    OceanBase在保险业的实践

    OceanBase在保险业的最佳实践,一个很好的案例就是人保健康险。如果不熟悉的朋友可以打开您的手机支付宝,在上面搜“好医保”就可以看到人保健康险的产品。人保健康利用了金融级分布式数据库OceanBase和金融级分布式中间件SOFAStack解决了高并发保单处理能力速度慢的问题,目前每日平均出单量在15万左右。

    自2018年4月11日人保健康险好医保产品成功上线后,截止到目前,好医保已成为支付宝网红保险产品。OceanBase上线中国人保健康以后,取得了显著的收益:

    处理能力提升了上千倍,并可根据业务情况动态扩容

    2018款好医保住院医疗保险,每天1万单的日结文件,处理速度从以前的4小时缩短至6分钟

    新产品上线时间缩短80%以上,从原来的数周缩短至数天

    采用多种协议转换和标准化对接流程,使外部渠道接入效率提升6倍,支持第三方业务快速拓展

    谢谢大家听完我的汇报,期待着未来我们可以用OceanBase数据库更好地服务于保险行业,和各位好朋友一起打造面向未来的保险业的核心业务系统。

    ]]>
    阿里云操作系统选择说明指南 如何选择阿里云服务器操作系统?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    ]]>
    如何轻松搞定SAP HANA数据库备份?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    ]]>
    企业上云等级保护三级解决方案-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 本文介绍企业上云满足等保合规三级的最佳实践。

    1.场景描述

    网络安全法中明确要求国家实行网络安全保护制度,网络运营者有义务履行等级保护制度要求。阿里云除了提供满足等保合规要求的云平台外,还为用户的应用系统提供完整的云原生、高性价比的等保三级解决方案。

    2.解决的问题

    • 等保2.0合规要求
    • 云上高等级安全体系建设

    3.部署架构图

    图1:企业上云等保三级合规部署架构图.png

    图1:企业上云等保三级合规部署架构图

    4.选用的产品

    更多有关以下产品的介绍,可点击这里或扫描文后二维码查看相关产品详情。

    4.1云安全中心

    云安全中心是一个实时识别、分析、预警安全威胁的统一安全管理系统,通过防勒索、防病毒、防篡改、合规检查等安全能力,帮助用户实现威胁检测、响应、溯源的自动化安全运营闭环,保护云上资产和本地主机并满足监管合规要求。

    4.2 Web应用防火墙

    阿里云Web应用防火墙(WAF)对网站或APP的业务流量进行恶意特征识别及防护,将正常、安全的流量回源到服务器。避免网站服务器被恶意入侵,保障业务的核心数据安全,解决因恶意攻击导致的服务器性能异常问题。

    4.3云防火墙

    集中管理公网IP的访问策略,内置威胁入侵防御模块(IPS),支持失陷主机检测、主动外联行为的阻断、业务间访问关系可视,留存6个月网络流量日志,等保必备。

    4.4 SSL证书

    在云上签发各品牌数字证书,实现网站HTTPS化,使网站可信,防劫持、防篡改、防监听、安全加密。统一生命周期管理,简化证书部署,一键分发到CDN、负载均衡、OSS等其它云上产品。

    4.5堡垒机

    集中管理资产权限,全程记录操作数据,实时还原运维场景,助力企业用户构建云上统一、安全、高效运维通道;保障云端运维工作权限可管控、操作可审计、合规可遵从。

    4.6数据库审计

    智能解析数据库通信流量,细粒度审计数据库访问行为,帮助企业精准识别、记录云上数据安全威胁,为云端数据库提供全方位的安全、诊断、维护及合规能力。

    4.7日志服务SLS

    行业领先的日志大数据解决方案,一站式提供数据收集、清洗、分析、可视化和告警功能。全面提升海量日志处理能力,实时挖掘数据价值,智能助力研发/运维/运营/安全等场景。

    4.8密钥管理服务

    密钥管理服务(KMS)提供安全合规的密钥托管和密码服务,助您轻松使用密钥来加密保护敏感的数据资产,控制云上的分布式计算和存储环境。您可以追踪密钥的使用情况,配置密钥的自动轮转策略,以及利用托管密码机所具备的中国国家密码管理局或者FIPS认证资质,来满足您的监管合规需求。

    5.详细信息

    点击这里或扫描下方二维码查看最佳实践详情。

    6.更多最佳实践

    点击这里或扫描下方二维码查看更多阿里云最佳实践。

    下载.png

    我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。

    image.png

    ]]>
    企业上云等保二级合规-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 本文档介绍企业上云满足等保合规2.0的最佳实践。

    1.场景描述

    阿里云安全帮助您快速、省心地通过等保合规。 在阿里云,您可享受一站式等保测评,包括完备的攻击防护、数据审计、数据备份与加密、安全管理服务。可充分利用云平台的免费管理软件,包括RAM、ActionTrail、云监控等,满足等保2.0需求。

    2.解决的问题

    • 等保2.0合规要求
    • 云上安全体系建设

    3.部署架构图

    图1.png

    图1:企业上云等保合规2.0部署架构图

    4.选用的产品

    更多有关以下产品的介绍,可点击这里或扫描文后二维码查看相关产品详情。

    4.1云安全中心

    云安全中心是一个实时识别、分析、预警安全威胁的统一安全管理系统,通过防勒索、防病毒、防篡改、合规检查等安全能力,帮助用户实现威胁检测、响应、溯源的自动化安全运营闭环,保护云上资产和本地主机并满足监管合规要求。

    4.2Web应用防火墙

    阿里云Web应用防火墙(WAF)对网站或者APP的业务流量进行恶意特征识别及防护,将正常、安全的流量回源到服务器。避免网站服务器被恶意入侵,保障业务的核心数据安全,解决因恶意攻击导致的服务器性能异常问题。

    4.3云防火墙

    集中管理公网IP的访问策略,内置威胁入侵防御模块(IPS),支持失陷主机检测、主动外联行为的阻断、业务间访问关系可视,留存6个月网络流量日志,等保必备。

    4.4SSL证书

    在云上签发各品牌数字证书,实现网站HTTPS化,使网站可信,防劫持、防篡改、防监听、安全加密。统一生命周期管理,简化证书部署,一键分发到CDN、负载均衡、OSS等其它云上产品。

    4.5数据库审计

    智能解析数据库通信流量,细粒度审计数据库访问行为,帮助企业精准识别、记录云上数据安全威胁,为云端数据库提供全方位的安全、诊断、维护及合规能力。

    4.6日志服务 SLS

    行业领先的日志大数据解决方案,一站式提供数据收集、清洗、分析、可视化和告警功能。全面提升海量日志处理能力,实时挖掘数据价值,智能助力研发/运维/运营/安全等场景。

    5.详细信息

    点击这里或扫描下方二维码查看最佳实践详情。

    6.更多最佳实践

    点击这里或扫描下方二维码查看更多阿里云最佳实践。

    image.png

    我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。

    image.png

    ]]>
    CentOS-7 安装 Redis-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 wget安装
    [root@RedisSrv1 ~]# yum install wget

    安装gcc依赖

    [root@RedisSrv1 ~]# yum install gcc -y
    -- 请先检查gcc的版本是否低于5,如果是请先升级,可以使用以下命令:
    [root@RedisSrv1 redis-stable]# gcc -v
    CentOS7默认安装的是4.8.5,而redis6.0只支持5.3以上版本,这里将gcc升级到9
    [root@RedisSrv1 redis-stable]# yum -y install centos-release-scl
    [root@RedisSrv1 redis-stable]# yum install devtoolset-9-gcc*
    gcc版本切换
    临时切换:scl enable devtoolset-9 bash
    永久切换:echo “source /opt/rh/devtoolset-9/enable” >> /etc/profile

    下载最新稳定版 Redis

    [root@RedisSrv1 /]# cd /opt/
    [root@RedisSrv1 /]# wget http://download.redis.io/releases/redis-stable.tar.gz

    解压redis安装包

    [root@RedisSrv1 opt]# tar -zxvf redis-stable.tar.gz

    进到解压后的redis目录中进行编译

    [root@RedisSrv1 opt]# cd redis-stable
    
    [root@RedisSrv1 redis-stable]# make MALLOC=libc
    make[1]: Leaving directory `/opt/redis-stable/src'
    
    编译完成后,进入到src目录下,可以看到,生成了可执行文件
    生成了src目录文件之后,进入src(源文件目录)继续编译
    [root@RedisSrv1 redis-stable]# cd src/
    
    #安装到 /usr/local/redis-stable 目录
    [root@RedisSrv1 src]# make install PREFIX=/usr/local/redis-stable
    
    Hint: It's a good idea to run 'make test' ;)
    
        INSTALL install
        INSTALL install
        INSTALL install
        INSTALL install
        INSTALL install
    
     --将配置文件移动到/home/redis/目录
    cp /opt/redis-stable/redis.conf /usr/local/redis-stable
    --修改文件权限  
    chmod -R 700 /usr/local/redis-stable/
    [root@RedisSrv1 redis-stable]# cd /usr/local/redis-stable/bin
    [root@RedisSrv1 bin]# ./redis-server /usr/local/redis-stable/redis.conf
    
    
    --关闭redis进程
    [root@server01 src]# ps -ef | grep redis
    root       1177      1  0 09:09 ?        00:00:00 ./redis-server 0.0.0.0:6379
    root       1185   1147  0 09:11 pts/0    00:00:00 grep --color=auto redis
    [root@server01 src]# 
    [root@server01 src]# ps -aux | grep redis
    root       1177  0.0  0.2 144008  2028 ?        Ssl  09:09   0:00 ./redis-server 0.0.0.0:6379
    root       1187  0.0  0.0 112708   976 pts/0    R+   09:11   0:00 grep --color=auto redis
    [root@server01 src]# 
    [root@server01 src]# kill -9 1177
    [root@server01 src]# 
    [root@server01 src]# ps -aux | grep redis
    root       1189  0.0  0.0 112708   980 pts/0    R+   09:12   0:00 grep --color=auto redis
    [root@server01 src]# 
    
    开放防火墙6379端口
    firewall-cmd --zone=public --add-port=6379/tcp --permanent
    
    重新加载防火墙设置
    firewall-cmd --reload
    
    查看是否生效
    firewall-cmd --list-ports
    
    

    卸载Redis

    查看进程
    [root@RedisSrv1 src]# ps aux |grep redis
    
    杀掉进程
    kill -9 进程号
    
    查看相关文件
    [root@RedisSrv1 src]# find / -name "redis*"
    
    删除文件
    rm -rf 文件
    

    Redis 自启动

    [root@RedisSrv1 ~]# vim /usr/lib/systemd/system/redis.service
    [Unit]
    Description=Redis persistent key-value database
    After=network.target
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=forking
    PIDFile=/var/run/redis_6379.pid
    ExecStart=/usr/local/redis-stable/bin/redis-server /usr/local/redis-stable/redis.conf --supervised systemd
    ExecReload=/bin/kill -USR2 $MAINPID
    ExecStop=/usr/local/redis-stable/bin/redis-cli -p 6379 shutdown
    
    [Install]
    WantedBy=multi-user.target
    
    [root@RedisSrv1 ~]# systemctl daemon-reload
    [root@RedisSrv1 ~]# systemctl start redis
    [root@RedisSrv1 ~]# systemctl status redis
    [root@RedisSrv1 ~]# systemctl stop redis
    ]]>
    操作审计日志分析实战一:使用 SQL 分析投递到 OSS 中的操作审计日志-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 简单了解原理

    (1)在操作审计创建跟踪可以将账号下发生的云上管控操作日志持续投递到SLS Logstore和OSS Bucket;
    (2)在数据湖分析(DLA)服务,可以通过简单的设置将操作日志从OSS Bucket导入DLA。

    dla-oss.png

    DLA是一款基于Serverless的强大的交互式数据查询分析服务,能够便捷的对不同格式的数据源进行格式化整合并使用统一SQL查询分析。将OSS Bucket 中的操作日志导入DLA后,
    (1)DLA将OSS Bucket内以Array形式保存的一行多条日志记录拆分为多条数据;
    (2)DLA将以JSON保存的每条操作日志转换为结构化的数据表。
    这使面向OSS Bucket的数据解析被大大的简化,直接实现可视化的标准SQL分析。

    需求背景.png

    开始实践

    Step1:确认最佳实践的前提条件

    1、确认您已经在操作审计创建了跟踪。如果还未创建跟踪,请先完成创建账号追踪操作,并配置将操作记录投递到对象存储(OSS)。
    2、确认开通了DLA服务,请参见开通DLA服务

    Step2:在DLA服务中创建Schema

    1、登录Data Lake Analytics管理控制台
    2、在页面左上角,选择与OSS所在地域一致的DLA地域。
    3、单击左侧导航栏的数据湖构建 > 数据入湖,在数据入湖页面单击ActionTrail日志清洗中的进入向导。
    4、在ActionTrail日志清洗页面,根据页面提示进行参数配置。

    创建Schema_1.png

    5、完成上述参数配置后单击创建,创建Schema。
    服务端预设的操作审计日志Schema结构如下方表格所示。

    1111111111111111111.png

    Schema表结构介绍

    表格长图.png

    Step3:开启同步

    Schema创建成功后,ActionTrail投递到OSS Bucket中的日志数据尚未同步到DLA中,DLA中尚未创建OSS日志文件对应的表,您还需要通过单击立即同步来创建表并同步表数据。
    1、单击立即同步启动数据同步任务。

    在配置页签下,单击更新更新Schema配置。

    立即同步.png

    2、单击表页签,查看数据同步情况。

    元数据管理.png

    数据同步到DLA以后,您就可以在DLA中使用标准SQL语法对ActionTrail日志数据进行分析。

    Step4:数据分析示例

    1、单击DLA控制台左侧 SQL执行 选项卡,选择目标前面设置的数据库。

    SQL界面.png

    2、输入查询语句,在这里输入单击 同步执行

    输入SQL.png

    3、得到查询结果

    查询结果.png

    您可以使用任何符合SQL语法的语句去对DLA中的日志信息进行查询。

    常用查询案例

    案例1:查询某个AK的操作日志

    1、输入语句:select * from action_trail where user_identity_access_key_id = '你的目标AK' limit 20;

    案例查询1语句.png

    2、单击 同步执行 得到前20条符合条件的记录如下

    案例1查询结果.png

    案例2:查询某个AK访问某个产品的操作日志
    1、输入语句,查询AK为指定值,调用Ecs服务的记录:select * from action_trail where user_identity_access_key_id = '你的目标AK' AND service_name = 'Ecs' limit 20;

    案例查询2语句.png

    2、单击 同步执行 得到前20条符合条件的记录如下
    案例2查询结果.png

    ]]>
    阿里云高效基因序列检索助力新冠肺炎病毒序列快速分析-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 AnalyticDB for MySQL是云端托管的PB级高并发低延时数据仓库,通过AnalyticDB for MySQL向量检索功能构建基因检索系统,支持毫秒级针对10亿级别的向量数据进行查询分析,更加快速、高效地为新冠肺炎病毒防控、研发治疗药物以及相关疫苗提供帮助。

    1.背景信息

    2019年年底,中国的新兴商业中心武汉,爆发了一种名为新型冠状病毒肺炎(简称新冠肺炎)的疫情。在新冠肺炎流行的两个多月中,中国造成了3300多人死亡,8万2千多人感染。随着疫情的进一步蔓延,目前已经横跨了109个国家,造成了80多万人感染,4万多人失去了生命。到目前为止,疫情使得50多个国家停摆,全世界范围内造成了数千亿美元的经济损失。在疫情防治期间,阿里云提供了高效基因序列检索技术,助力新冠肺炎病毒序列分析。

    2.基因序列检索技术应用范围和现状

    对于当下疫情,基因序列检索技术主要应用于以下场景:

    • 用于新冠肺炎的溯源和分析,帮助疫情防控找到病毒宿主,做好有效防范。
      通过基因序列检索技术,发现蝙蝠和穿山甲身上的冠状病毒RNA序列匹配度高达96%和99.7%,可以推断蝙蝠和穿山甲很可能是新冠肺炎的宿主。
    • 用于分析新冠肺炎病毒的复制和传播过程,为研发治疗药物和疫苗提供帮助。
      通过基因序列检索技术对基因序列按功能区域划分,了解各个模块的功能,从而更好地分析出病毒的复制和传播过程,进而找到关键节点,为研发治疗药物和疫苗提供帮助。
    • 用于检索到与冠状病毒相似的病毒基因序列。
      基因序列检索技术也可以检索与新冠肺炎病毒相似的病毒基因序列,例如SARS、MERS等病毒,从而借鉴相关药物靶点设计机制,更快、更高效地研发检测试剂盒、疫苗以及相关的治疗药物。

    基于当下疫情的快速蔓延,当前的基因匹配算法太慢,迫切需要高效匹配算法进行基因序列检索。阿里云AnalyticDB for MySQL团队将基因序列片段转化成对应的1024维特征向量,将两个基因片段的匹配问题,转换成了两个向量间的距离计算问题,从而大大降低了计算开销,实现毫秒级返回相关基因片段,完成基因片段的首次筛选。然后,使用基因相似计算BLAST算法,完成基因相似度的精确排查,从而高效率完成基因序列的匹配计算。匹配算法从原来O(M+N)的复杂度降低到O(1)。同时,阿里云AnalyticDB for MySQL提供强大的机器学习分析工具,通过基因转向量技术,将局部的和疾病相关的关键靶点基因片段转成特征向量,用于基因药物的研发,大大加速了基因分析过程。

    3. AnalyticDB for MySQL基因检索系统

    新冠肺炎病毒的RNA序列可以用一串核酸序列(又称碱基序列)表示,RNA序列含有四种核苷酸,分别用A、C、G和T表示,分别代表腺嘌呤、胞嘧啶、鸟嘌呤、胸腺嘧啶。每个字母代表一种碱基,无间隔排列在一起。每一个物种的RNA序列均不相同但又有规律,基因检索系统可以通过输入一串病毒的基因片段,检索相似的基因,用来对病毒的RNA序列进行分析。
    为方便演示AnalyticDB for MySQL基因片段检索方法,我们从GenBank下载了大量病毒的RNA片段,并将GenBank内部关于病毒的论文以及Google Scholar中相关病毒的论文导入AnalyticDB for MySQL基因检索数据库中。
    AnalyticDB for MySQL基因检索的演示界面如下图所示,将新冠肺炎病毒的序列(COVID-19)上传到AnalyticDB for MySQL基因检索系统中,AnalyticDB for MySQL基因检索系统只需几毫秒即可检索到相似的基因片段(当前示例系统只返回匹配度超过0.8的基因片段)。从返回的基因片段得出穿山甲携带的新冠肺炎病毒(GD/P1L)、蝙蝠携带的新冠肺炎病毒(RaTG13)以及SARS和MARS病毒,其中GD/P1L的序列匹配度最高为0.974,由此推断出新冠肺炎病毒很可能是通过穿山甲传染到人的。

    图1:AnalyticDB for MySQL基因检索演示界面.png

    图1:AnalyticDB for MySQL基因检索演示界面

    如果RNA片段非常相似,说明这两个RNA可能有相似的蛋白质表达和结构。通过基因检索工具,可以看到SARS和MARS与新冠肺炎病毒的匹配度为0.8以上,说明可以将一些SARS或者MARS的研究成果应用到新冠肺炎病毒上。系统提取了每种病毒的论文,通过文本分类算法,将论文划分为检测类、疫苗类和药物类,例如下图为SARS的七种检测方法、四种疫苗接种方法和10中治疗药物。其中,对SARS有效的荧光定量PCR检测,目前正应用于新冠肺炎病毒的检测;基因疫苗的方法以及诱导体内免疫疫苗的方法,也正在展开研究;治疗药物中瑞德西韦以及相关的干扰素也都用于新冠肺炎病毒的治疗上。

    图2:SARS病毒相关论文检索分类结果.png


    图2:SARS病毒相关论文检索分类结果

    单击上图干扰素链接可以查看相关论文,当前系统调用了自动翻译软件,抽取中文版文件名关键词作为文件名,方便用户阅读。

    图3:论文查看效果.png


    图3:论文查看效果

    4.实现架构

    图4:基因检索实现架构.png


    图4:基因检索实现架构

    AnalyticDB for MySQL基因检索系统中,AnalyticDB for MySQL负责存储和查询所有结构化数据(例如基因序列的长度,长度包含基因的论文名称、基因种类、DNA或者RNA等)和基因序列产生的特征向量。查询数据时,通过基因向量抽取模型将基因转化成向量,在AnalyticDB for MySQL向量数据库中进行粗排检索,然后在返回的向量匹配结果集中使用经典的BLAST算法进行精确检索,返回最相似的基因序列。
    AnalyticDB for MySQL基因检索系统的核心是基因向量抽取模型,该模块可以将核苷酸序列转化成向量。目前AnalyticDB for MySQL抽取了各种病毒的RNA全部序列样本进行训练,可以非常方便地对病毒的RNA进行相似度计算。同时,基因向量抽取模型也可以扩展应用于其他物种基因检索。

    5.基因向量抽取算法

    目前词向量技术已经非常成熟,被广泛应用于机器翻译、阅读理解、语义分析等相关领域,并取得了巨大成功。词向量化采用了分布式语义的方法表示一个词的含义,一个词的含义就是这个词所处的上下文语境。例如高中英语中的完形填空题,一篇短文空出10个地方,学生根据空缺词的上下文语境选择合适的词。也就是说上下文语境能够准确地表达这个词,如果某位同学选择了正确的选词,表示该同学理解了空缺词的含义。因此,通过上下文词的关系,采用词向量算法,可以为每个词生成一个向量,通过计算两个词向量之间的相似度,得到两个词的相似度。
    同样的道理,基因序列的排列具有一定的规律,并且每一部分基因序列所表达的功能和含义不同。可以将很长的基因序列划分成小的单元片段(也就是词)进行分析,并且这些词也有上下文语境,这些词相互连接、相互作用共同完成相对应的功能,形成合理的表达。因此,生物科学家们采用词向量算法对基因序列单元进行向量化,两个基因单元相似度很高,说明需要这两个基因单元共同来表达和完成相应的功能。
    总体而言,AnalyticDB for MySQL基因向量抽取算法分为三步:
    (1)在氨基酸序列中定义词。生物信息学中用K-mers来分析氨基酸序列,K-mer是指将核酸序列分成包含K个碱基的字符串,即从一段连续的核酸序列中迭代选取长度为K个碱基的序列,若核酸序列长度为L,K-mer长度为K,那么可以得到L-K+1个K-mers。例如下图所示,假设某序列长度为12,设定选取的k-mer长度为8,则得到(12-8+1=5)5个5-mers。这些k-mer,就是氨基酸序列中的词。

    图5:8-mers核酸序列示意图.png


    图5:8-mers核酸序列示意图

    (2)找到氨基酸序列的上下文语境,将基因序列中的词转换成1024维向量。对于词向量算法而言,另一个重要的问题就是上下文的语境。AnalyticDB for MySQL基因向量抽取算法在氨基酸片段中选择一个长度为L的窗口,该窗口内的氨基酸片段可认定为在同一语境内。例如CTGGATGA是一段核酸序列,选取了长度为10的窗口,AnalyticDB for MySQL基因向量抽取算法将CTGGATGA转换成5个5-mers即{AACTG, ACTGG, CTGGA, GGATG, GATGA}。对于其中一个5-mer{CTGGA}而言,另外四个{AACTG, ACTGG, GGATG, GATGA}5-mers就是当前5-mer {CTGGA}的上下文语境。AnalyticDB for MySQL基因向量抽取算法套用词向量空间训练模型,对已有生物基因的K-mers进行训练,便可将一个K-mer(基因序列中的一个词)转换成1024维向量。
    (3)类似于词向量模型,K-mer向量模型也拥有和词向量模型相似的数理计算性质。公式一说明核苷酸序列ACGAT的向量减去GAT序列的向量和AC序列的向量距离非常接近。公式二说明核苷酸序列AC的向量加上ATC序列的向量和ACATC序列的向量距离也很接近。因此,根据这些数理特征,计算一个长氨基酸序列向量时,可以将这个序列中每一段的K-mer序列进行累加,最后进行归一化就能得到整个氨基酸序列的向量。同时,为提升精度,可以将基因片段看作一个文本,使用doc2vec4将整个序列转换成向量进行计算。为进一步验证算法性能,AnalyticDB for MySQL基因向量抽取算法计算了常用于基因检索库中的BLAST算法序列与基因转向量l2距离序列的相似度,两个序列的斯皮尔曼等级相关系数是0.839。以上得出结论,将DNA序列转换成向量用于相似基因片段的初次筛选,是有效且可行的。

    6.向量检索功能概述

    一般包含向量检索的应用系统中,开发者通常会使用向量检索引擎(例如Faiss)存储向量数据,然后使用关系型数据库存储结构化数据。因此,查询时也需要交替查询两个系统,明显额外增加了开发人员的工作量,数据查询性能也不是最优。
    AnalyticDB for MySQL是云端托管的PB级高并发低延时数据仓库,可以毫秒级针对10亿级别的向量数据进行查询,100毫秒级别的响应时间。AnalyticDB for MySQL全面兼容MySQL协议以及SQL:2003语法标准,其向量检索功能支持对图像、文本推荐、声纹、核苷酸序列等相似性进行查询和分析,目前在多个城市的安防项目中已大规模部署了AnalyticDB for MySQL。
    AnalyticDB for MySQL支持结构化和非结构化数据的近似检索和分析,通过SQL接口即可快速搭建基因检索或者基因+结构化数据混合检索等系统。在混合检索场景中AnalyticDB for MySQL的优化器会根据数据的分布和查询条件选择最优执行计划,在保证数据召回率的同时,得到最优的性能。例如,通过以下一条SQL即可检索RNA核酸序列。

    -- 查找RNA和提交的序列向量相近的基因序列。
    select  title, # 文章名
            length, # 基因长度
            type, # mRNA或DNA等
            l2_distance(feature, array[-0.017,-0.032,...]::real[]) as distance # 向量距离 
    from demo.paper a, demo.dna_feature b
    where a.id = b.id
    order by distance; # 用向量相似度排序
    

    上述SQL中表demo.paper用于存储上传的每篇文章的基本信息,demo.dna_feature存储各个物种的基因序列对应的向量。通过基因转向量模型,将要检索的基因转成向量[-0.017,-0.032,...],然后在AnalyticDB for MySQL数据库中进行检索。
    当前系统也支持结构化信息+非结构化信息(核苷酸序列)的混合检索,例如查找和冠状病毒相关的类似基因片段时,只需要在SQL中增加where title like'%COVID-19%'即可。
    本文参考的相关文献,感兴趣的读者可访问这里或扫描下方二维码了解详情。

    二维码.png

    作者:李倩

    阿里云云原生数据仓库AnalyticDB产品经理

    阿里云云原生数据仓库AnalyticDB产品经理,见证了AnalyticDB从初创到至今的壮大发展,参与了所有重大功能设计。

    我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。

    image.png

    ]]>
    钉钉猛增40倍流量压力 阿里云DBA如何应对-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 1.背景

    由于受新型冠状病毒感染的肺炎疫情影响,钉钉流量从春节后开始出现了飞跃性增长。此次疫情流量主要来源于钉钉远程办公和在线教育功能,从字面来看,好像只是钉钉的两个业务功能,但在钉钉内部依赖模块不下20个,主要有消息、视频会议、直播、家校、健康打卡等业务场景。如何保障超过20个业务在如此爆发式增长下的性能和稳定性,是对钉钉后台系统、数据库系统的一个很大挑战。
    本文将从数据库DBA的视角来介绍我们是如何打赢这场“战役”的,在这个过程中我们究竟遇到了哪些挑战,我们是如何组织我们的团队,如何思考,如何真正利用技术克服这些挑战,最后通过这场战役,我们又沉淀了哪些经验及技术。

    2.对数据库系统的挑战

    数据库是钉钉业务系统运行的强依赖,在这种类似双11的场景下,如何规划部署数据库成了稳定性中最重要的一环。但是这次的战役来得突然,并没有很多时间准备,因此面临了非常多的困难与挑战,总结下来有以下3点:
    (1)系统所需要的容量是多少,无法预估
    以消息模块为例,在春节前,钉钉消息日常流量峰值不到千万,第一次容量评估,大家给2月3号定的目标是日常峰值的3倍。随着2月10号开课高峰的到来,又将2月10号的目标调整为10倍。之后又因为2月17号开学季的到来,再次将目标调整为40倍。所以总容量相比日常峰值翻了40倍!
    (2)时间紧,扩容需求众多,资源不足
    疫情流量的猛增,给系统带来的冲击不亚于每年的双11。电商会花半年时间准备双11,但这次留给我们的时间只能以小时来计。另一方面,钉钉出于成本的考虑,资源池中基本没有空余的机器,现有的资源部署密度也比较高,如何腾挪资源在较短的时间内为钉钉接近20个核心集群进行扩容是一个很大的问题。
    (3)极限场景下如何保障系统稳定性与用户体验
    在各种因素制约导致集群无法扩容且系统达已经达到瓶颈时我们能怎么办?有哪些应急手段能用?是否存在一个平衡点,将对用户的影响降到最低?

    3.应对措施

    3.1人员合理化安排

    (1)数据库团队成立疫情期间钉钉业务保障小组
    小组成员包含了数据库团队DBA/数据库内核/CORONA/TDDL/DTS/精卫/NOSQL各产品线同学。根据钉钉业务线进行分工,每个DBA跟进一个业务线,参与高峰期的保障,及时播报线上系统状况与水位,让重保决策人员及时了解系统的状况。对线上出现的问题紧急处理,保证问题在短时间内得到修复。对不合理的业务场景进行优化,保证已知问题只出现一次。参与系统的压测,发现潜在风险点及时修正,对系统容量不够的系统进行及时扩容,在资源满足的情况下让数据库在高峰来临之前已经具备足够的容量。
    (2)数据库团队与钉钉稳定性团队紧密合作
    由于前期资源有限,需要扩容的系统众多,此时钉钉稳定性团队主动站出来帮DBA分担了大量的的压力。他们将数据库的扩容需求根据业务的重要性进行优先级划分,统一扩容需求,DBA根据优先级顺序,结合业务的目标容量进行判断,在有限的资源下有条不紊地进行扩容,保证资源优先用在刀刃上,大大提升了扩容效率。

    3.2资源紧急协调

    疫情突然爆发,所有人都预期流量会增长,但涨多少很难预估,必须要早作准备。为了保证资源不会成为系统扩容的阻力,DBA和云资源团队进行合理规划,短期内通过借用集团上云的机器,同时缩容其他BU数据库集群,凑出400台左右的机器,保证高优先级系统的扩容需求。同时协调云资源进行搬迁,在短短几天内搬迁了300多台机器到钉钉资源池,保证了钉钉所有数据库的扩容需求。
    资源到位后就是检验数据库弹性的时候了,依托于PolarDB-X三节点分布式的部署架构,我们可以较为方便地对原有集群进行在线升级和扩容,对用户影响很低,并且保证数据的一致性。有些场景用户需要从原有集群将数据迁移到分库分表更多的新集群,我们利用DTS搭配成熟的管控平台也能较为流畅地完成。最终可以做到只要有资源,数据库也能具有极致的弹性,满足业务需求。

    3.3应急与优化

    在系统高峰来临之前,数据库团队内部已经准备好紧急预案:

    • 参数降级,调整数据库参数充分发挥数据库能力,提高吞吐
    • 资源降级,调整资源限制,CPU隔离放开及数据库BP大小紧急上调
    • 针对异常SQL,确认影响后紧急限流,或者通过SQL Execute Plan Profile进行紧急干预
    • 全集群流量备库分流,依据压力情况最大可100%读流量切换到备库
    • 准备数据库弱一致脚本,在必要时进一步提高数据库吞吐

    同时结合业务的限流/降级预案保证了很多数据库系统在未知高峰流量到来时的稳定运行。
    但业务限流降低了很多用户的体验,之前业务限流值设置为30QPM/群,表示为每个群在一分钟之内只能发送30条消息,很多时候在1分种的前20s甚至更短时间就已经发出30条消息,在剩下40s以上的时间内用户的体验就是无法使用钉钉。针对这种情况DBA建议减小限流窗口,将限流值30QPM改成30/20S,限流降低了97%,大大改善了用户的体验。

    3.4 DB容量预估及性能分析

    业务上往往通过集群的CPU情况即可大概分析出系统的水位,但是对DB而言不仅是CPU,IO、网络、SQL、锁等等,任何一个组件的瓶颈往往都会成为最终容量的瓶颈。不同的业务模型,往往瓶颈不一样,即使都是查询量较大的业务,有些可能是CPU的瓶颈,有些可能是内存命中率不够导致的瓶颈,有些则是索引设计不合理导致的瓶颈。更复杂的部分在于,有些瓶颈往往不是线性的,可能压力提升2倍还没什么问题,硬件能力都还有富余,但是提升到3倍就直接崩溃。在这种场景下我们如何比较准确地评估DB的容量呢?
    以往我们都是通过经验并和业务方一起进行全链路压测进行DB容量(集群能支撑多少读写)的预估,这种方式有以下几个问题:(1)压测数据集和数据库总量相比往往比较小,DB命中率基本100%,这对于分析有IO的业务模型存在较大误差;(2)成本较大,需要打通上下游整个链路,需较多的人员参与,即使进行全链路压测,真正压到DB端的往往也只是核心的几个接口,无法100%覆盖线上所有的接口,而很多慢SQL往往都来自这些易忽略的接口。
    解决这个痛点问题的方法很容易想到——只要把线上的业务流量全部采集下来回放一遍即可,但实现起来是非常复杂的。我们真正需要的其实是针对DB的一种通用的单链路压测能力,并不依赖上游业务,DB层可以自己进行流量的生成、放大或缩小,甚至具备将事务比例更改后再次压测的能力。从2019年开始,在DBA和达摩院数据库实验室科学家们共同的努力下,我们开发了ClouDBench实现了上述的需求,并在此次的战役中帮助DBA进行容量的评估。效果如下图所示:

    图1:ClouDBench容量评估效果展示.png

    图1:ClouDBench容量评估效果展示

    蓝色是真实业务在某个时刻的性能曲线,绿色是我们采集DB端流量回放出来的性能曲线,可以看出两条曲线在时序上高度拟合,特别是InnoDB内部的指标都非常接近,包括流量的波动。
    当我们能够比较真实地回放出业务的workload,我们即可以对压力进行放大,以此来分析DB的容量,并分析出极限场景下的性能瓶颈,从而进行DB的优化及验证优化效果。ClouDBench目前已经在公共云数据库自治服务Database Autonomy Service(DAS)中灰度上线。

    4.成果及思考

    短短两周内各数据库系统具备了数倍到40倍以上的能力,其中不乏超大型数据库集群,存储空间超过1PB,所有这些都充分证明了阿里云数据库的弹性能力。此次疫情带来的爆发式流量对我们来说是毫无防备的,经历过此役,经验总结下来有以下几点:

    4.1人员组织

    首先在人员组织上,业务和开发要对突发流量具备敏锐的嗅觉,及时发现提早准备,由业务方稳定性负责人成立应急小组,梳理依赖业务以及对应后台系统,将各业务线owner和后台数据库产品owner纳入应急小组。由应急小组统一容量规划、人力配备以及资源协调,实现业务方、后台产品团队、资源团队联动。

    4.2技术架构

    在技术架构上,一方面是要使用具有足够弹性的数据库产品,保证使用的数据库产品有自由扩容和缩容的能力,既要保证流量增大后能扩容,也要保证日常流量时可以缩容。管控等各个运维组件需要在实现自动化运维的同时,对于很多关键操作留有应急开关,确保在一些极端场景下,可以较方便地从自动驾驶切换成手动模式,确保任务平稳高效地运行下去。

    4.3应急手段

    在面对系统瓶劲时,在业务上和数据库产品上都要提前做好预案。在业务上要有降级和限流功能,在系统无法承受压力时,可以降级一部分非核心功能,限制一些次核心功能来保核心业务的正常运行。在数据库产品上需要具有在不扩容的情况下,通过一些优化手段瞬间提升数据库吞吐的能力,更重要的是这些能力需要有较好的兼容性,在不同的部署环境、不同的DB架构下都具有相应的工具和预案。
    另一方面,我们需要有评估和检测预案效果的手段,我们现在可以利用ClouDBench对DB进行容量的分析和预测,但是当前的使用成本还是过高,后续ClouDBench需要更加自动化,降低使用成本,将能力透传给业务的owner,在大促之前,自动进行大量的DB单链路压测,评估系统水位,发现性能瓶颈,优化DB参数,验证预案效果。

    作者:章左中

    阿里云智能数据库产品团队运维专家

    阿里巴巴运维专家,从事数据库领域十年以上,先后在甲骨文(中国)、网易等公司任职,在传统行业和互联网行业都有着丰富的经验。目前在阿里云数据库事业部从事专家服务相关工作,擅长数据库优化、架构设计及异构数据库之间的迁移等。

    作者:陈荣耀

    阿里云智能数据库产品团队运维专家

    曾就职于烽火通信任职Oracle DBA,2015年加入阿里,现任阿里云数据库运维专家,有丰富的Oracle、MySQL运维开发经验,擅长数据库故障诊断、性能调优、稳定性建设。目前主要负责数据库性能压测、流量回放(ClouuDBench )等。

    我们是阿里云智能全球技术服务-SRE团队,我们致力成为一个以技术为基础、面向服务、保障业务系统高可用的工程师团队;提供专业、体系化的SRE服务,帮助广大客户更好地使用云、基于云构建更加稳定可靠的业务系统,提升业务稳定性。我们期望能够分享更多帮助企业客户上云、用好云,让客户云上业务运行更加稳定可靠的技术,您可用钉钉扫描下方二维码,加入阿里云SRE技术学院钉钉圈子,和更多云上人交流关于云平台的那些事。

    image.png

    ]]>
    Java创建对象的方法有哪些?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 1.运用New 关键字创建实例,这是最常用的创建对象方法。
    2.运用反射,调用Java.lang.Class类当中newInstance方法。只能调用公共的无参构造函数。
    3.运用反射,调用java.lang.reflect.Constructor类中的newInstance方法提供无参或有参实例。除了无参构造器,还可以调用有参数的/私有的/受保护的构造函数。事实上Class的newInstance方法内部调用Constructor的newInstance方法。这也是众多框架Spring、Hibernate、Struts等使用后者的原因。
    4.调用对象的clone方法。必须先实现java.lang.Cloneable接口。
    5.使用序列化和反序列化。必须先实现Serializable接口。
    6.使用unsafe.allocateInstance(class)创建对象。
    本文来源于:奈学开发者社区,如有侵权,请联系我删除~

    ]]>
    Zeppelin SDK :Flink 平台建设的基石-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 作者:章剑锋(简锋),阿里巴巴高级技术专家

    用过 Zeppelin 的人应该比较熟悉 Zeppelin 的 UI,因为 Zeppelin 的主要使用场景都是交互式,用户需要手动来操作。那除了这种手动的方式,还有其他的方式吗?如果你不想用 Zeppelin UI,但又想用 Zeppelin 提交和管理大数据作业 (比如 Flink Job)的能力该怎么办?或者是你在 Zeppelin 里写好了代码,想定时调度起来,或者集成到其他系统里,该怎么办?

    如果你有这样的诉求,那么 Zeppelin Client API (SDK)就是你所需要的东西。

    Zeppelin 简介

    对于不熟悉 Zeppelin 的人,可以用一句话来解释 Zeppelin:大数据引擎的入口,交互式大数据分析平台底座。Zeppelin 最大的特点是连接多种引擎,具有可插拔式,下面这张图例举了一些常用的引擎,当然 Zeppelin 还支持其他很多引擎,这里就不一一例举。

    image3.png

    虽然 Zeppelin 有 Rest API,但是 Zeppelin 的 Rest API 太多,对于很多不熟悉 Zeppelin 的人来说使用 Rest API 门槛太高,所以 Zeppelin 专门开发了一个 Client API (SDK),方便大家做集成。Zeppelin Client API (SDK)分为 2 个层面的的东西(接下来会逐个详细介绍):

    • Zeppelin Client API (Low Level API)
    • Session API (High Level API)

    Zeppelin Client API (Low Level API)

    Zeppelin Client API 可以在 Note 和 Paragraph 的粒度进行操作。你可以先在 notebook 里写好代码 (比如开发阶段在 notebook 里写代码,做测试),然后用 Low Level API 用编程的方式把 Job 跑起来(比如生产阶段把作业定时调度起来)。Zeppelin Client API 最重要的 class 是 ZeppelinClient,也是 Zeppelin Client API 的入口。下面例举几个重要的接口(这些 API 都比较直观,我就不多做解释了)。

    public String createNote(String notePath) throws Exception 
    
    public void deleteNote(String noteId) throws Exception 
    
    public NoteResult executeNote(String noteId) throws Exception 
    
    public NoteResult executeNote(String noteId, 
                                  Map<String, String> parameters) throws Exception
                                  
    public NoteResult queryNoteResult(String noteId) throws Exception 
    
    public NoteResult submitNote(String noteId) throws Exception
    
    public NoteResult submitNote(String noteId, 
                                 Map<String, String> parameters) throws Exception 
                                 
    public NoteResult waitUntilNoteFinished(String noteId) throws Exception
    
    public String addParagraph(String noteId, 
                               String title, 
                               String text) throws Exception
                               
    public void updateParagraph(String noteId, 
                                String paragraphId, 
                                String title, 
                                String text) throws Exception
                                
    public ParagraphResult executeParagraph(String noteId,
                                            String paragraphId,
                                            String sessionId,
                                            Map<String, String> parameters) throws Exception
                                            
    public ParagraphResult submitParagraph(String noteId,
                                           String paragraphId,
                                           String sessionId,
                                           Map<String, String> parameters) throws Exception
                                           
    public void cancelParagraph(String noteId, String paragraphId)
        
    public ParagraphResult queryParagraphResult(String noteId, String paragraphId) 
        
    public ParagraphResult waitUtilParagraphFinish(String noteId, String paragraphId)

    那这些 API 能用来做什么呢?

    一个典型的用途是我们在 Zeppelin 里写好代码,做好测试,然后在第三方系统里集成进来。比如下面的代码就是把 Zeppelin 自带的 Spark Basic Features 用编程的方式跑起来,你不仅可以跑 Zeppelin Note,还可以拿到运行结果 (ParagraphResult)。怎么处理运行结果,就留给你发挥想象的空间吧(可以在你的系统里展示出来,或者可视化出来,或者传给其他系统做消费等等)。

    此外,对于 Dynamic forms(动态控件,比如文本框,下拉框等等),你还可以动态的提供参数,如下面例子里的 maxAge 和 marital。

    ClientConfig clientConfig = new ClientConfig("http://localhost:8080");
    ZeppelinClient zClient = new ZeppelinClient(clientConfig);
    
    String zeppelinVersion = zClient.getVersion();
    System.out.println("Zeppelin version: " + zeppelinVersion);
    
    ParagraphResult paragraphResult = zClient.executeParagraph("2A94M5J1Z", "20150210-015259_1403135953");
    System.out.println("Execute the 1st spark tutorial paragraph, paragraph result: " + paragraphResult);
    
    paragraphResult = zClient.executeParagraph("2A94M5J1Z", "20150210-015302_1492795503");
    System.out.println("Execute the 2nd spark tutorial paragraph, paragraph result: " + paragraphResult);
    
    Map<String, String> parameters = new HashMap<>();
    parameters.put("maxAge", "40");
    paragraphResult = zClient.executeParagraph("2A94M5J1Z", "20150212-145404_867439529", parameters);
    System.out.println("Execute the 3rd spark tutorial paragraph, paragraph result: " + paragraphResult);
    
    parameters = new HashMap<>();
    parameters.put("marital", "married");
    paragraphResult = zClient.executeParagraph("2A94M5J1Z", "20150213-230422_1600658137", parameters);
    System.out.println("Execute the 4th spark tutorial paragraph, paragraph result: " + paragraphResult);

    这下面这张图就是上面我们要 Zeppelin Client API 跑的 Zeppelin 自带的 Spark Basic Features。

    image2.png

    Session API (High Level API)

    Session API 是 Zeppelin 的high level api,Session API 里没有 Note,Paragraph 的概念,粒度是你提交的代码。Session API里最重要的class就是 ZSession,这也是Session API的入口,一个 ZSession 代表一个独立的Zeppelin Interpreter 进程,对于 Flink 来说就是一个独立的 Flink Session Cluster。下面例举一些典型的接口(这些 API 都比较直观,我就不多做解释了)。

    public void start() throws Exception
    
    public void start(MessageHandler messageHandler) throws Exception
    
    public void stop() throws Exception
    
    public ExecuteResult execute(String code) throws Exception
    
    public ExecuteResult execute(String subInterpreter,
                                 Map<< span="">String, String> localProperties,
                                 String code,
                                 StatementMessageHandler messageHandler) throws Exception
    
    public ExecuteResult submit(String code) throws Exception
    
    public ExecuteResult submit(String subInterpreter,
                                Map<< span="">String, String> localProperties,
                                String code,
                                StatementMessageHandler messageHandler) throws Exception
                               
    public void cancel(String statementId) throws Exception
     
    public ExecuteResult queryStatement(String statementId) throws Exception
    
    public ExecuteResult waitUntilFinished(String statementId) throws Exception

    那这个 API 能用来做什么呢? 一个典型的用途是就是我们动态创建 Session (Zeppelin Interpreter 进程),动态的提交运行代码,并拿到运行结果。比如你不想用 Zeppelin 的 UI,要自己做一个 Flink 的开发管理平台,那么你就可以自己做 UI,让用户在 UI 上配置 Flink Job,输入 SQL,然后把所有的这些信息发送到后端,后端调用 ZSession 来运行 Flink Job。

    下面的 Java 代码就是用编程的方式调用了 2 条 Flink SQL 语句,并且在 MyStatementMessageHandler1 和 MyStatementMessageHandler2 中读取源源不断发送过来更新的 SQL 运行结果 (怎么来使用这个结果就靠你的想象力了)。

    需要说明的是像 Flink Interpreter 这种流式结果数据更新是通过 WebSocket 实现的,所以下面的代码里有会有 CompositeMessageHandler,MyStatementMessageHandler1 以及 MyStatementMessageHandler2,这些 MessageHandler 就是用来处理通过 WebSocket 发送过来的流式数据结果。下面是 2 条我们在 Zeppelin 里运行的 Flink SQL。

    image5.png
    image8.png

    接下来我们会用 Zeppelin Session API 来跑着这 2 条 Flink SQL,然后我们会在MyStatementMessageHandler1,MyStatementMessageHandler2 里拿到结果展示出来。

    ZSession session = null;
    try {
        ClientConfig clientConfig = new ClientConfig("http://localhost:8080");
        Map<< span="">String, String> intpProperties = new HashMap<>();
    
        session = ZSession.builder()
            .setClientConfig(clientConfig)
            .setInterpreter("flink")
            .setIntpProperties(intpProperties)
            .build();
    
        // CompositeMessageHandler allow you to add StatementMessageHandler for each statement.
        // otherwise you have to use a global MessageHandler.
        session.start(new CompositeMessageHandler());
        System.out.println("Flink Web UI: " + session.getWeburl());
    
        System.out.println("-----------------------------------------------------------------------------");
        String initCode = IOUtils.toString(FlinkAdvancedExample.class.getResource("/init_stream.scala"));
        ExecuteResult result = session.execute(initCode);
        System.out.println("Job status: " + result.getStatus() + ", data: " + result.getResults().get(0).getData());
    
        // run flink ssql
        Map<< span="">String, String> localProperties = new HashMap<>();
        localProperties.put("type", "update");
        result = session.submit("ssql", localProperties, "select url, count(1) as pv from log group by url",
                                new MyStatementMessageHandler1());
        session.waitUntilFinished(result.getStatementId());
    
        result = session.submit("ssql", localProperties, "select upper(url), count(1) as pv from log group by url",
                                new MyStatementMessageHandler2());
        session.waitUntilFinished(result.getStatementId());
    
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (session != null) {
            try {
                session.stop();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    public static class MyStatementMessageHandler1 implements StatementMessageHandler {
    
        @Override
        public void onStatementAppendOutput(String statementId, int index, String output) {
            System.out.println("MyStatementMessageHandler1, append output: " + output);
        }
    
        @Override
        public void onStatementUpdateOutput(String statementId, int index, String type, String output) {
            System.out.println("MyStatementMessageHandler1, update output: " + output);
        }
    }
    
    public static class MyStatementMessageHandler2 implements StatementMessageHandler {
    
        @Override
        public void onStatementAppendOutput(String statementId, int index, String output) {
            System.out.println("MyStatementMessageHandler2, append output: " + output);
        }
    
        @Override
        public void onStatementUpdateOutput(String statementId, int index, String type, String output) {
            System.out.println("MyStatementMessageHandler2, update output: " + output);
        }
    }

    除了编程方式跑 Flink Job,这个 Session API 还能给我们带来什么呢?

    在 Zeppelin 里如果你可以通过 %flink.conf 来对你的 Flink Cluster 进行非常丰富的配置,但是 %flink.conf 是纯文本的配置,不熟悉 Flink 的人很容易配错(如下图)。如果你是自己做 Flink 开发平台的话就可以做一个更完整的 UI,用一些下拉框等等把一些配置选项固定下来,用户只要选择就行了,不需要自己输入文本来配置。

    image7.png

    还有下面这类 paragraph 的 local properties 配置,比如 type,template, resumeFromLatestCheckpoint 也是比较容易写错的,同理你可以在自己 UI 里用一些控件把这些选项提前固定下来,而不是让用户输入文本的方式。

    image6.png

    我相信 Zeppelin Client API 还有很多可以发挥和想象的空间,大家脑洞起来吧。

    ▼ 视频演示 ▼

    视频演示链接
    https://v.qq.com/x/page/m3146grr5e1.html

    更多 Flink 技术干货及使用交流可加入 Flink 社区钉钉大群。

    最新钉群二维码.jpeg

    ]]>
    闲鱼直播三周内实现点击率翻倍,我们是这么做到的...-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 作者:闲鱼技术-莫癫

    1. 业务背景

    闲鱼直播业务上线后面临的最大问题是增长问题。闲鱼BI同学分析发现,对比短时观看和长时观看人群,发现两部分人群有较明显的兴趣阶段性差异。
    业务希望在理解直播、主播和用户的基础根据兴趣对头部优质直播精准投放, 放大头部主播马太效应实现直播转化和观看时间的增长。

    2. 目标

    简单概括需要达成两个结果:

    • 在三周内实现精准投放平台,沉淀基础运营平台的基础设施;
    • 业务上保证头部直播间场均转化uv达成一定目标,转换率得到明显提升;

    那么单纯借助算法模型实现优质直播推荐,是否也可以达成业务上的目标?然后现实却是,巧妇难为无米之炊。 直播上线时间短, 播放和观看场次有限, 使得模型的训练没有足够的样本直接去理解用户对直播的兴趣, 平台也未对主播直播内容做强控实现内容的结构化。那么就需要将运营对直播领域经验与BI分析、算法结合, 在理解用户、直播和直播间的基础上,实现对直播间到兴趣人群的投放,并沉淀平台化能力。

    3. 实现方案

    给兴趣人群投放实时直播间的第一步是要实现对人的理解,包括C端用户以及主播的理解,其次是直播的理解。理解的结果最终会以兴趣人群、主播人群的方式与页面资源位关联,形成人(用户)货(直播)场(资源位)的初步匹配。


    用户的理解依赖于用户的特征数据,包括闲鱼用户基础特征,搜索、浏览、发布、交易等商品相关行为记录,互动行为特征和用户兴趣标签特征等。这些特征对实时性要求不高,大部分特征通过离线计算产出,后续通过离线计算方式对不同数据来源的特征归一化。


    用户所有特征会同步到人群圈选平台,通过交并差的方式实现人群圈选,进行人群预览和导出。
    直播投放整体设计.png
    平台整体设计


    圈选的人群数据是以userId和人群Id的映射表方式保存离线,与投放的配置进行联合后得到<用户, 资源位, 主播>的关联关系,而后关系数据会同步到图数据库Igraph,提供给算法在线推荐时查询关联直播实现按兴趣推荐和曝光。受限的是整体的曝光流量有额度的,算法会基于模型,在有限PV额度内对在线直播间实现较优的选择。


    下面详细阐述是怎么实现用户理解直播间投放的。

    用户理解

    对用户理解的常规特征生产不是个难事, 而用户的兴趣标签需要针对闲鱼用户从零开始, 弥补这方面能力的缺失。 兴趣标签主要是通过分析用户历史行为产生的行为文本,找出其与领域标签涉及到词组的关联性。 包含如图商品和帖子的各类行为文本,目前数据在逐渐补充中。

    CDAD267B-747D-4790-9311-909702FD01D9.png


    运营会整理不同领域的关键词词组作为输入, 匹配到关联度高的用户关联上领域标签特征。 要实现兴趣标签的产出, 要解决三个问题: 存储、检索和相关度计算。
    image.png
    兴趣标签产出(方案一)


    如图方案一是最初设想方案, 整体流程如下:

    • 关键词结构化: BI同学完成行为文本明细的处理, 包括数据源归一、去重和UDF处理分词, 并根据关键词频次和预设权重算分。 输出结构化后的用户行为文本明细, 包括用户ID、实体ID、关键词列表和关键词对应的分值列表;
    • 打标规则DSL化:对运营输入的行业兴趣关键词组进行分词后转成数据库可执行的DSL;
    • 兴趣用户DUMP: 执行DSL检索出与输入关键词匹配的结构化行为文本, 进行用户去重, 完成用户兴趣标签关联;
    • 人群圈选: 基于用户兴趣标签和其它特征数据做交并差后导出最终人群, 该步骤是在二方人群圈选平台进行;


    整个方案是可行的, 而且具备很好的灵活性, 离线部分可不断完善和丰富结构化行为文本, 工程测专注于DSL可视化优化和整个数据流的流转提效, 整个平台可以良性迭代进化。 但是该方案确难以实行, 主要存在以下问题:

    • 能给的工期短, 要求2到3周完成所有链路功能上线并支撑业务验证, 实现该方案是几乎不可能的;
    • 存储成本巨大, 测算大概需要30PB的在线存储资源, 这对于一个未验证价值的业务来数也是不可能申请到的;


    有同学也许很快发现, 从文本结构化到检索特定兴趣用户的过程不就是一个可以用搜索引擎实现的业务场景吗? 最大的问题仍然是预算问题, 搭建搜索引擎也是个不小的成本,而且从搜索引擎dump大量数据存在着严重的性能问题,同时也无法支持BI同学在整个流程中进行优化。
    4E3F537D-6CCD-4000-9CF7-DC3DD4641255.png
    搜索引擎基本流程


    在线方案是比较理想的, 可以实现运营利用自己的行业经验自助完成兴趣标签关联和人群圈选。由于上述客观条件限制, 最终我们选择了离线关联用户和兴趣标签的方式, 快速接入部分兴趣标签, 而后逐步推进在线方案的方式。 这里得益于BI同学全面的能力, 完成了“离线搜索引擎”, 以及未雨绸缪沉淀了部分用户兴趣标签。 这样整体方案就是这样的:

    • 离线处理非结构化文本,通过去重、分词和算法得到结构化文本(该步骤与方案一相同);
    • 整理领域标签关联的关键词词组
    • 离线计算方式检索匹配关键词词组的用户


    方案二的最大弊端就是通用性没方案一高,每个兴趣标签的产出需要BI开发,只能满足T+1的实时性。但也一些优点,离线存储成本低,离线计算可支持自定义复杂UDF。离线部分更详细的介绍可以参考数据团队的兴趣标签体系实现介绍。
    image.png
    兴趣标签产出(方案二)

    投放实现

    投放分为离线和在线两部分, 运营维护的投放配置存储在RDB (关系型数据库), 需要同步到数据仓库, 离线计算完成用户与兴趣主播关系关联, 形成<用户,兴趣主播列表>关系。 关联的数据同步到在线图关系数据库, 提供算法在兴趣主播中推荐。 整个数据链路需要自动流转, 尽可能及时:

    • 在线配置无法做到实时同步到离线, 目前每一个小时调度一次, 达到准时时要求;
    • 离线任务之间通过依赖任务驱动, 基本能满足准实时行要求,并每次全量更新“用户主播兴趣关系”新增新分区,同时增加与新分区时间一致的done分区;
    • 离线数据同步到在线图数据库是基于数据交换组件, 会定时检查离线表done分区, 有新done分区则会通过同步消息机制进行对应相同时间分区的全量数据更新;

    image.png

    4. 首页效果

    在三周不到的时间,完整链路的平台实现并上线,运营人群圈选、投放配置可在分钟级内完成上线。
    对部分领域的头部直播在首页进行试投放后,效果明显:

    • 所有头部直播间,UV点击数远超目标;
    • 对比大盘,试投放大部分领域PV和UV的点击转化率得到显著提升,最高达到倍数提升;

    5. 展望

    整个项目由于时间比较短, 实现的是兴趣直播投放功能的最小集合, 以支持快速验证并得到较好反馈和结果。在此雏形上,未来会逐渐完善和丰富其能力:

    • 在对接BI兴趣标签的基础上, 需要不断丰富对接兴趣标签等各维度的特征数据能力,同时支持运营同学自助产出通用兴趣标签以及其它特征;
    • 丰富对资源位的投放能力支持,并具备多维度AB方案和多指标通用报表分析能力。能支持更多业务的快速尝试、快速反馈和快速调整;
    • 沉淀和抽象出核心链路, 不局限于支持直播业务, 可以平台化支持更多的社区和非社区业务。同时在理解用户兴趣的基础, 更好的支持理解内容, 实现内容结构化, 实现用户和兴趣内容的低成本运营;


    ~~

    ]]>
    郑荣:世界的香格里拉——从“藏在深闺无人识”到“网红旅游目的地” | 阿里CIO学院名人堂-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 7月中旬,迪庆藏族自治州文化和旅游局宣传推广及对外交流与合作科科长郑荣作为阿里创新学院的学员走进阿里巴巴,参与了为期两天的数智化升级培训班。

    image.png

    带着打造“世界的香格里拉”的决心,郑荣在参会期间认真听取了阿里巴巴关于数字化营销、数字化管理、数字化转型等相关话题的分享,并对此有了更为系统的认识。会后,郑荣接受阿里CIO学院新媒体访谈,分享了他对文旅行业数字化转型的未来构想。

    郑荣先生认为文旅行业的数字化转型主要有三方面的切入点,分别是政府管理、文旅企业以及游客需求。以这三个切入点为引,他为我们分享了迪庆文旅产业以往发展的一些经验,指出了未来在数字化转型这条道路上文旅行业可能会面临的挑战。

    在郑荣先生的构想里,文旅行业未来发展离不开文旅产品和业务的创新,只有创新才能带来发展,让“世界的香格里拉”这一天生具备网红基因的旅游胜地更好地走向全国、走向世界。

    用数字化技术要让传统文旅资源活起来

    阿里CIO学院:郑先生您好,请问这次走进阿里巴巴参与两天的学习交流给您带来的真实感受是什么?

    郑荣:本次学习交流首先让我了解了阿里巴巴的企业文化和业务生态。通过聆听与会专家大咖们的演讲,我对数字化营销、数字化管理、数字化转型和创新等有了系统性的认识,了解到互联网科技发展的最新动态。这次学习对于我今后工作的开展大有裨益,我们将会更深入地探索迪庆文旅产业发展的数字化转型和创新,进一步擦亮“世界的香格里拉”这一品牌。

    阿里CIO学院:您认为文旅行业在数字化转型过程中的切入点是什么?在数字化转型的过程中可能会面临哪些挑战?

    郑荣:我认为文旅行业数字化转型的切入点主要在三个方面。

    一是政府管理,通过数字技术赋能行政部门的公共服务和行业监督,通过智能化管理来构建新服务和新监管的格局。

    二是文旅企业,通过数字技术变革传统文旅商业模式和业态,让传统的文化和旅游资源“活起来”。

    让传统文旅资源活起来,关键是在于融合,包括文化和旅游的融合、资源和数字化技术的融合,从而打造文旅行业新业态。以迪庆州来说,全州现有县级以上非遗项目200余项,但是更多的是“藏在深闺无人识”。随着旅游业的发展,我们提出了开发“非遗之旅”的策略,让游客在欣赏自然风光之外,可以选择体验尼西黑陶制作、唐卡绘画、藏香制作等延续千年的藏族传统文化。同时,以具有民族代表性的非遗项目为载体,创意设计研发文创旅游产品,也是文化和旅游融合最佳途径之一。

    而借助最前沿的数字化技术,以文化和旅游资源打造线上虚拟景区、线上虚拟博物馆,将使得文旅资源没有障碍地触达更广泛的人群。

    三是游客需求。数字化技术正在不断地影响着游客的行为和体验认知,游客的个性化需求越来越明显。随着移动互联网技术发展,我们已经进入了个性化定制时代,旅游业也正从传统大众观光游时代走向个性化消费时代转变。

    个性化需求的表现有很多市场细分,比如追求新鲜和新奇、寻求新潮和心跳、偏爱自驾和小团体出游,讲究游玩的主题和深度游,还有追求豪华和野趣等。

    应对旅游的个性化需求,首先我们要加强大数据收集、分析和运用,通过大数据分析形成旅游消费者画像,从而形成人群细分,挖掘不同人群的个性化需求,在此基础上进行旅游线路产品的设计和开发。数字化技术的应用可以提供更受游客青睐的交互式、沉浸式的旅行体验。

    关于旅游业的数字化转型的挑战,我觉得首要是人才的瓶颈,尤其是在我们云南迪庆州,数字化技术人才是相当稀缺的,这也是制约我们实施数字化转型和创新的最大难题。其次,文旅数字化转型不能狭隘地停留在单一的政府部门或企业行动上,而应该从整个文旅行业发展角度出发,要有整体性的数字化转型规划和推进策略。

    举例而言,在数字化转型过程中,迪庆州文旅局不断强化在旅游管理和服务上的数字化运用,同时不断地引导文旅企业搭上数字化转型的列车,推动主要景区加强数字信息化技术的应用。

    从目前我们的经验来说,就是要避免政府一手包办,文旅部门更多扮演的是牵头引导的角色,更主要的是发挥文旅企业的积极能动性,让他们在项目运作中感受到切实的利益和收获,不断提升文旅企业对数字化转型的认知。比如:2019年迪庆州文旅局与抖音合作开展的“世界的香格里拉”抖音全国互动挑战赛,由文旅局牵头落实,旅游企业和主要景区共同承担费用,同时也是活动的主角取得了不错的成效。

    文旅产业数字化转型营销要先行

    阿里CIO学院:您认为在数字化转型的路上,文旅行业产品与业务创新应该如何变化?数据智能将会对文旅行业的行业格局带来怎样的变化?

    郑荣:文旅产品和业务创新表现在以下几个方面:

    首先是要加强数字化技术的应用。从VR、AR到人工智能、大数据、云计算、物联网、5G等,文旅企业应该通过这些技术手段的应用,不断推动传统文化和旅游资源深度融合,进行文旅产品的革新,推出更具有交互性和沉浸式的文旅新产品。

    其次,数字化转型目前对于迪庆文旅企业的改变主要体现在营销宣传和景区服务上。目前越来越多的景区已经装载了智慧讲解、智慧门禁、智慧停车场等服务设施,使得景区的服务水平和游客体验有了一定的提升。其次,文旅企业通过互联网新媒体开展品牌、产品营销宣传的意识不断增强,可以让游客消费者多渠道多维度的了解认识迪庆的多民族传统文化和壮丽的自然景观。对于旅游景区而言,应该通过数字化技术的运用,打造“智慧景区”,提升景区的整体服务水平,给广大游客创造更好的旅行体验。

    再次,文旅产品的营销上,要注重挖掘游客的新体验和新需求,并借用数字技术手段进行人群细分、目标精准的营销推广。近年来,迪庆不断推进非物质文化遗产的数字化记录工作,利用图文、音视频等手段进行非遗资源采集,构建非遗数据库。

    数字化采集记录将非遗项目立体留存下来,可以让更多人熟悉、了解、喜欢迪庆的民族文化瑰宝,通过互联网等传播途径,也让非遗文化传播到更广阔的时空。

    数字化转型和数字化营销取得明显提升

    阿里CIO学院:在数字化转型这条道路上,有什么成功或失败的经验能和我们分享的吗?

    郑荣:近年来,迪庆州文旅局一直在探索文旅行业的数字化转型,逐步积累了一些经验。自2018年开始,迪庆州全面推进智慧景区建设,包括智慧门禁系统、智慧停车场、智慧厕所、电子导游等,景区的数字化水平得到明显提升。

    image.png

    数字化营销宣传也是迪庆州文旅局近年重点发力的方向,迪庆文旅与人民网、新华网、中国网、携程、抖音、微信、微博、新浪、网易以及海外的Google(谷歌)、Facebook(脸书)、YouTube(优兔)等众多平台开展合作,以互联网新媒体营销将香格里拉打造成为全国“网红旅游目的地”。在目前的互联网新媒体合作中,最成功的案例当属2019年与抖音合作开展的“世界的香格里拉”抖音全国互动挑战赛,本次挑战赛在云南省首开先河,以迪庆州文旅局牵头,联合迪庆州内主要景区共同参与。

    本次挑战赛期间有30余人次的知名网红来到迪庆,为迪庆文旅拍摄创意短视频。挑战赛覆盖网民超过5000万+人次,优质短视频参与数量超过50000+,挑战赛话题播放量达7亿次,视频点赞超过1000万+。

    虽然取得了一些成绩,但对于迪庆文旅行业长远发展来讲,无论是政府职能部门还是行业企业,实施数字化转型和创新依然任重道远。

    迪庆藏族自治州文化和旅游局介绍

    image.png

    2019年3月11日,新组建的迪庆藏族自治州文化和旅游局正式挂牌,香格里拉市、德钦县、维西县等县市级文化和旅游局相继挂牌,标志着迪庆州文化和旅游迈出了深度融合的步伐。

    十三五”期间,州委、州政府高度重视文化和旅游融合发展,主要领导亲自部署,分管领导全力以赴,狠抓落实,在全州上下形成了重视文化和旅游融合、大抓文化和旅游发展的良好氛围。

    通过不断优化文化旅游营造软环境,吸引了一批优秀的民营企业在迪庆的长期旅游投资建设,如巴拉格宗、松赞精品山居、独克宗花巷等一批重量级旅游项目均是由民间企业投资并成功运营。

    近年来,迪庆州把 “世界的香格里拉”品牌宣传和旅游产品营销有机结合,创新方式,积极参加国际国内旅游宣传促销,组织开展昆明、上海、北京、成都等主要客源市场的旅游宣传营销活动,大力宣传推广迪庆冬季旅游产品和线路,冬季节庆活动和非遗产品,开通“世界的香格里拉”文化和旅游官方抖音号。

    迪庆州邀请中央权威媒体以及旅游卫视、旅游报、文化报、经济网、中国日报、新华网、人民网等家媒体到迪庆开展以“旅游扶贫”为主题采风活动。通过线上线下、传统媒体与新媒体相结合,形成综合旅游品牌影响力、旅游产品吸引力、旅游价格竞争力的立体宣传营销体系,扩大了迪庆州在国内外的影响力,促进了客源市场的稳步增长。

    据了解,随着旅游产业的不断发展,旅游产业链不断扩大,截至目前我州旅游从业人员达12.6万人,占全州总人口的30.7%,其中旅游直接从业人员达2.6万人,间接从业人员达10万人,切实解决了就业难问题。二是景区反哺带动旅游扶贫。到2018年,全州景区直接及间接带动村民共涉及5600余户,28000多人,每年总收入7000多万,平均每户年增收12600多元,人均达2520元左右。

    文章来源:阿里飞天CIO学堂微信公众号

    名人堂

    名人堂是阿里CIO学院打造的一档大伽访谈栏目,每周一期。以推动企业创新与数智化升级为愿景,通过采访行业顶尖客户,帮你更好地了解和思考企业数字化转型中可能面临的挑战,梳理行业痛点和方法路径,从而相互滋养,共同成长。

    更多文章

    点击查看青岛华通集团智能研究院明磊:拥抱数字化转型正在成为CIO头等大事 | 阿里CIO学院名人堂>>>

    点击查看ERIC,ZHANG:地产业数字化转型按下“加速键”美好人居正当时 | 阿里CIO学院名人堂>>>

    点击查看李锋:联接数智化生态,打造“数字化越秀” | 阿里CIO学院名人堂>>>

    点击查看龙湘君:基金行业奏响数字化转型五部曲 | 阿里CIO学院名人堂>>>

    点击查看段晓力:从一个小目标的对立 到万个小目标的融合 | 阿里CIO学院名人堂>>>

    点击查看贾坤:扶贫基金事业借数字化转型助力决胜脱贫攻坚战 | 阿里CIO学院名人堂>>>

    ]]>
    中华保险荣获IDC大奖,阿里云、蚂蚁金融科技成“助推器”-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 8月28日,知名调研机构IDC中国举办线上的“2020 IDC中国未来金融论坛暨颁奖典礼”,中华保险“理赔服务资源管理系统”凭借创新的金融业务场景和技术应用,荣获中国金融行业技术应用场景创新奖。本次获奖意味着中华保险的数字化创新能力受到权威机构的认可与肯定。

    0005.jpg

    作为全球知名的IT市场研究机构,IDC一直密切关注着中国金融行业的发展与变革。今年是IDC主办的第六届中国未来金融论坛暨颁奖典礼,基于金融云、普惠金融、智慧网点等金融行业技术应用场景,共有近150个优秀项目参与评选。此次获奖的“理赔服务资源管理系统”借助金融云分布式架构和AI等技术,以数据为驱动,分析渠道和客户,灵活调配资源,集中资源响应优质客户的谈判,进而改善车商渠道业务的经营状况。

    IDC评价,该项目通过重塑送修服务流程与管理模式,在提高理赔客服工作效率的同时,实际的送修成功率有效提升,进而促进车商渠道业务的增长,实现车商业务的精细化管理和高质量发展。同时,迎合线上化理赔发展趋势,解决客户等待时间过长、服务不连贯、体验不佳等问题,推动传统经营模型向数字化智能化转型。

    中华保险始创于1986年7月15日,2002年,经国务院批复同意,冠名“中华”,成为全国唯一一家以“中华”冠名的国有控股保险公司,市场规模位居国内财险市场第五,农险业务规模稳居全国第二。当前,中华保险正在加速数字化转型进程,希望通过建设新一代核心业务系统,推进保险业务朝着线上化、数字化、智能化方向发展。

    据了解,中华保险新一代核心业务系统采用阿里云全套专有云平台、数据中台、业务中台与金融科技产品,并创新性地引入金融云公共平台。整个方案包含“飞天”云计算操作系统蚂蚁金融分布式架构 SOFAStack分布式数据库OceanBase金融数据智能平台金融核心套件bPaaS保险专家服务mPaaS移动开发平台金融钉钉等一系列产品技术与服务,助力中华保险加速“数字中华”建设。

    “我们希望未来能变成一家真正以客户为中心,科技和创新驱动的保险公司”,中华财险相关负责人表示,对保险行业来讲,这次与阿里云合作可能是业内第一次有保险公司完完整整地去重构业务模式、业务理念以及IT配套。

    目前,包括蚂蚁移动开发平台mPaaS、金融级分布式架构SOFAStack、企业级分布式关系数据库OceanBase等在内的产品和解决方案正通过阿里云新金融统一对外输出,服务各种类型的金融机构。未来,还会有越来越多的蚂蚁技术产品通过阿里云新金融对外输出,全力助推金融客户完成金融数字化转型。

    蚂蚁SOFAStack白皮书已于近期发布,点击此处即可获取。

    ]]>
    开源直播系统源码,为什么一定要使用PHP语言开发-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 进行开源直播系统源码的开发工作时,开发者们遇到的最多问题就是使用什么语言开发的,回答大多是PHP语言。对于没有开发经验的人来说,很难理解PHP语言到底代表着什么,又有哪些作用。

    直播2.jpg

    其实,PHP是一种开源脚本语言。语法吸收了C语言、java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。
    PHP由内核Zend引擎和扩展层组成,PHP内核负责处理请求、完成文件流错误处理等操作,Zend引擎可以将PHP程序文件转换成刻在虚拟机上运行的机器语言,扩展层提供一些应用层操作需要的函数类库等,比如数组和MySQL数据库的操作等。
    开源直播系统源码Zend引擎是用C语言实现的,将PHP代码通过词法语法解析成可执行的opcode并实现相应的处理方法和基本的数据结构进行内存分配和管理等,对外提供相应的可供调用的API方法。Zend引擎是PHP的核心,所有的外围功能都是围绕它实现的。扩展层通过组件的方式提供各种基础服务、内置函数,标准库都是通过它实现的。用户也可以编写自己开源直播系统源码的扩展来实现特定的需求。服务端应用编程接口,通过一系列钩子函数使得PHP可以和外围交互数据。我们平时开源直播系统源码编写的PHP程序就是通过不同的SAPI方式得到不同的应用模式,如通过web实现的web应用和命令下运行的脚本等。

    直播11.jpg

    作为开源直播系统的开发语言,PHP语言的优势在于:
    1.PHP的开发成本低,入门学习快,语法也相对简单,并且提供丰富的类库
    2.PHP与Linux、Nginx、Apache、MySQL可以方便快捷的搭建出一套系统,支持直接调用系统命令,用代码完成许多操作Linux的工作

    直播12.jpg

    3.PHP支持使用多种数据库,其中与MySQL的结合是最为流行的,PHP提供三种链接MySQL的扩展。PDO扩展是PHP退出的连接MySQL和其他类型的数据库的一种统一解决方案。可移植性很高,使用它可以灵活方便的切换不同类型的数据库,而且不需要变动更多的代码
    4.PHP是解释执行的脚本语言,写完程序后,可以立即执行,所以它的开发效率很高
    声明:以上内容为云豹科技作者本人原创,未经作者本人同意,禁止转载,否则将追究相关法律责任

    ]]>
    想提升专业技能?阿里云9月ECS和AI千人训练营为你助力!!-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 阿里云高校计划首次 ECS千人训练营即将来袭,9月高校计划ECS和AI训练营等你来参加!获取云计算和AI项目经验和提升技术技能!UP! UP!

    1598866732841-5a27afab-d8f9-43f7-9861-d84ee934c82a.png

    阿里云高校计划团队精心设计的ECS课程,从0开始学习云计算,7天3个项目带你快速积累云计算项目经验;AI训练营五天三个云上AI项目,手把手带你入门视觉AI

    ECS高校训练营:入门班和进阶班
    每班只招500人,入门+进阶共招1000人
    AI训练营仅招100人


    ECS训练营参与进阶班的同学完成打卡+任务+作业就发ACA资格!阿里奖品多多!同时,这次的AI训练营仅招100人,高校的同学们一定不要错过这次机会!

    记好这些时间呦
    ECS训练营
    报名参营
    • 报名开始时间:9月17日 10:00(可能提前开始)
    • 报名结束时间:9月20日 24:00
    上课打卡
    • 打卡开始时间:9月23日
    • 打卡结束时间:9月28日


    AI训练营

    报名参营
    报名开始时间:9月17日 10:00
    报名结束时间:9月20日 24:00
    上课打卡
    打卡开始时间:9月24日
    打卡结束时间:9月28日

    敲重点!
    ECS训练营是什么?


    ECS 7天实践训练营由阿里云高校计划发起,旨在帮助对云计算感兴趣的同学更好地开展云上实践、积累项目经验,为云计算人才成长助力。训练营由阿里云大学资深讲师和技术大咖联手策划,陪你动手上云实践。

    ECS训练营有什么?


    ECS训练营有阿里云高校计划精心准备的课程,建网站做项目,能让你快速积累项目经验,完成作业和打卡就可以获得699元阿里云ACA官方认证考试资格。7天,每天30分钟,云计算技能全方位提升,为你的升学就业加分!

    训练营路线怎么选?


    根据你的技术学习水平进行选择。入门班/新手路线适合0基础云计算小白,进阶班适合学过“新手路线” or 有一定云计算基础以及想要考ACA的同学,如果你想为你的简历增加闪光点一定要来报名参加ECS训练营。

    AI训练营是什么?


    视觉AI训练营四位导师带你入门视觉AI,体验AI技术。五天时间完成身份证识别、人脸+表情识别、车辆保险等云上项目,快速入门视觉AI,为求学升职加分。你的AI第一课,阿里云陪你完成!

    阿里云高校计划训练营为什么值得来?
    团队学习,进步更快

    同学们根据自己的技术水平报名了ECS训练营入门班和进阶班和AI训练营报名参营后,将与来自全国高校的同学们一起组团进行7天的ECS训练营和5天的AI训练营学习。同学们会竞选班长和组长,成班成组进行学习,每天要按时交作业——学习笔记,会有严格的学习监督机制,督促你学习成长。

    开营结营直播助力学习


    为了帮助同学们了解训练营和认识同学们,我们会在9.22日召开ECS训练营开营直播和9.23进行AI训练营开营直播,并在9月28日进行结营直播。直播中我们会邀请往期参营和考过ACA的同学为大家分享经验,解答问题。开营直播更有两轮抽奖送出阿里周边。

    精美丰厚奖品等你拿


    开营直播两轮抽奖送阿里周边好礼
    精选笔记送好礼:好的学习笔记可以帮助你学习和成长,我们会挑选好的学习笔记,大家共同-学习成长,被精选笔记的同学会收到阿里周边奖品。

    头条抽奖 3个阿里云棒球帽

    DOWLO_f09f703c3121987d23dd0385f46cb3b0 (2).jpg

    微博抽奖:3个阿里云棒球帽

    DOWLO_f09f703c3121987d23dd0385f46cb3b0 (2).jpg

    预热直播抽奖 7个 阿里云公仔 有奖问答送三本《弹性计算》书籍
    开营直播抽奖 7个 阿里云公仔 有奖问答送三本《弹性计算》书籍

    IMG_8256.JPG

    阿里云公仔

    1598958068042-d2b38e34-bf52-4fb5-8b56-1d4547b38ec0.png


    《弹性计算》



    参营:打卡+完成作业 送ACA考试资格(进阶班)
    优秀笔记获奖者 送阿里云笔记本
    ECS 入门班送12本阿里云笔记本
    ECS 进阶班送12本阿里云笔记本
    AI训练营送6本阿里云笔记本


    IMG_8238.JPG
    IMG_8239.JPG

    阿里精美笔记本

    结营直播:
    优秀营员(群里表现积极活跃+每日打卡+按时完成作业)三营共评选20人 送阿里棒球帽

    DOWLO_f09f703c3121987d23dd0385f46cb3b0 (2).jpg

    优秀组长和班长 评选3人 送阿里云徽章


    lALPGqGobAkQy1_NAXbNAZc_407_374.png


    想看往期同学参营感想,点这里:
    https://mp.weixin.qq.com/s/T399HWt86EgM5UvEAMM_eg

    报名及收取最新开营消息见下图

    步骤.jpg

    附上课程路线
    · ECS 7天训练营(新人路线)
    o 9月23日:阿里云云服务器ECS介绍https://developer.aliyun.com/lesson_46_6557#_6557
    o 9月24日: ECS服务器购买和准备https://developer.aliyun.com/lesson_71_18415#_18415
    o 9月25日: ECS云服务器新手上路https://developer.aliyun.com/adc/scenario/410e5b6a852f4b4b88bf74bf4c197a57
    o 9月26日:安装Putty工具远程连接ECS服务器 https://developer.aliyun.com/lesson_71_18416#_18416
    o 9月27日:安装Linux服务器面板管理工具 https://developer.aliyun.com/lesson_71_18417#_18417
    o 9月28日:快速搭建LAMP环境
    https://developer.aliyun.com/adc/scenario/6869de098ad44fc8a1560a1836a7c5f2
    · ECS 7天训练营(进阶路线)
    o 9月23日:基于ECS搭建FTP服务
    https://developer.aliyun.com/adc/scenario/74b64efe414c47fbaf305957a7fb458b
    o 9月24日:快速搭建Docker环境
    https://developer.aliyun.com/adc/scenario/9fd79b8711984e309f20d82bc65a26fa
    o 9月25日:ECS+SLB 负载均衡实践https://developer.aliyun.com/adc/scenario/d82547cc96d74b43a3027e0dc018cf1c
    o 9月26日:使用ECS和PolarDB搭建门户网站https://developer.aliyun.com/adc/scenario/a7161434e6cd499e9e26f2e62d0242fb
    o 9月27日:搭建个人Leanote云笔记本 https://developer.aliyun.com/adc/scenario/b1ac9deecdb143469de985471b440aa7
    o 9月28日:案例分享——钉钉 https://developer.aliyun.com/lesson_46_1538#_1538

    AI训练营
    · 打卡开始时间:9月24日
    · 打卡结束时间:9月28日

    课程路线
    · 9月24日:达摩院视觉AI技术应用探索https://developer.aliyun.com/live/2761?spm=a2c6h.14795454.J_4770946980.3.3a065794QAk5ML
    · 9月25日:身份证识别系统搭建 https://developer.aliyun.com/live/2762?spm=a2c6h.14795454.J_4770946980.4.3a065794HT7Kl7
    · 9月26日:电子相册搭建(人脸、表情识别)https://developer.aliyun.com/live/2763?spm=a2c6h.14795454.J_4770946980.5.3a065794ramEfR
    · 9月27日:作业日-车辆保险应用
    · 9月28日:创意日-你的图像识别项目

    ]]>
    Apache的代码居然也有"bug"?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 引言

    二狗:二胖快醒醒,赶紧看看刚才报警邮件,你上次写的保存用户接口耗时(《二胖的参数校验坎坷之路》)大大上升,赶紧排查下原因。
    二胖:好的,马上看,内心戏可十足(心里却在抱怨,大中午的搅我发财美梦,刚刚梦见我买的股票又涨停了就被叫醒了)。牢骚归牢骚,自己的问题还是得看啊,毕竟是自己写的bug,含着泪也要把它修复掉。二胖对分析这种问题还是得心应手的,毕竟已经是久经职场的老油条了。

    测试环境复现问题

    二胖首先通过内部的监控工具看了下这段时间的网络是否正常,以及cpu的使用情况、数据库的耗时等,这些指标看起来都是正常的,唯一稍微有点区别的是这段时间流量上涨了一些,肯定又是公司花钱搞营销砸广告了。接着二胖又通过cat(大众点评开源监控工具)分析了几个请求,每个阶段的耗时看下来都ok。卧槽这可咋办列居然难倒二胖了,如果生产环境问题可以在测试环境复现就好了,这样解觉问题就简单多了。生产不是流量上涨了一些吗?那测试环境来压测一把吧,二胖果断的下载了一个jmeter(压测工具)在测试环境进行了一把疯狂的压测,果然出现了和生产一样的问题。能够复现问题就好,这样离解决问题就近了一大步。

    arthas定位问题

    问题是复现了,接下来就是找出接口比较耗时的地方了。一般我们找接口耗时较长的地方,都是通过记录日志打印每一步的耗时。这是比较常见做法,不过二胖记得上次部门技术大拿“二狗”分享过一个神器arthas可以输出方法路径上的每个节点上耗时。苦于一直没有机会拿它来用于实际操作,今天终于可以拿它来好好练手了。安装什么的就不介绍了,这个官网都写的比较详细,并且文档也是中文的,非常容易上手。下面我们就来使用下arthas吧。
    启动成功的界面
    在这里插入图片描述
    下面我们根据arthas提供的trace命令来看看接口的耗时都是在哪里。
    在这里插入图片描述我们从上面可以看出主要耗时是集中在 org.apache.commons.beanutils.BeanUtils#copyProperties这个方法上面的,不就一个实体之间的属性赋值转换吗,需要这么耗时这么久吗?不科学啊,apache提供的方法还能这么low吗?带着这些问题我们看看其他提供的属性拷贝的工具类效率如何。

    使用JMH对常见属性赋值操作性能比较

    • 使用getset方法复制。
    • cglibBeanCopier
    • SpringBeanUtils
    • apacheBeanUtils
    • MapStruct
      下面我们就来对上面这些操作来进行一波性能比较。

    编写下面的测试类。

    /**
     * @author:
     * @Date: 2020/7/11
     * @Description:
     */
    @BenchmarkMode(Mode.AverageTime)
    @Warmup(iterations = 3, time = 1)
    @Measurement(iterations = 5, time = 5)
    @Threads(6)
    @Fork(1)
    @State(value = Scope.Benchmark)
    @OutputTimeUnit(TimeUnit.NANOSECONDS)
    public class BeanCopyTest {
        @Param(value = {"1","10","100"})
        private int count;
    
        public UserBO bo;
    
        public  BeanCopier copier;
    
        @Setup(Level.Trial) // 初始化方法,在全部Benchmark运行之前进行
        public void init() {
            copier = BeanCopier.create(UserBO.class, UserVO.class, false);
            bo = new UserBO();
            bo.setUserName("java金融");
            bo.setAge(1);
            bo.setIdCard("88888888");
            bo.setEmail("java金融@qq.com");
        }
    
    
        public static void main(String[] args) throws RunnerException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
           Options opt = new OptionsBuilder().include(BeanCopyTest.class.getSimpleName()).result("result.json").resultFormat(ResultFormatType.JSON).build();
            new Runner(opt).run();
    
        }
    
        /**
         * 使用mapStruct来操作
         */
        @Benchmark
        public void mapStruct() {
            for (int i = 1; i <= count; i++) {
                UserVO vo = UserMapping.INSTANCE.converter(bo);
            }
        }
    
        /**
         * 手动set和Get
         */
        @Benchmark
        public void setAndGet() {
            for (int i = 1; i <= count; i++) {
                UserVO userVO = new UserVO();
                userVO.setUserName(bo.getUserName());
                userVO.setEmail(bo.getEmail());
                userVO.setSex(bo.getSex());
                userVO.setIdCard(bo.getIdCard());
                userVO.setAge(bo.getAge());
            }
        }
    
        /**
         * 使用cglib的copy方法
         */
        @Benchmark
        public void cglibBeanCopier() {
            for (int i = 1; i <= count; i++) {
                UserVO vo = new UserVO();
                copier.copy(bo, vo, null);
            }
        }
    
        /**
         * 使用spring提供的copyProperties方法
         */
        @Benchmark
        public void springBeanUtils() {
            for (int i = 1; i <= count; i++) {
                UserVO vo = new UserVO();
                BeanUtils.copyProperties(bo, vo);
            }
        }
    
        /**
         * 使用apache的copyProperties方法
         * @throws InvocationTargetException
         * @throws IllegalAccessException
         */
        @Benchmark
        public void apacheBeanUtils() throws InvocationTargetException, IllegalAccessException {
            for (int i = 1; i <= count; i++) {
                UserVO vo = new UserVO();
                org.apache.commons.beanutils.BeanUtils.copyProperties(vo, bo);
            }
        }

    最后的测试结果如下所示:

    Benchmark                     (count)  Mode  Cnt          Score          Error  Units
    BeanCopyTest.apacheBeanUtils        1  avgt    5    2462103.419 ±  2292830.495  ns/op
    BeanCopyTest.apacheBeanUtils       10  avgt    5   21025926.689 ± 11254755.603  ns/op
    BeanCopyTest.apacheBeanUtils      100  avgt    5  193235312.113 ± 37929707.246  ns/op
    BeanCopyTest.cglibBeanCopier        1  avgt    5          4.936 ±        1.187  ns/op
    BeanCopyTest.cglibBeanCopier       10  avgt    5          4.820 ±        1.963  ns/op
    BeanCopyTest.cglibBeanCopier      100  avgt    5          4.269 ±        0.890  ns/op
    BeanCopyTest.mapStruct              1  avgt    5          4.809 ±        1.720  ns/op
    BeanCopyTest.mapStruct             10  avgt    5          4.947 ±        1.320  ns/op
    BeanCopyTest.mapStruct            100  avgt    5          4.440 ±        1.191  ns/op
    BeanCopyTest.setAndGet              1  avgt    5          3.780 ±        1.785  ns/op
    BeanCopyTest.setAndGet             10  avgt    5          3.930 ±        1.788  ns/op
    BeanCopyTest.setAndGet            100  avgt    5          4.069 ±        2.181  ns/op
    BeanCopyTest.springBeanUtils        1  avgt    5       1190.563 ±      165.574  ns/op
    BeanCopyTest.springBeanUtils       10  avgt    5      10887.244 ±     1228.026  ns/op
    BeanCopyTest.springBeanUtils      100  avgt    5     109686.562 ±     7485.261  ns/op

    在这里插入图片描述

    • 从上述结论中我们可以发现性能最好的是排名 用getset方法复制,其次是mapStructcglib的BeanCopier,再接着是Spring的beanUtils,最后的是apache的BeanUtils
    • 如果对上述测试性能感兴趣的话,代码都已上传到github上可自行下载运行对比下结果。代码地址
    • 关于对JMH的使用就不介绍了,感兴趣的可自行谷歌。不过如果要进行性能比较的话,真心推荐使用下,结果可以通过导出json文件然后生成图表。

    为什么apacheBeanUtils性能最差

    apacheBeanUtilsspringbeanUtils都是底层都是使用反射来进行赋值的,为什么apacheBeanUtils的性能要差一大截列。源码之下无秘密,下面我们来看看这个方法的源码。
    在这里插入图片描述
    Apache BeanUtils 打印了大量的日志、以及各种转换、类型的判断等等导致性能变差。

    • springbeanUtil直接使用反射省,干净利索,核心代码见下图。
      在这里插入图片描述
    • 其实在《阿里巴巴开发手册》(可在公众号【java金融】回复“泰山”获取)里面也有说明属性的copy避免使用apcheBeanUtils
      在这里插入图片描述
    • 如果生产环境已经大量使用Apache BeanUtils的话需要替换spring BeanUtils的话需要注意下他们两个虽然提供的方法都是copyProperties但是他们的参数是反的,这点需要注意下,不要直接换个引入的包名完事。

    总结

    • 实际使用中的话一般是不会使用getset方法复制,容易漏掉属性并且也是一个体力活。推荐使用mapStruct,在编译过程中,MapStruct将生成该接口的实现,并且它还可以实现不同名字的映射,比如可以把name映射到username,灵活性比较高。
    • 二胖感觉今天收获满满啊,一下学到了jmeterarthasJMH三个软件的使用。

    结束

    • 由于自己才疏学浅,难免会有纰漏,假如你发现了错误的地方,还望留言给我指出来,我会对其加以修正。
    • 如果你觉得文章还不错,你的转发、分享、赞赏、点赞、留言就是对我最大的鼓励。
    • 感谢您的阅读,十分欢迎并感谢您的关注。
      在这里插入图片描述
    ]]>
    开源 Flink + 实时计算 Flink 版训练营学习资料汇总-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 Apache Flink:全球领先的开源大数据计算引擎

    Apache Flink 是一个开源的分布式大数据处理引擎, 可对有限数据流和无限数据流进行有状态计算。作为 Apache 软件基金会 (ASF) 顶级项目之一,Flink 在流处理方面具有绝对的优势,提供高吞吐、低延时的计算能力, Exactly-once 语义保证数据的准确性,亚秒级别的处理延迟确保业务的快速响应。

    作为快速发展的新一代大数据引擎,Flink 本身的架构优势也吸引着越来越多的开源爱好者投入到社区的建设来。 截止到 2020 年 7 月,社区的 star 数达到 13600+ ,contributor 数达到 718,有 22989 次 commits。伴随着社区的快速发展,Flink 也成为类似阿里巴巴、腾讯、字节跳动、滴滴、美团点评等知名公司建设流处理平台的首选。

    【推荐阅读】

    Flink 社区技术发展风向标

    重磅!Apache Flink 1.11 功能前瞻抢先看!

    更易用!Hive 集成弯道超车

    Hive 终于等来了 Flink

    Flink PMC 联合各大厂用人主管助你升职加薪

    Flink 面试指南

    【企业案例】

    OPPO 实时数仓揭秘:从顶层设计实现离线与实时的平滑迁移
    单日总数据处理量超 10 万亿,峰值超每秒 3 亿
    bilibili 实时平台的架构与实践
    基于 Flink 的 bilibili Saber 实时计算平台
    美团点评基于 Flink 的实时数仓平台实践
    深度解析美团点评实时数仓案例

    【电子书】

    《零基础入门:从 0 到 1 学会 Apache Flink》
    30 天成长为 Flink 大神
    《Apache Flink 年度最佳实践》
    国内外一线大厂超大规模最佳实践案例合集

    阿里云实时计算 Flink 版

    实时计算 Flink版(Alibaba Cloud Realtime Compute for Apache Flink,Powered by Ververica))是阿里云提供的基于 Apache Flink 构建的企业级、高性能实时大数据处理系统,由Apache Flink创始团队官方出品。在 PB 级别的数据集上可以支持亚秒级别的处理延时,赋能用户标准实时数据处理流程和行业解决方案;在支持 Datastream API 作业开发的同时,提供了完整的SQL语义,使得 BI 场景下的开发变得更加简单;丰富的上下游 connector 保证了与用户已使用的大数据组件无缝对接;智能作业调优和诊断功能进一步简化了用户的开发和使用。

    实时计算 Flink版在 Apache Flink 核心功能的基础上还增强了企业用户所关注的集群稳定、性能优化、安全控制、系统监控和作业管理等。阿里云实时计算团队目前是全球最大、拥有 Committer 数量最多、专业性最强的 Flink 团队,为实时计算用户提供企业级的管理和咨询服务。2019 年 6 月,由数据中心联盟发起的大数据产品能力评测结果权威发布,阿里云实时计算 Flink版通过最新制定的分布式流处理平台基础能力评测,成为国内首批通过流计算产品能力评测的产品,并被数据中心联盟圈定为国内大数据流计算基础平台第一梯队。2020 年在国际知名咨询调研公司Forrester 的测评中,实时计算 Flink版成为中国唯一进入Forrester象限的实时流计算产品。

    【独享月度特惠】开通实时计算产品:

    master型号4核16GB+master数量1+slave型号4核16GB+slave数量2,计费周期1个月,详情:

    https://common-buy.aliyun.com/?spm=a2c0j.14094430.1053885.bnt1.307976feKRl1Au&commodityCode=blinkonecs#/buy
    Tips:开通成功算打卡成功

    解决方案

    [实时计算 Flink:基于 Apache Flink 构建的大数据计算平台(附白皮书)
    ](https://developer.aliyun.com/article/770133?groupCode=sc)

    Tips:完成PDF阅读,算打卡成功)

    最佳实践

    实时计算 Flink 版 最佳实践

    Tips:完成文章阅读,算打卡成功

    ]]>
    进击的Kubernetes调度系统(三):支持批任务的Binpack Scheduling Thu, 29 Oct 2020 12:16:15 +0800 作者:王庆璨 张凯

    进击的Kubernetes调度系统(一):Scheduling Framework
    进击的Kubernetes调度系统(二):支持批任务的Coscheduling/Gang scheduling
    进击的Kubernetes调度系统(三):支持批任务的Binpack Scheduling

    前言

    本系列的前两篇《进击的Kubernetes调度系统 (一):Scheduling Framework》进击的 Kubernetes 调度系统(二):支持批任务的 Coscheduling/Gang scheduling 分别介绍了Kubernetes Scheduling Framework和如何通过扩展Scheduling Framework实现Coscheduling/Gang scheduling调度策略。当我们的批任务作业在集群里边运行起来之后,随后要关注的就是资源的利用率。特别是对于GPU卡的价格昂贵,不希望有资源的浪费。本文将介绍在批任务的调度过程中如何通过Binpack的方式,减少资源碎片,提升GPU的利用率。

    为什么需要Binpack功能?

    Kubernetes默认开启的资源调度策略是LeastRequestedPriority,消耗的资源最少的节点会优先被调度,使得整体集群的资源使用在所有节点之间分配地相对均匀。但是这种调度策略往往也会在单个节点上产生较多资源碎片。

    下面拿一个简单的例子来说明这种问题。如下图所示,资源在节点之间平均使用,所以每个节点使用3个GPU卡,则两个节点各剩余1GPU的资源。这是有申请2GPU的新作业,提交到调度器,则因为无法提供足够的资源,导致调度失败。


    1587092661680-55bf016c-e041-47b8-8bc4-2b49db8f90ff.png
    ]]> 解读Knative 0.17.0版本特性 Thu, 29 Oct 2020 12:16:15 +0800 前言

    Knative 0.17.0 版本已于近期发布,对于 Knative v0.17.0 版本新特性,我们进行解读,让大家对 Knative 新版本快速了解。
    Knative 0.17.0 支持 k8s 最小支持版本为:1.16。

    Serving

    Autoscaling-自动扩缩容

    • 1)支持Revision初始POD数设置
      在0.17.0之前的版本中,创建新的Revision(即使新Revision流量比例为0)默认会先创建出 1 个POD实例,新的POD创建完成之后,如果没有流量,缩容为 0。 其实大多数场景下,新的Revision创建完成之后不需要立刻创建出POD。从0.17.0开始引入 inital scale 参数,可以指定新的 Revision 为 0。

    inital scale 参数可以通过注释设置:

    autoscaling.internal.knative.dev/initialScale

    核心 API

    组件HA高可用支持

    从0.17.0版本开始,默认开启组件HA,可以通过配置参数‘--disable-ha’ 关闭HA。

    Knative Service 特性支持

    • 1) 对 affinity, nodeSelector, tolerations 和 securitycontext 进行了支持。对于该特性的支持比较意外,因为该特性很早就被提出过,但开始的社区的反馈是 serverless(no server) 场景下不应该关心节点的调度。目前来看结合实际的使用需求场景,最终社区做出了妥协。
    • 2) 新增全局最大扩容Pod配置参数max-value,当没有设置autoscaling.knative.dev/maxScale值时,使用该全局配置作为最大扩容Pod。
    • 3) 优化 Revision 版本回收机制。新增Revision版本最大数maximum限制,同时支持禁用基于时间的Revision回收策略。

    Networking-网络

    KIngress

    • 1)最大超时设置。对于gRPC stream处理超时的问题,默认超时时间调整为了48小时。
    • 2)支持域名重写(RewriteHost)。通过该特性可以实现自定义域名。以Istio实现为例,自定义域名‘vanity.com’通过‘rewrite’实现重定向。
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: vanity-ingress
    spec:
      gateways:
      - knative-serving/knative-ingress-gateway
      hosts:
      - vanity.com
      http:
      - match:
        - authority:
            prefix: vanity.com
          gateways:
          - knative-serving/knative-ingress-gateway
        rewrite:
          authority: helloworld-go.default.example.com
        route:
        - destination:
            host: cluster-local-gateway.istio-system.svc.cluster.local
            port:
              number: 80

    Eventing

    PingSource优化

    0.17.0版本 PingSource 支持时区(time zone)设置

    事件处理优化

    在 In Memory Channel 和 Multi-Tenant Channel 中发送事件失败时,支持重试机制。

    总结

    Knative 0.17.0 版本中引入了版本初始化实例数设置以及对节点调度参数的支持(nodeSelector etc.), 表明Knative社区会更多的关注实际应用场景,相信后续有更多实用特性会提供出来。欢迎有兴趣的同学一起交流。

    欢迎加入 Knative 交流群

    image.png

    ]]>
    【漏洞预警】jackson-databind 反序列化远程代码执行漏洞(CVE-2020-24616等) Thu, 29 Oct 2020 12:16:15 +0800

    2020年8月27日,阿里云应急响应中心监测到jackson-databind官方发布安全通告披露jackson-databind < 2.9.10.6存在反序列化远程代码执行漏洞(CVE-2020-24616等)。利用漏洞可导致远程执行服务器命令,官方git已发布公告说明,请使用到jackson-databind jar组件的用户尽快升级至安全版本。


    漏洞描述

    jackson-databind是一套开源java高性能JSON处理器,受影响版本的jackson-databind中由于缺少黑名单类,如br.com.anteros:Anteros-DBCP,可导致攻击者实现远程代码执行,其相关CVE号为CVE-2020-24616,漏洞需要相关jar组件才能成功利用,影响面适中。此次版本升级官方还修复了多处利用链,包含org.arrahtec:profiler-core、com.nqadmin.rowset:jdbcrowsetimpl、com.pastdev.httpcomponents:configuration等。阿里云应急响应中心提醒jackson-databind用户尽快采取安全措施阻止漏洞攻击。


    风险评级

    CVE-2020-8840 中危


    影响版本

    jackson-databind < 2.9.10.6


    安全版本

    jackson-databind >= 2.9.10.6


    安全建议

    以下任意一种方法均可实现漏洞修复

    1、针对使用到jackson-databind组件的web服务升级jackson-databind组件至安全版本:https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.9.10.6/

    https://github.com/FasterXML/jackson-databind/releases

    2、针对无法升级jackson-databind的,排查并将相关jar组件从应用依赖中移除可阻止漏洞攻击(可能会导致应用不可用风险)


    相关链接

    https://github.com/FasterXML/jackson-databind/issues?q=label%3ACVE+is%3Aclosed



    我们会关注后续进展,请随时关注官方公告。

    如有任何问题,可随时通过工单或服务电话95187联系反馈。

    阿里云应急响应中心

    2020.08.27

    ]]>
    【升级】8月20日Neustar注册局维护通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【域名】【Neustar注册局维护通知】

    维护时间:北京时间 2020年8月20日 16:00 - 8月21日 01:00

    维护内容:接到注册局的通知,注册局将于上述时间对后台系统进行维护升级。

    维护影响:届时 .biz 域名的注册、信息修改和查询域名注册信息等操作,将会无法使用,在此期间会对您造成的影响如下:

    1、您提交的注册(购买)、转入、一口价域名业务在支付费用后状态为“处理中”,待维护结束后将变为正常的“成功”状态;

    2、维护过程中您无法对域名注册信息进行修改,将提示修改失败。

    如果您需要注册或管理以上业务操作,建议您避开该时间段,以免给您的业务造成影响。

    由此给您带来的不便,我们表示歉意,敬请谅解。

    ]]>
    【升级】8月26日DDoS高防(国际)升级通知 Thu, 29 Oct 2020 12:16:15 +0800

    【阿里云】【DDoS高防(国际)】【升级通知】

    升级窗口:北京时间2020年8月26日 10:00 - 22:00

    升级内容:清洗网络增加英国节点
    升级影响:升级后国际高防线路将新增回源网段,具体网段信息如下所示。如果您当前正在使用国际高防线路并且在服务器侧有相关针对源IP的访问控制策略,请及时更新白名单放行下述回源网段,避免误拦截造成业务影响。

    国际高防线路新增回源网段信息如下:

    170.33.88.0/24 

    170.33.92.0/24

    170.33.93.0/24 

    170.33.90.0/24

    8.208.75.0/26

    给您带来的不便敬请谅解,有任何问题,可点击联系我们进行咨询反馈。

    ]]>
    【漏洞预警】通达OA 多个高危漏洞 Thu, 29 Oct 2020 12:16:15 +0800

    2020年8月20日,阿里云应急响应中心监测到通达OA官方发布安全更新,其中修复了多个高危漏洞。


    漏洞描述

    通达OA(Office Anywhere网络智能办公系统)是由北京通达信科科技有限公司自主研发的协同办公自动化软件。近日通达OA官方发布安全更新,其中修复了多个高危漏洞。攻击者通过文件删除漏洞,以及配合早期版本的后台文件上传漏洞,可以获取服务器系统权限。阿里云应急响应中心提醒通达OA用户尽快采取安全措施阻止漏洞攻击。


    影响版本

    文件删除漏洞:通达OA V11.6

    任意文件上传:通达OA < V11.7

    结合任意用户登录利用链:通达OA < V11.5


    安全建议

    通达OA官方已经发布相应安全加固程序,请根据当前OA版本选择所对应的程序文件,运行前请先做好备份。

    安全更新下载地址:https://www.tongda2000.com/download/sp2019.php


    相关链接

    https://www.tongda2000.com/



    我们会关注后续进展,请随时关注官方公告。

    如有任何问题,可随时通过工单或服务电话95187联系反馈。

    阿里云应急响应中心

    2020.8.20

    ]]>
    【漏洞预警】宝塔面板数据库管理未授权访问漏洞 Thu, 29 Oct 2020 12:16:15 +0800

    2020年8月23日,阿里云应急响应中心监测到宝塔官方发布安全更新,修复了一处未授权访问漏洞。


    漏洞描述

    宝塔面板是一款使用方便、功能强大且终身免费的服务器管理软件,支持Linux与Windows系统。近日宝塔面板官方发布安全更新,修复了一处高危漏洞。攻击者通过访问特定路径,可以直接访问到phpmyadmin数据库管理界面,并可借此获取服务器系统权限。阿里云应急响应中心提醒宝塔面板用户尽快采取安全措施阻止漏洞攻击。


    影响版本

    Linux版本 7.4.2版本

    Linux测试版本 7.5.14版本

    Windows版 6.8版本


    安全建议

    宝塔面板官方已经发布相应安全加固程序,请根据当前版本选择所对应的程序文件,运行前请先做好备份。

    安全更新下载地址:https://www.bt.cn/bbs/thread-54644-1-1.html


    相关链接

    https://mp.weixin.qq.com/s/XSDbyU-5TNzFCrp0sb0qKw



    阿里云云安全中心应急漏洞模块已支持对该漏洞一键检测


    我们会关注后续进展,请随时关注官方公告。

    如有任何问题,可随时通过工单联系反馈。

    阿里云应急响应中心

    2020.8.23

    ]]>
    【漏洞预警】Qemu 虚拟机逃逸漏洞(CVE-2020-14364) Thu, 29 Oct 2020 12:16:15 +0800

    ISC2020第八届互联网安全大会上,QEMU-KVM虚拟机的0day漏洞(虚拟机逃逸)被公开。该漏洞可越界读写某一个堆之后0xffffffff(4 GB内存)的内容,可实现完整的虚拟机逃逸。阿里云已于2019年12月完成该漏洞的修复,云上主机已不受该漏洞影响。


    2020年8月24日,qemu 官方更新了安全补丁修复该漏洞,漏洞编号:CVE-2020-14364,https://xenbits.xen.org/xsa/advisory-335.html


    漏洞详情

    2019年11月17日天府杯国际网络安全大赛,第一次暴露出QEMU-KVM虚拟机的0day安全漏洞。2020年08月13日,ISC2020第八届互联网安全大会上,该漏洞被公开。该漏洞可越界读写某一个堆之后0xffffffff(4 GB内存)的内容,可实现完整的虚拟机逃逸,最终在宿主机中执行任意代码,造成较为严重的信息泄露。经阿里云工程师分析后判定,该漏洞是 Qemu 历史上最严重的虚拟机逃逸漏洞,影响到绝大部分使用 OpenStack 的云厂商。


    解决方法

    阿里云已于2019年12月完成该漏洞的修复,云上主机无需做修复操作。

    如果您有相关需求或反馈,请提交工单联系阿里云。


    相关链接

    https://help.aliyun.com/document_detail/179131.html

    阿里云应急响应中心

    2020.8.24

    ]]>
    Agile Development敏捷开发——培养敏捷精神-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 Manifesto敏捷开发宣言

    Offical 官方:

    Manifesto for Agile Software Development

    We are uncovering better ways of developing
    software by doing it and helping others do it.
    Through this work we have come to value:

    • Individuals and interactions over processes and tools
    • Working software over comprehensive documentation
    • Customer collaboration over contract negotiation
    • Responding to change over following a plan

    That is, while there is value in the items on
    the right, we value the items on the left more.

    Translation 翻译:

    敏捷开发宣言

    我们正在探索更好的发展方式通过做它和帮助别人做它。
    通过这项工作,我们认识到:

    • 个人和交互胜过过程和工具
    • 工作软件优于综合文档
    • 客户合作胜过合同谈判
    • 响应变化而不是遵循计划

    虽然右边有价值,但是左项具有更大的价值。

    Wrong Name Comprehend 错误的命名理解

    agile 翻译出自牛津英汉汉英词典

    ① (lithe) 敏捷的 ‹person, animal, movement›; (fit) 灵活的

    ② attributive(mentally acute) 机敏的 ‹mind, intellect›*

    敏捷,拼音是mǐn jié,解释出自百度百科

    意思指反应(多指动作或言行)迅速快捷。如:敏捷地跳上敞篷车,敏捷地翻身上马,敏捷地躲过攻击。出自《汉书·酷吏传·严延年》:“延年为人短小精悍,敏捷於事。”

    通过上述两个翻译的对比我们不难看出关于敏捷一词,中英的理解其实是完全不同的,在汉语中敏捷一词表达的更重要的意为迅速

    然而在英语的语境中,当aglie形容人时,意也指,然而当aglie用来形容思维时,更注重的是机敏灵活。

    所以这里更加取决于无论boss也好,leader也好,亦或是程序员也好,大家的共识里面认为软件开发究竟是一个体力活,还是一个头脑风暴,思维实现的过程。在进入公司的第一天,leader便告诉了我一个团队信条,“听懂做到讲明白”,"Jump to white board from keyboard",只有从根本上认可自己做的工作是思维工作而非重复劳动,才能深刻的理解到"敏捷"一词的意思。

    可是如果我们将《敏捷开发》翻译为《机敏开发》/《灵活开发》,可能敏捷开发对于当今的业界影响力,应该会大打折扣。毕竟敏捷开发这4个字就会得到boss或者leader的认可,因为快速高效正是中小型公司或是大型公司需要贯穿整个企业的工作方式。

    回归到敏捷开发真正的含义:一种一人为本,团队合作,快速响应变化和可工作的软件作为宗旨的开发方法。

    敏捷开发的高效并不在于一味的快速,敏捷开发推崇的是一个正向的循环,通过产品的不断迭代,每一次的code review (代码评审),product review(生产发布评审),Requirements review(需求评审),Standing meeting Daily(每日站会)来实现快速高效,协作同步。团队经历了不断的磨合,自然而然的最后可以回归到boss和leader的需求:快速高效。

    所以敏捷开发对于一个研发团队而言,可以拉平大家的信息理解,让大家可以随时确认大家的设计思想是一致的,而不是在中间的理解中出现了理解偏差,使得最后的整个产品根本不满足于市场。相信各位经历过程序返工的同僚,都可以想象真正的低效缓慢正是做的事不被boss/leader认可,不被市场认可,疲于返工,从而团队共识分崩离析,进入一个无限的恶性循环。

    Waterfall Development VS Agile Development

    在网络上提到瀑布式开发,总会给人一种二极管的感觉,更有一种踩一捧一的感觉,通过踩瀑布式开发来捧敏捷开发。这对于瀑布式开发个人认为是完全不公平的,难道瀑布式开发就真的被敏捷开发给完爆了吗?其实不然

    Waterfall Development 瀑布式开发

    (图片出自百度图片)

    1. Requirements/analysis(需求分析/调研)
    2. Design(设计)
    3. Coding(编码)
    4. Testing(测试)
    5. Maintenance(项目运维)

    Agile Development 敏捷开发

    图片出自敏捷开发入门教程-阮一峰

    1. 项目启动(Initial planing)
    2. 需求分析(requirements analysis)
    3. 设计(design)
    4. 编码(coding)
    5. 测试(testing)
    6. 部署和评估(deployment / evaluation)

    contrast对比

    瀑布开发 敏捷开发
    工作模式 以文为本:
    1. 文档将贯穿整个项目生命周期,从(需求分析,软件设计,编码设计,测试用例,运维部署)每个阶段都将输出相应的文档
    2. 每一个阶段的文档输出后都将作为下一个阶段的输入
    3. 以文档为基准,交流的作用不一定有文档可靠
    4. 产品上线后即可满足用户90%的需求,之后只需要投入少量的运维成本
    以人文本
    1. 强调了团队的合作,需要团队的共同协作与配合,实时拉平大家的理解,当然并不是说文档不重要,而是团队协作以人为本更加重要
    2. 迭代是产品的核心思维,产品的第一次上线可能结果并不乐观,但是需要根据市场的反馈来进行迭代,与各个团队的员工拉平市场的需求,进行产品的迭代
    3. 不断的迭代迭代,最终将产品进入一个正向循环的模式
    项目周期 第一次发布通常会花上半年及以上的时间,产品上线后投入少量人手运维即可 通常第一次发布会在两个月内,之后不断的迭代,实现符合市场的产品
    优点 1. 目标明确,各个阶段大家只需要完成自己的工作,最后输出相应的文档即可
    2. 产品上线后,即可撤出大量人手投入新的项目开发中,只需要少量人员运维即可
    3. 在团队中调配相应资源时非常的明确,因为各个阶段的目标是明确的
    1. 在经过了不断的迭代之后,输出的产品一定是符合市场需求的
    2. 灵活性高,如果出现了巨大的市场变革,亦或是紧急的需求,只需要加入新一轮迭代即可
    3. 以人为本,调动整个项目各方(包括市场)的参与,理想形态下,开发模式将不再是分配制,而是各个成员主动承担工作
    缺点 1.风险高,各个阶段如果有一个地方出错,那么将作为输入传入下一阶段,最终做出的产品或许完全无法满足市场的需求,需要回炉重做
    2.如果出现市场变革基本等于项目死亡,紧急的需求的插入也将影响整个软件的开发,甚至可能需要从头设计
    3.会出现人员空滞的情况,因为各个阶段都需要等待上一阶段的输出结果后才会展开工作
    以人为本,就是敏捷开发最大的风险。你是否可以相信团队中的每一个人,大家是否拥有着敏捷开发的五个价值观(出自敏捷开发Scrum):
    - 承诺 – 愿意对目标做出承诺
    - 专注– 把你的心思和能力都用到你承诺的工作上去
    - 开放– 项目中的一切开放给每个成员看,大家共同分享
    - 尊重– 尊重团队中的每个人,就事论事而不是有色眼镜看人
    - 勇气– 有勇气做出承诺,履行承诺,接受别人的尊重
    是否可以对每一个团队成员说出 “你永远可以相信我”
    适用项目 需求明确,在开发周期中(一年内)定不会出现巨大市场变革 互联网项目,敏捷开发可以响应互联网快速的发展变更
    需要急速上线,抢占市场的项目

    通过上述的对比我们可以看出,并不是任何产品都适合敏捷开发,敏捷开发并不是一个万灵药,如果在不适当的项目跟中强行使用敏捷开发,反而会让它变成愚笨开发,因为我们会将明确的需求反复沟通,反而降低了研发效率。更重要的是,你团队中的成员是否适合敏捷开发,以人文本即为敏捷开发的核心思想。

    培养敏捷精神

    敏捷开发的核心是以人为本,关于敏捷开发的流程,具体实现,在网络上已经有很多了,大家随时都可以看到网络上给出的示例,以及请专业的敏捷团队来公司进行培训。本篇文章的主要主题是如何培养敏捷的精神 ,接下来将会根据我从书籍文档中,工作经验中学到的敏捷精神,希望阅读了的你,不会感觉文章是一篇口水话鸡汤,而是能让你感同身受的文章。

    1. Blame can't help 指责没有帮助任何事

    指责并不会修复bug更不会帮助任何事。遇到问题我们的反应如果都是去思考解决问题的方案,而不是解决导致问题的人,才是一个正向的循环。

    勇敢的承认自己不知道的答案,与团队的各个成员讨论。如果出现了一个重大的错误,应该被当做是一个学习的机会而不是落井下石的机会,团队中应该互相帮助,而不是落井下石。特别是如果有一个东西,大部分人都知道是坑,此时去诱导一个并不清楚的人跳下去,就算自己逃过了一劫,那么在这样的团队中,怎能知道下一个坑自己是否能够躲过呢?如果次次都躲过,你并不会成为受人尊敬的人,而是行业老油条,是受人背地里唾弃的人,别人又将如何尊重你?

    你可能会说,如果真的有团队成员一而再,再而三的对团队造成了负面的影响,那么此时他应该离开团队,但我们并不该周而复始的指责他。

    2. Don't blindly seek of speed 不要盲目追求速度

    在各个公司,亦或是各个团队中,都会有一套编码规范,如果盲目的追求速度,我们就会在我们的代码中增加许多的魔法值,漏掉注释。最后这段代码将会晦涩难懂,甚至作者本身都不一定能看懂如何实现。

    追寻代码规范,不盲目追求速度,对自己新增的变量/对象命名负责,对自己的代码块注释负责,才是一个研发最基本的素养,而不是将代码工作想象为一场赛马比赛。如果遇到自己不确定的问题,特别是性能/设计上的问题,一定要向同事请教。

    我上周便向我的leader请教了

    假如同一个业务涉及到三张关联表。
    做某个接口服务时,是三表联查,直接得出结果,还是三个表分别查做隔离,组合成最后结果。

    leader和研发同事们都给出了自己的理解与解决方案,令我受益匪浅,或许在这类性能问题发生之前,我都不会再去因为这个问题而痛苦,当问题发生时,我相信我的团队会和我一起著力于解问题,得到更加适合的解决方案

    以下是我综合同事和leader给出的解决方案得到的答案:

    1. 根据阿里巴巴规范:首先超过三张表关联强制禁止join
    2. 如果单表查询能够使用缓存或者复用,建议使用单表
    3. 虽然多表关联能够省去很多业务代码,但是绝大多数情况并不能带来性能上的很大提升,数据库关联查询也会增加SQL的复杂度
    4. 单表查询还便于以后扩展分库分表,SQL层优化空间大,业务层对于大数据量可使用一定算法解决性能问题
    5. 在C端项目中,我们要完全避免联合查询,在B端项目中,我们可以尽可能避免联合查询,在G端项目中,我们完全无法避免联合查询

    3. Focus on issue,not person对事不对人

    人人都懂的道理,人人都喝过的鸡汤,却很难做到的事。做不到对事不对人,只会给整个团队带来一种消极,人人自危,人人想落井下石的氛围。

    Negativity kills Innovation (消极扼杀创新):

    我们每个人都可以想到一些极好的创新想法,同样也有可能萌生一些特别憨憨的想法。如果提出自己的观点前,担心自己被嘲笑,甚至被批评,你将会扼杀掉自己的创意。任何一个出色的产品都需要大量的创新力和市场洞察力,分享各自的观点,融合彼此的优良创新设计,才可以做出一款好的产品。

    “你不需要很出色才能起步,但你必须起步才能变得出色”——莱斯布朗

    “能欣赏自己并不接受的想法,表明你的头脑足够有学识”——亚里士多德

    以下的话说给作者自己听:

    如果你连起步的勇气都没有,请问出色和你这辈子能有什么关系呢?

    在抒发每个人的idea的过程中,我们一定会遇到无休止的讨论,甚至最后从头脑风暴变成了扯淡大会也不是没有可能,如何避免这类情况的发生呢?

    • 设定最终期限:在最终期限时,如果没能确定到最好的方案,我们需要的是寻找最适合的方案,而不是无休止的讨论,需要落地思维碰撞
    • 逆向思维:寻找方案/idea的缺点,如果最终有一个方案的缺点都是大家可以接受的,那么这个方案是不是就是最好的方案呢?
    • 仲裁人:仲裁人需要做到绝对公正,如果有人从头脑风暴变成了扯淡大会,那么需要仲裁人出来制止,维持会议正常进行
    • 支持决定:落地的方案需要执行下去,除非能够证明方案是错的,否则请尊重大家制定的方案

    4. Brave 勇气

    人类的赞歌就是勇气的赞歌 出自《JOJO的奇妙冒险》

    勇气,勇敢这是一个大家都从小听到大的概念,但是想要拥有勇气,拥有勇敢,真的是相当困难的事,做一个有勇气的人,这句话真的是能让人耳朵都听出茧来,又更何况在一家企业中这么做呢?

    勇气会让人感觉有点不自在,鼓足勇气需要魄力。有些时候,它是扫除障碍的唯一途径,否则问题将进一步恶化下去,最终会变成,明明知道了错误,却不断的将错就错。鼓起你的勇气,这能让你从恐惧中解脱出来。当然这是在你已经知道了正确答案的情况下,如果你此时的工作正是一个前无古人后无来者的工作,你作为这艘船上的船员,自己都不知道下一个领域会是哪里的时候,此时你的勇气究竟是破釜沉舟的航行下去,还是下船,这是一个哲学问题?如果你正在做一件没人知道答案的事,很羡慕你,我也想如同你一样。

    5.Tracking changes 跟踪变化

    互联网的进步实在是太快了,个人感触最深的例子就是jQuery与三大前端框架,这里甚至给了我一种断层式进步的感觉。再说到java,如果关注java的新特性,我们会发现从java8的Lambda到jdk14中间出现的各类语法糖,都会发现java正在不断的向函数式编程靠拢,js中也引入了很多面向对象的概念,每一门语言都在不断的去完善自身的特性,如果我们闭门造车,无法追随行业的变化,和在监狱中的囚犯又有什么区别呢?在电影《肖申克的救赎》中,当囚犯回归到城市时因为完全无法适应现代的变化,而在旅店选择了自杀,而主角因为不断的写信,阅读,始终与时代接轨,最终完成了自己的救赎。

    监狱的可怕并不在于关押了人很多年,更可怕的事情是,也许你自己成为了自己心灵的囚徒,是自己内心的监狱禁锢了你自己。

    想起来前段时间在网络中看到的一段很有意思的话

    任何在我出生时已经有的科技都是稀松平常的世界本来秩序的一部分。

    任何在我15-35岁之间诞生的科技都是将会改变世界的革命性产物。

    任何在我35岁之后诞生的科技都是违反自然规律要遭天谴的。

    ——英国科幻作家道格拉斯·亚当斯

    任何比我早出生10年及以上的人都是裹步不前的老顽固。

    任何出生时间和我相差10年以内的人都是这个社会的精英,中流砥柱。

    任何比我晚出生10年及以上的人都是无可救药垮掉的一代。

    ——纳什·沃夏尔·硕德

    囚徒究竟是被监狱囚禁了?还是自己囚禁了自己?

    如何做到跟踪变化呢?

    • 迭代和增量式学习:

    知识投资也是一样。你需要定期投资最低限度的时间量。养成一种习惯,如果需要的话。躲到你的家庭办公室里去或者走进有无线网络的咖啡厅。并非每期学习都同样富有成效,但是只要定期安排学习,长期来看一定会成功。如果你一直在等待空闲时间或者等待灵感的突现,那么它永远都不会发生。

    安排自己定期的学习时间,听到不熟悉的术语/新鲜事物时,记录下它,计划时间深入研究它

    • 逛逛论坛,知乎,掘金社区,简书,github:社区永远是最潮流的地方,书籍的潮流程度将会低于社区,但是书籍的严谨程度高于社区
    • 如饥似渴的阅读:reading,reading,reading!

    我扑在书本上,就像饥饿的人扑在面包上!——高尔基

    • 跟踪技术变化:不需要精通每一门技术,但是我们需要了解行业动态,规划自己的职业生涯

    个人脑洞:如果有一天出现了一门完全取代了java的语言,我会怎么做?我能否提前发现技术更迭的征兆,成为技术革命的受益者呢?

    6. Investment your team 对你的团队投资

    总是要成为你所在的那个乐队中最差的乐手。如果你是乐队中最好的乐手,就需要重新选择乐队了 ——爵士吉他手Pat Methany

    追赶团队,和团队中的各个成员形成正向的互补,有勇气抱有开放的心态与团队中的成员分享,尊重团队中的成员给出的意见,承担团队的任务。构建属于团队的学习平台。如果你认为分享知识你就亏大了,除非你是一个国家级的科研工作者,需要签订严格的保密协议,否则我们需要思考自己是不是井底之蛙呢?当你视若瑰宝的东西有一天被人发现所有人都知道了,甚至有更好的方案时,你那是的脸会不会像被人用皮鞋踢过一样,开始无能狂怒呢?最后愤然感慨“任何在我35岁之后诞生的科技都是违反自然规律要遭天谴的。”任何比我晚出生10年及以上的人都是无可救药垮掉的一代。

    7.Reduce 减法

    参考文档

    《高效程序员的45个习惯——敏捷开发修炼之道》

    敏捷开发入门教程-阮一峰

    github地址

    ]]>
    Why Oauth2.0?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 Guide

    本文仅作为Oauth2使用参考,如果本身已经接触过Oauth2.0,希望本篇文档能帮你打开一些思路,能够让你清晰的选择是否要使用Oauth2.0

    如果没有了解过Oauth2.0,请跳转阮一峰Oauth2.0讲解

    Base Q&A

    Question

    如果你最近正在参与关于是否要使用Oauth2.0的会议,你是否会在会议中不断的回到三个很基础的问题:

    • 什么是Oauth2.0?
    • Oauth2.0存在的意义是什么?
    • 为什么要使用Oauth2.0?

    Answer

    1. 首先我们需要明确一点Oauth2.0是协议,它包括了如下特征:

      • 授权协议:

      授权是Oauth2.0思想的核心,其目的就在于拥有了授权,就能够通过授权取得权限范围内的受保护资源

      • 委托协议:

      当用户授权第三方软件获取部分用户数据时,其本质就是资源所有者委托了第三方进行资源的使用

      • 安全协议:

      安全问题永远是互联网最为核心的问题,Oauth2.0协议本身就推荐了相当多的安全处理方案,因此说Oauth2.0也是安全协议

    更需要永远记住的一个观点是,Oauth2.0不是一种身份认证协议,如果思维不能明确Oauth2.0的协议边界线,那么接下来的讨论我们将会不断的回到上述提到的3个问题。

    1. OAuth 2.0 就是保证第三方(软件)只有在获得授权之后,才可以进一步访问授权者的数据
    2. OAuth 2.0 一词中的 “Auth” 表示 “授权”,字母 “O” 是 Open 的简称,表示 “开放”。简而言之Oauth的核心思想在于开放授权,因此在使用Oauth协议时,我们也不禁需要确认自己的远大目标,是否要做一个开放授权的系统

    谈到Oauth2.0就不得不提到Oauth1.0:

    在 OAuth 1.0 的时候,它有个 “很大的愿望” 就是想用一套授权机制来应对现实中的所有场景,比如 Web 应用场景、移动 App 应用场景、官方应用场景等等,但是这些场景并不是完全相同的。比如官方应用场景,你说还需要让用户来授权吗?如果需要,始终使用一套授权机制给用户带来的体验,是好还是坏呢?到了 OAuth 2.0 的时候,就解决了 OAuth 1.0 面临的这种“尴尬”。OAuth 2.0 不再局限于一种授权机制,它扩充了授权许可机制类型,有了授权码许可机制、客户端凭据机制、资源拥有者凭据机制和隐式许可机制。这样的 OAuth 机制就能够很灵活地适应现实中的各种场景,比如移动应用的场景、官方应用的场景,等等。

    具体的Oauth1.0 vs Oauth2.0比较可以参考下方参考文档,这里暂不赘述

    总结下来使用Oauth2.0的原因就是其改善了自身的授权机制,优化了安全处理,采用了多种授权的形式,以此来适应如今互联网在授权中会遇到的各类问题

    4 characters

    Oauth2.0中最重要的四个角色

    • 资源拥有者
    • 受保护资源服务器
    • 授权服务
    • 第三方应用

    不管我们在开放授权中的各类形式讨论,我们所有的讨论应该基于这4个角色,而不是在于使用Oauth2.0的哪种模式,因为模式的选择,其本质需要考虑所谓第三方应用是否可信,大家所处的是内部局域网,还是纯正的互联网第三方

    Todo Question

    希望上述的讲解可以让大家同步的是Oauth2.0的基本问题,如同做一个SaaS平台一样,我们需要的是先讨论什么是SaaS,什么是租户隔离,而不是刚开始就讨论如何去实现SaaS设计

    Q1:Oauth2为什么不是身份认证协议?

    在很多次的讨论中,我们会发现我们总是会认为Oauth2需要去实现用户的身份认证,因为获取授权的第一步,也是最重要的一步就是获取身份认证,这样我们才能判断是否要颁发access_token给请求方。既然说到了Oauth2不是一个身份认证协议,那么身份认证协议是什么呢?

    Answer1:OIDC

    OIDC是OpenID Connect的简称,OIDC=(Identity, Authentication) + OAuth 2.0(身份认证+授权协议)

    身份认证协议OIDC,他是Oauth2.0的加工版,如同我们将面粉加工成了面包

    在OIDC中会出现3个最为重要的角色:

    • EU(End User):代表最终用户
    • RP(Relying Party):第三方软件,即为认证服务的依赖方
    • OP(OpenID Provider):代表提供身份认证服务方。

    image-20200819160625871

    上图即为OIDC中的三角色与Oauth2.0中的四个角色的关系

    实现OIDC与实现Oauth2.0的区别是什么?

    根据目前的Oauth2实现方案,我们在用户登录授权后会返回4个值:

    • access_token
    • refresh_token
    • exp_time
    • refreshExp_time

    而基于OIDC的实现则会在返回第5个非常重要的信息:id_token

    可能谈到这里大家会比较恼火,为何又多了一个从来没有听说过的东西?微信开放平台不也没有id_token这种东西吗?

    基于我个人的认知,我个人认为微信开放平台是目前最为标准的Oauth2.0协议开放平台了,其实微信一直都返回了id_token

    相信大家可以看到在微信的获取access_token返回接口中返回了一个参数:openId

    其实openId的本质就是id_token,只是id_token的本质就是一个携带用户信息的jwtToken,微信在这里不过是返回形式直接返回了用户id,而非一个token的形式,毕竟如果是jwtToken我们又不得不去考虑它的自验证性的问题了,既然都是要暴露给第三方应用供其解析的,那openId自然可以明文返回

    聊到这里,大家应该明白了,我们目前的access_token中,携带了类似于openId的用户唯一标识,也就是说我们将access_token的功能放大了,他变成了一个身份认证授权通过token,而不是一个单纯的授权token了

    说的最为简单直白:

    id_token的作用代表了它是哪个用户

    access_token的作用在于可不可以访问

    那么我们需要回到话题了,我们做错了吗?是否access_token就一定不能携带用户信息呢?

    其实不然,在健身领域,关于健身补剂一直有一句俚语,抛开剂量谈毒性就是耍流氓

    在我们的身份认证服务中,我个人认为也有相应的一句俚语,抛开环境谈实现也是耍流氓,必须要考量的环境问题一定是

    大家之间是否可信?大家是否同属局域网还是互联网中?

    接下来将要来今天要讨论的第二个话题了

    Q2:如何选择适合我们家的实现

    首先一定会选择微服务架构,在此基础上我们将会考量如何实现OIDC,接下来的问题,参考文档皆为微服务架构设计-Oauth2&JWT

    这个架构的一个比较友好的地方在于,架构思路是基于k8s实现

    名词解析:

    End-User: 最终用户

    Internet:互联网

    FW:防火墙

    Nginx:Nginx反向代理

    Web:部署服务器

    Gateway:网关

    IDP:Identity Provider 认证服务提供者,实现框架:Spring-security可以考量

    BFF: Backend for Frontend 后端For前端微服务层

    DomainSvc:整个微服务架构的底层。这些服务包含业务逻辑,通常有自己独立的数据库存储,还可以根据需要调用外部的服务

    DB:数据库

    根据微服务分层原则,领域服务禁止调用其它的领域服务,更不允许反向调用 BFF 服务。这样做是为了保持微服务职责单一(Single Responsibility)和有界上下文(Bounded Context),避免复杂的领域依赖。领域服务是独立的开发、测试和发布单位。在电商领域,常见的领域服务有用户服务、商品服务、订单服务和支付服务等。

    由此我们可知晓,无论是BFF还是DomainSvc都不会去存储用户的信息,因为他们都是通过JWT token中包含的用户信息来获取,而JWT token中的用户信息来源是在于IDP服务所对应的LoginSvc Customer DB中

    接下来我们将会根据各个实际情况作为考量点

    Answer2-1:第一方应用 + 资源拥有者凭据模式

    第一方应用,即为完全由我们开发的且处于同一局域网下的完全可信的应用

    因为完全可信,我们可以选择OAuth 2.0 的资源拥有者凭据许可(Resource Owner Password Credentials Grant)

    相信大家看到这里一定会有了争论,这就是我们之前讨论的核心问题了,到底要不要将用户表集成进IDP中,但是我们当时都会产生一个额外的争论,就是Oauth只是一个授权服务。是的如果只看Oauth,我们永远只能得到这个结论,Oauth只是一个授权服务,可我认为我们的问题是否应该考虑,我们要做的是Oauth2.0还是OIDC呢?如果是OIDC,这一切是否就是即符合微服务架构思想,又符合OIDC协议,包含了Oauth2.0协议呢?

    Answer2-2:第三方应用+授权码模式

    关于第三方应用的定义,我们如何来界定一个第三方应用,我认为这一点是相当有必要确认好的

    需要判断第三方应用是否由我们开发,如果不为我们开发,则肯定是第三方应用

    如果由我们开发,处于同一局域网,是否是第三方应用?不处于局域网只能通过互联网交互,是否是第三方应用?

    从上述图示,我们可以得知,用户必须要在守望有用户信息才可以通过授权码模式得到对应的授权码,从而获取access_token

    以上就是关于Oauth2.0的第三方应用+授权码模式的获取Token流程

    综上所述,个人认为关于access_token中是否可以携带用户信息,应该取决于是否第一方应用,如果是第一方应用,对于受保护的资源而言是相当可信的,那么我们可以将用户信息密文存入token中,如果是第三方应用,认为应该将access_token与用户openId分开返回

    之后关于Oauth2.0的安全问题与防止攻击,将会在之后的文档中更新

    参考文档:

    PKCE代码交换证明密钥协议

    OIDC解析

    微服务架构设计-Oauth2&JWT

    极客时间-Oauth2.0实战课

    Oauth2.0 vs Oauth1.0
    github地址

    ]]>
    OAM 创始团队:揭秘 OAM Kubernetes 实现核心原理-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 image.png

    今年 5 月,阿里云和微软云共同宣布,Open Application Model (OAM) 社区携手知名混合云管理项目 Crossplane 社区,联合发布了 OAM 在 Kubernetes 平台上的标准实现与核心依赖库。本次合作达成后,OAM 社区成功的将标准应用定义和标准化的云服务管理能力统一起来,迈出了实现真正意义上的无差别云端应用交付的关键一步 。

    去年 10 月 ,阿里云和微软共同推出了 OAM 项目,旨在构建围绕 Kubernetes 的云原生应用规范。OAM 描述了一个模型 —— 开发人员可以在其中定义应用程序组件;应用程序操作员负责创建这些组件的实例并为它们分配应用程序配置;基础架构运营商负责定义、安装和维护平台上可用的基础服务。

    本次合作是阿里云、微软与 Crossplane 社区的三方技术合作,主要围绕 OAM 在 Kubernetes 上的标准实现以及 Crossplane 项目的 OAM 化展开。因为 Kubernetes 社区在落地 OAM 模型的过程中,提出了关于 OAM 标准实现的诉求。所以这次合作的一个重点,就是三方工程师使用 Go 语言开发了一个 OAM Kubernetes 核心依赖库。这个项目的名字叫做 oam-kubernetes-runtime。OAM Kubernetes Runtime 将会成为 OAM 社区官方维护的基础组件,目标是在 Kubernetes 上提供稳定且统一的 OAM 核心插件。

    为进一步了解本次合作的细节以及 OAM 项目的现状,阿里云高级技术专家 Andy Shi 以及阿里云技术专家孙健波(花名:天元)接受开源中国的专访,共同探讨了 OAM 项目存在的意义。

    详情戳:https://www.oschina.net/question/4487475_2317219

    OAM 因何而生

    我们知道,应用容器技术自诞生开始,就以 “彻底改变了软件打包与分发方式” 的魅力迅速征服了几乎所有的云厂商与数据中心。不过,软件打包与分发方式的革新,并没有能够让软件本身的定义与描述发生本质的变化,基于 K8s 的应用管理体验,也没有让业务研发与运维的工作变得更简单。

    实际上,Kubernetes 带来的云原生技术革命,在于实现了基础设施层的标准化和抽象,但这一层抽象距离业务研发与运维还是太过遥远了。一个最典型的例子,直到今天,Kubernetes 里面始终都没有 “应用” 这个概念,它提供的是更细粒度的 “工作负载” 原语,比如 Deployment 或者 DaemonSet。

    而在实际环境中,一个应用往往是由一系列独立组件的组合,比如一个 “PHP 应用容器” 和一个 “数据库实例” 组成的电商网站;一个 “参数服务节点” 和一个 “工作节点” 组成的机器学习训练任务;一个由 “Deployment + StatefulSet + HPA + Service + Ingress” 组成的微服务应用。

    “应用” 这个概念在 Kubernetes 项目中的缺失,既是一个有意而为之的设计,却也造成了今天云原生应用管理生态的极度碎片化和极高的学习门槛。如何通过标准化的方式去解决这个 “Kubernetes 里到底什么是应用” 的问题,正是 OAM 项目发布的最初始动机。

    有什么意义?

    在 OAM 发布之前,云原生生态里其实并没有一个叫做 “应用” 的概念。哪怕在今天,全世界几乎每一个在落地云原生的团队,都有一个自己定义的 “应用” 的概念,它们的抽象程度层次不齐,定义方式也丰富多样,这就导致了所有围绕着这些 “应用” 构建出来的系统,就成为了一个又一个的大烟囱。

    对于整个云原生生态来说,这种应用层的碎片化和烟囱化,其实对于整个生态演进是非常不利的。而今天的现状也已经证明了这一点,在 Kubernetes 逐渐标准化了基础设施能力的接入方式之后,原本更加接近用户、更加重要的应用管理层,却几乎停滞了演进,在最近几年里没有提出任何一个创新性的思想出来。

    应用管理层停滞不前的结果,就是全世界的业务研发和运维一夜之间都被迫变成了 “容器专家”,一边学习着根本不应该是他们关心的各种 “基础设施即数据(Infrastructure as Data)” 领域的概念(比如:声明式 API,控制器等),一边吐槽 Kubernetes 实在是太复杂了、设计太奇葩了。

    简而言之,Kubernetes 作为一个面向基础设施工程师的系统级项目,主要负责提供松耦合的基础设施语义,这就使得用户学习和操作 Kubernetes YAML 文件的时候,往往会感觉这些文件里的关注点非常底层,学习门槛很高。

    实际上,对于Kubernetes 真正的最终用户比如业务研发人员和运维人员来说,他们并不想配置这些如此底层的资源信息,而是希望有更高维度的抽象。这就要求一个真正面向最终用户侧的应用定义,需要能够为业务研发和应用运维人员提供各自视角的应用定义原语。所以说,OAM 带来的第一个改变,就是提供了一种大家都可以遵循的、标准化的方式来定义更高层级的应用层抽象,并且把“关注点分离”作为这个定义模型的核心思想。

    而 OAM 带来的第二个变化,则是为 Kubernetes 项目带来了应用定义,更确切地说,是对应用本身和它所需运维能力进行定义与描述的标准开源规范。站在 Kubernetes 项目的角度来讲,OAM 是一个 Kubernetes 原生的标准的“应用定义”项目,同时也是一个专注于封装、组织和管理 Kubernetes 中各种“运维能力”、以及连接“运维能力”与“应用”的平台层框架。

    详细的说,OAM 基于 Kubernetes API 资源模型(Kubernetes Resource Model)来标准化应用定义的规范,它强调一个现代应用是多个组件的集合,而非一个简单的工作负载或者 K8s Operator。所以在 OAM 的语境中,一个 PHP 容器和它所依赖的数据库,以及它所需要使用的各种云服务,都是一个“电商网站”应用的组成部分。更进一步的,OAM 把这个应用所需的“运维策略”也认为是一个应用的一部分,比如这个 PHP 容器所需的 HPA(水平自动扩展策略):

    image.png

    以 Crossplane 项目为例,它在本次合作中通过 OAM 升级之后得到了怎样的变化呢?

    “ 作为混合云管理领域中的佼佼者,Crossplane 的 OAM 化保证了今天任何一个符合 OAM 规范的待运行程序、运维能力和它所依赖的云服务,可以组成一个整体在混合云环境中无缝漂移。”

    这种平台无关的应用定义范式,使得应用研发人员只需要通过 OAM 规范来描述他们的应用程序,那么该应用程序就可以在任何 Kubernetes 群集或者 Serverless 应用平台甚至边缘环境上运行,而无需对应用描述做任何修改。本次合作中 Crossplane OAM 版的发布,则意味着 OAM 社区正在将标准应用定义和标准化的云服务管理能力统一起来,从而实现真正的 “云端应用交付” 。

    OAM 如何发挥作用?

    那么 OAM 在一个项目中是如何运作的呢?

    据介绍,OAM 以原生插件的方式运行在 Kubernetes 当中。OAM 强调整个模型是关注点分离的。即业务研发人员负责定义和维护组件 (Component) 来描述服务单元,而运维人员定义运维特征 (Trait),并将其附加到前面的组件上,最后构成 OAM 可交付物 ——ApplicationConfiguration。

    image.png

    这种设计是 OAM 在能够无限接入 Kubernetes 各种能力的同时,保证给业务研发与运维人员提供最佳的使用体验和最低的心智负担的重要基础。与此同时,基础设施工程师可以随时在 Kubernetes 中添加更多工作负载(例如 FaaS)以运行无服务器功能,或者添加运维特性(例如 CronHPA)来定义 CronJob 类型的 HPA 策略。OAM 以标准的声明方式在整个平台中管理应用交付能力和流程,并且提供面向各个角色的 API 原语来表达各自的诉求,最后通过 Kubernetes 把这些诉求落实。

    什么样的项目需要 OAM?

    实际上,几乎所有基于 Kubernetes 的应用管理平台都对通过 OAM 来以标准化的方式去构建自己的应用模型有明确的诉求。另一方面,由于 OAM 是原生的 Kubernetes API 资源模型,这里的迁移过程难度很低,可以通过 API 对象灰度纳管的方式逐步完成迁移操作(通过 OAM 对象逐步接管现有 Kubernetes 对象)。

    而相比于传统 PaaS 封闭的、不能同 “以 Operator 为基础的云原生生态” 衔接的现状,基于 OAM 和 Kubernetes 构建的现代云原生应用管理平台,本质上是一个 “以应用为中心” 的 Kubernetes ,保证了这个应用平台在能够无缝接入整个云原生生态。同时,OAM 可以进一步屏蔽掉容器基础设施的复杂性和差异性,为平台的使用者带来低心智负担的、标准化的、一致的应用管理与交付体验。这就使得一个基于OAM 构建的 Kubernetes 应用平台,首先能够隐藏底层基础设施的细节(例如,是云还是物联网),专注于应用层抽象,提供以应用为中心的资源模型。

    其次,OAM 划分了应用交付路径上的开发、运维、基础架构三种角色,分离了关注点,让流程更加清晰和易于管理。

    第三,OAM 站在 K8s API 资源模型的肩膀之上,提供了可移植的应用与基础设施抽象,让一个应用描述可以完全不加修改的云、边、端等任何环境下直接交付运行起来。

    image.png

    除此之外,OAM 还定义了一组核心工作负载/运维特征/应用范畴,作为应用程序交付平台的基石。而平台开发者也可以添加更多工作负载(例如 FaaS 或者任意云服务),或者添加运维特性(例如 CronHPA)来定义 CronJob 类型的 HPA 策略。OAM 以标准的声明方式在整个平台中管理应用交付能力和流程。当模块化的 Workload 和 Trait 越来越多,就会形成组件市场。而 OAM 就像是这个组件市场的管理者,处理组件之间的关系,把许多组件集成起来变成一个产品交付给用户。OAM 加持下的 Kubernetes 应用管理平台,可以像乐高积木一样灵活组装底层能力、运维特征、以及开发组件。使得应用管理变得统一,功能却更加强大。

    OAM 社区现状

    谈到 OAM 项目社区的现状。“ 作为一个没有同商业诉求绑定的中立开源社区,OAM 生态自成立以来保持着较高的活跃度和参与度,大量的社区 Issue/PR贡献都来自阿里和微软之外的团队比如 AWS、腾讯、字节跳动、谐云、青云、好雨云、第四范式等生态参与者。除了阿里和微软本身以及基于 OAM 实现了内部应用管理架构的统一和标准化之外,不少基于 OAM 的云服务比如阿里云 EDAS 也已经上线。”

    与此同时,OAM 技术体系也开始在很多大型社区用户(比如 MasterCard 万事达卡)中落地,同时也出现了产品和商业化的实践(比如:谐云的可视化OAM实现),甚至来自其它云厂商比如 AWS 的开源项目整合与对接。可以看到,OAM 社区正在迅速成长和壮大中。

    开源社区的运作模式一直是我们比较好奇的地方。据介绍,OAM 项目目前完全由社区驱动,由各子项目的 Maintainer 小组进行维护和管理。社区有每两周一次的社区会议(美国和北京时间各一个)来进行重大事项的讨论与决策和同步项目进度。整个社区的的工作流程按照 Maintainer 席位的投票机制来运转,同时兼顾最终用户的投票权。目前 OAM 社区的核心 Maintainer 来自阿里云,微软和 Crossplane 项目原有的成员。在推广策略上,由多个国际化大厂团队维护的 OAM 项目从诞生起就是完全面向国际化开源社区的运作方式,凭借阿里与微软自身场景,以及整个云原生社区和贡献者的高质量输入来驱动整个项目向正确的方向持续演进,在沟通、分享、协作的氛围中鼓励贡献和发展社区。这种模式下,一旦突破早期破冰阶段,在随后社区传播和推广方面会带来病毒式的效果。

    目前 OAM 的版本是 v1alpha2 ,OAM 的版本之后会不停迭代,根据实际的场景持续演进;当然,同时 spec 本身也会保证规范的稳定和兼容。这个标准的更新速度主要是取决于用户的接受程度和反馈的情况,并且会在今年发布 Beta 版。本次合作中,OAM 已经发布了 Kubernetes 的标准实现与核心依赖库,这也就意味着未来整个开源生态都可以直接通过对接 Crossplane 或者 oam-kubernetes-runtime 来支持 OAM 标准,所以这样的项目很快会越来越多。

    本文转自<阿里巴巴云原生技术圈>——阿里巴巴云原生小助手

    ]]>
    案例速览 | 如何为3~12岁孩子提供全方面监控能力?-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 17.jpg

    叫叫阅读系列是成都书声科技有限公司(铁皮人)旗下的教育 Apps 。主要针对 3-12 岁孩子,以儿童身心发展规律为依据,秉承叶圣陶先生的语文教育论,多读书,读好书,勤思考。由小学语文老师、幼小衔接专家、诵读老师、儿童节目主持人组成的优秀师资团队带领孩子解读名篇,领略汉语文字之美,建立其知识格局,完善其独立人格,提升其语文素养。通过“在线互动课堂+在线班主任辅导+线下配纸质书”的三位一体的教学模式,丰富孩子的知识,培孩子的能力,提升孩子的素养。

    2007 到 2011 年,叫叫阅读创作的绘本 500 余册,部分绘本被大中华,北美等地区选为课外指定阅读绘本;2011 到 2017 年,原创的教育类 App 以及叫叫系列产品诞生,斩获用户 7000 万;近年来,通过提供更为丰富的在线语文,数学课程,特别是疫情下,学员人数累创新高。

    新的需求

    随着在线教育的风口来临,叫叫阅读的业务呈现指数般增长,依托于以微服务化为基础的互联网架构下,系统中拆分的应用越来越多,应用间以及应用内的问题监控/定位/分析越发困难,急切需要一个如下功能的 APM 工具来解锁提升技术团队的相关能力:

    全方位的应用监控能力:不但可以监控 CPU /内存、网络、IO、磁盘等基础设施;还可以监控 JVM 、线程、异常、慢 SQL 等情况;最重要还可提供基于应用/接口的各种 metrics , 业务调用链的能力,最好能方便地获取 SQL 的绑定参数。

    无侵入的应用接入方式:不需要开发人员主动埋点,无需要业务方引入 jar 依赖,可在容器/ECS 等多种环境上部署便拥用全方位的应用监控能力。

    低损耗的资源占用比例:接入的 APM 工具对业务应用本身的资源占用比例绝大部分时间不超过 5% , APM 本身对宿主应用的资源占用的有保护措施。

    白屏化的配置使用能力:可以通过白屏化进行采样率 / SQL 绑定参数的提取等等的调整,也可以通过批量标签化管理应用的监控接入启停,提供丰富的告警配置能力。

    解决方案:

    通过阿里自研的 ARMS 应用实时监控工具,既满足无侵入的接入方式和低损耗的资源占用比例,还提供了全方位的应用监控能力和白屏化的配置使用能力,而且 ARMS 结合众多客户场景和专家经验,提供智能诊断功能。
    image.png

    效果:

    1、平稳支撑在线教育的增长风口:近来在线教育行业正在风口上高速增长,叫叫阅读在ARMS的帮助下,及早发现与修复问题,帮助业务系统渡过了一浪赛过一浪的学员使用峰值,为业务的增长提供了有力的保障。

    2、解锁技术团队的定位技能包:有了ARMS的支持,不但资深工程师掌握了快速定位分析问题的能力,刚上手的同学也能在短期内就拥有相同的技能包。在ARMS的长期使用熏陶中,整个技术团队的编码能力潜移默化地得到了升华,获得了生产力的提升。

    客户证言:

    “阿里云 ARMS 监控定位分析告警的能力超出了我们的预期,在接入与管理上非常灵活简洁!借助 ARMS 的能力,完全解锁了我们技术团队的系统定位分析技能包,对系统的稳定与高效运行有了质的飞跃,我们的业务部门对系统的提升也称赞不绝。”

    加入阿里云在线教育客户交流钉钉群

    欢迎扫码加入在线教育行业客户交流钉钉群,阿里巴巴众多专家将在群内定期分享行业最佳实践和前沿技术干货,扫码入群,与更多行业精英互动交流。钉钉扫码或搜索钉钉群号均可加入:35712134。
    image.png
    【填问卷抽淘公仔-阿里云中间件用户调研】

    点击链接,一分钟填问卷抽淘公仔:
    https://survey.aliyun.com/apps/zhiliao/YmW95Gk8bU

    ]]>
    云端IDE:阿里云机器学习与PAI-DSW | 《阿里云机器学习PAI-DSW入门指南》-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 经过20年的快速发展,阿里经济体已经组建了一个庞大的商业生态圈,并在支付、云计算、本地生活服务等行业保持互联网巨头地位。2020财年交易额突破1万亿美元,全球第一家;阿里云支撑了2019年双11 期间峰值 54.4 万笔/秒、单日数据处理量达到 970PB 的世界级的流量洪峰,成为业界第一个实现此壮举的云计算公司。

    阿里云机器学习平台正是伴随着这样庞大而复杂的阿里经济体业务成长起来的。下面我们将带着大家掀开阿里云机器学习技术大图的一角,看看阿里云机器学习,特别是机器学习工程上的发展、沉淀和创新。

    阿里云机器学习技术大图

    我们从用户和技术的两个角度来梳理阿里云机器学习的技术体系大图。从用户的角度来说,根据使用机器学习的深度不同,在云栖大会上,我们展示了飞天AI平台的技术分层关系:

    image.png(注:不是一个完整的产品列表,而是一些核心的样例)

    从技术的角度说,机器学习从算法到底层的硬件,都涉及到不同的技术方向。下面是我们对于核心技术能力上的一个总体描述:
    image.png
    每个技术方向上都形成各自的布局和沉淀,接下来我们会重点讲述作为机器学习重要组成部分的工程能力体系建设。

    阿里云机器学习工程能力体系

    阿里云在机器学习工程体系建设上,也经历了各领域业务需求驱动和技术驱动分阶段螺旋式递进上升的过程。由最初的通过传统机器学习算法进行数据价值的粗加工,到今天以深度学习为主、支撑各类“行业大脑”解决方案的人工智能工程体系。

    阿里云的机器学习工程能力体系建设始终围绕着更高效的融合人工智能三要素(算法、数据、算力)进行展开,即追求不断提升整个工程体系中的计算效率、数据效率以及工程效率,从而能够更好的支撑阿里经济体各方面业务快速发展的需求,并通过阿里云对外进行技术输出,推动人工智能领域的技术变革,产生更大的社会效益,实现普惠人工智能。

    经过多年的发展创新,阿里云在AI托管平台技术层进行了系统性的建设,极大提升了算法研发、共享、部署、输出的效率,在此基础上沉淀出多个具有用户粘性和场景差异化的开发平台,这里我们选取阿里云机器学习PAI(Platform of Artificial Intelligence)作为代表来着重来介绍。

    PAI是一款覆盖机器学习全流程的一站式机器学习平台产品,集数据预处理、特征工程、自动调参、模型训练、在线预测为一体,为用户提供低门槛、高性能的云端机器学习服务。

    PAI相关技术脱胎于阿里集团内数十个BU的上千个业务体系,沉淀了大量的覆盖各个领域的优质分布式算法、框架、平台等,同时也在不断完善和扩充机器学习生态。
    image.png

    阿里云机器学习PAI-DSW

    作为在AI战线上辛勤耕耘的算法工作者,你是否也常常遇到下面的情形:

    算法需要运行在GPU上,可是长时间申请不到GPU机器,只能干着急。

    终于GPU机器申请到了,却不能马上开始使用,需要先安装GPU驱动和各种依赖等等,感觉有些浪费时间。

    好不容易机器环境弄好了,可当某天更新算法代码后变得很慢, 排查半天才发现是GPU驱动需要升级补丁,很是无奈。

    生产环境机器网络隔离,在线上要debug代码,只能使用GDB在命令行进行,开发效率大大降低。

    在本地采用PyCharm这样的IDE开发好代码,而数据在生产环境,不允许下载,只能把代码拷贝到线上机器运行,发现问题后,又得回到本地修改调试后再来一遍,非常不便。

    PAI Studio采用图形化拖拽式,像搭积木一样分分钟就构建一个完整的工作流,很炫酷。 但想要定制发布自己的组件时,却不知从何下手。

    在长期与算法工程师同学沟通合作的过程中,我们发现了算法工程师面临的这些问题。提升机器学习工程效率,降低人工智能使用门槛,急需一个简单、轻量、好用的工具平台,从而让算法工程师更加专注于模型设计本身。PAI DSW(Data Science Workshop)就是PAI团队为解决算法工程师的以上痛点,新推出的一款云端机器学习开发IDE。

    PAI-DSW集成了Jupyterlab、WebIDE等多种开源项目,在阿里巴巴集团内上百个BU和上千名工程师的打磨之下性能和功能上都进行了一定的调优。数据上打通了ODPS等多个数据源,方便用户在构建模型的时候免去重新构建数据管道的工作。同时,在深度学习上,PAI-DSW内置了Tensorboard,可以通过简单的拖拽的方式来帮助深度学习的开发者更好的完成深度学习场景下神经网络的建模。下图展示了DSW在机器学习平台PAI产品架构中的位置:

    image.png
    (DSW在机器学习平台PAI产品架构中的位置)

    简单来说,PAI-DSW可以实现多实例、多环境,GPU/CPU资源、JupyterLab、WebIDE以及全屏使用Terminal无干扰工作。目前PAI-DSW已经向所有阿里云的用户免费开放了探索者版,只需要登陆阿里云然后打开 https://dsw-dev.data.aliyun.com/#/ 即可即刻开始云上数据科学之旅。本书后面两个章节将详细介绍如何使用PAI-DSW这一简单好用的工具。

    ]]>
    阿里云云原生数据湖分析DLA Serverless Spark重磅发布,助力企业低成本挖掘OSS数据价值-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 一、背景概述

    1.1 什么样的客户需要数据湖

    在数据处理领域,数据湖相对来说是一个比较新的概念,它的提出可以很好地帮助企业应对当前数据场景越来越多、数据结构越来越复杂、数据处理的需求越来越多样化的问题。传统的单机数据库技术倾向于大一统,一个数据库可以解决数据存储、在线交易、在线分析、离线报表等功能,好处是简单,数据只有一份,缺点是各个功能都做了取舍,很难解决规模的问题。为了突破数据规模的瓶颈,大数据技术更倾向于针对单独领域做深度定制,比如海量文件存储使用HDFS、海量对象存储使用OSS/S3、宽表存储使用BigTable/HBase、嵌套数据使用MongoDB、大规模TP数据使用PolarDB、大规模AP数据使用ADB/Clickhouse、日志数据使用LogService等等。

    在很多企业里面,不同的部门业务不同,采用的数据方案也不同。在企业发展的前期,更多是靠业务模式驱动、流量驱动,数据复杂度的问题还不明显,后期则需要精细化运营、向数据要红利,数据管理的难度就成为企业的痛点。数据湖的出现可以很好地解决这个痛点,这也是为什么各个云厂商都推出了数据湖产品,数据湖产品和解决方案越来越得到客户的认可。Gartner 2020年发布的报告显示目前已经有39%的用户在使用数据湖,34%的用户考虑在1年内使用数据湖。

    1.2 Aliyun DLA数据湖整体方案

    image.png

    Aliyun数据湖分析(DLA)产品提供了数据湖的一站式解决方案。OSS对象存储采用KV的技术架构,可以实现无限扩展,是公认的数据湖存储底座。用户可以通过离线ETL和在线增量ETL将在线数据和实时增量数据,同步到OSS中,然后对数据做深度的计算和分析。用户也可以直接访问这些在线库,做在线的联邦分析。为了方便用户管理数据湖中的数据,我们提供了统一的数据湖管理方案。数据湖管理可以统一存储数据湖中数据的元信息给计算引擎使用,另外还提供元数据动态爬取功能,可以动态解析OSS数据目录结构和数据格式,省去了用户手动创建表和分区的工作。DLA同时提供了SQL和Spark两个引擎,SQL基于Presto实现,可以实现在线分析,Spark可以实现用户自定义代码和复杂计算逻辑。同时,DLA跟DMS和QuickBI进行了深度集成,方便用户实现更丰富的开发和管理逻辑。

    二、DLA Serverless Spark架构解析

    2.1 DLA Spark为什么是云原生 + Serverless

    2.1.1 数据湖天然存储计算分离

    数据湖技术处理的对象是用户已存在的所有的数据。这里提到两个关键定语“已存在的”和“所有的”。要处理好“已存在的”原始数据,最好的方式显然不是先将其导入到数据仓库中,最好是能够原地分析,使用单独的计算资源来计算分析各种类型存储系统中的数据,这就是存储计算分离的架构。存储计算分离的架构能够做到存储和计算的分层弹性,存储可以无限扩展,计算能够按需弹性调度。这里提到了弹性计算,计算的弹性可以分很多层次:

    • 集群级弹性:用户可以按需购买ECS并部署集群,然后后再执行计算任务,任务执行完之后再释放掉集群;
    • 作业级弹性:用户每个作业都是单独的计算资源,作业执行完之后立即释放;
    • 作业内弹性:一个任务在执行过程中,不同的阶段所需要消耗的资源不同,典型地,分布式作业出现长尾时,大部分资源都是空闲的,此时可以将空闲资源释放掉;
    • 容器内弹性:计算任务的进程在执行过程中不同时段所需要的资源不同,是否可以做到动态调节;

    弹性的粒度越细,资源的利用率越高,成本也就越低。相对于传统IDC,云的最大的优势之一就是弹性,数据湖天然是存储计算分离的,跟云弹性的能力十分匹配,数据湖场景下,云原生 + 弹性是必然趋势。

    2.1.2 Serverless是云的趋势

    Serverless是业内公认的云发展的一个趋势。其实不难理解,从IDC自建到搬站上云再到Serverless化符合技术和客户需求发展的规律。

    在云最初产生的时候,大家把云计算基本等同于虚拟化技术,客户最普遍的需求是将线下的站点搬上云,用户把云当做对线下硬件的替换,企业的IT研发、运维大体跟上云前一致。用户对大数据系统,比如Hadoop集群,也类似,把线下集群换成虚拟集群,再由专门团队运维大数据集群。在云市场发展的第一阶段,这种模式有用户习惯的因素,也有性能、成本等的因素,自建跟云产品在性能上差距不太大,在成本上甚至更便宜,客户也拥有一定的掌控感。然而,云的技术会继续往精细化深入发展,从资源共享的角度来看,每套Hadoop集群都有一套自己的管控,这些管控包括Master节点,Core节点上面的守护进程,以及配套的监控、运维管理等系统。这些资源和人力投入实际上对企业来说都只是成本,并不产生真正的计算价值。

    随着云技术的发展,Serverless形态可以很好的解决企业在第一阶段遇到的问题,企业只需要关心自己的业务开发,只为真正参与计算的资源付费,云产品把管控的部分统一管理起来,边际成本可以做到很低。另外,云产品会深度扎根于云基础设施,对性能、弹性、使用体验等做持续深入优化,相对于第一阶段的用户自建模式可以实现数倍的性价比提升。最后,随着云产业的发展,云产品会越来越标准化,客户也不必担心被云绑定的问题。在云市场进入第二阶段,Serverless形态的产品让企业更专注于自身业务,进一步降低运维和资源成本,让开发者拥有更好的使用体验以及更低的入门门槛。

    2.1.3 Spark一站式解决数据湖计算需求

    “所有的”意味着数据的来源途径多种多样,存储位置多种多样,数据格式多种多样。这就要求计算引擎可以支持所有数据类型,并且可以很方便的做分析、计算,因为数据是“已存在的”,Schema只能在读取的时候才能确定,而不能依赖用户把表都提前建好。Spark非常适合数据湖场景:

    • Spark本身内置了十分丰富的数据源连接器,接口也很方便扩展;
    • Spark既支持使用SQL,又支持编写多种语言的DataFrame代码,兼具易用性和灵活性;
    • Spark一站式引擎能力,同一个引擎同时提供SQL、流、机器学习、图计算的能力;

    DLA团队将Serverless、云原生、Spark技术优势深度整合到一起,提供Serverless Spark产品,兼具三者优势。下面我们将对Serverless Spark产品架构进一步解析。

    2.2 自建Spark集群 VS Serverless Spark

    image.png

    上图中左半部分是传统最常见的集群版Spark,右边是Serverless Spark。集群版Spark大家都比较熟悉,每个用户一个集群,集群内部拥有一套完整的Spark管控,用户使用方式上跟传统IDC模式一致。

    Serverless Spark将管控完全多租户化,相对于传统的集群模式,Serverless Spark抽象出一个虚拟集群的概念。虚拟集群只是承载用户对作业进行控制的一些配置,包括网络的配置、安全隔离的配置、计算资源Quota的配置、作业通用参数的配置等。由于是虚拟集群,所以集群创建基本都可以做到秒级完成。用户创建完虚拟集群之后,就可以往虚拟集群提交作业,去访问用户在各个存储引擎中的数据。

    Serverless Spark在弹性能力上基于Aliyun Kubernetes云原生技术深度定制,调度层可以实现秒级拉起,一分钟可以并行拉起300个计算节点,后续还会持续优化。Serverless Spark控制服务实现了对云资源、作业、库表列元数据、租户、安全等管理,对上提供阿里云OpenAPI,用户可以通过OpenAPI实现作业的提交和管理。另外Serverless Spark会跟其他云产品深度集成,进一步丰富用户的使用场景,目前Serverless Spark已经跟DMS进行集成,可以实现工作流,定时调度等管理。

    对比维度 自建Hadoop集群 Serverless版
    内置存储 HDFS 数据湖存储OSS
    集群形态 ECS集群,需配置Master、Core规格 虚拟集群,只需配置资源quota
    集群管理 扩缩容、升降配 quota调整,参数配置
    售卖形态 实例型,集群粒度,按ECS规格售卖 服务型,按作业实际使用CU*时收费
    资源弹性 集群级别 作业级弹性
    性价比 低:管控开销+资源空闲开销 高:按需付费
    维护成本 高:运维团队维护集群 低:管理员分配资源
    作业管理 Livy、脚本、控制台、定时调度、作业编排 OpenAPI、脚本、控制台、定时调度、作业编排
    租户支持 依赖开源,配置复杂 Aliyun RAM
    学习成本 高:需要先学习集群管理与配置 低:只需要学习Spark开发

    在上表中,我们在集群运维、性价比、作业开发等方面对比了两种形态的差异。从使用体验上,Serverless Spark可以做到开箱即用,一分钟就可以跑通一个Spark作业;从成本上,由于将管控完全多租户化,用户不需要承担这部分额外开销,只需要实际使用付费;从运维方面,一个企业中一个管理员就可以实现整体管理工作,大大降低运维成本。

    三、DLA Serverless Spark性价比

    3.1 1TB Terasort DLA Spark vs 自建Hadoop 性价比对比

    image.png

    我们先对比下1TB数据情况下,数据湖方案跟传统Spark集群方式的性价比。相关配置说明如下:

    • TeraSort输入1TB + shuffle大约1TB + 输出1TB,作业每天跑一次。
    • Hadoop集群配置:单Master(4c8g) + 5个Core(8c32g),Core节点配置4块500GB的高效云盘。一般高效云盘采用2备份的HDFS配置。这里存储空间是4 500GB 5 / 2 = 5TB。
    • Serverless Spark采用40CU + 2TB OSS。

    对比结果如右图所示,作业性能上Serverless Spark跟Hadoop基本持平,但是性价比差异非常大,DLA Serverless Spark会节约80%。也就是会有4-5倍的性价比提升。

    需要说明的是:

    • Hadoop集群配置是一个总容量5TB集群的典型配置,一般情况下集群不能把磁盘都用满,要留一定buffer,否则系统可能会出现各种空间不足问题。
    • Serverless Spark完全按需使用存储和计算资源。
    • Serverless Spark对OSS访问实现了深度定制优化,性能相比于社区提升1倍左右。

    3.2 10TB Terasort DLA Spark vs 自建Hadoop 性价比对比

    image.png

    对于更大规模数据,比如10TB,对比结果如上图所示。相关配置说明:

    • TeraSort输入10TB + shuffle大约10TB + 输出10TB。作业每天跑一次。
    • Hadoop集群配置:单Master(4c8g) + 5个Core(16c64g),Core节点配置8 5.5TB的本地盘。一般本地盘采用3备份的HDFS配置。这里存储空间是5 8 * 5.5TB / 3 = 73TB。
    • Serverless Spark采用80CU + 50TB OSS。

    我们发现性能上DLA Spark提升了1倍,成本反而降低了一半,性价比提升4倍。

    需要说明的是:

    • Hadoop集群采用的是大数据量场景下的典型配置,采用本地盘D1机型,成本相对于云盘要便宜。由于本地盘机型要求空间比较大,16c64g的只能配置44TB的本地盘,考虑到Hadoop集群的本地盘通常不能打太满,为了公平起见,我们采用OSS的空间是50TB。
    • 在分析性能时发现,在10TB场景下,本地盘的存储和shuffle之间会有IO带宽上明显的争用,而Serverless Spark计算节点自带essd云盘,将shuffle盘完全独立,对性能提升有较大的贡献。

    3.3 Serverless Spark访问用户自建Hadoop

    image.png

    用户可以将自建Hadoop和Serverless Spark混合使用,用户Hadoop集群在高峰期需要更多的计算资源,用户可以直接提交Serverless Spark来实现对计算弹性的需求。由于Serverless Spark可以做到直接跟用户VPC打通,可以直接使用内网带宽,经过对比两者的性能基本持平。

    四、使用场景

    image.png

    面向数据湖中的各种各样的数据,Spark可以用于如下场景:

    • 生态打通:Spark的多数据源能力,提供外部数据源批量入库、联邦分析能力;DLA Spark会跟云上数据源做深度集成优化,解决稳定性问题并提升性能;
    • 算法及用户可编程:支持python、java、scala、R、SQL多语言,支持复杂的数据过程处理(类似PL/SQL)、机器学习等;
    • 离线数仓(复杂分析):支持复杂离线分析,提供天/月级别的报表等;
    • 半结构化/非结构化处理:搭配HDFS/OSS存储为数据库添加非结构化数据存储处理能管理(CSV、XML、Parquet多种存储);
    • 离线ETL:可以用于各存储引擎之间的数据转换、清洗、归档等操作;
    • 实时计算:Spark Streaming + Hudi可以实现数据实时转存,实现在不影响在线库稳定性情况下,对实时数据的复杂分析;Spark Streaming实时ETL将多个MySQL大表,合并为一个ADB宽表,避免大表在线join,提高在线分析性能。

    image.png

    上图是某游戏公司使用DLA解决数据湖场景问题的方案。用户要对在线库RDS做分析,但又怕影响RDS的稳定性,于是选择采用DLA一键建仓功能将其同步到OSS里面转为列存;用户游戏APP的日志数据会接入到Kafka里面,然后通过Spark Streaming实时写入到OSS,数据采用Hudi增量数据湖格式。数据流入到OSS后,用户会对数据使用DLA SQL(Presto)做在线分析,也会对历史数据做复杂分析和机器学习,挖掘游戏玩家的使用规律。

    五、总结与展望

    针对用户面临的越来越多的数据湖场景典型问题,阿里云DLA产品提供了一体化解决方案,从数据湖管理到数据湖分析和计算。相对于在线引擎,Spark更适合弹性计算架构,可以跟云原生的弹性能力深度整合起来。从传统IDC到搬站上云到完全Serverless化,这条路径已经被越来越被认可为云技术的发展路径。DLA Spark采用完全云原生 + Serverless形式,相对于传统的自建Hadoop在性价比上拥有数倍的优势。

    未来,DLA Serverless Spark会面向数据湖场景做进一步深度优化:

    • 更便宜:实现更细粒度的弹性继续降低成本;
    • 更快:优化Spark内核本身,特别是跟云存储之间做深入定制优化,提升引擎性能;
    • 更好用:降低Spark开发难度,更进一步提升用户使用体验。

    注:DLA Serverless Spark控制台使用链接,DLA Serverless Spark帮助文档

    image.png

    ]]>
    关于阿里云DRDS 5.3升级 详细介绍 性能提升300%-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800

    ]]>
    MySQL主从复制读写分离,看这篇就够了!-阿里云开发者社区 Thu, 29 Oct 2020 12:16:15 +0800 思维导图

    微信公众号已开启:【java技术爱好者】,还没关注的记得关注哦~

    文章已收录到我的Github精选,欢迎Starhttps://github.com/yehongzhi/learningSummary

    前言

    在很多项目,特别是互联网项目,在使用MySQL时都会采用主从复制、读写分离的架构。

    为什么要采用主从复制读写分离的架构?如何实现?有什么缺点?让我们带着这些问题开始这段学习之旅吧!

    为什么使用主从复制、读写分离

    主从复制、读写分离一般是一起使用的。目的很简单,就是为了提高数据库的并发性能。你想,假设是单机,读写都在一台MySQL上面完成,性能肯定不高。如果有三台MySQL,一台mater只负责写操作,两台salve只负责读操作,性能不就能大大提高了吗?

    所以主从复制、读写分离就是为了数据库能支持更大的并发

    随着业务量的扩展、如果是单机部署的MySQL,会导致I/O频率过高。采用主从复制、读写分离可以提高数据库的可用性

    主从复制的原理

    ①当Master节点进行insert、update、delete操作时,会按顺序写入到binlog中。

    ②salve从库连接master主库,Master有多少个slave就会创建多少个binlog dump线程。

    ③当Master节点的binlog发生变化时,binlog dump 线程会通知所有的salve节点,并将相应的binlog内容推送给slave节点。

    ④I/O线程接收到 binlog 内容后,将内容写入到本地的 relay-log。

    ⑤SQL线程读取I/O线程写入的relay-log,并且根据 relay-log 的内容对从数据库做对应的操作。

    如何实现主从复制

    我这里用三台虚拟机(Linux)演示,IP分别是104(Master),106(Slave),107(Slave)。

    预期的效果是一主二从,如下图所示:

    Master配置

    使用命令行进入mysql:

    mysql -u root -p

    接着输入root用户的密码(密码忘记的话就网上查一下重置密码吧~),然后创建用户:

    //192.168.0.106是slave从机的IP
    GRANT REPLICATION SLAVE ON *.* to 'root'@'192.168.0.106' identified by 'Java@1234';
    //192.168.0.107是slave从机的IP
    GRANT REPLICATION SLAVE ON *.* to 'root'@'192.168.0.107' identified by 'Java@1234';
    //刷新系统权限表的配置
    FLUSH PRIVILEGES;

    创建的这两个用户在配置slave从机时要用到。

    接下来在找到mysql的配置文件/etc/my.cnf,增加以下配置:

    # 开启binlog
    log-bin=mysql-bin
    server-id=104
    # 需要同步的数据库,如果不配置则同步全部数据库
    binlog-do-db=test_db
    # binlog日志保留的天数,清除超过10天的日志
    # 防止日志文件过大,导致磁盘空间不足
    expire-logs-days=10 

    配置完成后,重启mysql:

    service mysql restart

    可以通过命令行show master statusG;查看当前binlog日志的信息(后面有用):

    Slave配置

    Slave配置相对简单一点。从机肯定也是一台MySQL服务器,所以和Master一样,找到/etc/my.cnf配置文件,增加以下配置:

    # 不要和其他mysql服务id重复即可
    server-id=106

    接着使用命令行登录到mysql服务器:

    mysql -u root -p

    然后输入密码登录进去。

    进入到mysql后,再输入以下命令:

    CHANGE MASTER TO 
    MASTER_HOST='192.168.0.104',//主机IP
    MASTER_USER='root',//之前创建的用户账号
    MASTER_PASSWORD='Java@1234',//之前创建的用户密码
    MASTER_LOG_FILE='mysql-bin.000001',//master主机的binlog日志名称
    MASTER_LOG_POS=862,//binlog日志偏移量
    master_port=3306;//端口

    还没完,设置完之后需要启动:

    # 启动slave服务
    start slave;

    启动完之后怎么校验是否启动成功呢?使用以下命令:

    show slave statusG;

    可以看到如下信息(摘取部分关键信息):

    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.0.104
                      Master_User: root
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000001
              Read_Master_Log_Pos: 619
                   Relay_Log_File: mysqld-relay-bin.000001
                    Relay_Log_Pos: 782
            Relay_Master_Log_File: mysql-bin.000001 //binlog日志文件名称
                 Slave_IO_Running: Yes //Slave_IO线程、SQL线程都在运行
                Slave_SQL_Running: Yes
                 Master_Server_Id: 104 //master主机的服务id
                      Master_UUID: 0ab6b3a6-e21d-11ea-aaa3-080027f8d623
                 Master_Info_File: /var/lib/mysql/master.info
                        SQL_Delay: 0
              SQL_Remaining_Delay: NULL
          Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
               Master_Retry_Count: 86400
                    Auto_Position: 0

    另一台slave从机配置一样,不再赘述。

    测试主从复制

    在master主机执行sql:

    CREATE TABLE `tb_commodity_info` (
      `id` varchar(32) NOT NULL,
      `commodity_name` varchar(512) DEFAULT NULL COMMENT '商品名称',
      `commodity_price` varchar(36) DEFAULT '0' COMMENT '商品价格',
      `number` int(10) DEFAULT '0' COMMENT '商品数量',
      `description` varchar(2048) DEFAULT '' COMMENT '商品描述',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品信息表';

    接着我们可以看到两台slave从机同步也创建了商品信息表:
    在这里插入图片描述

    主从复制就完成了!java技术爱好者有点东西哦~

    读写分离

    主从复制完成后,我们还需要实现读写分离,master负责写入数据,两台slave负责读取数据。怎么实现呢?

    实现的方式有很多,以前我公司是采用AOP的方式,通过方法名判断,方法名中有get、select、query开头的则连接slave,其他的则连接master数据库。

    但是通过AOP的方式实现起来代码有点繁琐,有没有什么现成的框架呢,答案是有的。

    Apache ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 JDBC、Proxy两部分组成。

    ShardingSphere-JDBC定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。

    读写分离就可以使用ShardingSphere-JDBC实现。
    在这里插入图片描述

    下面演示一下SpringBoot+Mybatis+Mybatis-plus+druid+ShardingSphere-JDBC代码实现。

    项目配置

    版本说明:

    SpringBoot:2.0.1.RELEASE
    druid:1.1.22
    mybatis-spring-boot-starter:1.3.2
    mybatis-plus-boot-starter:3.0.7
    sharding-jdbc-spring-boot-starter:4.1.1

    添加sharding-jdbc的maven配置:

    <dependency>
        <groupId>org.apache.shardingsphere</groupId>
        <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
        <version>4.1.1</version>
    </dependency>

    然后在application.yml添加配置:

    # 这是使用druid连接池的配置,其他的连接池配置可能有所不同
    spring:
      shardingsphere:
        datasource:
          names: master,slave0,slave1
          master:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver
            url: jdbc:mysql://192.168.0.108:3306/test_db?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
            username: yehongzhi
            password: YHZ@1234
          slave0:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver
            url: jdbc:mysql://192.168.0.109:3306/test_db?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
            username: yehongzhi
            password: YHZ@1234
          slave1:
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver
            url: jdbc:mysql://192.168.0.110:3306/test_db?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
            username: yehongzhi
            password: YHZ@1234
        props:
          sql.show: true
        masterslave:
          load-balance-algorithm-type: round_robin
        sharding:
          master-slave-rules:
            master:
              master-data-source-name: master
              slave-data-source-names: slave0,slave1

    sharding.master-slave-rules是标明主库和从库,一定不要写错,否则写入数据到从库,就会导致无法同步。

    load-balance-algorithm-type是路由策略,round_robin表示轮询策略。

    启动项目,可以看到以下信息,代表配置成功:

    编写Controller接口:

        /**
         * 添加商品
         *
         * @param commodityName  商品名称
         * @param commodityPrice 商品价格
         * @param description    商品价格
         * @param number         商品数量
         * @return boolean 是否添加成功
         * @author java技术爱好者
         */
        @PostMapping("/insert")
        public boolean insertCommodityInfo(@RequestParam(name = "commodityName") Strin