第2 章 移动大前端 前端从 "人工化" => "工具化" => "工程化" => "智能化"。我们将所有用户涉及的操作的终端都理解为前端范畴,前端逐渐被泛化为大前端,技术领域也从传统的浏览器前端,扩展到以iOS/Android 原生开发,Cordova,React Native
为代表的跨平台开发框架,以及微信,支付宝等小程序开发框架。随着前端技术的蓬勃发展,就需要配套的工程化平台来解决沟通协作的效率问题。携程开发了MCD平台,用于移动端和H5前端的集成发布。前端的广泛应用,使之对应的数据收集,性能监控,故障排查,异常收集等系统必不可少。2.1 CRN 框架 CRN(Ctrip React Native)基于 React Native 框架优化。2.1.1 背景介绍 React Native(RN) 是 Facebook 开源的跨平台开发框架,是FB开源的视图渲染框架React 在原生移动应用平台的版本。RN 可以让用户只使用JS语言,构建原生移动应用程序,
支持iOS和Android。为什么引入RN?1.App占用内存使用RN,实现同样功能的App,占用的内存远远小于原生App。2.用户体验RN通过 JavaScriptCore(JSC)引擎解析js模块,转换成原生(Native)App组件渲染,与h5相比,不再局限于WebView,渲染性能大大提升,运行时的用户体验媲美原生App。3.成熟度Android/iOS 的RN都已经开源,原生APP提供的组件和API相对丰富,并且跨平台基本一致,对外的接口也趋于稳定,适合业务开发。4.动态更新在原生app开发中,Android平台通过 插件化框架,可以实现动态加载远端代码和资源的功能。但是在iOS平台上,因为系统限制,不能动态执行远端下载的原生代码,而RN可以满足该需求。5.跨平台RN 提供的API和组件,大部分支持跨平台使用,对少数不支持跨平台使用的组件可以进行二次封装抹平,让业务开发人员开发一份代码,运行在iOS和Android平台上,大大提高开发效率,降低开发维护成本。2.1.2 框架设计 1.开发框架:工具和文档,组件和解决方案,跨平台打通(H5),代码托管主要在开发阶段的支持,包括工具和文档,组件和解决方案,扩平台打通(H5)和代码托管功能。其中,工具主要包括CLI和Packer;文档包括api文档和设计文档;跨平台打通(H5)是指抹平平台组件间的API的功能;代码托管是指方便业务团队,特别是新加入CRN开发的团队参考已有的业务代码,快速上手功能。CRN开发框架方面:开发CRN-CLI 脚手架,对RN原始的CLI进行二次包装,提供工程创建,服务启动,等常用功能。文档方面:提供API文档和设计文档。API 文档采用 YUI Doc。设计文档:主要包含一些组件和API的设计文档。组件方面:提供100多个业务和公共组件支持。2.性能优化:框架拆分,框架预加载,首屏性能优化,稳定性优化主要解决首屏渲染的性能问题和RN框架的稳定性问题。为了解决首屏渲染的性能问题,我们开发了框架拆分和框架预加载,业务按需加载,业务预加载和渐进式渲染的方案。页面加载流程:首先是CRN容器创建,然后是增量包(如果有)下载和安装,之后进行CRN框架加载(包含Native和JS组件),并在CRN框架加载完成之后,进行业务代码加载,计算页面虚拟DOM,通知Native渲染业务页面,如果有业务网络请求,则在请求完成之后,重新渲染。1.CRN容器创建2.增量包下载3.增量包安装4.CRN框架加载5.业务代码加载6.业务页面渲染7.业务网络请求8.页面重新渲染真实的RN页面的渲染性能包含4,5,6三个部分,针对这3个部分,我们提供了不同的性能优化方案:1.CRN框架加载:框架和业务代码拆分,框架代码预加载,JSC执行引擎缓存2.业务代码加载:业务代码按需加载,业务代码预加载3.业务页面渲染:渐进式渲染,骨架图预渲染3.发布运维:动态打包配置,发布系统及监控,页面性能监控,线上错误监控主要提供动态打包配置,发布系统及监控,页面性能监控和线上错误监控等平台,使业务人员依托完备的系统去发现和解决线上的问题。2.1.3 性能优化 1.CRN 框架加载优化将框架代码和业务代码进行拆分,生成框架包和业务包。框架包可以在后台进行线程加载,业务包在进入业务时才开始加载。2.业务代码加载优化对于业务代码加载优化而言,我们主要从两个方面考虑,分别为按需加载和预加载。差别是:按需加载是进入业务模块时,只加载对应的页面的代码;预加载是在尚未进入业务模块时,就把需要的业务页面的代码在后台进行加载并执行。3.业务页面渲染优化随着页面复杂度的增加,渲染耗时也会逐渐增加。这是因为,完成页面渲染需要计算虚拟的DOM的Diff,传输数据给Native,如果数据传输发生延时,就会出现"掉帧"的情况,为了使页面尽快显示出来,就需要简化首次渲染。1.渐进式渲染2.骨架图2.1.4 配套支撑系统建设 1.发布系统除了常规的 按照版本/平台/环境发布,灰度发布,回滚发布,还增加了发布结果和实时到达率的报表,从而方便在项目发布后,对发布效果进行评估。在项目发布后,需要重点关注以下几个监控指标:1.发布结果在项目发布后,可以按照平台/App/版本 来展示这个包的成功,失败次数,以及失败的原因分布。2.实时到达率这是业务最关注的数据,因为它可以直观的展示,在项目发布后,有多少比例的用户已经使用了最新的包。2.性能报表系统项目上线后,就需要统计线上业务首屏加载的耗时趋势,分布和使用量。3.错误报表系统错误报表系统用于收集客户端上报的RN错误,包括JS执行异常,Native Runtime 的一些异常,在业务模块发布后,必须在此系统中确认自己发布的业务模块的稳定性是否异常。2.2 Web 框架 2.2.1 微信小程序应用框架CWX CWX 可以消除不同终端差异的,为上层业务提供基础微服务的业务体系框架。CWX 框架的主要组成部分:CWX 框架主要分为CLI,运行时框架和发布自动化三大部分。1.CLI 部分CLI的中文含义是 命令行界面,我们可以通过node脚本编写命令行工具完成一些重复的,机械化的工作,并将此CLI命名为 wxtools。2.运行时框架部分运行时框架部分主要解决不同小程序之间的语法差异问题,基于统一的语法实现业务逻辑,封装绝大多数常用的操作。3.发布自动化部分自动化测试:小程序的自动化测试,目前主要是JSLint的语法检测,以及依赖于微信小程序的UI自动化测试。自动化发布:自动化发布需要经历 自动化打包,自动化提交,自动化通知这3个步骤。2.2.2 CRN 浏览器端运行框架CRN-Web CRN-Web 是在React的基础上,以 React-Native 为规范,结合CRN(CRN负责iOS和Android,CRN-Web 负责Web平台),最终实现项目在 iOS,Android,H5,PC 多端运行的框架。1.CRN-Web 框架能带来什么一致性:用户体验和开发体验都和 React-Native 保持一致。优越性:与一般web相比,使用 VirtualDOM,PWA,条件编译,TreeShaking 等技术提升了性能。经济性:一套业务代码多端运行,节省了开发成本和测试成本,提升产品迭代速度。基础性:在CRN-Web框架的基础上可以构建新工具。扩展性:系统具有高度的可扩展性,Native模块可以根据规则采用Web实现,web版本的组件可以插入CRN-Web框架。CRN-Web 框架的组成:1.UI层子系统2.编译子系统3.部署子系统4.发布子系统2.2.3 下一代前端框架解决方案 NFES 起因,之前纯客户端渲染框架,无论是页面性能还是技术栈开发效率都比较低,再加上之前功能模块和框架的耦合使用户无法以类似插件的形式使用功能模块,导致框架整体显得比较繁琐。设计思路:1.引入同构渲染,即前后端共同使用JS(易于开发和维护),它既能通过服务端提升首屏加载速度,让用户第一时间看到有价值的信息而不是颇具"喜感"的加载页面,又能保持客户端的良好的用户体验。2.引入独立的插件化设计,使模块和框架零耦合,便于业务单独使用子模块。3.建立一站式开发工具DevTools和CLI,提升开发效率。2.3 插件化 插件化技术是指将应用按照业务功能模块拆分,将不同的业务模块打包成不同的独立插件,并在运行时根据用户的操作加载对应的功能插件的技术。携程的插件化框架除了
提供最基础的动态加载能力,还在业务解耦,组件化和热修复方面进行了扩展。2.3.1 插件化的来源 插件化动态加载架构方案会为我们带来巨大的收益:1.编译速度需要提升2.启动速度需要提升3.A/BTesting4.可选模块按需下载国内各大厂商都推出了自己的插件化解决方案,阿里巴巴的 Atals,360的 RePlugin,滴滴的 VirtualAPK。每种方案的细节实现和侧重点都不相同,但底层的实现方式大同小异。所有的插件化方案其实都是围绕如何在主 Bundle 中加载子 Bundle 这一核心流程来进行的。2.3.2 方案的实现 插件化的核心是在主 Bundle 中按需加载子 Bundle。Android APK 的打包流程,其本质是两个流程:一个是资源的编译,另外一个是代码的编译。与之相关的环节,aapt,javac,dx。a) aapt 是andorid 资源编译依赖的主要工具。b) javac 是Java提供的编译Java源代码的工具。它将Java源文件编译成虚拟机可执行的字节码文件,c) dx 是 android 工具链中将 Java 编译好的字节码文件转换成 android 虚拟机可执行的字节码文件的工具。对于插件化框架而言,首先需要打包出能够满足要求的插件的Bundle,这个Bundle其实是一个独立的APK。实现分为两类:针对插件子工程进行的编译流程改造;运行时的动态加载改造。通过编译改造构建出主Bundle和插件Bundle,接下来就需要在运行时加载插件Bundle。运行时的动态加载包括三部分:资源的动态加载,运行时类的动态加载,Native SO 的动态加载。2.4 Node.js 2.4.1 应用场景技术栈只是解决技术问题的途径,所谓术业有专攻,"能高效,稳定的解决问题的语言都是合适的语言"。node.js 在携程的应用场景:1.DA(数据聚合)DA 的主要功能是提升加载速度,减少重复的数据逻辑处理次数。2.SSR(Server-Size Rendering)3.内部工具2.4.2 应用部署 1.部署流程    1.Develop 会使用脚手架生成项目,同时安装公共业务模块。2.Build负责对Develop阶段产出的项目进行构建工作,包括C++模块编译和环境集成,同时会设置构建的缓存机制。3.Release负责应用的启动和运行,与Build Docker 相比,更加轻量。在这个阶段需要关注的是Docker的数量,cpu,MEM 等基础信息。4.Publish负责应用启动后的健康检查。在健康检查完成后,会将Docker拉入集群并提供外部访问。2.版本选择2.4.3 运维与监控 1.Docker化nginx + PM2 模式。2.核心指标3.监控模型4.日志排障2.4.4 公共服务 1.存储服务2.业务服务3.监控服务4.公共服务5.缓存服务6.DR(Disaster Recovery,灾备)2.5 移动发布平台MCD 2.5.1 平台服务架构 MCD(移动发布平台),分为4大模块:1.前台web服务该服务直接面向使用人员,在平台上进行的操作和交互都由该服务实现,与此同时,前台web服务负责与后台打包服务进行通信。2.后台打包服务用户在前台触发的耗时较长的任务,如源码编译,应用打包等都会由前台web服务传递给后台打包服务,并由后台打包服务进行任务分配工作。后台打包服务负责生成任务信息,保存任务初始数据,但是后台打包服务并不会直接调度Jenkins服务进行任务执行,而是会通过消息队列方式将任务交给后台任务调度服务。3.后台任务调度服务后台任务调度服务发现有需要执行的任务时会先寻找合适的Jenkins节点,并等待节点完成其他任务后再调用Jenkins服务执行实际的任务。与此同时,当任务执行完成后,后台任务调度服务还需要对Jenkins服务的任务执行结果进行回收和整理,并将最终的结果同步到后台打包服务和前台web服务中。4.Jenkins任务执行服务使用Jenkins作为任务的执行容器,可以极大的减少开发工作量,可以在Jenkins上自由定制不同类型的任务模板,并利用脚本语言执行最终的任务,极大的降低了任务维护的难度。2.5.2 生命周期管理 1.集成阶段该阶段主要面对项目经历和应用开发人员,包括项目管理模块,代码打包模块,应用集成模块等。在该阶段中,首先由项目经理创建发布计划,设定应用的开发周期和集成周期,并根据模板配置好应用的模块;然后,在开发周期内,各业务线的应用开发人员会在规定的时间内提交自己模块的代码,并进行功能自测;在进入集成周期后,系统会根据配置定期的进行应用模块检查,督促各个模块负责人进行最终代码的提交和功能确认,与此同时,还会定期构建可用的集成测试包,为各方测试人员提供统一的测试APP;在集成的最后阶段,系统会自动限制代码提交,收集各业务线测试结果,并由项目经理根据测试结果决定集成测试是否通过。2.测试阶段从应用的生命周期看,这个阶段其实与集成阶段密不可分,这是因为在集成过程中就会不断执行相关的测试任务,单独设置该阶段的主要是考虑相关测试入口的统一性,方便测试人员快速展开测试任务,提供测试效率。3.发布阶段该阶段的场景主要是应用发布后对线上功能进行实时更新。现在的应用大多数都需要在上线后实现实时更新,从而进一步增强用户体验,提供应用质量。基于携程自研的增量框架,其App可以达到在线更新的目的。MCD平台定制了一个完善的增量发布流程,有效的保证了新功能的动态更新。4.运营阶段借助监控体系,可以实时监控线上应用的崩溃和卡顿情况,并结合服务端与应用端的埋点,可以实时监控服务访问时长和成功率等性能指标。2.5.3 开发流程管理 统一和规范的开发流程可以有效的减少开发和测试人员的沟通成本,开发和测试人员根据标准流程进行相关工作,可以极大的提高工作效率。在MCD平台,整个应用开发流程被分成3个步骤:1.模块打包核心思想是将完整的应用拆分成多个独立的模块,并且模块之间存在一定的依赖关系。在应用开发初期,开发人员会提交自己模块的代码,并在平台上将代码编译成可执行格式(android为so文件,iOS为.a文件)。在每次编译该模块时,都会生成一个新的版本,版本共有3个不同的类型:第一种是普通类型,任何编译成功的版本都属于普通类型;第二种是Latest类型,表示每一个模块最新成功编译的版本;第三种是RC类型,表示经过测试的稳定版本。应用在打包发布时会从各个模块中挑出一个版本,并根据所选择的版本类型的不同分别进行测试发布和集成发布。2.测试发布测试发布默认选择Lastest版本,测试人员在开发人员提交代码,打包Bundle后,就可以直接使用最新版本的Bundle打出测试包,此时打包的任务只需要将各个模块组装在一起即可。在打包完成后,测试人员对新功能进行测试,并在测试完成后将该包中的模块标记为RC版本,以待后续集成时使用。3.集成发布集成发布所使用的版本均为RC版本,由系统在应用集成阶段自动挑选,自动打包。在进入集成发布阶段后,测试人员不再关心测试发布的结果,可以直接使用集成发布的结果进行功能测试,并在平台上实时反馈测试结果。当全体测试通过后,由项目经理进行最终的发布确认。2.5.4 发布流程管理 应用在开发完成,进入应用市场后并不代表应用的开发周期已经完结,还有很多业务需要在线上进行实时更新,此时就需要使用MCD平台的增量发布功能。增量发布流程:功能开发 => (提交代码) => 测试发布 => (生产授权) => 灰度发布 => (实时监控) => 全量发布1.在提出线上功能更新需求后,由各业务开发人员完成相关功能的代码编写,并在本地测试完成后进行代码提交。2.在开发人员提交代码后,系统会根据相关配置自动将相应的代码编译成增量文件并发布到测试环境中。然后,测试人员开始进行实际功能的测试,并在测试和确认功能正常后申请生产授权。3.在完成授权后,将新的模块发布到线上环境,此时发布停留在灰度状态。所谓的灰度状态,就是待发布的文件并不会直接下发到每一个客户端,而是会根据一定的比例(灰度率)及白名单进行下发。4.当测试人员再一次在生产环境中完后功能验证后,可以逐渐下调下发比例,直到完全下发为止。在整个下发的过程中,系统会实时监控线上的错误情况,如果发现错误数据异常,就会对开发人员进行实时提醒。2.6 用户行为监测UBT UBT(用户行为追踪)是用于用户行为数据收集的系统。是大数据的基石,承担客户端性能追踪,故障报警,用户行为统计等任务,为商业智能提供重要支撑。2.6.1 数据采集 App上架后,如何了解用户在使用过程中的响应是否顺畅?如何评估及改善用户体验?如何分析营销渠道的价值?只有充分收集信息,才能进行后续的数据导向的产品改进,才能开发商业智能。采集系统提供两种类型的数据采集:1.自主采集使用公司的统一逻辑,解决常规需求。2.自定义采集由各个团队按需定制并进行个性化采集。为了提升数据的可用性,包括自定义采集内,采集sdk统一规范了一些基础数据模型。该基础数据模型约束了数据的组织方式,包括针对用户行为和针对终端设备两种视角的数据组织。1.用户行为视角将所有数据组织到树形结构中,顶层是访客,中间是会话,下面是页面访问及其他。2.终端设备视角针对的是手机APP,与用户行为视角的主要区别是,使用进程生命周期取代了用户行为的会话,可以被称为终端设备会话。该模式主要是为了方便技术人员排障和监控。2.6.2 传输与存储 在客户端原始的信息采集完成后,信息就进入了传输阶段,主要环节包括收集服务,消息系统,分发系统等。在App端,数据使用自定义的应用层协议以tcp方式上报,对原始数据采集信息进行打包和gzip压缩处理,并对报文大小进行控制,合理封包,以提高效率。在web场景中,数据上报采用http协议。收集服务在解包并对原始数据进行基本的加工后,会将其推入消息系统。2.6.3 实时分析 实时分析平台主要涉及 Storm,Spark等分布式计算平台,以及HBase,Redis,ElasticSearch等存储于索引组件。常规的实时分析包括一些重要数据的实时索引和统计指标的实时预聚合。实时索引是为了让数据实现实时检索,如让开发人员及时看到客户端捕获的异常等,主要采用HBase与ElasticSearch相结合的方案。HBase可以支撑更大的数据量级,但其Row Key机制使得检索不够灵活;而es则相反,其强项在于对复杂查询的支持。经过实践,简单的场景直接使用HBase,复杂场景事宜使用HBase+es。比如,多条件组合查询,我们会通过es获取Row Key信息,再通过HBase获取真正的数据。es官方给出的最佳实践在10亿以下。如果符合这个量级,可以直接使用es。实时聚合是为了提供快速的数值统计,如实时的性能指标监控等。2.7 CData CData 是实时报表系统,负责常规的应用检测与报警,涵盖性能管理,错误统计,访问量统计,以及排障支持等。2.7.1 性能管理 性能是 应用/站点 的重要用户体验指标。1.服务性能   服务性能体现的是客户端监测的真实服务调用耗时。相对于服务端自行统计的耗时,客户端统计的耗时更能代表用户的真实体验。类似于dns解析,建立连接等步骤的耗时,只有客户端才能检测到。服务性能报表维度:1.终端2.服务号3.状态码4.地域5.网络类型2.加载性能无论是web还是app,都会涉及到许多资源的加载操作,如图片的加载。资源的加载对用户体验往往有着直接影响。另外,许多资源是通过cdn提供商加载的,这时对性能的检测,还能起到对cdn供应商服务质量的持续监督。3.白屏时间和渲染性能白屏时间/渲染性能 能体现的是包括 网络和代码质量在内的综合执行效率,该类指标与用户体验的联系更密切。白屏时间/渲染性能 报表维度:1.终端2.页面标识3.技术栈4.网络类型2.7.2 错误统计 客户端的错误统计主要针对崩溃和执行异常这些影响较大的场景。这部分的重要工作是多场景的适配与报表的抽象统一。2.7.3 访问量统计 1.页面访问量统计页面被浏览的次数,是反映网站/应用使用情况的一个主要指标。通过对页面访问量进行分析,可以辅助完善操作流程设计,评估用户热度,监测渠道效果,预测未来趋势等。2.终端统计主要分析用户使用的设备型号,系统信息,应用/浏览器信息等。这一系列的指标对把握未来技术方向,合理设定兼容目标等具有重要意义。3.访问流与转化率访问流偏重于分析访问量的来龙去脉,各环节的比重等,比如用户第一步到达哪些页面,各有多少流量,这些流量如何流向第二步,等等;而转化率更直接的关注某个目标的达成情况,每步操作的流失情况等。2.7.4 排障支持 1.轨迹重现我们将信息按匿名访问标识组织成时间序列,并进行可视化展现。在收到客户报障并获取标识之后,排障人员可以查看对应时段从客户设备上收集到的信息,包括性能统计,报错,特定业务埋点等多种信息。2.全链路追踪从客户端的一个请求到经过的服务,以及服务发起的SOA请求,数据库SQL操作等,均可通过标识信息关联起来。

2.携程架构实践 --- 移动大前端相关推荐

  1. 【社区图书馆】JAVA开发与架构(携程架构实践)

    发这篇博文主要是想学习一下携程的架构.携程出了一本<携程架构实践>,无奈现在还没开源.看京东价大概109元人民币.如果看到次博文的网友能发我一本<携程架构实践>pdf.不胜感谢 ...

  2. 【社区图书馆】携程架构与实践图书

    发这篇博文主要是想学习一下携程的架构.携程出了一本<携程架构实践>,无奈现在还没开源.看京东价大概109元人民币.如果看到次博文的网友能发我一本<携程架构实践>pdf.不胜感谢 ...

  3. 携程是如何把大数据用于实时风控的

    携程是如何把大数据用于实时风控的 大数据 风控 携程 阅读20608  本文由携程技术中心投递,ID:ctriptech.作者:郁伟,携程技术中心风险控制部高级开发经理.2010加入携程,参与了携程结 ...

  4. 携程到底有没有大数据杀熟?!

    作者 | 胡巍巍 出品 | CSDN(CSDNnews) 牛了,这几个案例让你迅速掌握AI技术! https://edu.csdn.net/topic/ai30?utm_source=cxrs_bw ...

  5. 研发管理-质量与效率提升-混沌工程在携程的实践

    研发管理-质量与效率提升-混沌工程在携程的实践 前几天听了携程SRE运维总监方菊女士的演讲,特别有感触,也是因为负责的产品和项目团队在上线过程中出现了很多的故障.本人前几篇文章介绍了携程在故障处理方面 ...

  6. 中小型研发团队架构实践三要点(转自原携程架构师张辉清)

    如果你正好处在中小型研发团队-- 中小型研发团队很多,而社区在中小型研发团队架构实践方面的探讨却很少.中小型研发团队特别是 50 至 200 人的研发团队,在早期的业务探索阶段,更多关注业务逻辑,快速 ...

  7. 干货 | 日访问过亿,办公IM及开放式平台在携程的实践

    作者简介 Jim,携程高级研发经理,关注Java&Go技术栈后端研发.目前致力于TripPal开放平台的高可用.开放化进程及核心衍生服务. 简介 携程内部的办公IM项目最早在2016年立项,经 ...

  8. 图形验证码在携程的实践之路

    作者简介:闵杰,携程信息安全部产品经理.2015年加入携程,主要负责黑产防刷,验证码,反爬以及UGC方面的产品设计,关注在低成本的前提下,解决以上场景的实际问题.本文由携程技术中心投稿,微信公号ID: ...

  9. Spark SQL在携程的实践经验分享

    本文根据张翼老师在2018年5月13日[第九届中国数据库技术大会]现场演讲内容整理而成. 讲师简介: 张翼,10年互联网老兵;2015年3月加入携程,携程的大数据平台技术总监,带领团队构建稳定,高效的 ...

  10. 携程Docker实践

    原文地址:http://www.iteye.com/news/31468         请点击原文阅读 ---------------------以下是原文--------------------- ...

最新文章

  1. Android 性能优化
  2. python编程基础与应用-Python程序设计:从编程基础到专业应用
  3. TCP、UDP以及HTTP的简单讲解
  4. java冒泡排序_JAVA实现经典排序算法(冒泡排序、选择排序、插入排序、希尔排序、堆排序、归并排序、快速排序)...
  5. 实用ExtJS教程100例-002:MessageBox的三种用法
  6. mongodb连接失败_深入浅出mongodb(一)
  7. centos配置occi环境变量_拓展学习-golang的下载、安装和环境配置教程
  8. Python基础语法-三种函数特殊形参定义以及使用方式
  9. Orion算法:GOOGLE干掉百度的核武器?
  10. 基于线性回归的波士顿房价预测
  11. .net知识和学习方法系列(十四)TraceListener的应用
  12. 为什么NX10帮助功能无法找到HTML,NX10.0 新功能介绍视频教程专辑
  13. SpringBoot报错 org.apache.catalina.LifecycleException: Protocol handler start failed
  14. Python高级——魔法属性和方法
  15. r语言 图形一览_R语言实战(第2版):第三章 图形初阶(01)
  16. 自然语言处理 -- NLP作业 1 :训练词向量
  17. [USACO06JAN]牛的舞会---洛谷P2863
  18. 使用echarts来显示世界地图和全国地图,并且可以下钻层级
  19. poj4474 Scout YYF I(概率dp+矩阵快速幂)
  20. 智能合约漏洞检测工具mythril使用

热门文章

  1. 表关系+表的详细操作+字段详细操作+特殊表--day40
  2. P3935 Calculating
  3. vmware12安装vmtools
  4. 移动开发:怎么去掉点击时出现背景蓝色
  5. xampps mysql无法启动
  6. USACO / Mother's Milk (DFS)
  7. 2007年7月23日旅游
  8. [转]利用处理程序错误攻击(下)
  9. 菜鸟也要懂点设计模式|用Python设计一个请假模式
  10. 基于R实现统计中的检验方法---卡方检验