-
[indent]原文:The Basics Of API Management 作者:Kin Lane 翻译:Vincent [/indent]译者注:作者在本文中将API管理的一些基础知识整合成了综合列表,这些列表是由一位API管理大神提炼出来的,可以说是API管理的不同组件了。以下为译文。 我正在开发一套基础的API管理策略。这套管理策略涉及到的每一个方面,都倾注了我的毕生之所学。这么多年过去了,我已经将API管理的许多方面单独分离出来,形成了一组核心元素,这些元素也反映了API管理是如何一步一步发展成为数字商品的。总的来说,这有助于我去认真思考API操作的每个方面,而且也能将我平日里面所学习到的内容应用到我正在从事的项目,这样我就可以对API管理做进一步的提炼。 API管理是我所有研究领域中存在时间最久的。正是它启发了我对于其他方面的研究,而且同时它也是API经济里面相对比较成熟的了。我正在研究的这个项目给了我一个机会,让我去思考API管理究竟是什么,应该拆分为哪些不同的关注领域。我已经把API管理的精髓给提炼出来,大概包括以下几个方面: [*]Portal - 是一个单独的URL,可以用来查找关于API的所有信息,将该服务启动运行起来,并使用所有的可用资源。 [*]On-Boarding - 只需要考虑如何让新开发人员在portal主页上登陆,以实现API的第一次调用,接下来就是在生产应用实现调用。 [*]Accounts - 允许API使用者注册一个帐户,用于个人或企业访问API资源。 [*]Applications - 允许每个帐户持有人注册一个或多个应用程序,这些应用程序将使用API资源。 [*]Authentication - 为API使用者提供一种或多种方式进行身份验证,从而能够访问API资源。 [*]Services - 定义在一个或多个API路径上提供哪些服务,从而提供对各种业务服务的HTTP访问。 [*]Logging - 对API的每个调用都通过API管理层记录,以及DNS、web服务器、文件系统和数据库级别。 [*]**ysis - 了解API是如何被使用的,以及应用程序如何将API资源用于使用,识别所有API的使用模式。 [*]Usage - 对所有帐户和它们的应用程序进行量化使用,然后向所有API使用者报告、计费和协调使用。 [*]APIs - API访问帐户、身份验证、服务、日志记录、分析和使用API资源。 还有一些与API管理**在一起的比较常见的元素,这些元素也反映了API管理的核心是什么——API的业务。哪些人拥有哪些权限,他们又使用了哪些权限,将这些信息都记录下来。API管理中还有许多其他方面也需要考虑,但我已经将它们作为一些单独的模块了。这些元素包括: [*]Documentation - 静态或交互式文档,用于所有可用的API路径、参数、头,以及API请求和响应表面积的其他细节。 [*]Support - 自助服务,或直接支持通道,API消费者在此过程中使用这些通道来获得帮助。 [*]SDKs - 用于web、移动或其他类型应用程序的SDKs、示例、库和其他支持代码元素。 [*]Road Map - 当涉及到API时,交流未来的内容。 [*]Issues - 有关API的可用性的任何公开问题的通知。 [*]Change Log - 关于更改API的历史。 这些领域也对API管理做了补充,但应该超越API操作的日常管理方面。我还考虑了身份验证、日志记录和分析,而不仅仅是API管理,因为这三个领域都应该不仅仅涵盖API,但是它们仍然与API管理的核心部分紧密相连。在我的定义中,API管理在很大程度上是关于管理资源的消耗,而不是API操作的其他方面。这不仅仅是我的定义,而是我所看到的API管理的商品化,就像我们在Amazon Web服务上看到的那样。 AWS API Gateway实际上是关于帐户、应用程序、身份验证以及服务的。日志、分析等都是由AWS CloudWatch提供的。对于正在研究的这个特定项目,我使用了GitHub和Jekyll作为Portal,并分别使用自定义交付、使用和支持api。进一步缩小我对API管理的定义。我想说,AWS在API管理方面表现得不错,与AWS API Gateway和AWS CloudWatch之间的关注点分离。如果你将AWS Cognito应用于身份验证,那么你可以将另一个应用程序分离出来。我没有看到任何可行的解决方案来处理使用、计费和API管理的业务和货币化方面。 我正在从事的API项目已经使用了AWS作为操作后端,因此我也有机会去更好的了解API管理中的活动件在AWS平台中是怎么一回事。在AWS平台里面认真研究一下API管理如何解耦是非常意义的,因为它们是商品化的主要参与者,而且也在日益趋于成熟。一旦完成了AWS以后,谷歌和Azure将是接下来的目标,这些也都是定义API管理未来的主要参与者。
-
在市场中很多人分不清框架和库的区别,部分只知道框架模糊的概念。所以在选择webUI框架的时候就会仁者见仁智者见智,会存在各抒己见也是很正常的,这里整体都叫框架吧,在市场中不断的淘汰与创新,主要以Vue、React和Angular三大底层框架为主,很多基于jQuery研发的框架在不断的创新,也有和Vue、React和Angular三大框架并驾齐驱的框架出现。 这里跟大家谈谈为什么我们要使用webUI框架? 选择Web UI框架的目的 了解了如果没有框架,我们需要做的工作,这对选择框架有非常大的帮助。 框架,直白点说,就是一个半成品,能够帮我们做一些事情的半成品。 框架的选择,就是看哪个框架最合适,从而减少开发的工作量,提高开发的效率和质量,并有效减少维护的工作量,最终达到节约综合开发成本,获取更多的收益。 选择Web开发框架的标准 声明:这里所谈的选择WebUI框架的标准,只是我们的总结和一家之言,并不是放之四海而皆准的真理,请根据您的体会客观的看待我们的总结。 另外:我们这里更多的讨论业务功能性应用程序的WebUI框架。 1:选择能够对我们的开发过程提供更多、更好帮助的Web开发框架 2:Web框架的学习一定要简单,上手一定要快,没有什么比使用能得到更深的体会。那些动不动就需要半个月或者一个月学习周期的框架,实在是有些恐怖。 3:一定要能得到很好的技术支持,在应用的过程中,或多或少都会出现这样或者那样的问题,如果不能很快很好的解决,会对整个项目开发带来影响。一定要考虑综合成本,其实这是目前应用开源软件最大的问题,碰到问题除了死肯文档就是查阅源代码,或者是网上搜寻解决的办法,通常一个问题就会导致1-2天的开发停顿,严重的甚至需要一个星期或者更长,一个项目有上这么几次,项目整体的开发成本嗖嗖的就上去了。 4:Web框架结合其他技术的能力一定要强 5:WebUI框架的扩展能力一定要强。在好的框架都有力所不及的地方,这就要求能很容易的扩展Web开发框架的功能,以满足新的业务需要。同时要注意扩展的简单性,如果扩展框架的功能代价非常大,还不如不用呢。 6:WebUI框架最好能提供可视化的开发和配置,可视化开发对开发效率的提高,已经得到业界公认。 7:Web框架的设计结构一定要合理,应用程序会基于这个框架,框架设计的不合理会大大影响到整个应用的可扩展性。 8:WebUI框架一定要是运行稳定的,运行效率高的。框架的稳定性和运行效率直接影响到整个系统的稳定性和效率。 9:WebUI框架一定要能很好的结合目前公司的积累。在多年的开发中已有了很多积累,不能因为使用Web开发框架就不能再使用了,那未免有些得不偿失。 10:选择开发框架另外要注意的一点就是:任何开发框架都不可能是十全十美的,也不可能是适应所有的应用场景的,也就是说任何开发框架都有它适用的范围。所以选择的时候要注意判断应用的场景和开发框架的适用性。 使用框架的必然性 框架,即(framework)。其实就是某种应用的半成品,把不同应用程序中有共性的一些东西抽取出来,做成一个半成品程序,这样的半成品就是所谓的程序框架。 软件系统发展到今天已经很复杂了,特别是服务器端软件,涉及到的知识,内容,问题太多。在某些方面使用别人成熟的框架,就相当于让别人帮你完成一些基础工作,你只需要集中精力完成系统的业务逻辑设计。这样每次开发就不用白手起家,而是可以在这个基础上开始搭建。 使用框架的最大好处:减少重复开发工作量、缩短开发时间、降低开发成本。同时还有其它的好处,如:使程序设计更合理、程序运行更稳定等。基于这些原因,基本上现在在开发中,都会选用某些合适的开发框架,来帮助快速高效的开发应用系统。 Web层开发的工作 在开发中,分层是基本的思想,3层架构或者多层架构早已深入人心,在这里我们就把目光集中到Web层,看看到底Web层开发做了那些工作: 1:数据可视化 Web层需要从逻辑层获取需要展示的数据,然后以合理的方式在页面进行展示 2:人机交互 用户需要从界面上输入数据,在界面上进行按钮点击,进而触发事件,标准的事件驱动模型,然后跟后台进行数据交换,出现新的界面。 3:收集数据,调用逻辑层接口 Web层收到用户的事件请求,需要调用相应的逻辑层接口来进行处理,Web层是不会有任何逻辑处理的。调用逻辑层接口,需要传递参数,这时需要收集用户在界面上输入的数据,然后进行组织,组织成为逻辑层接口需要的数据封装形式(通常都是ValueObject)。 4:根据逻辑层的数据来重新展示页面 Web层开发的步骤 注意:这里讨论的Web层开发,是不使用任何开发框架时候的开发。 1:写页面Html,到底有哪些数据需要在界面上表现 2:每个数据的具体表现形式,如:有的需要表现成为下拉列表,有的需要表现成为单选按钮等。 3:界面表现形式的逻辑布局,所谓逻辑布局是指某些数据的表现形式应该放在前面,某些应该放在后面;某些放在上面,某些放在下面。如:某个请假申请 的业务,有请假开始时间和结束时间,很明显开始时间的表现就应该排在结束时间的前面。而美工是负责最后页面的美观,一般美工不能动界面的逻辑布局。 4:完成前面3步,页面的表现形式的大致模样就有了,下面需要来做功能性的开发。第一个就是这些表现形式的值的来源,如:下拉列表显示的值从什么地方来。值的来源方式很多,有数据库中来、固定值、某断程序运行的中间结果、前面页面传递过来等等,当然典型的还是来自数据库。 好了,确定了值的来源,开发人员就要写代码来获取这些值,然后把这些值赋值到对应的表现形式里面。 5:还有一些比较特殊,也就是真实操作的是一类值,但是在界面上显示的是另一类值,比如:数据库中有用户编号,到了界面上就得显示用户姓名,但是所 有的操作都是要操作用户编号的。我们把这种情况分做:真实值和表现值,他们有一定的内在联系。这些都是要开发人员去转化和维护的。 6:接下来就应该开发功能性的事件响应了。用户点击了某个按钮或者触发了某个事件,首先是客户端:数据检测、客户端事件处理;然后提交到服务端,服务端要获取到客户端提交的数据,然后调用相应的逻辑层接口来响应。当然如何写逻辑层的实现这里就不去谈论了。 7:逻辑层执行完过后,返回数据和信息到Web层,开发人员还需要写代码去处理,选择哪个页面来显示,如何显示这些数据和信息等。 8:在整个交互的过程中,还必须考虑到如何控制权限,如:某些数据不能显示,某些数据不能编辑等等;同样还需要考虑到消息的配置和国际化等等。这些功能起源于逻辑层,但是实际的控制要到Web层,这些都需要开发人员来控制。 9:完成了上面的开发步骤,页面基本的功能开发就告一段落,接下来开发人员需要考虑页面美观的问题了。大家可能会说:“不是有美工吗,还需要开发人 员干什么?”。事实上美工多半只能出一个静态页面的美化模版,美工对于一推Java代码和Html的混杂物,多半是没有办法的,更不要说还有一些内容是动 态生成的,美工就更不可能搞定了。还是得开发人员上阵,按照美工给的模版,开始添加Css:class、id、style…… 10:完成上面的开发,基本页面的开发工作就完成了,最后的一个步骤就是把各个页面有机的组织起来,开发应用程序的整体应用导航框架,通常就是菜单,然后把各个功能页面跟菜单结合起来,形成一个完整的应用。 原文链接:http://www.uileader.com/news/news_content_88.html?id=88
-
本帖最后由 coding 于 2017-10-27 16:37 编辑 很幸运地能收到网易的面试通知,就毫不犹豫翘了课去面试了hhhh~三点的面试,因为从来没去过那个中关村西北旺区,吃完饭早早就去了,想象中那里应该是繁华的地方hhhh,到了发现都在建设中,很多还在建设中,看到了网易旁边的百度和搜狐,都是长长的大楼或者是高高的建筑,满满大企业的既视感~一进网易楼就没网= =,在里面也没事干,就呆在外面看看前端的东西准备下,到2点40的时候跟前台说了下,一个网易年轻姐姐就带我上去了~ 步入正题-笔试 本来我以为只有面试的,发现那个姐姐并不是带我去面试的,带我去了个房间,留了两张题目给我,说半小时来说,毫无防备hhh接下来步入正题吧~ 1.alert(1&&2),alert(1||0) 具体我不记得了反正就这两个,我以为考的是纯粹的与运算和或运算,后来发现太天真了 3902 2.mouseenter和mouseover的区别 这个之前看了下,大概是答出来了,但可能不够详细吧 3903 3.用正则表达式匹配字符串,以字母开头,后面是数字、字符串或者下划线,长度为9-20 看到这题我是崩溃的,因为正则学的不多,但是稍微写了下也差不多只是忘了些 3904 4.js字符串两边截取空白的trim的原型方法的实现 3905 5.三道判断输出的题都是经典的题 39066.写出position不同值和区别 突然想到还有inherit,当时忘记了,后来面试的时候又重新问了我一下 [*]absolute: 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。(不占位) [*]relative: 生成相对定位的元素,相对于其正常位置进行定位。因此,”left:20” 会向元素的 LEFT 位置添加 20 像素。(占位) [*]static:默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)inherit:规定应该从父元素继承 position 属性的值。 [*]fixed:生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。 7.写一个div+css布局,左边图片右边文字,文字环绕图片,外面容器固定宽度,文字不固定(这是后来根据面试官描述的,笔试题上只有图我就不放上来了) 这道题我没答好,刚开始我不清楚那个文字是要自适应的面试官说用p标签包裹文字,我当时就紧张了下,把p标签错当成内联了,然后我再修正,然后加左浮动,然后不行,我就跟面试官说,我以前都直接就一个img它float:left,加文字不加p标签就好了然后我回来试一试才发现= =,直接加p标签就可以了啊= =,omg我的错误!!! 8.讲述你对reflow和repaint的理解 这个真不会了没接触,第一个我猜是重新布局,第二个倒是见过就是重绘,就想到document.write(),这个后来也没再问我了查查查 repaint就是重绘,reflow就是回流。repaint主要是针对某一个DOM元素进行的重绘,reflow则是回流,针对整个页面的重排 严重性: 在性能优先的前提下,性能消耗 reflow大于repaint。 体现: repaint是某个DOM元素进行重绘;reflow是整个页面进行重排,也就是页面所有DOM元素渲染。(web前端学习交流群:328058344 禁止闲聊,非喜勿进!) 如何触发: style变动造成repaint和reflow。不涉及任何DOM元素的排版问题的变动为repaint,例如元素的color/text-align/text-decoration等等属性的变动。除上面所提到的DOM元素style的修改基本为reflow。例如元素的任何涉及长、宽、行高、边框、display等style的修改。 常见触发场景: 触发repaint: 3907 触发reflow: 3908 如何避免: 尽可能在DOM末梢通过改变class来修改元素的style属性:尽可能的减少受影响的DOM元素。 避免设置多项内联样式:使用常用的class的方式进行设置样式,以避免设置样式时访问DOM的低效率。 设置动画元素position属性为fixed或者absolute:由于当前元素从DOM流中独立出来,因此受影响的只有当前元素,元素repaint。 牺牲平滑度满足性能:动画精度太强,会造成更多次的repaint/reflow,牺牲精度,能满足性能的损耗,获取性能和平滑度的平衡。 避免使用table进行布局:table的每个元素的大小以及内容的改动,都会导致整个table进行重新计算,造成大幅度的repaint或者reflow。改用div则可以进行针对性的repaint和避免不必要的reflow。 避免在CSS中使用运算式:学习CSS的时候就知道,这个应该避免,不应该加深到这一层再去了解,因为这个的后果确实非常严重,一旦存在动画性的repaint/reflow,那么每一帧动画都会进行计算,性能消耗不容小觑。 面试部分 半小时写完笔试后,等待面试,中途遇到了北邮的师兄聊了一些nodejs的东西步入正题面试 [*]什么时候开始学前端 [*]如何学前端 [*]看过谁的博客 [*]开始看我的简历问了,问项目,问webpack/gulp区别,问项目如何实现什么的,再问了笔试题(上面讲过了) [*]等等等都问的项目 基本也就这些,面试官人挺好的,感觉没什么压力~最后也让我过了吧,就后面暑假放假再去联系~说我还得多去看看基础的东西~确实基础还不够扎实哈,不过总的来说,这人生第一次面试还挺顺利的说,也是运气好吧~希望学校早放假能去实习一番~
-
本帖最后由 那个逻辑先生 于 2017-10-17 11:28 编辑人与人之间最重要的是信任,但程序的世界里,可能信任越少越好;我越发觉得越是高性能高可用的系统里,不信任原则会体现得更加淋漓尽致。 为了少走弯路,写下这篇文章留给自己参考,其中一些是自己踩过的一些坑;一些是接手他人系统时触过的雷;还有一些是从别人分享的经验学习得来;能力有限,先记下自己的一些体会,错误的地方再慢慢改正。 3032 编程的世界里十面埋伏 编程,是一件容易的事,也是一件不容易的事。说它容易,是因为掌握一些基本的数据类型和条件语句,就可以实现复杂的逻辑;说它不容易,是因为高性能高可用的代码,需要了解的知识有很多很多。 编程的世界,也跟扫雷游戏的世界一样,充满雷区,十面埋伏,一不小心,随时都可能踩雷,随时都可能 Game Over。 而玩过扫雷的人都知道,避免踩雷的最好方法,就是提前识别雷区并做标记(设防)避免踩踏。 鉴于此,编程的世界里,从输入到输出同样需要处处设防,步步为营。 01对输入的不信任 对空指针的检查 不只是输入,只要是使用到指针的地方,都应该先判断指针是否为 NULL,而内存释放后,应当将指针设置为 NULL。 【真实案例】:注册系统某段逻辑,正常使用情况下,都有对指针做检查,在某个错误分支,打印日志时,没检查就使用了该字符串;结果可正常运行,但当访问某个依赖模块超时走到该分支,触发 Bug,导致 coredump。 对数据长度的检查 使用字符串或某段 buf,特别是 memcpy / strcpy 时,需要尽量对数据长度做下检查和截断。 【真实案例】:接手 oauth 系统后运行数月表现良好,突然有一天,发生了 coredump,经查,是某个业务不按规定,请求包中填写了超长长度,导致 memcpy 时发生段错误,根本原因还是没有做好长度检查。 对数据内容的检查 某些场景下,没有对数据内容做检查就直接使用,可能导致意想不到的结果。 【真实案例】:SQL 注入和 XSS 攻击都是利用了服务端没有对数据内容做检查的漏洞。 02对输出(变更)的不信任 变更的影响一般体现在输出,有时候输出的结果并不能简单的判断是否正常,如输出是加密信息,或者输出的内容过于复杂。 所以,对于每次变更: 修改代码时,采用不信任编码,正确的不一定是“对”的,再小的修改也应确认其对后续逻辑的影响,有些修正可能改变原来错误时的输出,而输出的改变,就会影响到依赖该改变字段的业务。 发布前,应该对涉及到的场景进行测试和验证,测试可以有效的发现潜在的问题,这是众所周知的。 发布过程,应该采用灰度发布策略,因为测试并非总是能发现问题,灰度发布,可以减少事故影响的范围。常见灰度发布的策略有机器灰度、IP灰度、用户灰度、按比例灰度等,各有优缺点,需要根据具体场景选择,甚至可以同时采用多种的组合。 发布后,全面监控是有效发现问题的一种方法。因为测试环境和正式环境可能存在不一致的地方,也可能测试不够完整,导致上线后有问题。 所以需采取措施进行补救: [*]如使用 Monitor 监控请求量、成功量、失败量、关键节点等。 [*]使用 DLP 告警监控成功率。 [*]发布完,在正式环境测试一遍。 【真实案例】:oauth 系统某次修改后编译时,发现有个修改不相关的局部变量未初始化的告警,出于习惯对变量进行了初始化(初始化值和编译器默认赋值不一样),而包头某个字段采用了该未初始化的变量,但在测试用例中未能体现,监控也没细化到每个字段的值,导致测试正常,监控正常;但前端业务齐齐互动使用了该包头字段,导致发布后影响该业务。 服务程序的世界里防不胜防 一般的系统,都会有上下游的存在,如下图所示: 3033 而上下游的整个链路中,每个点都是不能保证绝对可靠的,任何一个点都可能随时发生故障,让你措手不及。因此,不能信任整个链路中的任何一个点,需进行设防。 01对服务本身的不信任 主要措施如下: [*]服务监控。前面所述的请求量、成功量、失败量、关键节点、成功率的监控,都是对服务环节的单点监控。在此基础上,可以加上自动化测试,自动化测试可以模拟应用场景,实现对流程的监控。 [*]进程秒起。人可能在程序世界里是不可靠的因素(大牛除外),前面的措施,多是依赖人来保证的;所以,coredump 还是有可能发生的,这时,进程秒起的实现,就可以有效减少 coredump 的影响,继续对外提供服务。 02对依赖系统的不信任 可采用柔性可用策略,根据模块的不可或缺性,区分关键路径和非关键路径,并采取不同的策略: 对于非关键路径,采用柔性放过策略。当访问非关键路径超时时,简单的可采取有限制(一定数量、一定比重)的重试,结果超时则跳过该逻辑,进行下一步;复杂一点的统计一下超时的比例,当比例过高时,则跳过该逻辑,进行下一步。 对于关键路径,提供弱化服务的柔性策略。关键路径是不可或缺的服务,不能跳过;某些场景,可以根据目的,在关键路径严重不可用时,提供弱化版的服务。 举例如派票系统访问票据存储信息严重不可用时,可提供不依赖于存储的纯算法票据,为弥补安全性的缺失,可采取缩短票据有效期等措施。 03对请求的不信任 对请求来源的不信任,有利可图的地方,就会有黑产时刻盯着,伪造各种请求,对此,可采取如下措施: [*]权限控制。如 IP 鉴权、模块鉴权、白名单、用户登录态校验等。 [*]安全审计。权限控制仅能打击一下非正常流程的请求,但坏人经常能够成功模拟用户正常使用的场景;所以,对于一些重要场景,需要加入安全策略,打击如 IP、号码等信息聚集,频率过快等机器行为,请求重放、劫持等。 对请求量的不信任,前端的请求,不总是平稳的;有活动时,会暴涨;前端业务故障恢复后,也可能暴涨;前端遭到恶意攻击时,也可能暴涨;一旦请求量超过系统负载,将会发生雪崩,最终导致整个服务不可用。 对此种种突发情况,后端服务需要有应对措施: [*]频率限制,控制各个业务的最大请求量(业务根据正常请求峰值的2-3倍申请,该值可修改),避免因一个业务暴涨影响所有业务的情况发生。 [*]过载保护,虽然有频率限制,但业务过多时,依然有可能某个时间点,所有的请求超过了系统负载,或者到某个 IDC,某台机器的请求超过负载。 为避免这种情况下发生雪崩,将超过一定时间的请求丢弃,仅处理部分有效的请求,使得系统对外表现为部分可用,而非完全不可用。 运营的世界里不可预测303101对机器的不信任 机器故障时有发生,如果服务存在单点问题,故障时,则服务将完全不可用,而依赖人工的恢复是不可预期的。对此,可通过以下措施解决: 容灾部署。即至少有两台以上的机器可以随时对外提供服务。 心跳探测。用于监控机器是否可用,当机器不可用时,若涉及到主备机器的,应做好主备机器的自动切换;若不涉及到主备的,禁用故障机器对外提供服务即可。 02对机房的不信任 现实生活中,整个机房不可用也是有发生过的,如 2015 年的天津滨海新区爆炸事故,导致腾讯在天津的多个机房不能对外提供正常服务,对此采取的措施有: [*]异地部署。不同 IDC、不同城市、不同国家等部署,可以避免整个机房不可用时,有其他机房的机器可以对外提供服务。 [*]容量冗余。对于类似 QQ 登陆这种入口型的系统,必须保持两倍以上的冗余;如此,可以保证当有一个机房故障时,所有请求迁移到其他机房,不会引发系统过载。 03对电力的不信任 虽然我们越来越离不开电力,但电力却不能保证一直为我们提供服务。断电时,其影响和机器故障、机房故障类似,机器会关机,数据会丢失。所以,需要对数据进行备份: [*]磁盘备份。来电后,机器重启,可以从磁盘中恢复数据,但可能会有部分数据丢失。 [*]远程备份。机器磁盘坏了,磁盘的数据会丢失。对于重要系统,相关数据应当考虑采用远程备份。 04对网络的不信任 不同地方,网络时延不一样,一般来说,本地就近的机器,时延要好于异地的机器,所以,比较简单的做法就是近寻址,如 CMLB。 也有部分情况,是异地服务的时延要好于本地服务的时延,所以,如果要做到较好的最优路径寻址,就需要先做网络探测,如 Q 调。 常有网络有波动或不可用情况出现,和机器故障一样处理,应当做到自动禁用;但网络故障和机器故障又不一样,经常存在某台机器不可用。 但别的机器可以访问的情况,这时就不能在服务端禁用机器了,而应当采用本地回包统计策略,自动禁用服务差的机器;同时需配合定时探测禁用机器策略,自动恢复可正常提供服务的机器。 05对人的不信任 人的因素在运营的世界里也是不稳定的因素(大牛除外)。所以,不能对人的操作有过多的信任: 操作备份。每一步操作都有记录,便于发生问题时的回溯,重要的操作需要 review,避免个人考虑不周导致事故。 效果确认。实际环境往往和测试环境会存在一些差异,所有在正式环境做变更后,应通过视图 review 和验证来确认是否符合预期。 变更可回滚。操作前需对旧程序、旧配置等做好备份,以便发生故障时,及时恢复服务。 自动化部署。机器的部署,可能有一堆复杂的流程,如各种权限申请,各种客户端安装等,仅靠文档流程操作加上测试验证是不够的。可能某次部署漏了某个步骤而测试又没测到,上线后就可能发生事故,若能所有流程实现自动化,则可有效避免这类问题。 一致性检查。现网的发布可能因某个节点没同步导致漏发,也就是不同的机器服务不一样;对此,有版本号的,可通过版本号监控发现;没版本号的,则需借助进程、配置等的一致性检查来发现问题。 备注:以上提到的不信任策略,有的不能简单的单条使用,需要结合其他的措施一起使用。 最重要的还是那句话,程序的世界里,应该坚持不信任原则,处处设防。 作者:佚名 来源:tencent
-
本帖最后由 码小玩 于 2017-10-9 17:18 编辑[color=rgb(51,51,51)]摘要:Facebook 高速发展的 2007 年到 2016 年,他们一天部署 3 次代码,cherry-pick 集齐成千上万个 commit;现在使用类似持续交付的方法,每个 commit 能自动部署到 production。公司里有很多员工、很多用户的好处:新代码让公司所有员工先用上,因为员工数足够多,能很快发现问题;然后让 2% 的访问量用上新代码,最后慢慢增加到 100% 的访问量。[color=rgb(51,51,51)]不久前有篇关于缩短 Facebook 发布流程的文章,阐述了将代码投入生产的灵活方法。这篇文章着重讲述了他们在一年之内如何从“ cherry-picking ”升级到“ push-from-master ”策略。早些时候, Facebook 也分享了他们部署过程的细节。作者 Chuck Rossi 是 Facebook 的首位发布工程师,目前是 Facebook 发布工程的工程总监。[color=rgb(51,51,51)]Facebook 的发布周期是“ quasi-continuous ” (准连续)——这只是一种委婉的说法,表明并非每次提交都会部署到生产环境,实际上它采用的是对几十到几百个提交进行批处理,每隔几个小时就进行推送。这种分层发布的方式使任何变更的回滚很容易。[color=rgb(51,51,51)]这个新系统从 2016 年 4 月开始,经过一年的时间慢慢地完善。早先的模式是从主干分支的提交中选择特定的变更放到发布分支上。发布分支每天将这些变更推送到生产环境。这种“ cherry-picking ”的特点是,每天选择变更的数量为 500 ~ 1000。剩下的变更就推入到每周发布分支中。随着时间的推移,提交的数量和参与其中的工程师都有所增加,发布工程师的手工劳动变得过多,以至于无法持续。[color=rgb(51,51,51)]这个 CD 系统的关键组件是一种控制方法,即谁将接收变更,以及用于部署和测量的自动化工具。在第一步中,经过一系列自动化测试后,变更就从内部推送到 Facebook 员工。在这一阶段发现的任何回归,都会被认为这一进程受阻或者停止。下一步涉及到“ canary deployment ”(金丝雀部署),只推送至生产环境的 2% 。依靠连续的监测来检测问题。如果一切顺利,这些变更将 100% 部署到生产环境中。名为 Flytrap 的工具收集用户报告,并发送任何异常情况的告警。[color=rgb(51,51,51)][color=rgb(51,51,51)][color=rgb(51,51,51)]Facebook 中的 Web 和移动产品遵循两条不同的路径,原生移动变更的部署频率低于 Web 。这两个都由名为 Gatekeeper 的系统控制。除此之外,Gatekeeper 还分离出了部署和发布。这种分离带来了挑战,包括维护向下兼容性。[color=rgb(51,51,51)]由于工具和部署选项的性质,移动持续部署面临着一些特定的挑战。Web 部署则更为容易,因为 Facebook 拥有完整的技术栈和工具。为了解决这些挑战,Facebook 已经构建了一些专注于更快的移动开发的工具和库,包括 Buck 、Phabricator、 Infer、 React 以及 Nuclide 。Facebook 的移动部署是以三层来并发运行。[*][color=rgb(51,51,51)]构建:合并到移动主分支上的所有代码都会进行构建,这会针对受影响的所有产品(Instagram、Messenger)并且会跨各种芯片架构。[*][color=rgb(51,51,51)]静态代码分析:Linters 和静态分析工具的组合,称为 Infer ,用于检查各种问题,包括资源泄漏、未使用的变量、有风险的系统调用和编码准则违规。[*][color=rgb(51,51,51)]自动测试:包括单元、集成和端到端测试,会使用到 Roboelectric、XCTest、JUnit 和 WebDriver 等工具。[color=rgb(51,51,51)]在代码变更的生命周期内,每次提交都会执行移动构建并运行测试栈,这样就会运行很多次。单单 Android 一天就有 5 万到 6 万个构建版本。移动部署系统遵循较早的基于 Web 的模式,每周发布一次,按 cherry-picking 策略随机选择变更。尽管代码传输速度和发布频率有所增长,但工程师的生产率保持不变。然而,本文提到的标准(代码行和推送次数),可能并非衡量生产率的最佳标准。[color=rgb(51,51,51)]据 2016 年 IEEE 的论文和相关讨论,Facebook 早在 2005 年就利用了某种形式的 CD。该论文中的一些结论列出了 CD 成功的先决条件:可观的持续投资、高度熟练的开发人员、强大的技术管理,开放和平等的文化,风险回报权衡管理、客观回顾失败以及有专注力的小团队。[color=rgb(51,51,51)]Facebook 的准连续部署系统具备这几个优点:没有推送热补丁的手工开销,对分布式工程师团队有更好的支持,为工程师提供了更快的反馈循环。[color=rgb(51,51,51)]查看英文原文:[color=rgb(255,66,0)]How Facebook Achieves Rapid Release at Massive Scale[color=rgb(51,51,51)][color=rgb(255,66,0)][color=rgb(51,51,51)]译者:sambodhi
-
例如:输入ni haohttps://s.geekbang.orghello world页面将会展示[indent]ni haohttps://www.a.com/bcd/e?a=1&c=2hello world[/indent]就如同 SegmentFault 提问编辑器中具有功能一样。请问是怎么做到的?
-
在登录之后,前端获取后端的token,然后存在localStorage里面,在需要token的api请求中加上token,但是token存在localStorage里面这样是不是非常不安全?用户可以打开浏览器直接查看ajax请求看到token或者查看存储可以看到token,如果token被盗取呢?这样的安全问题怎么解决呢?
-
本帖最后由 达康书记 于 2017-9-23 16:13 编辑不同人对noVNC窗口大小有不同的诉求,笔者教大家如何自己调整,高手飘过,请轻拍砖。 华为云Windows服务器Web VNC的窗口大小取决于系统的分辨率,Windows可以在操作系统内部调整分辨率来改变窗口的大小。 可选择:800*600像素,1024*768像素(推荐使用),1280*1024像素 2263 2264
-
本帖最后由 达康书记 于 2017-9-23 16:13 编辑不同人对noVNC窗口大小有不同的诉求,笔者教大家如何自己调整,高手飘过,请轻拍砖。 管理控制台终端Web VNC窗口大小实际是由系统设置的分辨率相关,Linux系统控制分辨率需要将vga参数传递到kernel中。 通过VGA启动参数来设置屏幕分辨率模式: [code] Mode 0x0317: 1024x768 (+2048), 16 bits Mode 0x0318: 1024x768 (+4096), 24 bits --------推荐使用 Mode 0x0314: 800x600 (+1600), 16 bits Mode 0x0315: 800x600 (+3200), 24 bits Mode 0x0311: 640x480 (+1280), 16 bits Mode 0x0312: 640x480 (+2560), 24 bits[/code]修改VNC窗口大小方法如下: 编辑文件/boot/grub/grub.conf,在kernel的最后一行加入:vga=0x0318 (代表1024x768,24色) [code]default=0 timeout=5 splashimage=(hd0,1)/boot/grub/splash.xpm.gz hiddenmenu title CentOS (2.6.32-696.6.3.el6.x86_64) root (hd0,1) kernel /boot/vmlinuz-2.6.32-696.6.3.el6.x86_64 ro root=UUID=f382872b-eda6-43df-9516-5a687fecdce6 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM vga=0x0318 rhgb quiet initrd /boot/initramfs-2.6.32-696.6.3.el6.x86_64.img [/code]输入命令:vi /boot/grub/grub.conf,然后在窗口中编辑。修改后保存,重启服务器后生效。 2262
-
本文来源知乎网由于我们为我们的客户创造开源软件、开发很多应用并改进他们的质量,我们一直在寻找能提高我们所开发的软件质量的东西。部分工作是在盯着一些让我们眼花的提议和新兴的标准,从而找到高效可用的部分。在这里,我们将探索已经开始使用的或者在将来工作中考虑用到的五个新兴的web标准。CSS变量/自定义属性在过去的十多年里,web工程师一直在用变量来创建和管理复杂的CSS系统,他们仍然是驱动对CSS预处理器产生需求的主要特性的一种,像Sass、less、Stylus。用得好的话,通过规范所有用来描述颜色、文字、边距等的值,他们能极大地增强大型代码库的可维护性。随着时间的推移,预处理器变量已经随着设计或习惯融合了一系列可共享的特性。 [*]有前缀:例如,为了防止与已有的CSS关键词冲突的 $或 @ [*]有作用域:在.container中可以用.container > .child访问$bgColor,但反过来就不成立了。 [*]可以被重写: $bgColor: blue;.container { $bgColor: red; background-color: $bgColor; /* will be red */} 原生的CSS变量(或“自定义属性”)采用了所有这些约定,这使得转换成原生的支持简单直观。CSS变量必须以两个破折号为前缀:--,他们的作用域为定义的选择器内,可以被后代继承,可能在后代中被重写。例如::root { --bgColor: periwinkle;}.container { background-color: var(--bgColor); /* will be periwinkle */}.container .child { --bgColor: lime; background-color: var(--bgColor); /* will be lime */} 在这个例子里,CSS变量和预处理器变量之间有一些明显的差异: [*]CSS变量在使用的时候必须被var()包裹 [*]--前缀与已有的预处理器使用的任何其他前缀都不一样,因此能一起使用。 [*]CSS变量必须在选择器内定义,所以最接近“全局”作用域是:root [*]预处理器不知道DOM,因此靠嵌套来实现继承。CSS变量的值继承自DOM树,这一点跟普通CSS变量的继承方式一样。 预处理器变量和CSS变量之间另一个显著差异在上文的代码中并不明显:因为它们没有被编译成静态值,CSS变量可能在浏览器运行的时候被更新。这意味着CSS变量可以在Javascript代码里读写,用来做计算或是动画。以下的Codepen示例示范了怎么样用CSS变量和Javascript来创建手风琴动画。codepen例子CSS变量能被 Firefox, Chrome, 和 Safari支持,当前版本的Edge部分支持: http://caniuse.com/#feat=css-variablesCSS模块化变量并不是唯一一种Javascript渗透到CSS的概念。特别是在近几年,Javascript开发者已经把目光转向CSS组织,在Atwood’s Law(阿特伍德定律,即:任何可以用JavaScript来写的应用,最终都将用JavaScript来写)的延伸上思考着“我能做的更好”。这里有一些好的理由可以证明: [*]不像JavaScript,CSS类名在全局的命名空间一直存在 [*]在大型的编译过的样式中解决冲突是靠不住的,并且容易产生意想不到的行为,或是仅仅通过增加权重解决 [*]样式透过DOM层级,能够用出人意料的方式改变子元素的样式 [*]用Javascript来管理CSS允许CSS规则以运行逻辑为基础 React在这种思路上尤其前卫,被Javascript控制的行内样式可以当做这些问题的答案。(可能不是样式渗透子元素,但是确实减少了一定数量的这种样式冲突的案例)。然而,它也有自己的一些缺点: [*]伪类(如: :hover或 :focus)在CSS很容易实现,但在Javascript必须被伪造 [*]在Javascript中重新实现媒体查询是劳动密集工作 [*]内联样式失去了被更高权重覆盖的能力,因为它们已经处于权重层次结构的顶端。 [*]在动态样式上切换类名、Css变量、函数(像 calc())已经解决了大多数难题 [*]性能:DOM数量是一方面,CSS能被缓存 CSS模块化,在某些方面来说是CSS开发者回归到被Javascript开发者侵入的地盘:是一种解决批评和改进样式表而不会完全消除它们的方法。CSS模块本质上归结为可以引入JavaScript的局部作用域的CSS文件,并编译成唯一的类名。例如,这里:JavaScript:import * as css from ‘css/buttonComponent.css’;const buttonHTML = `${buttonText}`; CSS:.root { background-color: #ffffff; color: blue; border: 1px solid blue;} 将会被编译成以下内容:HTML:="buttonComponent_root_**2718"[/color>Button with modular CSS CSS:.root { background-color: #ffffff; color: blue; border: 1px solid blue;} 因为 buttonComponent.css里的类是局部作用域的,并且在一个命名清晰的CSS文件中,所以就不再需要特定的类名了例如 .button。相反,推荐的格式是使用单个标准化的“根”类名称,如 .root或 .normal,然后使用特定状态的类名,如 .error, .success或 .disabled,所有这些类名可能在一定条件下应用于JavaScript 。CSS模块化还通过弱化写多个类名并使用composes解决样式容易覆盖的问题。composes关键字类似于Sass的 @extends的预处理器装饰器,除了在CSS中编译样式之外,composes以可预见的顺序返回多个命名空间的类名。例如:CSS:.root { display: inline-block; padding: 10px; color: blue;}.success { composes: root; color: green;} JavaScript:import * as css from 'css/buttonComponent.css';// css.success = 'buttonComponent_root_**2718 buttonComponent_success_pi3141'const buttonHTML = `${buttonText}`; HTML:="buttonComponent_root_**2718 buttonComponent_success_pi3141"[/color>Button with green text CSS也有一种更强的工具来增强样式的模块化: all关键词,与CSS模块化区分,能用来重置所有的属性到最原始的状态,例如.root { all: initial; }。因为这是一个新的CSS属性而不是依赖于webpack或Browserify编译器的类型,IE和Edge仍然缺少支持度。Async/Await/能让你的代码变得很棒随着越来越多的成功和偶尔(捕获)的错误,JavaScript用Promise来改进异步代码的处理。在promise出现以前,一个回调可能看起来像下面的嵌套末日: doAsyncFunction(function(result) { doSecondAsyncFunction(result, function(resultTwo) { doThirdAsyncFunction(resultTwo, function(resultThree) { // and so on… }, catchError); }, catchError);}, catchError); 以上代码用promise能被转换成链式顺序,用.then()完成请求回调,用.catch()结束:doAsyncFunction() .then(result => doSecondAsyncFunction(result)) .then(resultTwo => doThirdAsyncFunction(resultTwo)) // and so on… .catch(catchError); 跟早期金字塔形的传入回调和错误处理相比,这种链式语法显然更干净清晰,更容易理解。使用 async函数,开发人员不必等到写异步代码像同步代码一样直观的那天。使用async / await的初始示例如下所示:(async function() { try { const result = await doAsyncFunction(); const resultTwo = await doSecondAsyncFunction(result); const resultThree = await doThirdAsyncFunction(resultTwo); return resultThree; } catch(error) { catchError(error); }})(); 每个await将会中断代码的执行,直到它的promise成功回调,整段代码被包含在try/catch块内,就像同步代码一样。要记住的最重要的点:await可能只用在async 方法里作为特定的关键词,async方法本身还是异步的,不会阻塞周围的代码运行。这个三个promise的例子显示三个promise进程如何能够被逐个执行,Promise.all和Promise.race能与async/await同时运行:async function doAsyncStuff() { const [resultOne, resultTwo, resultThree] = await Promise.all([ doAsyncFunction(), doSecondAsyncFunction(), doThirdAsyncFunction() ]); // do stuff with resultOne, resultTwo, and resultThree} 在技术上,await甚至不需要通过promise,因为它将在Promise.resolve中包含任何非promise的值。任何promise解决方案都会被push到调用堆栈的末尾,这个事实可能会导致一些稍微奇怪但有趣的结果: async function getAnswer() { const answer = await 42; console.log(`The answer to life, the universe, and everything is ${answer}`);}getAnswer();console.log(‘Vogons blow up Earth’);// will log:// “Vogons blow up Earth”// The answer to life, the universe, and everything is 42 阻塞元素 / 惰性元素对于任何需要创建模态框并关注可访问性的开发人员来说,管理焦点一直是并且仍然是一个难以解决的问题。焦点应该从不被放到隐藏或是挡住的DOM元素,但做出合适的行为是痛苦而密集的。两个基本的监听聚焦事件选项,当人们尝试离开模态框,或是通过设置tabindex="-1"来实现手动移除所有聚焦中的非模态框元素。这两种解决方法通常以使用大型而脆弱的DOM查询来在代码里监听焦点元素结束。document.querySelectorAll('a[href], button:not([disabled]), area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]); 即使焦点已经被处理,隐藏的部分应该将aria-hidden设置为true,因此它不会被屏幕阅读器等辅助技术所读取。两个规范提案建议将从整体上解决模态问题:inert和blockingElements。首先,HTML属性inert,将会从关注的顺序里移除一段DOM树(好像所有可聚焦的元素都接受tabindex="-1"),并从辅助技术隐藏。blockingElements将几乎完全相反:暴露一堆“blocking elements”,这将有效地使所有其他DOM树变得惰性。例如,如果我有以下DOM结构:="content"[/color>="modal"[/color> Modal contentcolor> Other content, including linksbuttons/etc="sidebar"[/color>为了打开这个对话框,我将移除inert属性,并调用document.$blockingElements.push(document.querySelector('.modal')),这将渲染成不仅仅是直接的兄弟树inert,而且是父级和组先级的兄弟inert。inert和blockingElements仍然是提案,所以在任何当前的浏览器中都不是本地支持的。然而,有可用的polyfills可以使用它们现在使用: https://github.com/WICG/inert 和 https://github.com/PolymerLabs/blockingElements交叉观察器观察元素滚动到视口内一直都是滚动插件开发的内容,这些插件使用一些滚动事件监听(希望能节流)。现在,交叉观察器允许开发者用一些选项和回调来创建一个观察器来观察元素滚动到视口内,这仅仅用vanilla JavaScript就可以实现。IntersectionObserver与其他DOM观察很像(像MutationObserver),在这里,你可以用一个回调和选项来创建,然后在一个DOM元素上调用.observe。每当元素与视口的交叉距离增加10%时,简单实现更新可以如下所示:const observerOptions = { root: null, rootMargin: '0px' threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]};function intersectionCallback(entries) { entries.forEach((entry) => { const percent = Math.floor(entry.intersectionRatio * 100); console.log(`Element ${entry.target} scrolled ${percent}% into view`); });}const observer = new IntersectionObserver(intersectionCallback, observerOptions);observer.observe(myElement); 对象由以下属性组成: [*]root:包含滚动区域的元素(如果空着,默认为文档的视口viewport) [*]rootMargin:在根元素周围能够增加或收缩,用来计算临界点 [*]threshold:一组数字格式,表示回调应该触发的目标元素的可见性的百分比。例如[0,0.5,1],将在元素滚动过0%,50%、100%可见区域时触发。 为了停止观察特定元素——如果回调仅仅在元素第一次滚动的时候才需要,或是,它需要被用来观察大量元素滚动进入或退出视窗,只需要调用observer.unobserve(myElement);。断开整个观察,执行observer.disconnect();。在IntersectionObserver,一个使用unobserve()的好的案例是懒加载图片脚本,这个脚本在滚屏时用到。 function onImageIntersect(entries) { entries.forEach(entry => { entry.target.src = imageSource; observer.unobserve(entry.target); }}document.querySelectorAll('img').forEach(img => observer.observe(img)); 浏览器仍然在慢慢渐渐给出支持,但它不用polyfill就已经可以用在Chrome, Firefox和 Edge了。IE和Safari现在还缺少原生的支持。
-
本文来源前端大全这是一个经典的技术争论,许多人都会自问:URL、URI,很可能还有URN,它们之间的区别是什么。虽然,现在我们简单地把 URN 和 URL 都看做 URI,但严格来说URI可以进一步划分为URL、URN或者这两者的组合,所以了解这三者之间的区别将会非常有趣并让人受益匪浅。如果你恰好在某个地方碰到了这些东西,那么至少应该知道它们的含义。我认为,尽管对一般人来说,不了解这三个缩略词之间的技术差异以及它们各自的含义并不是什么问题。但是,如果你作为一个计算机科学家、一个Web开发者、一个系统管理员,或者更笼统地说,你工作在IT领域,那么了解这些知识就非常有必要了。这篇文章旨在于清楚地讲解URL、URI和URN之间的区别,帮助你快速理解这些必备知识。你是不是对这个话题也感到困惑?那么我们开始吧!起源这三个缩略词是Tim Berners-Lee在一篇名为RFC 3986: Uniform Resource Identifier (URI): Generic Syntax的文档中定义的互联网标准追踪协议。引文:统一资源标识符(URI)提供了一个简单、可扩展的资源标识方式。URI规范中的语义和语法来源于万维网全球信息主动引入的概念,万维网从1990年起使用这种标识符数据,并被描述为“万维网中的统一资源描述符”。Tim Berners-Lee ,万维网的发明者,同时也是万维网联盟(W3C)的负责人。照片由 Paul Clarke 遵循CC BY-SA 4.0 协议提供。区别首先我们要弄清楚一件事:URL和URN都是URI的子集。换言之,URL和URN都是URI,但是URI不一定是URL或者URN。为了更好的理解这个概念,看下面这张图片。通过下面的例子(源自 Wikipedia),我们可以很好地理解URN 和 URL之间的区别。如果是一个人,我们会想到他的姓名和住址。URL类似于住址,它告诉你一种寻找目标的方式(在这个例子中,是通过街道地址找到一个人)。要知道,上述定义同时也是一个URI。相对地,我们可以把一个人的名字看作是URN;因此可以用URN来唯一标识一个实体。由于可能存在同名(姓氏也相同)的情况,所以更准确地说,人名这个例子并不是十分恰当。更为恰当的是书籍的ISBN码和产品在系统内的序列号,尽管没有告诉你用什么方式或者到什么地方去找到目标,但是你有足够的信息来检索到它。引自这篇文章:所有的URN都遵循如下语法(引号内的短语是必须的):URN > ::= "urn:" NID > ":" NSS >其中NID是命名空间标识符,NSS是标识命名空间的特定字符串。一个用于理解这三者的例子我们来看一下上述概念如何应用于与我们息息相关的互联网。再次引用Wikipedia ,这些引文给出的解释,比上面人员地址的例子更为专业:关于URL:URL是URI的一种,不仅标识了Web 资源,还指定了操作或者获取方式,同时指出了主要访问机制和网络位置。关于URN:URN是URI的一种,用特定命名空间的名字标识资源。使用URN可以在不知道其网络位置及访问方式的情况下讨论资源。现在,如果到Web上去看一下,你会找出很多例子,这比其他东西更容易让人困惑。我只展示一个例子,非常简单清楚地告诉你在互联网中URI 、URL和URN之间的不同。我们一起来看下面这个虚构的例子。这是一个URI:http://bitpoetry.io/posts/hello.html#intro我们开始分析http://是定义如何访问资源的方式。另外bitpoetry.io/posts/hello.html是资源存放的位置,那么,在这个例子中,#intro是资源。URL是URI的一个子集,告诉我们访问网络位置的方式。在我们的例子中,URL应该如下所示:http://bitpoetry.io/posts/hello.htmlURN是URI的子集,包括名字(给定的命名空间内),但是不包括访问方式,如下所示:bitpoetry.io/posts/hello.html#intro就是这样。现在你应该能够辨别出URL和URN之间的不同。如果你忘记了这篇文章的内容,至少要记住一件事:URI可以被分为URL、URN或两者的组合。如果你一直使用URI这个术语,就不会有错。为了纠正一些错误,已经更新了这篇文章。如果你发现新的错误,无论是技术上的还是语法上的,请不要犹豫,告诉我们吧!
-
XEN和KVM镜像如何兼容统一,必须将Linux原生xen-pv和virtio前端驱动装载到动到initrd中,这个如何做到的呢? 只需要添加module形式存在OS内的驱动,在内核中以build-in形式存在的驱动不需要添加。 [*]RHEL、CentOS、Oracle系列操作系统,以CentOS 7.1为例,需修改“/etc/dracut.conf”文件,在add-driver项中添加xen-pv以及virtio的驱动(xen-pv驱动:xen-blkfront、xen-netfront;virtio驱动:virtio_blk、virtio_scsi 、virtio_net、virtio_pci、virtio_ring、virtio),驱动名之间以空格隔开,保存并退出/etc/dracut.conf文件,执行dracut -f命令,重新生成initrd。 [*]Ubuntu和Debian系列系统,修改/etc/initramfs-tools/modules文件,添加xen-pv以及virtio的驱动(xen-pv驱动:xen-blkfront、xen-netfront;virtio驱动:virtio_blk、virtio_scsi 、virtio_net、virtio_pci、virtio_ring、virtio),驱动名之间是空格隔开,保存并退出/etc/initramfs-tools/modules文件,执行update-initramfs -u命令,重新生成initrd。 [*]SUSE和openSUSE系列系统,修改/etc/sysconfig/kernel文件,在INITRD_MODULES=""添加xen-pv以及virtio的驱动,(xen-pv驱动:xen_vnif、xen_vbd、xen_platform_pci;virtio驱动:virtio_blk、virtio_scsi 、virtio_net、virtio_pci、virtio_ring、virtio),驱动名之间是空格隔开,执行mkinitrd命令,重新生成initrd。 1、以CentOS为例,修改/etc/dracut.conf在add-driver项中添加xen-pv和virtio的驱动(具体格式要根据OS本身的要求来决定): [code][root@CTU10000xxxxx ~]# vim /etc/dracut.conf # additional kernel modules to the default add_drivers+="xen-blkfront xen-netfront virtio_blk virtio_scsi virtio_net virtio_pci virtio_ring virtio" ……[/code] 2、保存并退出/etc/dracut.conf文件,执行dracut -f命令,重新生成initrd。 3、检查是否已经成功装载了XEN和KVM的PVOPS相应模块。 [code][root@CTU10000xxxxx home]# lsinitrd /boot/initramfs-`uname -r`.img | grep xen -rwxr--r-- 1 root root 54888 Jul 16 17:53 lib/modules/2.6.32-573.8.1.el6.x86_64/kernel/drivers/block/xen-blkfront.ko -rwxr--r-- 1 root root 45664 Jul 16 17:53 lib/modules/2.6.32-573.8.1.el6.x86_64/kernel/drivers/net/xen-netfront.ko [root@CTU10000xxxxx home]# lsinitrd /boot/initramfs-`uname -r`.img | grep virtio -rwxr--r-- 1 root root 23448 Jul 16 17:53 lib/modules/2.6.32-573.8.1.el6.x86_64/kernel/drivers/block/virtio_blk.ko -rwxr--r-- 1 root root 50704 Jul 16 17:53 lib/modules/2.6.32-573.8.1.el6.x86_64/kernel/drivers/net/virtio_net.ko -rwxr--r-- 1 root root 28424 Jul 16 17:53 lib/modules/2.6.32-573.8.1.el6.x86_64/kernel/drivers/scsi/virtio_scsi.ko drwxr-xr-x 2 root root 0 Jul 16 17:53 lib/modules/2.6.32-573.8.1.el6.x86_64/kernel/drivers/virtio -rwxr--r-- 1 root root 14544 Jul 16 17:53 lib/modules/2.6.32-573.8.1.el6.x86_64/kernel/drivers/virtio/virtio.ko -rwxr--r-- 1 root root 21040 Jul 16 17:53 lib/modules/2.6.32-573.8.1.el6.x86_64/kernel/drivers/virtio/virtio_pci.ko -rwxr--r-- 1 root root 18016 Jul 16 17:53 lib/modules/2.6.32-573.8.1.el6.x86_64/kernel/drivers/virtio/virtio_ring.ko[/code] 说明: 如果误将build-in形式存在内核中的驱动添加到initrd或initramfs文件中,不会影响虚拟机正常使用,这里全写进去只是为了修改的方便,但是使用lsinitrd命令无法检查到。可使用如下方法确定这些驱动是否以build-in形式存在内核中,例如: [code][root@ CTU10000xxxxx home]# cat /boot/config-`uname -r` | grep CONFIG_VIRTIO | grep y [root@ CTU10000xxxxx home]# cat /boot/config-`uname -r` | grep CONFIG_XEN | grep y[/code]
-
本帖最后由 DevCloud 于 2017-9-22 16:06 编辑
-
本帖最后由 DevCloud 于 2017-9-22 16:06 编辑
-
本帖最后由 DevCloud 于 2017-9-22 16:07 编辑
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签