首页 文章 精选 留言 我的

精选列表

搜索[过拟合],共10002篇文章
优秀的个人博客,低调大师

美图运维之旅:在阿里云上的经验以及踩过的坑

前言 美图公司是如何使用阿里云的 我们是如何做成本优化的 我们在阿里云上遇到了哪些坑 我们如何做自动化运维的 前言 本篇文章可能更多的是文字表述,没啥高深的用词,都是大白话,需要各位朋友有耐性的阅读下去,也希望各位朋友能够提出宝贵建议。 美图公司是如何使用阿里云的 关于使用方面,我想从以下几个点简单叙述一下, 权限规划 区域规划 网络规划 型号规划 统一登录规划 命名规划 权限规划 权限规划只要是在账号权限规划上,一般是主账号+子账号,然后通过ram来进行对应授权,为什么要做这个,因为主账号一般控制在运维手上,子账号可能会存在其他运维手上以及某些开发手上,那么就需要做严格的权限控制。目前阿里云ram有几个点:用户,群组,角色,策略等功能,目前角色和策略都支持自定义,然后可以应用到用户上,群组上。角色可以附加到ecs上,可以用高权限获取一些云上资源信息。 区域规划 做区域规划需要考虑几点: 第一、你的业务架构,比如我有idc机房在北京,那么我们上云的话一般会考虑北京region,又比如我的业务用户主要分布在江浙一带,那么我们一般就考虑上海或者杭州region。 第二、一定要找阿里云技术问到当前region的最新可用区是哪个,机器储备量级是多少,因为新可用区一般会有新机器,新型号,一般来说带来的好处就是性能高还便宜;另外老可用区机器型号非常少,经常会遇到售馨的问题。 第三、当我们定好了区域之后,后续再改变会非常麻烦,所以前期的调研准备一定要完善,考虑要全面。 网络规划 关于网络规划,主要有以下几点需要考虑下: 第一、vpc规划,可以按照你的业务架构划分vpc,不同vpc之间可以做一些安全组也隔离流量。例如我有大数据业务,普通业务,运维业务,那么我可以简单创建几个vpc:大数据vpc,生产业务vpc,测试业务vpc,运维vpc。 第二、子网划分,每一个vpc划分多个子网,比如我拿生产业务vpc来举例子,可以划分为:容器子网,mysql子网,redis子网等。(注意:子网在阿里云就是交换机的概念) 第三、子网的ip数量,这个的定义需要提前规划和统计业务量级,vpc本身是一个大的网段,单个子网的网段要合适,太大浪费,太小扩展麻烦。 我们内部的子网划分: 型号规划和命名规划 把这两个放一起讲,一般来说公司会选择一款型号来作为自己的主力机型,这个配置比较贴近自己的业务形态,另外这个机型也要跟阿里云备案,让他们提供足够大的节点池。命名规划的话,我们可以按照业务提供能力来做不同的命名方式: k8s节点: aly-k8snode-10-10-10-1.meitu.commysql: aly-mysql-A-10-10-10-2.meitu.comredis: aly-redis-B-10-10-10-3.meitu.com 做好这个,第一能更好区分不同节点功能,第二能更好的去做自动化运维工作。 统一登录规划 做统一登录就是要做跳板机、做权限管理。有以下几点要考虑: 第一、用户登录虚机需求,运维侧需要做一个公共跳板机,所有的登录操作都需要通过该机器跳转。 第二、开发用户对于线上的机器不能有永久权限,开放的一般是临时权限,所以我们需要有一套授权,回收权限的平台。 第三、做好操作追踪,防止一些 高危人员做一些非法操作。 我们内部的工单平台: 我们是如何做成本优化的 关于成本优化,是一个非常重要并且也非常头疼的一件事情,当服务趋于稳定后,一定要慢慢去优化成本。那么关于成本优化的事项,我们做了这些事情: 容器化 弹性伸缩的深入使用 做好资源开通记录和监控 架构规划(内网和公网) 增加混布实例 定时巡检,删除无用资源 最低实例实行包年包月 容器化 容器化趋势,他也是作为成本优化最好的方案之一,目前我们公司95%的业务已经容器化。我们在云上使用的是托管的k8s集群,另外我们自己有一套自研的k8s管理工具,来做日常的业务发布,迭代等操作。 弹性伸缩的深入应用 我认为云服务和自建IDC最大的差距就是弹性伸缩的应用,我个人也是非常喜欢弹性伸缩这一个服务,因为他能很好的提升资源利用率,并且显著的降低成本。我们在以下几个场景用了弹性伸缩服务: 第一、托管k8s服务的容器节点。 第二、普通虚机业务开通弹性伸缩。 第三、容器业务服务开通HPA。 第四、共享带宽的弹性。 结合这些弹性伸缩的场景,我们做了一些工具,主要是观察全局的一个情况。阿里云弹性伸缩控制台总览: 容器单个业务伸缩策略详情: 做好资源开通记录和监控 这个非常重要,因为我们经常会遇到一个情况是:业务临时有个需求,需要开一台测试机器来做业务验证,我们开通完交付。他们测试完成之后并不会通知你是否需还需要这台机器,导致慢慢被遗忘,所以增加了额外的费用。另外一点我们也可以根据记录去做一些下线工作:当一个业务需要下线时候,我们可以根据他们的资源申请单去下线相关的服务,避免漏下或者错下。 架构规划(内网和公网) 这个点涉及到的一般就是流量费用,公网带宽费用,我们遇到过一些情况是:业务调用能走内网的他不走内网,非要走公网,甚至他根本就不知道有内网地址。所以基于这个我们做了以下几点: 第一、服务上线评审,新服务上线一定要拉上运维,开发一起做一个评审,因为开发不懂线上网络结构,他们认为只要服务能够正常通就是没问题的,所以他们忽略了非常多的细节,比如内网调用等。 第二、服务提供内网域名,公司业务越多,那么存在互相依赖的地方就越多,这些内部依赖的动作能通过内网的一定要通过内网,不要从公网绕一圈。比如我在阿里云上下载oss图片,明显有内部的oss地址可用。 第三、服务部署规划,当有A的子服务B需要上线,且B是完全给A调用的,那么该服务上线的区域一定是A所在区域,不要存在跨可用区,跨region,跨专线等操作,这些都会带来额外的流量费用。 增加混布实例 混布一般是针对非容器化业务的,虽然混布不建议,但是也是不能缺少的。公司肯定会有类似的业务,并且年代久远,无人维护,像这类业务就可以统一丢到一两台机器上部署即可。 定时巡检,删除无用资源 这一步也是运维日常,我们会跑一些自动化的脚本去删除一些无用的服务,并且列出一些无主资源去让业务方确认是否释放。 镜像。阿里云的镜像可以只留最新的几个,删除老的镜像。 快照。跟镜像类似。 磁盘。删除无挂载,也无需保留的磁盘。 OSS。清理oss空间,业务方会保留非常多的静态资源,他们也不会删除,也不会去管,所以需要我们来推动他们来确认清理。 ECS。删除临时测试机器,删除业务已经下线的机器。 ...... 虽然这些都是比较便宜,不过积少成多,成本优化本身就是一个漫长的过程,所以一点点的优化才是王道。 最低实例实行包年包月 这个方案主要是针对弹性伸缩来说的,我们会观察每一个弹性伸缩组一天的监控数据,包括cpu利用率,实例数量。然后观察几周的数据,发现最低的一个实例数量,把这部分实例转成包年包月。 如下图,我们可以拿2-3台进行转包月操作: 我们在阿里云上遇到了哪些坑 其实阿里云在国内市场已经做的非常好了,遇到的坑也大多比较贴近自身业务,有些坑他们也已经做了架构调整规避了。 区域资源配额问题 NAT 带宽问题 实例售馨问题 可用区交换机网段过大 其实坑还有很多,只不过有些都是小坑,有些可能我自己也有点忘记了。 下面简单解释下这些坑: 区域资源配额问题 我们在重要节日推广,需要大量的机器储备,某年春节的时候遇到了区域资源配额瓶颈问题,即这个账号默认可以使用多少的vcpu(这个主要是按需的,包年包月的不会计算进来)。当时推广的时候,我们机器完全扩不上来了,最终排查到是资源配额上限了,也是紧急通知阿里云帮忙调整。 NAT 带宽问题 最早阿里云的 NAT 还是有单独的带宽配置的,当时我们有一个服务推广效果比较好,直接把 NAT 打满了,导致我们整个vpc内的网络都非常慢,严重影响了我们服务质量。目前阿里云刚把 NAT 带宽调整成共享带宽包,带宽和 NAT 实现了分离,另外带宽也可以动态调整,非常的方便。 实例售馨问题 如前面所说的,一个企业一般会选用一个主力型号,当时是弹性的机器过多,导致该型号实例售馨,新机器无法创建。针对这个问题,我们做了如下两个解决方式: 设置多实例弹性,弹性伸缩可以配置弹多个实例型号,并且也有优先级。 替换大规格机器,简单来说就是用一台大规格实例顶替多台小规格实例。 可用区交换机网段过大 遇到这个坑的背景也是我们想使用新可用区,因为我们IDC跟阿里云是默认专线打通的,所以会存在网段分配的问题,当初分配给阿里云的网段已经用完了,所以我想开新区,必须释放老的交换机或者拆分它。分配的网段用完了的根本原因还是:当初规划不合理,交换机设置过大,然后根本用不到这么多。 我们如何做自动化运维的 弹性伸缩服务更新 统一登录权限申请 云上资源数据统计 自定义资源监控告警 定时弹性伸缩控制成本 重要业务推广通知 移动端运维 关于自动化运维这一块,其实需要紧密贴近公司的业务来做。只要你平时感觉哪个操作经常做,又非常繁琐,那么他就可以用工具替代,所以下面的东西都是我平时经常操作而抽象出来的。 弹性伸缩服务更新 弹性伸缩服务,一个非常重要的操作就是更新,我们每个弹性伸缩组都有上百个实例,不可能去一个一个更新,肯定是创建一个镜像后,然后按照这个镜像进行滚动更新。我们有100个左右的弹性伸缩组,所以这个更新操作是经常需要的,所以我做了自动更新操作,并集成到了移动端和web端。 统一登录权限申请 我们有自己的一套权限申请平台,相应的人员可以申请线上的机器,申请可以是临时的,也可以是拥有的。 云上资源数据统计 这个统计信息会统计我们当前阿里云使用了多少机器,多少cpu,多少内存。这个信息会发给我们老大,同时开发老大也会关注这个,因为涉及到成本。 自定义资源监控告警 其实阿里云集成的监控告警已经比较全面了,他可以通过邮件、短信、钉钉等方式发送出来。不过涉及到业务层面的,或者更贴合我们自己需求的,一般都会自定义通知,大家可以看我这篇chat,《美图分享:适用于中小型企业自研的监控告警通知系统(附源码)》,我平时自定义告警都是通过这个项目进行发送的,种类繁多。 定时弹性伸缩控制成本 我们完全按照阿里云弹性伸缩设置默认的伸缩规则有时候可能还不能满足,借此我们可能还会设置一些定时伸缩,比如我晚上2点就让它维持两台机器。这个也是控制服务稳定性的一个操作,因为在某些时刻,服务是1台机器扛不住,两台机器会缩容的状态。我们开发了一个工具展示定时任务的列表(由于业务迁移了,所以这里没数据了,嘿嘿) 重要业务推广通知 一般我们的业务在重要节日中,都会有推广。那么推广前,我们一定需要保障该服务的稳定性,该扩容的扩容,该加配置的加配置,所以我们做了重要推广通知的平台,来重点保障春节,五一,国庆等重要节日业务推广。 移动端运维 移动端运维也是今年我们新引入的,因为我们已经厌烦了天天背着电脑了,能在手机上操作就在手机上操作了。其实上面的很多服务都是移动端的界面。由于自己开发能力有限,所以只开发了 IOS 客户端,后端就是python写的。(有兴趣的朋友,可以一起交流一下!) 本文分享自微信公众号 - 程序猿的野生香蕉(gh_2e510bc5c532)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

Python网络爬虫之利用urllib2通过URL抓取网页内容

所谓网页抓取,就是把URL地址中指定的网络资源从网络流中读取出来,保存到本地。 类似于使用程序模拟IE浏览器的功能,把URL作为HTTP请求的内容发送到服务器端, 然后读取服务器端的响应资源。 一、通过urllib2抓取百度网页 在Python中,我们使用urllib2这个组件来抓取网页。urllib2是Python的一个获取URLs(Uniform Resource Locators)的组件。它以urlopen函数的形式提供了一个非常简单的接口。最简单的urllib2的应用代码只需要四行。 urllib2抓取百度网页 我们通过浏览器可以打开百度主页,右击,选择查看源代码(火狐OR谷歌浏览器均可),会发现也是完全一样的内容。也就是说,上面这四行代码将我们访问百度时浏览器收到的代码们全部打印了出来。这就是一个最简单的urllib2的例子。 当然,除了"http:",URL同样可以使用"ftp:","file:"等等来替代。HTTP是基于请求和应答机制的:客户端提出请求,服务端提供应答。 二、urllib结合Request用法 urllib2用一个Request对象来映射你提出的HTTP请求。在它最简单的使用形式中你将用你要请求的地址创建一个Request对象,通过调用urlopen并传入Request对象,将返回一个相关请求response对象,这个应答对象如同一个文件对象,所以你可以在Response中调用.read()客户端提出请求,服务端提供应答。 urllib+Request用法 可以看到,以上两种用法的输出结果都是一致的。 三、HTTP请求的同时传入参数data 设置Headers到http请求 有一些网站不喜欢被程序(非人为访问)访问,或者发送不同版本的内容到不同的浏览器。默认的urllib2把自己作为“Python-urllib/x.y”(x和y是Python主版本和次版本号,例如Python-urllib/2.7),浏览器确认自己身份是通过User-Agent头,当你创建了一个请求对象,你可以给他一个包含头数据的字典。 Headers请求HTTP

优秀的个人博客,低调大师

MySQL 5.6通过Keepalived+互为主从实现高可用架构

本文将介绍两台Mysql如何实现高可用架构。通常我们会配置主从同步,但这样若主的Mysql挂掉,还需要手动干预,例如把指向主库的IP地址修改为指向从库的IP,为了实现自动切换到从数据库,我们可以使用Keepalived配置一个浮动的VIP出来供前端访问,主的Mysql故障了VIP会立即自动切换到从的Mysql,省去了人工干预的时间,但要想故障的那台Mysql起来后也能作为从Mysql自动去同步数据,就需要配置成互为主从。拥有VIP的Mysql可认为是主库,才能进行数据的写入,由于VIP可以在两台Mysql之间浮动切换,因此这两台mysql是互为主从。 一、测试环境 操作系统版本:Red Hat Enterprise Linux Server release 6.5 (Santiago) Mysql版本:MySQL-5.6.38-1.el6.x86_64.rpm-bundle.tar keepalived版本:keepalived-1.2.7-3.el6.x86_64.rpm node01:192.168.10.71 node02:192.168.10.72 VIP:192.168.10.70 二、配置node01为主、node02为从的主从同步 1、node01和node02分别安装好Mysql 5.6.38,安装方法请参考上一篇博文《MySQL 5.6.38在RedHat 6.5上通过RPM包安装》。 2、在node01和node02分别编辑/etc/my.cnf,配置如下: [mysqld] log-bin=mysql-bin server-id = 1 [mysqld_safe] log-error = /var/log/mysqld.log pid-file = /var/run/mysqld/mysqld.pid replicate-do-db = all 3、重启mysql服务 [root@node01 ~]# service mysql restart [root@node02 ~]# service mysql restart 4、登录node01的mysql,创建用于同步的账户repl,密码为123456,并查询master状态,记下file名称和posttion数值 mysql> GRANT REPLICATION SLAVE ON *.* to 'repl'@'%' identified by '123456'; Query OK, 0 rows affected (0.00 sec) mysql> show master status; 5、登录node02的mysql,执行以下语句开启从服务器,注意master_host要填写node01的IP mysql> change master to master_host='192.168.10.71',master_user='repl',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=318; Query OK, 0 rows affected, 2 warnings (0.36 sec) 1 2 3 4 5 6 7 命令参数解释: master_host='192.168.10.71'##Master的IP地址 master_user='repl'##用于同步数据的用户(在Master中授权的用户) master_password='123456'##同步数据用户的密码 master_log_file='mysql-bin.000001'##指定Slave从哪个日志文 件开始读复制数据(可在Master上使用showmasterstatus查看到日志文件名) master_log_pos=429##从哪个POSITION号开始读 mysql> start slave; Query OK, 0 rows affected (0.03 sec) 6、查询从服务的状态,状态正常 7、在node01创建一个数据库、一个表并插入一行数据,用于测试node02是否能同步过去 mysql> create database mysql_long; Query OK, 1 row affected (0.00 sec) mysql> use mysql_long; Database changed mysql> create table test(id int(3),name char(5)); Query OK, 0 rows affected (0.13 sec) mysql> insert into test values (001,'jlong'); Query OK, 1 row affected (0.01 sec) 8、登录到node02的Mysql,同步正常 三、配置node02为主、node01为从的主从同步 1、登录node02的mysql,创建用于同步的账户repl,密码为123456,并查询master状态,记下file名称和posttion数值,并查询master状态 mysql> GRANT REPLICATION SLAVE ON *.* to 'repl'@'%' identified by '123456'; Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.10 sec) 2、登录node01的mysql,执行以下语句开启从服务器,注意这里master_host要填写node02的IP mysql> change master to master_host='192.168.10.72',master_user='repl',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=318; Query OK, 0 rows affected, 2 warnings (0.36 sec) mysql> start slave; Query OK, 0 rows affected (0.03 sec) 3、查询从服务的状态,状态正常 4、在node02创建一个数据库、一个表并插入一行数据,用于测试node01是否能同步过去 mysql> create database mysql_long2; Query OK, 1 row affected (0.00 sec) mysql> use mysql_long2; Database changed mysql> create table test2(id int(3),name char(10)); Query OK, 0 rows affected (0.71 sec) mysql> insert into test2 values (001,'jianlong'); Query OK, 1 row affected (0.00 sec 5、node01同步正常。 这样互为主从就配置好了,两台机既是对方的Master,又是对方的Slave,无论在哪一台机上数据发生了变化,另一台都能及时进行同步数据,下面我们开始配置keepalived实现高可用。 四、keepalived配置 1、在node01上使用yum安装keepalived [root@node01 ~]# yum install keepalived -y 2、在node02上也使用yum安装keepalived [root@node02 ~]# yum install keepalived -y 3、编辑node01的keepalived的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 [root@node01~] #cat/etc/keepalived/keepalived.conf !ConfigurationFile for keepalived global_defs{ notification_email{ acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server192.168.200.1 smtp_connect_timeout30 router_idLVS_DEVEL } vrrp_instanceVI_1{ stateBACKUP ##node01和node02都配置成BACKUP,角色由优先级确定 interfaceeth2 virtual_router_id71 priority100 ##node01的优先级设置比node02的高 advert_int1 nopreempt ##设置不抢占(需在BACKUP状态下设置才有效) authentication{ auth_typePASS auth_pass1111 } virtual_ipaddress{ 192.168.10.70 } } virtual_server 192.168.10.703306{ delay_loop6 lb_algowrr lb_kindDR nat_mask255.255.255.0 persistence_timeout50 protocolTCP real_server192.168.10.713306{ weight100 notify_down /etc/keepalived/stopkeepalived .sh #3306端口不可用则执行脚本 TCP_CHECK{ connect_timeout10 nb_get_retry3 delay_before_retry3 connect_port3306 } } } 4、编辑node02的keepalived的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 [root@node02~] #cat/etc/keepalived/keepalived.conf !ConfigurationFile for keepalived global_defs{ notification_email{ acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server192.168.200.1 smtp_connect_timeout30 router_idLVS_DEVEL } vrrp_instanceVI_1{ stateBACKUP ##node01和node02都配置成BACKUP,角色由优先级确定 interfaceeth3 virtual_router_id71 priority90 ##node02的优先级设置比node01的低 advert_int1 nopreempt ##设置不抢占(需在BACKUP状态下设置才有效) authentication{ auth_typePASS auth_pass1111 } virtual_ipaddress{ 192.168.10.70 } } virtual_server 192.168.10.703306{ delay_loop6 lb_algowrr lb_kindDR nat_mask255.255.255.0 persistence_timeout50 protocolTCP real_server192.168.10.723306{ weight100 notify_down /etc/keepalived/stopkeepalived .sh #3306端口不可用则执行脚本 TCP_CHECK{ connect_timeout10 nb_get_retry3 delay_before_retry3 connect_port3306 } } } [root@node02~] # 5、node01和node02都编辑一个keepalived的自杀脚本/etc/keepalived/stopalived.sh,一旦检测到Mysql的3306端口不通,便执行此脚本触发vip的切换,脚本内容很简单,就是service keepalived stop就行,因为keepalived服务停止便会触发高可用的切换动作。 6、启动keepalived服务 [root@node01 ~]# service keepalived start Starting keepalived: [ OK ] [root@node02 ~]# service keepalived start Starting keepalived: [ OK ] 7、观察node01的message日志,由于node01的优先级高,因此进入了master角色,vip也已经加上了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 [root@node01~] #tail-f/var/log/messages Oct3022:47:46 node01Keepalived[3170]:StartingKeepalivedv1.2.7(09 /26 ,2012) Oct3022:47:46 node01Keepalived[3171]:StartingHealthcheckchildprocess,pid=3173 Oct3022:47:46 node01Keepalived[3171]:StartingVRRPchildprocess,pid=3174 Oct3022:47:46 node01Keepalived_vrrp[3174]:Interfacequeueisempty Oct3022:47:46 node01Keepalived_vrrp[3174]:NetlinkreflectorreportsIP192.168.10.71added Oct3022:47:46 node01Keepalived_vrrp[3174]:NetlinkreflectorreportsIP fe80::20c:29ff:fe20:a6c8added Oct3022:47:46 node01Keepalived_vrrp[3174]:RegisteringKernelnetlinkreflector Oct3022:47:46 node01Keepalived_vrrp[3174]:RegisteringKernelnetlink command channel Oct3022:47:46 node01Keepalived_vrrp[3174]:RegisteringgratuitousARPsharedchannel Oct3022:47:46 node01kernel:IPVS:Registeredprotocols(TCP,UDP,SCTP,AH,ESP) Oct3022:47:46 node01kernel:IPVS:Connection hash tableconfigured(size=4096,memory=64Kbytes) Oct3022:47:46 node01kernel:IPVS:ipvsloaded. Oct3022:47:46 node01Keepalived_vrrp[3174]:Opening file '/etc/keepalived/keepalived.conf' . Oct3022:47:46 node01Keepalived_vrrp[3174]:Configurationisusing:63319Bytes Oct3022:47:46 node01Keepalived_vrrp[3174]:UsingLinkWatchkernelnetlinkreflector... Oct3022:47:46 node01Keepalived_healthcheckers[3173]:Interfacequeueisempty Oct3022:47:46 node01Keepalived_healthcheckers[3173]:NetlinkreflectorreportsIP 192.168.10.71added Oct3022:47:46 node01Keepalived_healthcheckers[3173]:NetlinkreflectorreportsIP fe80::20c:29ff:fe20:a6c8added Oct3022:47:46 node01Keepalived_healthcheckers[3173]:RegisteringKernelnetlinkreflector Oct3022:47:46 node01Keepalived_healthcheckers[3173]:RegisteringKernelnetlink command channel Oct3022:47:46 node01Keepalived_healthcheckers[3173]:Opening file '/etc/keepalived/keepalived.conf' Oct3022:47:46 node01Keepalived_healthcheckers[3173]:Configurationisusing:11970Bytes Oct3022:47:46 node01Keepalived_vrrp[3174]:VRRPsockpool:[ifindex(2),proto(112),fd(11,12)] Oct3022:47:46 node01Keepalived_healthcheckers[3173]:UsingLinkWatchkernelnetlinkreflector... Oct3022:47:46 node01Keepalived_healthcheckers[3173]:Activatinghealthchecker for service [192.168.10.71]:3306 Oct3022:47:46 node01kernel:IPVS:[wrr]schedulerregistered. Oct3022:47:47 node01Keepalived_vrrp[3174]:VRRP_Instance(VI_1)TransitiontoMASTERSTATE Oct3022:47:48 node01Keepalived_vrrp[3174]:VRRP_Instance(VI_1)EnteringMASTERSTATE Oct3022:47:48 node01Keepalived_vrrp[3174]:VRRP_Instance(VI_1)settingprotocolVIPs. Oct3022:47:48 node01Keepalived_vrrp[3174]:VRRP_Instance(VI_1)SendinggratuitousARPson eth2 for 192.168.10.70 Oct3022:47:48 node01Keepalived_healthcheckers[3173]:NetlinkreflectorreportsIP 192.168.10.70added 8、观察node02的message日志,node02进入了BACKUP角色,VIP自然不会加上。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 [root@node02~] #tail-f/var/log/messages Oct3022:48:54 node02Keepalived[16633]:StartingKeepalivedv1.2.7(09 /26 ,2012) Oct3022:48:54 node02Keepalived[16634]:StartingHealthcheckchildprocess,pid=16636 Oct3022:48:54 node02Keepalived[16634]:StartingVRRPchildprocess,pid=16637 Oct3022:48:54 node02Keepalived_vrrp[16637]:Interfacequeueisempty Oct3022:48:54 node02Keepalived_healthcheckers[16636]:Interfacequeueisempty Oct3022:48:54 node02Keepalived_vrrp[16637]:NetlinkreflectorreportsIP192.168.10.72added Oct3022:48:54 node02Keepalived_vrrp[16637]:NetlinkreflectorreportsIP fe80::250:56ff:fe34:ca7added Oct3022:48:54 node02Keepalived_vrrp[16637]:RegisteringKernelnetlinkreflector Oct3022:48:54 node02Keepalived_vrrp[16637]:RegisteringKernelnetlink command channel Oct3022:48:54 node02Keepalived_vrrp[16637]:RegisteringgratuitousARPsharedchannel Oct3022:48:54 node02Keepalived_vrrp[16637]:Opening file '/etc/keepalived/keepalived.conf' . Oct3022:48:54 node02Keepalived_healthcheckers[16636]:NetlinkreflectorreportsIP 192.168.10.72added Oct3022:48:54 node02Keepalived_healthcheckers[16636]:NetlinkreflectorreportsIP fe80::250:56ff:fe34:ca7added Oct3022:48:54 node02Keepalived_healthcheckers[16636]:RegisteringKernelnetlinkreflector Oct3022:48:54 node02Keepalived_healthcheckers[16636]:RegisteringKernelnetlink command channel Oct3022:48:54 node02Keepalived_healthcheckers[16636]:Opening file '/etc/keepalived/keepalived.conf' . Oct3022:48:54 node02Keepalived_healthcheckers[16636]:Configurationisusing:11988Bytes Oct3022:48:54 node02Keepalived_vrrp[16637]:Configurationisusing:63337Bytes Oct3022:48:54 node02Keepalived_vrrp[16637]:UsingLinkWatchkernelnetlinkreflector... Oct3022:48:54 node02Keepalived_vrrp[16637]:VRRP_Instance(VI_1)EnteringBACKUPSTATE Oct3022:48:54 node02Keepalived_healthcheckers[16636]:UsingLinkWatchkernelnetlinkreflector... Oct3022:48:54 node02Keepalived_vrrp[16637]:VRRPsockpool:[ifindex(2),proto(112),fd(10,11)] Oct3022:48:54 node02Keepalived_healthcheckers[16636]:Activatinghealthchecker for service[192.168.10.72]:3306 9、测试vip是否可能用来登录mysql,由于此时vip在node01上,我们就在node02上使用vip来测试登录,可见是没有问题的 五、Mysql高可用测试 1、停止node01的mysql服务,3306端口自然不通,keepalived检测到3306端口不通后执行自杀脚本停止自身服务,VIP被移除释放出来 1 2 [root@node01~] #servicemysqlstop ShuttingdownMySQL..[OK] 2、观察node01的messages日志可以明显看出整个过程,VIP也已经不见了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@node01~] #tail-f/var/log/messages Oct3023:06:42 node01Keepalived_healthcheckers[3173]:TCPconnectionto[192.168.10.71]:3306failed!!! Oct3023:06:42 node01Keepalived_healthcheckers[3173]:Removingservice[192.168.10.71]:3306 fromVS[192.168.10.70]:3306 Oct3023:06:42 node01Keepalived_healthcheckers[3173]:Executing[ /etc/keepalived/stopkeepalived .sh] for service[192.168.10.71]:3306 in VS[192.168.10.70]:3306 Oct3023:06:42 node01Keepalived_healthcheckers[3173]:Lostquorum1-0=1>0 for VS[192.168.10.70]:3306 Oct3023:06:42 node01Keepalived_healthcheckers[3173]:SMTPconnectionERRORto[192.168.200.1]:25. Oct3023:06:42 node01kernel:IPVS:__ip_vs_del_service:enter Oct3023:06:42 node01Keepalived[3171]:StoppingKeepalivedv1.2.7(09 /26 ,2012) Oct3023:06:42 node01Keepalived_vrrp[3174]:VRRP_Instance(VI_1)sending0priority Oct3023:06:42 node01Keepalived_vrrp[3174]:VRRP_Instance(VI_1)removingprotocolVIPs. 3、观察node02的messages日志,可以看到node02进入了MASTER角色,接管了VIP,VIP已经加上,从日志的时间看,切换的过程不过花了1秒,可说是秒级切换了。 1 2 3 4 5 6 7 8 9 10 11 12 [root@node02~] #tail-f/var/log/messages Oct3023:06:42 node02Keepalived_vrrp[16637]:VRRP_Instance(VI_1)TransitiontoMASTERSTATE Oct3023:06:43 node02Keepalived_vrrp[16637]:VRRP_Instance(VI_1)EnteringMASTERSTATE Oct3023:06:43 node02Keepalived_vrrp[16637]:VRRP_Instance(VI_1)settingprotocolVIPs. Oct3023:06:43 node02Keepalived_vrrp[16637]:VRRP_Instance(VI_1)SendinggratuitousARPs oneth3 for 192.168.10.70 Oct3023:06:43 node02Keepalived_healthcheckers[16636]:NetlinkreflectorreportsIP192.168.10.70added 由于node01的keepalived进程被自杀脚本停止了,因此需要手动启动。之前我想是否需要跑一个监控脚本把keepalived服务自动开起来呢,后来我觉得不必要,因为如果mysql的服务依然异常,就算keepalived的服务起来了,它检测到本机的3306端口不通,还是会再次自杀。而既然mysql服务已经异常、端口都不通了,一般也是需要手动检查干预把mysql启动起来的,因此在mysql服务正常后再顺便手动起一下keepalived就好了。 本文转自Mr大表哥jianlong1990 博客,原文链接: http://blog.51cto.com/jiangjianlong/1981994 如需转载请自行联系原作者

优秀的个人博客,低调大师

Kubernetes高级实践:Master高可用方案设计和踩过的那些坑

今天我将为大家介绍如何构建Kubernetes Master High Availability环境。此次分享内容是我在工作中经验总结,如果有不正确的或者需要改进的地方,欢迎各位大神指正。 Kubernetes作为容器编排管理系统,通过Scheduler、Replication Controller等组件实现了应用层的高可用,但是针对Kubernetes集群,还需要实现Master组件的高可用。 本次分享论述的Master高可用方案,主要基于社区的高可用方案的实践,但是社区的高可用方案中采用的GCE的External Loadbalancer,并未论述如何实现External Loadbalancer,而且也并没有将Kubernetes集群组件容器化。所以,我们的高可用方案在社区高可用方案的基础之上进行了如下两个方面的提升: 第一,除了kubelet之外,Kubernetes所有组件容器化; 第二,通过haproxy和keepalived构建Loadbalancer实现Master的高可用。 下面我们分四个章节来详细论述Kubernetes Master High Availability环境的搭建。 1. HA Master整体架构 2. 核心技术点和难点 3. 实践中的遇到的那些坑 4. 社区关于HA Master的未来发展 一、HA Master整体架构 我们已经成功将支持Master High Availability的Kubernetes集群部署到企业私有云平台,底层采用的是Ubuntu 14.04操作系统。下面是一个典型的部署环境: Static Pods是由其所在节点上的kubelet直接管理,而不需要通过Apiserver来监视它们。Static Pods的资源类型只能是Pod,而且不与任何的Replication Controller相关联,它们完全由kubelet来监视,并且当它们异常停止的时候由该kubelet负责重启它们。 (haproxy, keepalived):这里表示我们将haproxy和keepalived放置在同一个pod中。 1.1 kubelet对static pod高可用的支持 我们需要为kubelet进程配置一个manifests监视目录: 如果有新的yaml/manifest文件添加到该目录,kubelet则根据yaml/manifest文件创建一个新的static pod; 如果我们把某个yaml/manifest文件从该目录删除,kubelet则会删除由该yaml/manifest文件所产生的static pod; 如果该目录下的yaml/manifest文件有更新,kubelet则会删除原来的static pod,而根据更新后的yaml/manifest文件重新创建一个新的static pod; 如果manifests目录下的文件没有任何变化,但是其下某个yaml/manifest文件所产生的static pod错误退出或者被误删后,kubelet仍然会根据该yaml/manifest文件重新创建一个新的static pod。 这样,kubelet在一定程度上保证了static pod的高可用。 1.2 kubelet进程的高可用 kubelet通过manifests监视目录保证了static pod的高可用,但是如果kubelet进程本身错误退出或者被误删后,谁来负责重新启动kubelet进程呢? 在Linux系统中,我们可以通过Monit、Upstart、Systemd、Supervisor等工具实现对服务的监控保证服务的高可用。 在Ubuntu 14.04操作系统中,我们将kubelet做成系统服务,利用Upstart来保证kubelet服务的高可用,下面是kubelet服务基于Upstart的服务启动脚本/etc/init/kubelet.conf: 其中: respawn:该命令设置服务或任务异常停止时将自动启动。除stop命令外的停止都是异常停止。 respawn limit:该命令设置服务或任务异常停止后重启次数和间隔时间。 1.3 Master High Availability Kubernetes整体架构图 从架构图中我们可以看到: 1) Upstart保证docker服务和kubelet服务的高可用,而Kubernetes的其他组件将以static pod的方式由kubelet保证高可用。 2) 两台lb节点通过haproxy和keepalived构建出一个External Loadbalancer,并提供VIP供客户端访问。 3) Haproxy配置成“SSL Termination”方式,外网client通过HTTPS请求访问集群,而内网client则可以通过HTTPS/HTTP请求访问。 4) Kubernetes高可用集群通过flannel static pod构建一个Overlay网络,使集群中的docker容器能够通过Kubernetes Cluster IP进行通信。 二、核心技术点和难点 2.1 运行在特权模式的组件 Kubernetes集群中的一些组件需要通过内核模块来为集群提供服务,因此这些组件需要运行在特权模式下,以便能访问相应的内核模块。 2.1.1. 开启特权模式 为了支持docker容器在特权模式下运行,我们需要开启Kubernetes集群的特权模式权限: 这里主要体现在kubelet服务和apiserver服务。 1) Kubelet service kubelet服务需要开启特权模式权限,以便允许docker容器向kubelet请求以特权模式运行。 2) Apiserver static pod apiserver static pod需要开启特权模式权限,以便运行在特权模式下的docker容器能够访问apiserver服务。 2.1.2. 运行在特权模式下的docker容器 运行在特权模式下的docker容器,在yaml文件中需要添加如下字段: 这里主要体现在kubeproxy服务、flannel服务和keepalived服务。 1) Kubeproxy static pod kubeproxy需要通过Iptables设置防火墙规则。 2) Flannel static pod flannel需要访问vxlan、openvswitch等路由数据报文。 3) Keepalived static pod keepalived需要访问IP_VS内核模块来建立VIP。 2.2 Static pod必须运行在主机网络下 如上所述的这些以static pod形式存在的Kubernetes集群组件,必须工作在主机网络下: 虽然Overlay网络是为了让不同节点间的docker容器进行通信,而上述以static pod形式存在的组件也都是docker容器,但是它们之间的心跳和信息交流都需要通过主机网络而不是类似于flannel等的Overlay网络。理由如下: 这些static pods不同于应用的pods,它们的稳定保障了Kubernetes集群的稳定性,它们之间的心跳和信息交流都是通过它们配置文件中的静态IP地址进行的,而docker/flannel网络是动态的,我们无法保证docker/flannel网络中IP地址的稳定性,同时也无法事先知道IP地址。 kubeproxy、flannel、haproxy需要通过主机网络修改路由规则,从而使主机上的服务能被其他主机访问。 haproxy需要将外网请求重定向到内网后端服务器上,也必须需要主机网络。 2.3 External Loadbalancer部署要点 对于如何配置haproxy和keepalived,网络上有非常多的资源,所以这里不在论述。下面我们来分析一下部署过程中的一些要点。 External Loadbalancer由至少两台lb node组成,通过haproxy和keepalived pod实现Master的负载均衡,对外提供统一的VIP。 我们可以将haproxy和keepalived分别放置在不同的pod中,也可以将它们放置在同一个pod中。考虑到keepalived需要监测haproxy的状态,我们会把haproxy和keepalived放在一起做成一个loadbalancer pod。 2.3.1. lb node配置 1) 使能内核IPVS模块 由于keepalived需要通过IPVS模块实现路由转发,所以我们需要使能内核IPVS模块。 从Linux内核版本2.6起,ip_vs code已经被整合进了内核中,因此,只要在编译内核的时候选择了ipvs的功能,Linux即能支持LVS。因此我们只需要配置操作系统启动时自动加载IPVS模块: 我们可以通过如下命令查看ip_vs模块是否成功加载: 如果没有加载,我们可以通过modprobe命令加载该模块: 2) 修改内核参数 为了使keepalived将数据包转发到真实的后端服务器,每一个lb node都需要开启IP转发功能: 另外,keepalived设置的VIP有可能为非本地IP地址,所以我们还需要使能非本地IP地址绑定功能: 2.3.2. keepalived监测haproxy状态的方法 对于普通进程来说, keepalived进程可以通过“killall -0 haproxy”命令检测haproxy进程是否正常运行(注: Sending the signal 0 to a given PID just checks if any process with the given PID is running)。 然而在docker容器环境下,各容器都有自己的PidNamespace和NetworkNamespace,我们就需要开启haproxy的健康检查页面,然后keepalived通过健康检查页面的URL来检测haproxy目前是否正常运行。 haproxy健康检查页面配置: keepalived对haproxy的状态检测: 2.3.3. haproxy SSL配置 haproxy代理ssl配置有两种方式: haproxy本身提供SSL证书,后面的web服务器走正常的http协议; haproxy本身只提供代理,直接转发client端的HTTPS请求到后端的web服务器。注意:这种模式下“mode”必须是“tcp”模式, 即仅支持4层代理。 考虑到:第一,用户亲和性访问需要7层代理的支持;第二,loadbalancer和master走的都是集群内网。所以本实践采用了第一种方式,配置如下: 2.3.4. haproxy配置:haproxy.cfg 2.3.5. keepalived配置:keepalived.conf 1) lb-1上keepalived配置 2) lb-2上keepalived配置 lb-2跟lb-1的配置差不多,除了下面两个字段: 2.4 flannel网络设置 2.4.1 Master节点flannel网络设置 对于Master节点,需要等待Etcd Pod集群启动完后,先在Master上创建Flannel网络,然后Flannel Pod客户端才可以从Etcd中获取到各个Master节点的IP网段,获取到IP网段后会在主机上产生文件:“/var/lib/flannel/subnet.env”,然后根据该文件修改docker启动参数: 并重启docker服务。 2.4.2 非Master节点flannel网络设置 对于非Master节点,待Loadbalancer起来之后,Node节点能够访问Apiserver之后,Flannel Pod客户端才能从Etcd获取到该Node节点的IP网段,并且同样会在主机上产生文件:“/var/lib/flannel/subnet.env”。然后修改docker启动参数,并重启docker服务。 三、实践中的遇到的那些坑 3.1 官网“haproxy docker image”的坑 Docker Hub上“haproxy image”的“docker-entrypoint.sh”内容如下: 问题就出在“haproxy-systemd-wrapper”。如果运行命令:“haproxy -f /etc/haproxy/haproxy.cfg”, 而实际上运行的是经过“haproxy-systemd-wrapper”包装后的命令: 执行命令“haproxy -f /etc/haproxy/haproxy.cfg”时,真正执行的是: “/usr/local/sbin/haproxy -p /run/haproxy.pid -f /etc/haproxy/haproxy.cfg -Ds”,对于“-Ds”选项, 官网是这么描述的: 原来,“haproxy”经过“haproxy-systemd-wrapper”包装后在后台执行,而docker container不允许进程后台执行,否则docker容器将该启动命令执行完后就退出了。官网image的这个坑很大。 所以,当我们用官网“haproxy image”的时候,就需要用haproxy的完全路径来执行。比如在yaml文件中: 3.2. haproxy container exited with 137 首先137退出码表示,其他进程向haproxy container发起了“kill”信号,导致haproxy container退出,容器日志如下: 其次,当通过“docker run”命令执行haproxy container,使用的命令与yaml文件中的一样,而且照样输出上述的“WARNING”,但是容器却不退出。 然后,无奈之下,我试着先将这个“WARNING”解决:这个错误是由于haproxy.cfg中添加了SSL证书导致的, 可以通过设置参数“default-dh-param”解决: 当我解决这个“WARNING”之后,奇迹出现了,haproxy container奇迹般的正常运行了。原来在容器的世界,一个“WARNING”也不能疏忽。 四、社区关于HA Master的未来发展 熟悉kubelet配置参数的都知道,我们在给kubelet配置apiserver的时候,可以通过“--api-servers”指定多个: 这看起来似乎已经做到apiserver的高可用配置了,但是实际上当第一个apiserver挂掉之后, 不能成功的连接到后面的apiserver,也就是说目前仍然只有第一个apiserver起作用。 如果上述问题解决之后, 似乎不需要额外的loadbalancer也能实现master的高可用了,但是,除了kubelet需要配置apiserver,controller manager和scheduler都需要配置apiserver,目前我们还只能通过“--master”配置一个apiserver,无法支持多个apiserver。 社区后续打算支持multi-master配置,实现Kubernetes Master的高可用,而且计划在Kubernetes 1.4版本中合入。 即使将来社区实现了通过multi-master配置的高可用方式,本次分享的Master High Availability仍然非常有意义,因为在私有云场景中,External Loadbalancer除了实现Master的高可用和负载均衡外,还可以针对Worker Node实现Nodeport请求的负载均衡,从而不仅实现了应用的高可用访问,同时也大大提高了应用的访问速度和性能。 Q&A Q1:请问访问Docker时,k8s节点上的kubeproxy性能瓶颈如何破? A1:这是个好问题。在我们的私有云场景,通过k8s节点上kubeproxy的请求,大部分都是来自外网,我们在每个节点上都开了NodePort。然后,仍然利用Externel LoadBalancer做NodePort的负载均衡,这样,可以避免单节点上Kubeproxy负载过重。 Q2:那么在2.3“External Loadbalancer部署要点”这一节中集成lvs就是解决这个问题的吗? A2:嗯,那个就是为了实现LoadBalancer负载均衡用的。因为,我们已经将LoadBalancer也容器化了,在我们的集群里面,一个LoadBalancer就是一个Pod,这样,我们可以很快启动一个针对NodePort负载均衡的LoadBalancer。甚至,可以为任何其他服务,迅速启动LoadBalancer。另外,k8s社区后面会把kubelet也容器化。 Q3:为什么运行命令要经过“haproxy-systemd-wrapper”包装,是出于什么目的? A3:这个是haproxy官网包装的,在我的分享中,“-Ds passe en daemon systemd.This patch adds a new option "-Ds"which is exactly like "-D", but instead offorking n times to get n jobs running and thenexiting, prefers to wait for all thechildren it just created. With this done,haproxy becomes more systemd-compliant,without changing anything for other systems”这段英文已经解释了,这个包装中最重要的就是加了“-Ds” 参数。 作者介绍 唐继元 现任才云科技云开源高级工程师 曾在华为中央软件院服务器OS部门负责LTP关于内存管理和内存文件系统的测试代码的开发和完善 曾在华为中央研究院香农实验室系统软件组负责云计算软件方向以及对Kubernetes调度等研究 本文来自云栖社区合作伙伴"DBAplus",原文发布时间:2016-06-30

优秀的个人博客,低调大师

技术合集:新春来袭,锦囊妙计助程序员过个好年

更多深度文章,请关注:https://yq.aliyun.com/cloud 新春来临,诸位CTO,以及大神程序员们是否已经撸起袖子准备回家了?这个时候,最大的噩耗莫过于BOSS含情脉脉的出现在你的身边温柔的告诉你,春节流量大,春节有大促,春节有红包..总之,春节需要你值班,霎那间电闪雷鸣有没有!! 所以,小云妹子准备了一袋锦囊,专门推给诸位CTO,程序员大神GG,从最近最火的视频直播,到高QPS的场景,以及金融,红包,社交,大促等各个维度讨论如何通过云计算度过一个安稳妥当的新春佳节。 我们的口号是,春节与业务齐飞,云计算让程序员人生更美好。 2016年最火的是什么?短视频,直播,在双11期间,阿里云成功的通过直播大考,积累的经验,分享在第一个叫做视频的锦囊中: 新春如何应对一大波用户袭来,千万级直播架构搭建 再不玩直播就老了!!快速搭建一个完整的移动直播系统春节上线玩? 央视也在用,阿里云Redis真的这么好? 专注年轻一代,基于E-MapReduce梨视频推荐系统 数娱行业存储,为视频而生 新春佳节,总是分享第一,买买买也是日常,如何在高QPS的情况下,让系统安然度过春节? 短时间搭建起亿级社交信息分享平台 设计用户超过1亿的应用—数据库调优战春节 高并发IM系统架构优化实践 阿里云数据库专家玄惭:云数据库超大流量峰值保障最佳实践 高峰将至!CTO春节省钱指南CDN篇 如何使用SLB实现持续性高并发访问? 红包是重头戏,每一年春节,红包这个事儿都能愁坏程序员,所以,第三个锦囊当然是关于红包与金融的: 老庙黄金2016春晚抢红包活动技术架构详解 互联网“红包”架构三板斧 第四个锦囊应了中国古代的一句老话,安全第一。 业务再强,安全也是重中之重,特别是新春佳节,你们懂的。 如何使用OSS RTMP功能直播/鉴黄? 通过MongoDB安全事件来谈谈为什么要用云服务 路途再远也要回家,天地之大,总要相逢,这是情感,也是情怀。 第五个锦囊和大家探讨一下技术人的情怀。 12306的西天取经路 - 春节抢票与PostgreSQL数据库设计思考 一场IT民工 与 人贩子 之间的战争

优秀的个人博客,低调大师

新款IBM POWER8通过NVLINK与Tesla P100互联

【大咖・来了 第7期】10月24日晚8点观看《智能导购对话机器人实践》 近日在GTC CHINA 2016大会上, NVIDIA与IBM共同宣布***合作项目,全新 POWER8 家族将通过NVLINK与NVIDIA Tesla P100实现强势组合。NVIDIA的科技在IBM的服务器中,能加速人工智能、深度学习和数据分析这类高度融合的工作,为企业更快获得人工智能。 数据中心的工作负载在不断发生变化,加速数据中心的需求也在不断增强。不久之前,这些系统主要用于处理存储和提供网页,而现在它们越来越多地需要负责人工智能领域的工作,比如理解语音、文字、图片和视频或者分析大数据以提供见解。数十亿的消费者希望即刻获得许多问题的答案,而企业公司需要分析激增的数据来更好地满足客户需求。这些问题都将由数据中心提供解决方案。 IBM 在几年前便注意到了这种趋势,并与NVIDIA合作,加快新数据中心工作负载的处理速度。经过四年的研发,备受关注的POWER8服务器联合了NVIDIA的Tesla P100 GPU和NVLink互联技术,实现了更高的数据性能分析和深度学习能力提升。 该系统使用了两个IBM POWER8 CPU和四个NVIDIA Tesla P100 GPU,并通过NVLink高速接口使其互联互通。这是一款定制的GPU加速器服务器,其中NVLink接口集成在主板路由上,并且使用 NVIDIA的Tesla P100 GPU。 技术联合,合力树立行业标杆 IBM Power System S822LC采用了两个IBM POWER8 CPU和四个NVIDIA Tesla P100 GPU,并通过NVLink实现互联。 IBM和NVIDIA技术如此紧密的结合使得数据流动速度比使用PCIe快了5倍,从而加快了目前诸如高级分析、深度学习和人工智能等极其重要的应用提供见解的速度。 IBM Power Systems总经理Doug Balog表示:“企业能通过高级分析、机器学习和人工智能提供的用户见解和商业价值越来越多地受到性能的制约。加速计算能够显著加快大数据工作负载的处理速度,并将成为这个认知时代的基础。凭借我们与 NVIDIA 等合作伙伴联手推动的 OpenPOWER 创新,搭载 POWERAccel 技术的全新 OpenPOWER Linux 服务器将为这些工作负载树立新标杆。” 通往 Summit 和 Sierra 之路 IBM 已经收到了多个客户的订单,其中包括一家大型跨国公司以及美国能源部橡树岭国家实验室 (ORNL) 和劳伦斯利福摩尔国家实验室 (LLNL) 等研究机构。 ORNL和LLNL两个实验室将把新系统用作开发平台来优化应用,以充分利用 NVIDIA NVLink 技术。这些系统将用作为新一代超级计算机 Summit 和 Sierra 开发应用的试验台,IBM 公司预计将于 2017年把Summit和Sierra分别交付给ORNL和LLNL。 橡树岭国家实验室领导计算设施项目总监 Arthur S. (Buddy) Bland 提到:“在 Power 平台上采用 NVLink 技术能够确保 CPU 和 GPU 中多个内存层次结构的一致性。作为 GPU 的长期用户,我们认为它将提升我们的应用性能,使用户能够更容易地获得重大的科学发现。” 【责任编辑: 云中子 TEL:(010)68476606】 点赞 0

优秀的个人博客,低调大师

中小企业Docker实战:那些年我们踩过的五个坑

云栖TechDay活动第十八期中,来自南京路特软件有限公司的CTO戚俊带来了题为《中小企业如何巧用容器技术》的分享,主要分享了路特软件公司使用阿里云容器服务和Docker中遇到的问题,以及获得的经验教训,从业务的角度着重讲解了容器技术对生产过程及总体生产力带来的影响,对中小企业有着极大的借鉴意义。 幻灯下载地址:https://yq.aliyun.com/attachment/download/?filename=57b4e3fec55729378d21fe76850682e4.pdf 以下为现场分享观点整理。 我们的困境 首先来看一下我们遇到困境: 第一个困境是产品线内子产品太多,并且相互有重叠,进而导致基础服务有大量的重复,如邮件服务、短信服务等,但在开发阶段,无法将其拆开。 第二个困境是运维方面,目前全公司共有40台服务器和一堆服务,但

优秀的个人博客,低调大师

全国首个内容审核大模型过审 云从科技破解Agent时代谣言难题

随着智能体逐步进入真实应用场景,企业对AI的期待,已经不只是“能不能生成内容”,而是“能不能进入流程、帮助处理具体工作”。 但这也带来一个很现实的问题: 当AI开始参与客服、运营、内容分发、信息整理等环节,企业怎么保证输出内容的质量、风险和一致性? 近日,由云从科技联合网络安全人才与创新基地打造的晏清大模型,正式通过国家生成式人工智能服务备案,成为全国首个通过国家级备案的垂直领域专用内容审核大模型。 这一进展,配合着监管侧对AI应用治理进一步强化。 中央网信办近期部署开展“清朗·整治AI应用乱象”专项行动,明确提出将围绕大模型备案、安全审核能力、训练语料安全、生成内容标识等关键环节开展整治,同时重点治理利用AI生成虚假信息、低俗内容、侵害未成年人权益等问题。 此外,网信办正在指导各地各网站平台全面推进落实三项工作: 规范短视频内容标注标签; 将内容标注设为短视频发布必经环节; 对新增短视频标注情况加强审核。 一、Agent时代的合规难题,只有原生适配的国家级合规基座能解 晏清大模型的核心价值,从来不是一个简单的审核工具升级,而是国内唯一一套为Agent时代量身打造、拿到国家级合规通行证的内容安全治理体系,精准命中了行业三大核心痛点。 首先,它彻底解决了传统审核对AI生成内容“防不住”的难题。 不同于只能做关键词匹配的传统小模型、通用大模型外挂的审核插件,晏清是专为内容安全而生的专用大模型,可无缝嵌入AI智能体的底层逻辑,实现从内容生成、事前审核、事中管控到事后谣言溯源的全流程闭环,对AI多轮交互生成的变体谣言、深度伪造内容、对抗性违规信息的识别准确率远超行业平均水平,真正做到“AI的风险用AI解决”。 其次,它拥有行业独一份的国家级官方合规背书。作为落地于中央网信办主导的国家级网安基地的标杆成果,晏清大模型从训练数据、模型架构到合规体系,全程对标国家网络内容安全监管标准,本次通过国家备案,更是直接拿到了全国通用的合规经营“通行证”,企业、开发者接入即可获得国家级合规能力,无需再投入巨额成本自研模型、申请备案,大幅降低了AI智能体落地的合规门槛。 而这份对AI智能体的原生适配能力,恰恰源于云从科技深耕多年的AI智能体战略。 作为国内最早布局AI智能体全链路技术的企业之一,云从科技深度掌握智能体从生成、交互、决策到迭代的全流程逻辑,比任何纯审核厂商都更懂AI智能体的安全风险点,这也让晏清大模型不是被动的“事后堵漏”,而是主动的“原生防控”,从根源上适配Agent时代的内容治理需求。 二、从算力底座到生态赋能,云从双轮战略筑牢不可复制的行业壁垒 晏清大模型能成为全国首个落地的国家级备案审核大模型,绝非单点技术的突破,而是云从科技AI基础设施+AI智能体双轮战略的集中落地,形成了同行无法复制的全链路壁垒。 在AI基础设施端,云从科技是国家网安基地智算中心的核心运营方,手握125P自主可控算力集群,攻克了异构算力调度核心技术,可实现昇腾等多架构芯片的统一池化、高效调度,既解决了大模型规模化落地的“卡脖子”算力难题,也走出了一条贴合中国市场的轻资产高壁垒路线——无需重资产囤卡建数据中心,而是靠技术把现有算力资源的效率拉满,通过算力精细化运营释放价值且具备稳定的国家级底座支撑。 在AI智能体生态端,晏清大模型不是一个孤立的产品,而是开放给全行业的合规基础设施。 基于国家级算力底座的支撑,它可提供多层级服务能力:中小开发者可通过标准化API接口开箱即用,快速获得国家级合规审核能力;大型政企、互联网平台可获得定制化微调、私有化部署服务,适配专属业务场景;更可叠加智算中心的算力服务,为客户提供“国产化算力+国家级合规审核+智能体落地支持”的全栈服务,一站式解决AI智能体落地的所有核心难题。 目前国家网安基地已汇聚220余家网安头部企业、科研机构与政企单位,本身就是AI智能体与合规服务的精准需求池,而云从科技作为基地运营方与标杆模型打造方,可直接将能力辐射至全生态,再逐步覆盖全国千行百业,实现从单点标杆到行业级基础设施的量级跨越。 晏清大模型的备案通过,从来不是终点,而是Agent时代合规基建的起点。在AI智能体全面爆发的前夜,云从科技以国家级合规模型为切口,以“AI基础设施+AI智能体”双轮战略为支撑,既守住了AI时代国家内容安全的核心防线,也为千行百业拥抱AI智能体,打通了最关键的合规通路。

优秀的个人博客,低调大师

粉色 X 袭过,价值链接一切:ZadigX 线上发布会回顾

Zadig 开源交流:加入Zadig 技术交流群🔥(Zadig on Github;Zadig on Gitee) ZadigX 企业咨询:提交您的具体需求 Zadig 开源 2 年以来,KodeRover 始终追求“让今天的工程师,能像伏尔泰笔下古巴比伦的哲人 Zadig 一样,追求真理,绽放智慧”。在开源 Zadig 国内用户企业超过 2000 家之际,越来越多的企业希望 Zadig 产品能覆盖从需求到发布的数字研发全链路,Zadig 企业版及专业服务 “ZadigX” 应运而生。 4 月 27 日,ZadigX 通过线上直播的形式,正式对外发布。 直播当天,我们将办公室改装成了临时直播间,在 KodeRover、开源中国、云原生社区、掘金开发者社区 4 大平台微信直播号同时直播。 极氪副总裁、路特斯运维总监、3 位阿里云计算产品负责人、GitLab 副总裁、Gitee 总架构师,携手 6 位云原生创业公司的创始人 CEO 线上参与,探讨如何冲破传统认知,摸索国产软件公司铸造“伟大”基因的路线。 ZadigX 的发布主题“价值驱动一切,链接最酷玩家”,一经提出便吸引了广大开发者的兴趣,3 个多小时的直播迎来了 4749 名观众、其中 377 人参与讨论、平均同时在线人数 128 人。 各环节重点介绍 在产品发布环节:李倩 Landy(KodeRover 创始人兼 CEO)为大家带来 ZadigX 的背后故事;Lilian(KodeRover 产品专家)为大家讲述 ZadigX 的特点,对工程师、对企业的价值;Minmin(KodeRover 后端工程师)为大家做了现场的产品演示;郭健(KodeRover 创始人兼 COO)介绍了 ZadigX 面向企业提供的服务及解决方案类型。 在企业客户伙伴对话环节:郭健(KodeRover 创始人兼 COO)和 ZadigX 的几位客户伙伴进行圆桌对话。闫成洋(极氪汽车研发总监)、覃途远(路特斯汽车运维总监)、王雪飞(光环有云 CTO)就大家极为感兴趣的问题展开了讨论,包括为什么从开源用户转为企业客户,如何衡量购买后的实际落地价值等等。 在生态伙伴 OpenTalk 对话环节:Landy(KodeRover 创始人兼 CEO)与何川(阿里云计算巢产品负责人)、董振华(阿里云 MSE 产品负责人)、董凯(阿里云 DMS 产品负责人)、张家庆(极狐 GitLab 副总裁)、罗雅新(Gitee 架构师 & 研发负责人,主要负责人)展开对话,探讨生态上下游广袤的合作场景。 在标杆客户数字化转型环节:Landy(KodeRover 创始人兼 CEO)和 Zadig 客户刘昊(极氪汽车的副总裁)、王亚军(前龙湖集团首席战略官)隔空对话,探讨组织和技术的进化。 在云原生最酷玩家环节:包括温铭(API7.ai 联合创始人兼 CEO)、王涛(PingCode 创始人兼 CEO)、徐丹青(Bytebase 联合创始人兼 CTO)、卢中阳(火线安全联合创始人兼 CTO)、来炜(快猫星云创始人兼 CEO)、王文金(Apipost 研发负责人)的 6 位行业领先的云原生先锋公司的负责人圆桌对话,探讨如何更好地链接,创造数字价值。 现场花絮、礼品放送 抽奖获奖名单公布 奖项 1:价值 3 万元的 ZadigX 全年授权 *珂186****7056 董*飞 AA*子 185****0233 奖项 2:王亚军老师亲笔签名《企业即算法》实体书 阮 138****3495 罗*豪 187****6030 温*远 138****2448 云原生周边王炸大礼包 詹*强 150****7668 *乐 182****4637 *萌 135****6592 *辉 186****1092 *克 187****0569 *晨 176****3945 奖项 3:Zadig 定制 T 恤 刘*烔 152****6891 杨*晶 152****8424 刘*磊 159****0496 何*文 182****4183 番*酱 135****0355 从*始 156****0950 *航 187****6804 罗*豪 187****6030 *莉 159****1194 小*士 152****9706 奖项 4:获得 ZadigX 定制陆冲板 1)直播抽奖中奖者 *冯 187****9310 *张 178****7999 *杨 151****8267 2)以下 3 位评论区互动的同学: 黑鹰 朱亚光 小呆助手 奖项 5:ZadigX 免费 90 天授权和免费 DevOps 咨询 32 家企业获得。 在填写调查问卷的人群中,八成正在使用 Zadig 系列产品,两成已升级为 ZadigX 用户并和 KodeRover 团队一起积极探索 ZadigX 的无限可能。 感谢各位小伙伴对于 ZadigX 的支持,希望 ZadigX 能够伴随各位走向更加广阔的未来。 Zadig,开放,链接,专业。 Zadig 开源交流:加入Zadig 技术交流群🔥(Zadig on Github;Zadig on Gitee) ZadigX 企业咨询:提交您的具体需求

优秀的个人博客,低调大师

前车之鉴:聊聊钉钉 Flutter 落地桌面端踩过的“坑” | Dutter

作者:刘太举(驽良) 《Dutter 系列文章》将阐述钉钉基于 Flutter 构建的跨四端应用框架(代号 Dutter)的技术实践与踩坑经验,共分为上、下两篇,上篇内容可点击 Dutter | 钉钉 Flutter 跨四端方案设计与技术实践,本文为下篇,感谢阅读。 本文主要介绍一下钉钉 Flutter 业务灰度过程中,在桌面端遇到并处理过的几个 FlutterEngine 层面的 Bug。具体包含: Mac 端: FlutterEngine 退出之后内存泄漏问题; FlutterEngine shutdown 阶段死锁问题; 低版本 macOS OpenGL 析构阶段 Crash 问题; Windows 端: Win7 设备渲染模块「Crash + 残影」问题; FlutterPlugin 注册阶段野指针 Crash; Flutter Window 可见性变化之后页面白屏。 下面来为大家分别介绍一下。 FlutterEngine Mac 端问题 1.1 FlutterEngine 退出之后内存泄漏问题 问题背景 Mac 端 FlutterViewController 在销毁之后,其开辟的内存并未并实际释放,会出现内存泄漏问题。此问题在 Flutter issue 中有一些讨论,但一直未有明确定位。在钉钉 Mac 端 Flutter 业务灰度过程中也遇到此问题,如无法处理将直接影响 Dutter 在 Mac 端落地的可行性: 定位分析 一句话原因: Mac 端 FlutterEngine 实现中对 weak property 使用不合理导致。FlutterViewController 强持有 FlutterEngine,后者持有一个指向 FlutterViewController 的 weak property。FlutterViewController 在 dealloc 流程中尝试释放 FlutterEngine,但是此时 FlutterEngine 中持有的 weak property 已经无法正确访问(nil),导致释放流程未能正常执行,出现泄漏。 下面结合具体实现来为大家做一个简单说明。 由于设计到 OC 和 C++ 对象生命周期管理问题, FlutterEngine 内部对象持有关系略微特殊一些,大致如下图所示: FlutterViewController 作为对外暴露的主要 Class,负责创建并持有 FlutterEngine 以及 FlutterView; FluterEngine 在初始化阶段会自己强持有自己,并在 shutdown 时自我 Release; FlutterEngine 会创建并持有 FlutterRenderer,FlutterRenderer 会强持有 FlutterView; FlutterEngine 间接强持有 FlutterView; FlutterEngine 有一个指向 FlutterViewController 的弱引用指针。 正常情况下,FlutterViewController 退出之后,会通过调用 FlutterEngine 的 setViewController 传入 nil 的方式,来触发 FlutterEngine shudown 动作。参考实现如下: 即正常情况下,FlutterViewController dealloc 之后应该触发 369 行代码运行,进而释放 FlutterEngine 资源。但是实际运行情况缺不是这样,在代码运行到 359 行时,尝试判断 if (_viewController != controller) 时并未成立。通过上述代码我们知道,controller 是外部传入的对象此时为 nil;_viewController 作为一个 weak proptry,在 FlutterViewController 进入 dealloc 流程之后也变为 nil。因而在此流程下,我们希望中的 shutDownEngine 方法并未被调用。 处理方案 问题定位之后处理方式就很简单了,可以在 FlutterViewController dealloc 的时候手动触发 FlutterEngine shutDownEngine 方法。并且通过在上层通过 OC 动态特性 hook 实现、或者直接修改重新编译 FlutterEngine 都可以。 但此处修改一定要谨慎,注意完整还原 FlutterEngine 中的 shutdown 流程,否则可能导致我们遇到的第二个问题:死锁。 1.2 FlutterEngine shutdown 阶段死锁问题 问题背景 钉钉最初在处理上述「FlutterEngine 泄漏」问题时,采用了一种相对比较简单的方案:在 FlutterViewController dealloc 方法中,手动调用 FlutterEngine 提供的 shutDownEngine 方法,手动触发相关资源释放。 通过此方案,FlutterViewController 退出之后内存确实出现了下降,但是在灰度时发现偶尔会有整个页面卡死的情况。通过对出现问题的链路进行简单分析以及配合暴力测试,我们在 debug 环境对问题做了还原。最终初确认 UI 线程与 Raster 线程出现死锁,死锁之后的线程状态大致如下。 UI 线程状态: Raster 线程: 定位分析 一句话原因: 钉钉侧调用 FlutterEngine shutDownEngine 方法不合理导致。shutDownEngine 之前,必须先调用 FlutterView 的 shutdown 方法来停止渲染流程。待渲染流程正常停止之后,才可进入 FlutterEngine 资源释放流程,否则即有可能出现上述死锁问题。 因为此问题为钉钉调用不合理导致,具体异常原因不再深入分析,感兴趣的同学可以根据上述线索自行查阅。 处理方案 在上层补全 FlutterEngine 释放流程,在调用 FlutterEngine shutDownEngine 之前首先调用 FlutterView shutdown 停止 Raster 线程。 1.3 低版本 macOS OpenGL 析构阶段 Crash 问题 问题背景 此问题还是接两个问题,在处理完问题1和问题2之后,参考 FlutterEngine shutdown 流程,钉钉会在 FlutterViewController 析构之后做3件事情: 将 FlutterRenderer 中绑定的 FlutterView 置为 nil; 调用 FlutterView shutdown 方法; 调用 FlutterEngine shutDownEngine 方法。 经过一系列处理之后,测试发现内存泄漏和死锁问题基本得以根治。但是在内部灰度过程中发现低版本 macOS 上会出现 Crash,堆栈大致如下: 定位分析 一句话原因: 与问题2类似,此问题也是因为钉钉处理泄漏问题而引入。其大致由两方面因素迭代导致。一方面因为重置 FlutterOpenGLRenderer 绑定的 FlutterView,导致在 embedder 层创建的 OpenGL 对象被提前释放;另外一方面因为低版本 macOS OpenGL 实现不完善析构流程中未能对关键链路做保护,进而导致异常。 下面对异常相关代码做一下简答分析,避免其他同学再遇到类似问题。 1、在 FlutterEngine setViewController 方法中,如果处于释放流程,会调用 FlutterOpenGLRenderer setFlutterView 方法,并传入 nil: 2、FlutterOpenGLRenderer setFlutterView 方法在入参为 nil 时,会释放其内部维护的 NSOpenGLContext 对象: 3、FlutterEngine 底层实现会在 GrDirectContext 对象析构时执行 flush,如果此时 OpenGL 相关对象已经释放,在低版本 macOS(10.11, 10.12)会出现 Crash: 处理方案 由于出现问题的部分是由钉钉上层代码触发,处理相对比较简单。最终我们在所有使用 OpenGL 渲染的 Mac 设备上(macOS 10.14 之前的版本)移除 FlutterView 置空动作。即最终 FlutterViewController 释放阶段只执行以下两个动作: 调用 FlutterView shutdown 方法; 调用 FlutterEngine shutDownEngine 方法。 FlutterEngine Windows 端问题 2.1 Win7 设备渲染模块「Crash + 残影」问题 问题背景 此问题背景略微有些复杂,如果细分来看的话,此问题应该可以拆分为两个子问题。 第一个问题是,在部分 Win7 设备上(x86 + x64)出现 d3d11 导致的 Crash,堆栈大致如下: 由于迟迟无法定位导致此问题的具体原因、且 Flutter 官方表示他们对 Win7 设备的覆盖度并不完善「参考」。因此我们决定对 FlutterEngine 稍加定制,在 Win7 等陈旧设备上强制通过「软解模式」来渲染 Flutter 页面。 本以为通过此方式可以绕过此问题,但很不幸运的是此方案暴露了 FlutterEngine 里另外一个 Bug:通过「软解模式」来渲染页面时,FlutterViewController 关闭只有有一定概率会导致 Windows 桌面出现残影。 定位分析 一句话原因: 此问题主要是因为 FlutterEngine 内部 shutdown 流程中,未及时修改 FlutterWindowsEngine 指向 FlutterWindowsView 对象的指针,导致多线程场景下出现野指针;因为野指针导致raster 线程在 FlutterWindowsView 已经销毁情况下仍向其输出绘制帧,进而导致异常。 在定位时,我们通过增加辅助 log 的方式来加快问题定位过程。通过对关键节点补充日志,我们很快发现了可疑点: 上图是出现问题之后关键节点输出的日志。我们通过日志可以得到以下关键信息: OnBitmapSurfaceUpdated 是 FlutterWindowsView 的成员函数。但是在输出最后两行 OnBitmapSurfaceUpdated 方法时,FlutterWindowsView 的析构函数已被执行(野指针); 最后一次执行 OnBitmapSurfaceUpdated 时,渲染使用的 Window 句柄为 nullptr,即可供渲染的窗口(与 FlutterWindowsView 绑定)以被释放。 因为最后渲染所使用 Window 句柄为 nullptr,进而导致出现残影问题。 补充说明:在调用 C++ 成员函数时,即使调用时 this 已经为野指针,但只要成员函数中并未访问到 this 对象,则不会出现内存访问异常(Crash)。 处理方案 修改 FlutterEngine 内部实现,在 SoftwareRenderer 模式下 FlutterWindowsView 析构时,置空 FlutterWindowsEngine 指向其的指针(因 GPU 模式会有异常输出,暂未修改): 通过此方式,可以保证在 FlutterWindowsView 销毁之后 raster 线程中的任务不会再回调渲染接口: 2.2 FlutterPlugin 注册阶段野指针 Crash 问题背景 在钉钉 Flutter 版本「+面板」业务 Windows 端一灰、二灰阶段出现较多例 Crash,客户端整体 Crash 率高达 x%: 通过简单分析,还原 Crash 堆栈大致如下: 从堆栈可以达到两个比较重要的信息: Crash 出现在 FlutterEngine 初始化阶段,具体是在 Plugin 注册时出现异常; 导致 Crash 原因是野指针问题。 定位分析 一句话原因: Flutter 为 Windows 平台提供 wrapper 层代码中,包含一个设计上为单例的对象 PluginRegistrarManager。PluginRegistrarManager 主要服务于 FlutterPlugin 注册、设计上为一个单例,其内部通过 map 维持了一个 FlutterEngine 指针与 Registrar 的映射关系,保证 Registrar 与 FlutterEngine 生命周期保持一致。但是因为 wrapper 层的代码在构建时被编入了 pulgin.dll,导致每一个 plugin.dll 中都包含一份 PluginRegistrarManager 实现副本,即「单例机制」失效。带来的问题是 FlutterEngine 析构时无法正确清除 PluginRegistrarManager 中的绑定关系,导致其内部维护一个失效的指针地址,再次访问时出现 Crash。 下面简单介绍一下分析过程。通过暴力测试,我们可以复现问题: 根据上图可以确认,出现 Crash 是因为 FlutterEngine 对象野指针导致。进一步定位插件注册时 Engine 指针来源,最终可定位到 flutter::PluginRegistrarManager::GetInstance()->GetRegistrar() 方法中: 进一步分析 PluginRegistrarManager 中的实现,可知 GetRegistrar 内部需要 map + emplace 方法来维系 FlutterEngine 地址与 Registrar 关系: 其内部会通过 FlutterDesktopPluginRegistrarSetDestructionHandler 将方法注册到底层 Engine 对象中,其会在 FlutterEngine 析构时被调用,进而解除绑定关系: 问题即出现在此流程中,如果 PluginRegistrarManager 并非真正的单例,且 FlutterEngine 只能维护一份有效的 OnRegistrarDestroyed 回调,那么在 FlutterEngine 析构时,有部分 PluginRegistrarManager 对象中保存的 FlutterEngine 地址不会被清除,再次使用时即会导致问题。 处理方案 修改 FlutterEngine wrapper 层 PluginRegistrarManager 实现,优化「单例」实现方案。将单例生命周期周期管理下层到底层,wrapper 层仅负责提供相关服务。 具体可参考: 2.3 Flutter Window 可见性变化之后页面白屏 问题背景 在 Windows 端 Flutter 页面中,如果将 Flutter Window: 先通过 ShowWindow(flutter_wnd, SW_HIDE) 隐藏; 再通过 ShowWindow(flutter_wnd, SW_SHOWNORMAL) 显示出来。 会发现 Flutter 页面内容无法正常展示,画布上为空白一片。如果在白屏之后通过 setState 或者 拖拽窗口等方式触发 Flutter 页面刷新,则内容可被正常渲染。 定位分析 此问题相对比较明确,Flutter Windows 端实现存在 bug,在 Window 可见性发生变化之后,应重新出发 flush 将最新视图绘制到对应窗口,但是目前此流程并未实现,导致出现以上问题。 处理方案 此问题已经提交issue,暂时钉钉侧是通过上层补偿的方式来绕过此此问题。我们在 Native Window 可视性变化之后,手动通知 Flutter 侧刷新当前可见页面,以此触发重绘、规避问题。 总结 以上即为钉钉 Flutter 落地过程中桌面端处理的几大主要问题。从我们实际体验来看,虽然在 Flutter v2.10 版本已经正式发布对 Windows 的支持。但仅从稳定性角度来看,Flutter 在 Mac 端的表现无疑要优于 WIndows。如果有其它团队希望在使用 Flutter 在桌面单端做一下尝试,我们优先推荐选择 Mac 端,其无论是上手门槛还是性能稳定性表现,相比 Windows 端要更有优势。 关注【阿里巴巴移动技术】,阿里前沿移动干货&实践给你思考!

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册