• 关于

    钉钉小程序开发活动链接

    的搜索结果

回答

基础组件使用报错一般自助排查: 1、确认组件是否有版本要求,当前环境基础库是否符合要求。 2、检查导入的数据类型是否符合组件要求。 3、如果是样式不生效或渲染异常,检查是不是原生组件, 组件是不是支持自定义样式(支持自定义样式回在属性列表中列车class属性)。 4、使用ide开发工具调试器提供的样式选取功能,排查添加样式属性是否生效。 5、确认代码是否保存,可以使用快捷键:Ctrl+Shift+S保存全部tab/Ctrl+S保存当前tab。 6、可查看官方demo内的相关基础组件实现代码,参考里面的写法。 7、实际效果请以真机为准。 8、个别机型异常、Android和iOS一端正常一端异常等无法自行解决问题,收集相关信息(APPID,支付宝客户端版本,手机类型,简易可复现demo代码(必要时收集复现支付宝账号,复现时间)),咨询在线技术支持。 扩展组件使用报错一般自助排查: 扩展组件是使用小程序自定义组件能力实现的,基于小程序自定义组件规范。 1、检查是否已经安装对应扩展组件库,ui组件:mini-antui,营销组件:ant-mini-scratch-card。 2、有些自定义组件属性和对象依赖component2编译,检查ide模拟器右上角--详情--项目配置--启动component2编译 是否勾选启动。 3、可查看官方demo内的相关扩展组件实现代码,参考里面的写法。 4、使用ide开发工具调试器提供的样式选取功能,排查添加样式属性是否生效。 5、确认代码是否保存,可以使用快捷键:Ctrl+Shift+S保存全部tab/Ctrl+S保存当前tab。 6、实际效果请以真机为准。 7、个别机型异常、Android和iOS一端正常一端异常等无法自行解决问题,收集相关信息(APPID,支付宝客户端版本,手机类型,简易可复现demo代码(必要时收集复现支付宝账号,复现时间)),咨询在线技术支持。非小程序官方提供的组件请咨询组件提供者。 API使用报错一般自助排查: 1、确认API是否有版本要求,当前环境基础库是否符合要求。 3、可查看官方demo内的相关API实现代码,参考里面的写法。 4、确认代码是否保存,可以使用快捷键:Ctrl+Shift+S保存全部tab/Ctrl+S保存当前tab。 5、查看调试器console是否有报错,根据报错提示检查对应代码段。 6、添加fail回调函数,打印fail函数的返回,根据具体错误修改。 7、有些API 模拟器不一定支持模拟,可真机模式看下是否正常,实际效果请以真机为准。 8、个别机型异常、Android和iOS一端正常一端异常等无法自行解决问题,收集相关信息(APPID,支付宝客户端版本,手机类型,简易可复现demo代码(必要时收集复现支付宝账号,复现时间)),咨询在线技术支持。 自研小程序工具排查 小程序属于前端能力,小程序IDE开发工具提供了编写和调试功能,开发者可利用IDE开发工具调试能力,排查开发过程中遇到的问题;具体使用请参考小程序调试文档。 自研小程序联系技术支持 为了减少沟通耗时在联系技术支持前,请先收集相关信息(APPID,支付宝客户端版本,手机类型,简易可复现demo代码(必要时收集复现支付宝账号,复现时间)),咨询在线技术支持。 自研小程序联系售后 为了减少沟通耗时在联系技术支持前,请先收集相关信息(APPID,支付宝客户端版本,手机类型,简易可复现,收集复现支付宝账号,复现时间),咨询在线技术支持。 业务账单问题:对账有异议,遗留交易订单,订单资金未到账请联系商服电话:95188-1,服务时间:8:00-24:00。 自研小程序联系95188 小程序运营相关: 智能客服:智能客服相关问题咨询请参考文档提供联系方式进行咨询。 开发能力签约问题:请拨打商户客服电话咨询:95188-1,服务时间:8:00-24:00。 运营活动业务相关:请拨打商户客服电话咨询:95188-1,服务时间:8:00-24:00。 用户信息申请审核:预计会有1个工作日的审核时间,请耐心等待。如有问题请拨打商户客服电话咨询:95188-1,服务时间:8:00-24:00。 小程序审核相关: 小程序应用上线审核:预计会有1个工作日的审核时间,请耐心等待。如有问题请拨打商户客服电话咨询:95188-1,服务时间:8:00-24:00。 小程序应用信息修改审核:预计会有1个工作日的审核时间,请耐心等待。如有问题请拨打商户客服电话咨询:95188-1,服务时间:8:00-24:00。 小程序提交版本上架审核/驳回/催审:预计会有2个工作日的审核时间,请耐心等待。如有问题请拨打商户客服电话咨询:95188-1,服务时间:8:00-24:00。(技术相关可咨询在线技术支持) 账号被风控相关: 商家账号被风控(所有交易提示风险报错):申诉电话:95188-1,服务时间:8:00-24:00。 个人账号被风控(个人交易无法进行提示存在风险):申诉电话:95188-1,服务时间:8:00-24:00。 业务账单问题: 对账有异议,遗留交易订单,订单资金未到账请联系商服电话:95188-1,服务时间:8:00-24:00。 自研小程序各端支持: 香港版小程序问题咨询: 针对国际业务的特殊性,支付宝有专门的团队支持,香港版小程序咨询请点击以下链接进行咨询:https://global.alipay.com/open/faq.htm 钉钉端: 钉钉小程序咨询请点击以下链接进行咨询:https://ding-doc.dingtalk.com/doc#/qasupport/ngliko 淘宝端: 淘宝小程序咨询请点击以下链接进行咨询:https://miniapp.open.taobao.com/doc.htm?docId=117783&docType=1 高德端: 高德小程序咨询请点击以下链接提交工单:http://developer.amap.com/dev/ticket/type 天猫精灵: 天猫精灵小程序咨询请点击以下链接进行咨询:https://www.tmall.com/wow/portal/act/contact?spm=875.7931836/A.a2226n1.28.eTSmYy mPaaS平台: mPaaS小程序咨询请点击以下链接进行咨询:https://tech.antfin.com/support
保持可爱mmm 2020-05-05 16:17:53 0 浏览量 回答数 0

问题

【Java问答月】4月Java提问、答题有奖;24小时优先回答,不回答有礼物!

hello~developers~ 相信在学习Java或者工作实操中,大家一定会遇到各种各样的问题。也许你百思不得其解、头疼到直呼想要砸键盘的问题,在开发者社区问答频道可以被轻松的解决。无论是Java小白...
问问小秘 2020-03-30 16:25:50 1962 浏览量 回答数 6

回答

2020云栖大会开发者游乐园正在火热进行中,但是许多开发者表示,不知道这次开发者游乐园都有哪些礼品,或是不知道上哪赢取。 2020云栖大会奖品大盘点送给大家 礼品区1:参与万人开发,赢天猫精灵、高达模型、AirPods...... >>点击这里<< 前往Hands-on Labs活动专区! 奖品赢取流程:进入Hands-on Labs活动页,完成签到、提交Hello World代码后,你就能获得一个专属你的全球唯一序列号证书。完成这 3 步任务,只要您的完成顺序是 3 的倍数,即可获得 Apsara 官方 T 恤一件(每人限领一次)! 参加活动,加入钉钉群,每天18:00还会在群中抽取幸运程序员锦鲤1名,AirPods、高达PG模型、Cherry机械键盘等丰富大礼抱回家! Hands-on Labs还不止这些惊喜!完成8项打卡任务,还可获得价值10元的猫眼电影抵扣券(数量有限,先到先得)。 更有5大必玩实验室,参与Hands-on Labs实验室活动,5大奖区等你来拿: 奖区1:4000件Apsara官方T恤 来查收你的第一个线上博客,总量4000个Apsara定制T恤免费放送!每日限量,10点上新。提前完成任务,次日10点直接领取更方便。 奖区2:2000个免费顶级域名 从设计稿到AI应用,体验开发界的“神笔码良”!总量2000件免费顶级域名免费拿,活动开始后每天下午14点会进行补仓,记得直接来页面领取奖品哦~ 奖区3:价值20000元的DSW探索者版体验机会 截止9月18日,动手体验"数据科学",你只需完成"一见钟情"配对指数小游戏并查看原理,即可领取阿里云机器学习PAI-DSW团队为你带来的三大礼包——包含价值20000元的DSW探索者版体验机会和独家定制T恤! 奖区4:1000个intelliJ联名悠悠球 体验Java工程脚手架搭建工程&分享,完成微服务沙箱体验并通过答题,即可赢取联名悠悠球一个!总量1000个,每日限量,10点上新。提前完成任务,次日10点直接领取更方便! 奖区5:1000个云上实验室免费体验名额 最强CPU大脑,平头哥邀请全球1000个开发者内测云上实验室!1000个限量体验名额,点击标题立刻免费申请吧! 礼品区2:小孩子才做选择,大厂Offer和限量周边我都要! >>点击这里<< 前往Offer 5000活动专区! 奖品赢取流程:9月18日前,完成Offer 5000活动页面的5项任务,即可领取阿里云纪念勋章一套以及价值600元的阿里云ACA考试资格一份,限量700份! 好戏还在后头!截止9月18日,点击标题前往活动页,你还有机会获得本次云栖大会“Offer 来啦”活动推出的特别用户权益——火箭面试卡(限量100张哦)!获得火箭面试卡的用户将会在9月18日前收到投递企业的联络,直接进入面试流程并最快当天获得录用意向! >>点击这里<< 马上了解“火箭面试卡”吧! 还有超全阿里云+生态企业岗位直聘,赶快投递你的简历吧! 快点击链接前往Offer 5000活动专区吧!—— https://yunqi.aliyun.com/2020/offers 礼品区3:参与云栖训练营,赢阿里总部参观机会,机票酒店全免! >>点击这里<< 前往云栖训练营活动专区! 奖品赢取流程:本届云栖训练营分两波开启,目前第一波训练营正在火热报名中,点击上面的链接快去报名吧!加入训练营后,在指定时间内完成训练营页面的学习任务,丰富好礼等你拿! 热营先开,礼品先知!快点击训练营标题抢先参与吧! 阿里橙长之旅——宜搭低代码开发训练营 来回机票+菲住布渴智能酒店+阿里巴巴总部参观+阿里大咖面对面交流......你没看错!即日起报名参加宜搭低代码开发训练营,上面的“阿里橙长之旅”套餐都是你的!还有价值600元的阿里云低代码专业技能证书、宜搭定制帆布袋等你来拿! CNCF指尖陀螺——云原生开发者训练营 前往训练营页面,通过3天学习打卡+开通底部产品,一站式带你学透K8S,完成任务即可在页面领取限量CNCF指尖陀螺一枚! SLS联名限量T恤——DevOps日志分析训练营 9月14日起,在授课日当天完成钉群学习并在本页面完成打卡,结营时完成6天连续打满无空缺,即可获得ACA免费考试资格与SLS联名限量T恤! 阿里云定制纪念马克杯——小程序云开发训练营 9月14日起,在授课日当天完成钉群学习并在本页面完成打卡,结营时完成4天连续打满无空缺,参与结营作业评审,优秀学员有机会获得阿里云定制纪念马克杯1只! 限量版蚂蚁贴纸——mPaaS小程序训练营 9月14日起,在授课日当天完成钉群学习并在本页面完成打卡,结营时完成4天连续打满无空缺,即可获得限量版蚂蚁贴纸1件! 阿里云飞天代码定制T恤——云开发Web应用训练营 从入门到精通快速上手Serverless和云开发技术,无需保有服务器,轻松开发并上线自己的个人博客、小程序、管理系统!连续7天打卡,阿里云飞天代码T-shirt拿回家! 礼品区4:开发者的排位赛!限时“上分”赢定制T恤 >>点击这里<< 前往在线编程抢答赛活动专区! 奖品赢取流程:9月18日当天,参与早、中、晚任意一场云栖在线编程限时抢答赛,在比赛规定时间内完成答题,每场答题赛TOP100的选手可获得定制T恤1件。TOP101-200的选手可获得SuperCoder勋章1枚! 排行榜采用ACM赛制,提交用时+罚时为总用时,注意,非比赛时间可参与答题学习将不计入排行哦!最强王者还是嘴强王者,让代码替你说话吧! 快点击链接前往在线编程抢答赛活动专区吧!—— https://yunqi.aliyun.com/2020/games 以上就是本次云栖开发者的全部礼品啦!更多礼品陆续上线中,本文也将实时更新,为大家带来更多开发者奖品攻略!转评收藏不迷路哦!
KB小秘书 2020-09-14 10:40:59 0 浏览量 回答数 0

回答

第十名、R语言 颁奖词 R语言,一种自由软件编程语言与操作环境,主要用于统计分析、绘图、数据挖掘。R基于S语言的一个GNU计划项目,所以也可以当作S语言的一种实现,通常用S语言编写的代码都可以不作修改的在R环境下运行。R的语法是来自Scheme。 提名词 R语言作者,George Ross Ihaka:在奥克兰大学统计系任副教授,是R语言的最初作者。 排名理由 作者头发浓密度:100% 第九名、Python 颁奖词 Python是一种广泛使用的高级编程语言,属于通用型编程语言。作为一种解释型语言,Python的设计哲学强调代码的可读性和简洁的语法。相比于C++或Java,Python让开发者能够用更少的代码表达想法。不管是小型还是大型程序,该语言都试图让程序的结构清晰明了。 提名词 Python语言作者,Guido van Rossum:生于荷兰哈勒姆,计算机程序员,为Python程序设计语言的最初设计者及主要架构师。 排名理由 作者头发浓密度:95% 第八名、C语言 颁奖词 C是一种通用的编程语言,广泛用于系统软件与应用软件的开发。C语言具有高效、灵活、功能丰富、表达力强和较高的可移植性等特点。C语言编译器普遍存在于各种不同的操作系统中,例如Microsoft Windows、macOS、Linux、Unix等。C语言的设计影响了众多后来的编程语言,例如C++、Objective-C、Java、C#等。 提名词 C语言作者,Dennis MacAlistair Ritchie:美国计算机科学家。黑客圈子通常称他为“dmr”。他是C语言的创造者、Unix操作系统的关键开发者,对计算机领域产生了深远影响,并与肯·汤普逊同为1983年图灵奖得主。 排名理由 作者头发浓密度:85%(+胡须) 第七名、Go 颁奖词 Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能。 提名词 Go语言作者,Robert C. Pike:来自加拿大的程序员,曾经加入贝尔实验室,为 UNIX小组的成员。他与肯·汤普逊共同开发了UTF-8。目前为 google的工程师,参与编程语言 Go与Sawzall的研发工作。 排名理由 作者头发浓密度:80% 第六名、JavaScript 颁奖词 JavaScript,通常缩写为JS,是一种高级的,解释执行的编程语言。JavaScript是一门基于原型、函数先行的语言,是一门多范式的语言,它支持面向对象编程,命令式编程,以及函数式编程。它已经由ECMA(欧洲计算机制造商协会)通过ECMAScript实现语言的标准化。它被世界上的绝大多数网站所使用,也被世界主流浏览器(Chrome、IE、Firefox、Safari、Opera)支持。 提名词 JavaScript语言作者,Brendan Eich:美国程序员与企业家,JavaScript主要创造者与架构师,曾任Mozilla公司的首席技术官,并曾短暂担任首席执行官。 排名理由 作者头发浓密度:75% 第五名、Objective-C 颁奖词 Objective-C是一种通用、高级、面向对象的编程语言。它扩展了标准的ANSI C编程语言,将Smalltalk式的消息传递机制加入到ANSI C中。目前主要支持的编译器有GCC和Clang(采用LLVM作为后端)。 提名词 Objective-C作者,Brad Cox:美国计算机科学家。于傅尔曼大学主修化学与数学,于芝加哥大学取得数学生物学博士学位。Objective-C主要作者。 排名理由 作者头发浓密度:70% 第四名、PHP 颁奖词 PHP(全称:PHP:Hypertext Preprocessor,即“PHP:超文本预处理器”)是开源的通用计算机脚本语言,尤其适用于网络开发并可嵌入HTML中使用。PHP的语法借鉴吸收C语言、Java和Perl等流行计算机语言的特点,易于一般程序员学习。PHP的主要目标是允许网络开发人员快速编写动态页面,但PHP也被用于其他很多领域。 提名词 PHP语言作者,Rasmus Lerdorf:出生于格陵兰岛凯凯塔苏瓦克,是一个丹麦程序员,他拥有加拿大国籍。他也是编程语言PHP的创始人,其中PHP的头两个版本是由他编写的,后来他也参与PHP后续版本的开发。 排名理由 作者头发浓密度:60% 第三名、Java 颁奖词 Java是一种广泛使用的计算机编程语言,拥有跨平台、面向对象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。Java编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言。 提名词 Java语言作者,James Gosling:出生于加拿大,软件专家,Java编程语言的共同创始人之一,一般公认他为“Java之父”。 排名理由 作者头发浓密度:50% 第二名、C++ 颁奖词 C++是一种使用广泛的计算机程序设计语言。它是一种通用程序设计语言,支持多重编程模式,例如过程化程序设计、数据抽象、面向对象程序设计、泛型程序设计和设计模式等。 提名词 C++语言作者,Bjarne Stroustrup:生于丹麦奥胡斯郡,计算机科学家。他以创造C++编程语言而闻名,被称为“C++之父”。 排名理由 作者头发浓密度:40% 第一名、Visual Basic .NET 颁奖词 Visual Basic .NET(VB.NET)是.NET Framework框架下的一种多重编程范式高级语言。Visual Basic .NET属Basic系语言,其语法特点是以极具亲和力的英文单词为基础标识,以及与自然语言极其相近的逻辑表达,有时候你会觉得写VB.NET代码就好像在写英文句子一样,从这个角度来说,VB.NET似乎是最高级的一门编程语言,当然在Basic系语言中VB.NET也确实是迄今为止最强大的一门编程语言。 提名词 Visual Basic .NET作者,Alan Cooper:交互设计的提倡者。库珀有些时候被叫做 Visual Basic 之父,虽然大多数的工作是由微软的内部开发团队完成的,但是对于Windows可视化设计工具的创意是来源于库珀的。 排名理由 作者头发浓密度:0% 以上,就是世界上最难学的编程语言前十名,本次大赛组委会认为,作者的头发越稀少,说明这种语言在学习过程中要掉越多的头发,所以,推导出这种语言越难学。 你现在学得语言排名第几呢?欢迎在下方评论区留言哦~ 原文链接 加入阿里云钉钉群享福利:每周技术直播,定期群内有奖活动、大咖问答
有只黑白猫 2020-01-16 17:41:53 0 浏览量 回答数 0

回答

作者:九章算法 链接:https://www.zhihu.com/question/22744854/answer/763206431 来源:知乎 首先,这个神仙项目请你pick: https://github.com/sindresorhus/awesome 各领域各语言资源大合集 另外,可以关注GitHub的每日榜单,看看大家都在关注些什么(虽然有国外小哥吐槽榜单上都是中文哈哈 https://github.com/trending/python?since=daily 推荐不同语言的几个项目: Python : youtube-dl这个程序是一个开源的python项目。支持MacOS、Linux和Windows平台,可以在官网直接下载编译好的程序。可以用来下载YouTube视频,国内的一些视频站也可以进行下载。 interview_internal_reference: 总结了2019年最新的阿里,腾讯,百度,美团,头条等技术面试题目以及答案,分析汇总。 sherlock: 高级机器视觉软件,可以用于广泛的自动化检测应用。它提供了最大的设计灵活性,丰富的已验证的工具和功能。 DeepFaceLab: 这是一个github上的开源项目,所有人都可以查看源代码也能免费使用。个人认为这个项目的最大优点就是安装超级简单,几乎是无需安装,使用过程也不复杂 Manim: 解释数学视频的动画引擎。可以用来创建精确的2D动画。 XSStrike:XSStrike是一个Cross Site Scripting检测套件,配备四个手写解析器,一个智能有效载荷生成器,一个强大的模糊引擎和一个非常快速的爬虫。 XSStrike不是像其他工具一样注入有效载荷并检查它的工作原理,而是通过多个解析器分析响应,然后通过与模糊引擎集成的上下文分析来保证有效载荷。 f="https://github.com/wangshub">Douyin -Bot:抖音机器人。是用于机器人算法的Python代码。教你如何在抖音上找到漂亮小姐姐~~ Photon:快速抓取工具,可以提取网址,电子邮件,文件,网站帐户等等。 google-images-download:可以实现搜索和下载数百个Google图像的Python脚本到本地。 faceswap是个基于dlib的换脸程序。模型训练速度较快,同样配置下更快的到达低loss值,而且有gui界面版本。 you-getyou-get 是py上一个方便的下载工具。这个爬虫神器能爬取视频网站和图片网站,你不用写任何代码就能很容易的把你喜欢的视频或者图片甚至音频文件给扒下来。而且支持腾讯、搜狐、新浪、B站、央视网、芒果TV,乐视网、优酷、熊猫斗鱼等等大多数的国内主流视频网站。 Java: advanced-java: Java工程师进阶知识扫盲,适合系统学习。 vhr:一个前后端分离的人力资源管理系统,采用SpringBoot+Vue开发。这个项目的权限管理模块已经开发完成,其他模块还在开发当中。可以管理角色和资源的关系,管理用户和角色的关系。 cat:作为服务端项目基础组件,cat提供了 Java, C/C++, Node.js, Python, Go 等多语言客户端,已经在美团点评的基础架构中间件框架(MVC框架,RPC框架,数据库框架,缓存框架等,消息队列,配置系统等)深度集成,为美团点评各业务线提供系统丰富的性能指标、健康状况、实时告警等。 jeecg-boot:一款基于代码生成器的JAVA快速开发平台!全新架构前后端分离:SpringBoot 2.x,Ant Design&Vue,Mybatis,Shiro,JWT。强大的代码生成器让前后端代码一键生成,无需写任何代码,绝对是全栈开发的福音!! interviews:软件工程技术面试个人指南。可以这里找到针对很多面试问题的视频解决方案以及详细说明。 p3c:是阿里巴巴p3c项目组进行研发。根据《阿里巴巴Java开发规范》转化而成的自动化插件,并且实现了部分自动编程。 SpringAll:包括了Spring Boot,Spring Boot&Shiro,Spring Cloud,Spring Boot&Spring Security&Spring Security OAuth2等系列教程。toBeTopJavaer:Java工程师成神之路。总结的很好,直接理解学习就完了。 JavaScript: quasar:Quasar Framework是MIT许可的开源项目。能在记录时间内构建高性能VueJS用户界面 Daily-Interview-Question:前端大厂面试题汇总 next.js:一个基于React的一个服务端渲染简约框架。它使用React语法,可以很好的实现代码的模块化,有利于代码的开发和维护。 javascript-algorithms:这个存储库包含许多流行算法和数据结构的基于JavaScript的示例。每个算法和数据结构都有自己独立的自述文件,包含相关说明和链接,供进一步阅读 baidu-netdisk-downloaderx:一款图形界面的百度网盘不限速下载器,支持Windows,Linux和Mac。重点在不限速! 其他好玩的项目~ ChineseBQB:国内表情包大集合~~ komeiji-satori/Dress:女装大佬项目,一张图你就懂了 chinese-poetry最全的中文诗歌古典文集数据库.包含5.5万首唐诗、26万首宋诗和2.1万首宋词。唐宋两朝近1.4万古诗人, 和两宋时期1千多位词人 thefuck该项目的主要作用是,在terminal 里输错命令之后无需修改,fuck 一下,自动帮你更正命令,既解气又实用。 加入阿里云钉钉群享福利:每周技术直播,定期群内有奖活动、大咖问答 阿里云开发者社区
茶什i 2020-01-08 10:37:26 0 浏览量 回答数 0

回答

转自:思否 本文作者:Michael van der Gulik 原文链接:《Why WebAssembly is a big deal》 译者:敖小剑 WebAssembly 是每个程序员都应该关注的技术。WebAssembly 会变得更流行。 WebAssembly 将取代 JavaScript。WebAssembly 将取代 HTML 和 CSS。 WebAssembly 将取代手机应用。WebAssembly 将取代桌面应用。在 10 年内,我保证每个程序员至少需要知道如何使用工具来操作 WebAssembly 并理解它是如何工作的。 你可能会说,“太离谱了!” 好吧,请继续阅读。 什么是 WebAssembly 当前形式的 WebAssembly 是 Web 浏览器的新扩展,可以运行预编译代码…快速地。在 C ++ 中编写了一些小代码,然后使用 Emscripten 编译器将该代码编译为 WebAssembly。通过一些 Javascript 粘合,就可以在 Web 浏览器中调用这一小段代码,例如,运行粒子模拟。 WebAssembly 文件,扩展名为.wasm,本身是包含可执行指令的二进制格式。要使用该文件,必须编写一个运行某些 Javascript 的 HTML 文件来获取、编译和执行 WebAssembly 文件。WebAssembly 文件在基于堆栈的虚拟机上执行,并使用共享内存与其 JavaScript 包装器进行通信。 到目前为止,这似乎并不有趣。它看起来只不过是 JavaScript 的加速器。但是,聪明的读者会对 WebAssembly 可能成为什么有所了解。 WebAssembly 将成为什么? 第一个重要发现是 WebAssembly 是一个安全的沙盒虚拟机。可以从 Internet 运行喜欢的 WebAssembly 代码,而确保它不会接管 PC 或服务器。四个主流 Web 浏览器对它的安全性非常有信心,它已经默认实现并启用了。它的真正安全性还有待观察,但安全性是 WebAssembly 的核心设计目标。 第二个重要发现是 WebAssembly 是一个通用的编译目标。它的原始编译器是一个 C 编译器,这个编译器很好地指示了 WebAssembly 虚拟机的低级和可重定向性。许多编程语言都使用 C 语言编写虚拟机,其他一些语言甚至使用 C 本身作为编译目标。 此时,有人整理了一个可以编译为 WebAssembly 的编程语言列表。这份名单将在未来很多年中继续增长。 WebAssembly 允许使用任何编程语言编写代码,然后让其他人在任何平台上安全地运行该代码,无需安装任何内容。朋友们,这是美好梦想的开始。 部署问题 我们来谈谈如何将软件提供给用户。 为新项目选择编程语言的一个重要因素是如何将项目部署到客户。您的程序员喜欢用 Haskell,Python,Visual Basic 或其他语言编写应用程序,具体取决于他们的喜好。要使用喜欢的语言,他们需要编译应用,制作一些可安装的软件包,并以某种方式将其安装在客户端的计算机上。有许多方法可以提供软件 - 包管理器,可执行安装程序或安装服务,如 Steam,Apple App Store,Google Play 或 Microsoft store。 每一个安装机制都意味着痛苦,从应用商店安装时的轻微疼痛,到管理员要求在他的 PC 上运行一些旧的 COBOL 代码时的集群头痛。 部署是一个问题。对于开发人员和系统管理员来说,部署一直是一个痛点。我们使用的编程语言与我们所针对的平台密切相关。如果大量用户在 PC 或移动设备上,我们使用 HTML 和 Javascript。如果用户是 Apple 移动设备用户,我们使用……呃…… Swift?(我实际上不知道)。如果用户在 Android 设备上,我们使用 Java 或 Kotlin。如果用户在真实计算机上并且愿意处理掉他们的部署问题,那么我们开发人员才能在我们使用的编程语言中有更多选择。 WebAssembly 有可能解决部署问题。 有了 WebAssembly,您可以使用任何编程语言编写应用,只要这些编程语言可以支持 WebAssembly,而应用可以在任何设备和任何具有现代 Web 浏览器的操作系统上运行。 硬件垄断 想购买台式机或笔记本电脑。有什么选择?好吧,有英特尔,有 AMD。多年来一直是双寡头垄断。保持这种双寡头垄断的一个原因是 x86 架构只在这两家公司之间交叉许可,而且通常预编译的代码需要 x86 或 x86-64(也就是 AMD-64)架构。还有其他因素,例如设计世界上最快的 CPU 是一件很艰难但也很昂贵的事情。 WebAssembly 是一种可让您在任何平台上运行代码的技术(之一)。如果它成为下一个风口,硬件市场将变得商品化。应用编译为 WebAssembly,就可以在任何东西上运行 - x86,ARM,RISC-V,SPARC。即便是操作系统市场也会商品化;您所需要的只是一个支持 WebAssembly 的浏览器,以便在硬件可以运行时运行最苛刻的应用程序。 编者注:Second State 研发的专为服务端优化的 WebAssembly 引擎 SSVM 已经可以运行在高通骁龙芯片上。Github 链接:https://github.com/second-sta... 云计算 但等等,还有更多。云计算成为IT经理办公室的流行词已有一段时间,WebAssembly 可以直接迎合它。 WebAssembly 在安全沙箱中执行。可以制作一个容器,它可以在服务器上接受和执行 WebAssembly 模块,而资源开销很小。对于提供的每个服务,无需在虚拟机上运行完整的操作系统。托管提供商只提供对可以上传代码的WebAssembly 容器的访问权限。它可以是一个原始容器,接收 socket 并解析自己的 HTTP 连接,也可以是一个完整的 Web 服务容器,其中 WebAssembly 模块只需要处理预解析的HTTP请求。 这还不存在。如果有人想变得富有,那么可以考虑这个想法。 编者注:目前已经有人正在实现这个想法,Byte Alliance 计划将WebAssembly 带到浏览器之外,Second State 已经发布了为服务端设计的WebAssembly 引擎开发者预览版。 不是云计算 WebAssembly 足以取代 PC 上本地安装的大多数应用程序。我们已经使用 WebGL(又名OpenGL ES 2.0)移植了游戏。我预测不久之后,受益于WebAssembly,像 LibreOffice 这样的大型应用可以直接从网站上获得,而无需安装。 在这种情况下,在本地安装应用没什么意义。本地安装的应用和 WebAssembly 应用之间几乎没有区别。WebAssembly 应用已经可以使用屏幕,键盘和鼠标进行交互。它可以在 2D 或 OpenGL 中进行图形处理,并使用硬件对视频流进行解码。可以播放和录制声音。可以访问网络摄像头。可以使用 WebSockets。可以使用 IndexedDB 存储大量数据在本地磁盘上。这些已经是 Web 浏览器中的标准功能,并且都可以使用 JavaScript 向 WebAssembly 暴露。 目前唯一困难的地方是 WebAssembly 无法访问本地文件系统。好吧,可以通过 HTML 使用文件上传对话,但这不算。最终,总会有人为此创建 API,并可能称之为 “WASI”。 “从互联网上运行应用程序!?胡说八道!“,你说。好吧,这是使用 Qt 和 WebAssembly 实现的文本编辑器 (以及更多)。 这是一个简单的例子。复杂的例子是在 WebBrowser 中运行的 Adobe Premier Pro 或 Blender。或者考虑像 Steam 游戏一样可以直接从网络上运行。这听起来像小说,但从技术上说这并非不能发生。 它会来的。 让我们裸奔! 目前,WebAssembly 在包含 HTML 和 Javascript 包装器的环境中执行。为什么不脱掉这些?有了 WebAssembly,为什么还要在浏览器中包含 HTML 渲染器和 JavaScript 引擎? 通过为所有服务提供标准化 API,这些服务通常是 Web 浏览器提供的,可以创建裸 WebAssembly。就是没有 HTML和 Javascript 包装来管理的 WebAssembly。访问的网页是 .wasm 文件,浏览器会抓取并运行该文件。浏览器为WebAssembly 模块提供画布,事件处理程序以及对浏览器提供的所有服务的访问。 这目前还不存在。如果现在使用 Web 浏览器直接访问 .wasm 文件,它会询问是否要下载它。我假设将设计所需的 API 并使其工作。 结果是 Web 可以发展。网站不再局限于 HTML,CSS 和 Javascript。可以创建全新的文档描述语言。可以发明全新的布局引擎。而且,对于像我这样的 polyglots 最相关,我们可以选择任何编程语言来实现在线服务。 可访问性 但我听到了强烈抗议!可访问性怎么样??搜索引擎怎么办? 好吧,我还没有一个好的答案。但我可以想象几种技术解决方案。 一个解决方案是我们保留内容和表现的分离。内容以标准化格式编写,例如 HTML。演示文稿由 WebAssembly 应用管理,该应用可以获取并显示内容。这允许网页设计师使用想要的任何技术进行任意演示 - 不需要 CSS,而搜索引擎和需要不同类型的可访问性的用户仍然可以访问内容。 请记住,许多 WebAssembly 应用并不是可以通过文本访问的,例如游戏和许多应用。盲人不会从图像编辑器中获得太多好处。 另一个解决方案是发明一个 API,它可以作为 WebAssembly 模块,来提供想在屏幕上呈现的 DOM,供屏幕阅读器或搜索引擎使用。基本上会有两种表示形式:一种是在图形画布上,另一种是产生结构化文本输出。 第三种解决方案是使用屏幕阅读器或搜索引擎可以使用的元数据来增强画布。执行 WebAssembly 并在画布上呈现内容,其中包含描述渲染内容的额外元数据。例如,该元数据将包括屏幕上的区域是否是菜单以及存在哪些选项,或者区域是否想要文本输入,以及屏幕上的区域的自然排序(也称为标签顺序)是什么。基本上,曾经在 HTML 中描述的内容现在被描述为具有元数据的画布区域。同样,这只是一个想法,它可能在实践中很糟糕。 可能是什么 1995年,Sun Microsystems 发布了 Java,带有 Java applets 和大量的宣传。有史以来第一次,网页可以做一些比 和 GIF 动画更有趣的事情。开发人员可以使应用完全在用户的 Web 浏览器中运行。它们没有集成到浏览器中,而是实现为繁重的插件,需要安装整个 JVM。1995年,这不是一个小的安装。applets 也需要一段时间来加载并使用大量内存。我们现在凭借大量内存,这不再是一个问题,但在 Java 生命的第一个十年里,它让体验变得令人厌烦。 applets 也不可靠。无法保证它们会运行,尤其是在用户使用 Microsoft 的实现时。他们也不安全,这是棺材里的最后一颗钉子。 以 JVM 为荣,其他语言最终演变为在 JVM 上运行。但现在,那艘船航行了。 FutureSplash / Macromedia / Adobe Flash 也是一个竞争者,但是是专有的,具有专有工具集和专有语言的专有格式。我读到他们确实在2009年开启了文件格式。最终从浏览器中删除了支持,因为它存在安全风险。 这里的结论是,如果希望您的技术存在于每个人的机器上,那么安全性就需要正视。我真诚地希望 WebAssembly 作为标准对安全问题做出很好的反应。 需要什么? WebAssembly 仍处于初期阶段。它目前能很好的运行代码,而规范版本是 1.0,二进制格式定型。目前正在开展SIMD 指令支持。通过 Web Workers 进行多线程处理也正在进行中。 工具可用,并将在未来几年不断改进。浏览器已经让你窥视 WebAssembly 文件。至少 Firefox 允许查看WebAssembly 字节码,设置断点并查看调用堆栈。我听说浏览器也有 profiling 支持。 语言支持包括一套不错的语言集合–C,C++和Rust是一流的公民。C#,Go和Lua显然有稳定的支持。Python,Scala,Ruby,Java和Typescript都有实验性支持。这可能是一个傲慢的陈述,但我真的相信任何想要在21世纪存在的语言都需要能够在 WebAssembly 上编译或运行。 在访问外部设备的 API 支持方面,我所知道的唯一可用于裸 WebAssembly 的 API 是 WASI,它允许文件和流访问等核心功能,允许 WebAssembly 在浏览器外运行。否则,任何访问外部世界的 API 都需要在浏览器中的 Javascript 中实现。除了本地机器上的文件访问,打印机访问和其他新颖的硬件访问(例如非标准蓝牙或USB设备)之外,应用所需的一切几乎都可以满足。“裸WebAssembly”并不是它成功的必要条件; 它只是一个小的优化,不需要浏览器包含对 HTML,CSS 或 Javascript 的支持。 我不确定在桌面环境中让 WebAssembly 成为一等公民需要什么。需要良好的复制和粘贴支持,拖放支持,本地化和国际化,窗口管理事件以及创建通知的功能。也许这些已经可以从网络浏览器中获得; 我经常惊讶与已经可能的事情。 引发爆炸的火花是创建允许现有应用移植的环境。如果创造了“用于 WebAssembly 的 Linux 子系统”,那么可以将大量现有的开源软件移植到 WebAssembly 上。它需要模拟一个文件系统 - 可以通过将文件系统的所有只读部分都缓存为 HTTP 请求来完成,并且所有可写部分都可以在内存中,远程存储或使用浏览器可以提供的任何文件访问。图形支持可以通过移植 X11 或 Wayland 的实现来使用 WebGL(我理解已经作为 AIGLX 存在?)。 一些 SDL 游戏已经被移植到 WebAssembly - 最着名的是官方演示。 一旦 JVM 在 WebAssembly 中运行,就可以在浏览器中运行大量的 Java 软件。同样适用于其他虚拟机和使用它们的语言。 与 Windows 软件的巨大世界一样,我没有答案。WINE 和 ReactOS 都需要底层的 x86 或 x86-64 机器,所以唯一的选择是获取源代码并移植它,或者使用 x86 模拟器。 尾声 WebAssembly 即将到来。 它来得很慢,但现在所有的部分都可以在你正在使用的浏览器上使用。现在我们等待构建用于从各种编程语言中定位 WebAssembly 的基础设施。一旦构建完成,我们将摆脱 HTML,CSS 和 Javascript 的束缚。 加入阿里云钉钉群享福利:每周技术直播,定期群内有奖活动、大咖问答 阿里云开发者社区
茶什i 2020-01-07 10:32:35 0 浏览量 回答数 0

回答

Layout Go工程项目的整体组织 首先我们看一下整个 Go 工程是怎么组织起来的。 很多同事都在用 GitLab 的,GitLab 的一个 group 里面可以创建很多 project。如果我们进行微服务化改造,以前很多巨石架构的应用可能就拆成了很多个独立的小应用。那么这么多小应用,你是要建 N 个 project 去维护,还是说按照部门或者组来组织这些项目呢?在 B 站的话,我们之前因为是 Monorepo,现在是按照部门去组织管理代码,就是说在单个 GitLab 的 project 里面是有多个 app 的,每一个 app 就表示一个独立的微服务,它可以独立去交付部署。所以说我们看到下面这张图里面,app 的目录里面是有好多个子目录的,比方说我们的评论服务,会员服务。跟 app 同级的目录有一个叫 pkg,可以存放业务有关的公共库。这是我们的一个组织方式。当然,还有一种方式,你可以按照 GitLab 的 project 去组织,但我觉得这样的话可能相对要创建的 project 会非常多。 如果你按部门组织的话,部门里面有很多 app,app 目录怎么去组织?我们实际上会给每一个 app 取一个全局唯一名称,可以理解为有点像 DNS 那个名称。我们对业务的命名也是一样的,我们基本上是三段式的命名,比如账号业务,它是一个账号业务、服务、子服务的三段命名。三段命名以后,在这个 app 目录里面,你也可以按照这三层来组织。比如我们刚刚说的账号目录,我可能就是 account 目录,然后 VIP,在 VIP 目录下可能会放各种各样的不同角色的微服务,比方说可能有一些是做 job,做定时任务或者流式处理的一些任务,有可能是做对外暴露的 API 的一些服务,这个就是我们关于整个大的 app 的组织的一种形式。 微服务中的 app 服务分类 微服务中单个 app 的服务里又分为几类不同的角色。我们基本上会把 app 分为 interface(BFF)、service、job(补充:还有一个 task,偏向定时执行,job 偏向流式) 和 admin。 Interface 是对外的业务网关服务,因为我们最终是面向终端用户的 API,面向 app,面向 PC 场景的,我们把这个叫成业务网关。因为我们不是统一的网关,我们可能是按照大的业务线去独立分拆的一些子网关,这个的话可以作为一个对外暴露的 HTTP 接口的一个目录去组织它的代码,当然也可能是 gRPC 的(参考 B 站对外的 gRPC Moss 分享)。 Service 这个角色主要是面向对内通信的微服务,它不直接对外。也就是说,业务网关的请求会转发或者是会 call 我们的内部的 service,它们之间的通讯可能是使用自己的 RPC,在 b 站我们主要是使用 gRPC。使用 gRPC 通讯以后,service 它因为不直接对外,service 之间可能也可以相互去 call。 Admin 区别于 service,很多应用除了有面向用户的一些接口,实际上还有面向企业内部的一些运营侧的需求,通常数据权限更高,从安全设计角度需要代码物理层面隔离,避免意外。 第四个是 ecode。我们当时也在内部争论了很久,我们的错误码定义到底是放在哪里?我们目前的做法是,一个应用里面,假设你有多种角色,它们可能会复用一些错误码。所以说我们会把我们的 ecode 给单独抽出来,在这一个应用里面是可以复用的。注意,它只在这一个应用里面复用,它不会去跨服跨目录应用,它是针对业务场景的一个业务错误码的组织。 App 目录组织 我们除了一个应用里面多种角色的这种情况,现在展开讲一下具体到一个 service 里面,它到底是怎么组织的。我们的 app 目录下大概会有 api、cmd、configs、 internal 目录,目录里一般还会放置 README、CHANGELOG、OWNERS。 API 是放置 api 定义以及对应的生成的 client 代码,包含基于 pb 定义(我们使用 PB 作为 DSL 描述 API) 生成的 swagger.json。 而 cmd,就是放 main 函数的。Configs 目录主要是放一些服务所需的配置文件,比方说说我们可能会使用 TOML 或者是使用 YAML 文件。 Internal 的话,它里面有四个子目录,分别是 model、dao、service 和 server。Model 的定位职责就是对我们底层存储的持久化层或者存储层的数据的映射,它是具体的 Go 的一个 struct。我们再看 dao,你实际就是要操作 MySQL 或者 Redis,最终返回的就是这些 model(存储映射)。Service 组织起来比较简单,就是我们通过 dao 里面的各个方法来完成一个完整的业务逻辑。我们还看到有个 server,因为我一个微服务有可能企业内部不一定所有 RPC 都统一,那我们处于过渡阶段,所以 server 里面会有两个小目录,一个是 HTTP 目录,暴露的是 HTTP 接口,还有一个是 gRPC 目录,我们会暴露 gRPC 的协议。所以在 server 里面,两个不同的启动的 server,就是说一个服务和启动两个端口,然后去暴露不同的协议,HTTP 接 RPC,它实际上会先 call 到 service,service 再 call 到 dao,dao 实际上会使用 model 的一些数据定义 struct。但这里面有一个非常重要的就是,因为这个结构体不能够直接返回给我们的 api 做外对外暴露来使用,为什么?因为可能从数据库里面取的敏感字段,当我们实际要返回到 api 的时候,可能要隐藏掉一些字段,在 Java 里面,会抽象的一个叫 DTO 的对象,它只是用来传输用的,同理,在我们 Go 里面,实际也会把这些 model 的一些结构体映射成 api 里面的结构体(基于 PB Message 生成代码后的 struct)。 Rob Pike 当时说过的一句话,a little copying is better than a little dependency,我们就遵循了这个理念。在我们这个目录结构里面,有 internal 目录,我们知道 Go 的目录只允许这个目录里面的人去 import 到它,跨目录的人实际是不能直接引用到它的。所以说,我们看到 service 有一个 model,那我的 job 代码,我做一些定时任务的代码或者是我的网关代码有可能会映射同一个 model,那是不是要把这个 model 放到上一级目录让大家共享?对于这个问题,其实我们当时内部也争论过很久。我们认为,每一个微服务应该只对自己的 model 负责,所以我们宁愿去做一小部分的代码 copy,也不会去为了几个服务之间要共享这一点点代码,去把这个 model 提到和 app 目录级别去共用,因为你一改全错,当然了,你如果是拷贝的话,就是每个地方都要去改,那我们觉得,依赖的问题可能会比拷贝代码相对来说还是要更复杂的。 这个是一个标准的 PB 文件,就是我们内部的一个 demo 的 service。最上面的 package 是 PB 的包名,demo.service.v1,这个包使用的是三段式命名,全局唯一的名称。那这个名称为什么不是用 ID?我见过有些公司对内部做的 CMDB 或者做服务树去管理企业内部微服务的时候,是用了一些名称加上 ID 来搞定唯一性,但是我们知道后面那一串 ID 数字是不容易被传播或者是不容易被记住的,这也是 DNS 出来的一个意义,所以我们用绝对唯一的一个名称来表示这个包的名字,在后面带上这一个 PB 文件的版本号 V1。 我们看第二段定义,它有个 Service Demo 代码,其实就表示了我们这个服务要启动的服务的一个名称,我们看到这个服务名称里面有很多个 RPC 的方法,表示最终这一个应用或者这个 service 要对外暴露这几个 RPC 的方法。这里面有个小细节,我们看一下 SayHello 这个方法,实际它有 option 的一个选项。通过这一个 PB 文件,你既可以描述出你要暴露的是 gRPC 协议,又暴露出 HTTP 的一个接口,这个好处是你只需要一个 PB 文件描述你暴露的所有 api。我们回想一下,我们刚刚目录里面有个 api 目录,实际这里面就是放这一个 PB 文件,描述这一个工程到底返回的接口是什么。不管是 gRPC 还是 HTTP 都是这一个文件。还有一个好处是什么?实际上我们可以在 PB 文件里面加上很多的注释。用 PB 文件的好处是你不需要额外地再去写文档,因为写文档和写服务的定义,它本质上是两个步骤,特别容易不一致,接口改了,文档不同步。我们如果基于这一个 PB 文件,它生成的 service 代码或者调用代码或者是文档都是唯一的。 依赖顺序与 api 维护 就像我刚刚讲到的,model 是一个存储层的结构体的一一映射,dao 处理一些数据读写包,比方说数据库缓存,server 的话就是启动了一些 gRPC 或者 HTTP Server,所以它整个依赖顺序如下:main 函数启动 server,server 会依赖 api 定义好的 PB 文件,定义好这些方法或者是服务名之后,实际上生成代码的时候,比方说 protocbuf 生成代码的时候,它会把抽象 interface 生成好。然后我们看一下 service,它实际上是弱依赖的 api,就是说我的 server 启动以后,要注册一个具体的业务代码的逻辑,映射方法,映射名字,实际上是弱依赖的 api 生成的 interface 的代码,你就可以很方便地启动你的 server,把你具体的 service 的业务逻辑给注入到这个 server,和方法进行一一绑定。最后,dao 和 service 实际上都会依赖这个 model。 因为我们在 PB 里面定义了一些 message,这些 message 生成的 Go 的 struct 和刚刚 model 的 struct 是两个不同的对象,所以说你要去手动 copy 它,把它最终返回。但是为了快捷,你不可能每次手动去写这些代码,因为它要做 mapping,所以我们又把 K8s 里类似 DeepCopy 的两个结构体相互拷贝的工具给抠出来了,方便我们内部 model 和 api 的 message 两个代码相互拷贝的时候,可以少写一些代码,减少一些工作量。 上面讲的就是我们关于工程的一些 layout 实践。简单回溯一下,大概分为几块,第一就是 app 是怎么组织的,app 里面有多种角色的服务是怎么组织的,第三就是一个 app 里面的目录是怎么组织的,最后我重点讲了一下 api 是怎么维护的。 Unittest 测试方法论 现在回顾一下单元测试。我们先看这张图,这张图是我从《Google 软件测试之道》这本书里面抠出来的,它想表达的意思就是最小型的测试不能给我们的最终项目的质量带来最大的信心,它比较容易带来一些优秀的代码质量,良好的异常处理等等。但是对于一个面向用户场景的服务,你只有做大型测试,比方做接口测试,在 App 上验收功能的这种测试,你应用交付的信心可能会更足。这个其实要表达的就是一个“721 原则”。我们就是 70% 写小型测试,可以理解为单元测试,因为它相对来说好写,针对方法级别。20% 是做一些中型测试,可能你要连调几个项目去完成你的 api。剩下 10% 是大型测试,因为它是最终面向用户场景的,你要去使用我们的 App,或者用一些测试 App 去测试它。这个就是测试的一些简单的方法论。 单元测试原则 我们怎么去对待 Go 里面的单元测试?在《Google 软件测试之道》这本书里面,它强调的是对于一个小型测试,一个单元测试,它要有几个特质。它不能依赖外部的一些环境,比如我们公司有测试环境,有持续集成环境,有功能测试环境,你不能依赖这些环境构建自己的单元测试,因为测试环境容易被破坏,它容易有数据的变更,数据容易不一致,你之前构建的案例重跑的话可能就会失败。 我觉得单元测试主要有四点要求。第一,快速,你不能说你跑个单元测试要几分钟。第二,要环境一致,也就是说你跑测试前和跑测试后,它的环境是一致的。第三,你写的所有单元测试的方法可以以任意顺序执行,不应该有先后的依赖,如果有依赖,也是在你测试的这个方法里面,自己去 setup 和 teardown,不应该有 Test Stub 函数存在顺序依赖。第四,基于第三点,你可以做并行的单元测试,假设我写了一百个单元测试,一个个跑肯定特别慢。 doker-compose 最近一段时间,我们演进到基于 docker-compose 实现跨平台跨语言环境的容器依赖管理方案,以解决运行 unittest 场景下的容器依赖问题。 首先,你要跑单元测试,你不应该用 VPN 连到公司的环境,好比我在星巴克点杯咖啡也可以写单元测试,也可以跑成功。基于这一点,Docker 实际上是非常好的解决方式。我们也有同学说,其他语言有一些 in-process 的 mock,是不是可以启动 MySQL 的 mock ,然后在 in-process 上跑?可以,但是有一个问题,你每一个语言都要写一个这样的 mock ,而且要写非常多种,因为我们中间件越来越多,MySQL,HBase,Kafka,什么都有,你很难覆盖所有的组件 Mock。这种 mock 或者 in-process 的实现不能完整地代表线上的情况,比方说,你可能 mock 了一个 MySQL,检测到 query 或者 insert ,没问题,但是你实际要跑一个 transaction,要验证一些功能就未必能做得非常完善了。所以基于这个原因,我们当时选择了 docker-compose,可以很好地解决这个问题。 我们对开发人员的要求就是,你本地需要装 Docker,我们开发人员大部分都是用 Mac,相对来说也比较简单,Windows 也能搞定,如果是 Linux 的话就更简单了。本地安装 Docker,本质上的理解就是无侵入式的环境初始化,因为你在容器里面,你拉起一个 MySQL,你自己来初始化数据。在这个容器被销毁以后,它的环境实际上就满足了我们刚刚提的环境一致的问题,因为它相当于被重置了,也可以很方便地快速重置环境,也可以随时随地运行,你不需要依赖任何外部服务,这个外部服务指的是像 MySQL 这种外部服务。当然,如果你的单元测试依赖另外一个 RPC 的 service 的话,PB 的定义会生成一个 interface,你可以把那个 interface 代码给 mock 掉,所以这个也是能做掉的。对于小型测试来说,你不依赖任何外部环境,你也能够快速完成。 另外,docker-compose 是声明式的 API,你可以声明你要用 MySQL,Redis,这个其实就是一个配置文件,非常简单。这个就是我们在单元测试上的一些实践。 我们现在看一下,service 目录里面多了一个 test 目录,我们会在这个里面放 docker-compose 的 YAML 文件来表示这次单元化测试需要初始化哪些资源,你要构建自己的一些测试的数据集。因为是这样的,你是写 dao 层的单元测试的话,可能就需要 database.sql 做一些数据的初始化,如果你是做 service 的单元测试的话,实际你可以把整个 dao 给 mock 掉,我觉得反而还相对简单,所以我们主要针对场景就是在 dao 里面偏持久层的,利用 docker-compose 来解决。 容器的拉起,容器的销毁,这些工作到底谁来做?是开发同学自己去拉起和销毁,还是说你能够把它做成一个 Library,让我们的同学写单元测试的时候比较方便?我倾向的是后者。所以在我们最终写单元测试的时候,你可以很方便地 setup 一个依赖文件,去 setup 你的容器的一些信息,或者把它销毁掉。所以说,你把环境准备好以后,最终可以跑测试代码也非常方便。当然我们也提供了一些命令函,就是 binary 的一些工具,它可以针对各个语言方便地拉起容器和销毁容器,然后再去执行代码,所以我们也提供了一些快捷的方式。 刚刚我也提到了,就是我们对于 service 也好,API 也好,因为依赖下层的 dao 或者依赖下层的 service,你都很方便 mock 掉,这个写单元测试相对简单,这个我不展开讲,你可以使用 GoMock 或者 GoMonkey 实现这个功能。 Toolchain 我们利用多个 docker-compose 来解决 dao 层的单元测试,那对于我刚刚提到的项目的一些规范,单元测试的一些模板,甚至是我写了一些 dao 的一些占位符,或者写了一些 service 代码的一些占位符,你有没有考虑过这种约束有没有人会去遵循?所以我这里要强调一点,工具一定要大于约束和文档,你写了约束,写了文档,那么你最终要通过工具把它落实。所以在我们内部会有一个类似 go tool 的脚手架,叫 Kratos Tool,把我们刚刚说的约定规范都通过这个工具一键初始化。 对于我们内部的工具集,我们大概会分为几块。第一块就是 API 的,就是你写一个 PB 文件,你可以基于这个 PB 文件生成 gRPC,HTTP 的框架代码,你也可以基于这个 PB 文件生成 swagger 的一些 JSON 文件或者是 Markdown 文件。当然了,我们还会生成一些 API,用于 debug 的 client 方便去调试,因为我们知道,gRPC 调试起来相对麻烦一些,你要去写代码。 还有一些工具是针对 project 的,一键生成整个应用的 layout,非常方便。我们还提了 model,就是方便 model 和 DTO,DTO 就是 API 里面定义的 message 的 struct 做 DeepCopy,这个也是一个工具。 对于 cache 的话,我们操作 memcache,操作 Redis 经常会要做什么逻辑?假如我们有一个 cache aside 场景,你读了一个 cache,cache miss 要回原 DB,你要把这个缓存回塞回去,甚至你可能这个回塞缓存想异步化,甚至是你要去读这个 DB 的时候要做归并回源(singleflight),我们把这些东西做成一些工具,让它整个回源到 DB 的逻辑更加简单,就是把这些场景描述出来,然后你通过工具可以一键生成这些代码,所以也是会比较方便。 我们再看最后一个,就是 test 的一些工具。我们会基于项目里面,比方说 dao 或者是 service 定义的 interface 去帮你写好 mock 的代码,我直接在里面填,只要填代码逻辑就行了,所以也会加速我们的生产。 上图是 Kratos 的一个 demo,基本就是支持了一些 command。这里就是一个 kratos new kratos-demo 的一个工程,-d YourPath 把它导到某一个路径去,--proto 顺便把 API 里面的 proto 代码也生成了,所以非常简单,一行就可以很快速启动一个 HTTP 或者 gRPC 服务。 我们知道,一个微服务的框架实际非常重,有很多初始化的方式等等,非常麻烦。所以说,你通过脚手架的方式就会非常方便,工具大于约定和文档这个这个理念就是这么来的。 Configuration 讲完工具以后,最后讲一下配置文件。我为什么单独提一下配置文件?实际它也是工程化的一部分。我们一个线上的业务服务包含三大块,第一,应用程序,第二,配置文件,第三,数据集。配置文件最容易导致线上出 bug,因为你改一行配置,整个行为可能跟 App 想要的行为完全不一样。而且我们的代码的开发交付需要经过哪些流程?需要 commit 代码,需要 review,需要单元测试,需要 CD,需要交付到线上,需要灰度,它的整个流程是非常长的。在一步步的环境里面,你的 bug 需要前置解决,越前置解决,成本越低。因为你的代码的开发流程是这么一个 pipeline,所以 bug 最终流到线上的概率很低,但是配置文件没有经过这么复杂的流程,可能大家发现线上有个问题,决定要改个线上配置,就去配置中心或者配置文件改,然后 push 上线,接着就问题了,这个其实很常见。 从 SRE 的角度来说,导致线上故障的主因就是来自配置变更,所以 SRE 很大的工作是控制变更管理,如果能把变更管理做好,实际上很多问题都不会出现。配置既然在整个应用里面这么重要,那在我们整个框架或者在 Go 的工程化实践里面,我们应该对配置文件做一些什么事情? 我觉得是几个。第一,我们的目标是什么?配置文件不应该太复杂,我见过很多框架,或者是业务的一些框架,它实际功能非常强大,但是它的配置文件超级多。我就发现有个习惯,只要有一个同事写错了这个配置,当我新起一个项目的时候,一定会有人把这个错误的配置拷贝到另外一个系统里面去。然后当发现这个应用出问题的时候,我们一般都会内部说一下,你看看其他同事有没有也配错的,实际这个配错概率非常高。因为你的配置选项越多,复杂性越高,它越容易出错。所以第一个要素就是说,尽量避免复杂的配置文件。配得越多,越容易出错。 第二,实际我们的配置方式也非常多,有些用 JSON,有些用 YAML,有些用 Properties,有些用 INI。那能不能收敛成通用的一种方式呢?无论它是用 Python 的脚本也好,或者是用 JSON 也好,你只要有一种唯一的约定,不需要太多样的配置方式,对我们的运维,对我们的 SRE 同时来说,他跨项目的变更成本会变低。 第三,一定要往简单化去努力。这句话其实包含了几个方面的含义。首先,我们很多配置它到底是必须的还是可选的,如果是可选,配置文件是不是就可以把它踢掉,甚至不要出现?我曾经有一次看到我们 Java 同事的配置 retry 有一个重试默认是零,内部重试是 80 次,直接把 Redis cluster 打故障了,为什么?其实这种事故很低级,所以简单化努力的另外一层含义是指,我们在框架层面,尤其是提供 SDK 或者是提供 framework 的这些同事尽量要做一些防御编程,让这种错配漏配也处于一个可控的范围,比方重试 80 次,你觉得哪个 SDK 会这么做?所以这个是我们要考虑的。但是还有一点要强调的是,我们对于业务开发的同事,我们的配置应该足够的简单,这个简单还包含,如果你的日志基本上都是写在这个目录,你就不要提供这个配置给他,反而不容易出错。但是对于我们内部的一些 infrastructure,它可能需要非常复杂的配置来优化,根据我的场景去做优化,所以它是两种场景,一种是业务场景,足够简单,一种是我要针对我的通用的 infrastructure 去做场景的优化,需要很复杂的配置,所以它是两种场景,所以我们要想清楚你的业务到底是哪一种形态。 还有一个问题就是我们配置文件一定要做好权限的变更和跟踪,因为我们知道上线出问题的时候,我们的第一想法不是查 bug,是先止损,止损先找最近有没有变更。如果发现有变更,一般是先回滚,回滚的时候,我们通常只回滚了应用程序,而忘记回滚了配置。每个公司可能内部的配置中心,或者是配置场景,或者跟我们的二进制的交付上线都不一样,那么这里的理念就是你的应用程序和配置文件一定是同一个版本,或者是某种意义上让他们产生一个版本的映射,比方说你的应用程序 1.0,你的配置文件 2.0,它们之间存在一个强绑定关系,我们在回滚的时候应该是一起回滚的。我们曾经也因为类似的一些不兼容的配置的变更,二进制程序上线,但配置文件忘记回滚,出现过事故,所以这个是要强调的。 另外,配置的变更也要经过 review,如果没问题,应该也是按照 App 发布一样,先灰度,再放量,再全量等等类似的一种方式去推,演进式的这种发布,我们也叫滚动发布,我觉得配置文件也是一样的思路。 加入阿里云钉钉群享福利:每周技术直播,定期群内有奖活动、大咖问答 原文链接
有只黑白猫 2020-01-09 17:29:54 0 浏览量 回答数 0

云产品推荐

上海奇点人才服务相关的云产品 小程序定制 上海微企信息技术相关的云产品 国内短信套餐包 ECS云服务器安全配置相关的云产品 开发者问答 阿里云建站 自然场景识别相关的云产品 万网 小程序开发制作 视频内容分析 视频集锦 代理记账服务 阿里云AIoT