didida开店流程全部完成后为什么推荐人没有收到邮件件通知?

&figure&&img src=&https://pic2.zhimg.com/v2-0a6cdb8618a_b.jpg& data-rawwidth=&384& data-rawheight=&232& class=&content_image& width=&384&&&/figure&&blockquote& 作者 : 左潇龙
来源 : 博客园&/blockquote&&p&&br&&/p&&h2&&b&引言&/b&&/h2&&p&&br&&/p&&p&  其实本来真的没打算写这篇文章,主要是LZ得记忆力不是很好,不像一些记忆力强的人,面试完以后,几乎能把自己和面试官的对话都给记下来。LZ自己当初面试完以后,除了记住一些聊过的知识点以外,具体的内容基本上忘得一干二净,所以写这篇文章其实是很有难度的。&/p&&p&  但是,最近问LZ的人实在是太多了,为了避免重复回答,给自己省点力气,干脆就在这里统一回复了。&/p&&p&  其实之前LZ写过一篇文章,但是那篇文章更多的是在讨论“面试前该不该刷题”这个话题,而这篇文章将会更加聚焦在面试前如何准备,以及工作当中如何学习这个话题上,而且会尽量写出一些干货。&/p&&p&&br&&/p&&h2&&b&第一个问题:阿里面试都问什么?&/b&&/h2&&p&&br&&/p&&p&  这个是让LZ最头疼的一个问题,也是群里的猿友们问的最多的一个问题。&/p&&p&  说实话,LZ只能隐约想起并发、JVM、分布式、TCP/IP协议这些个关键字,具体的问题真的是几乎都没记住。而且就算LZ记住了,也告诉你了,你也背会了,但LZ觉得,在面试中,你被问到一模一样问题的可能性依然很小。&/p&&p&  甚至,就算你运气好被问到了,你也照着背下来了,也不一定就能对你的面试起到正面的作用,因为面试官万一多问一句,你可能就露馅了,那还不如干脆点说不会更好。&/p&&p&  LZ参加的是阿里的社招面试,而社招不同于校招,问题的范围其实是很随机的。因为能参加一些比较知名的互联网公司社招的人,70%以上都会有个3-5年的经验。这倒不是说一两年经验的同学没有机会进这些公司,而是因为这种公司,大部分情况下只招一些比较资深的开发和应届生,而不招那些处于中间阶段的人。而1-2年经验的同学,往往就刚好处于这个尴尬的阶段。&/p&&p&  对于能有3-5年经验的这部分人中,每个人的经历又都不同,所擅长的点也不一样,因此这就会导致每个人的问题和范围都不太一样。&/p&&p&  很少说有哪个知名的互联网公司,比如BAT、京东、360、搜狐、网易等这些公司,其社招面试还有固定的问题和模式,让你可以像应届生面试一样,在面试前靠临时抱佛脚度过这一关。&/p&&p&  大部分公司在社招的时候,不光是阿里,其它公司也都一样(因为LZ在一年多前也参加过很多其它知名互联网公司的面试。&/p&&p&&b&第一个阶段是主语言本身以及它的高级特性,第二个阶段是讲述自己的项目,并在中间穿插着问题。&/b&&/p&&p&  所以,LZ不妨就这两个阶段,谈谈社招面试的准备,而不是去把阿里面试的过程背一遍。说实话,LZ也确实记不住,所以不要再问LZ阿里面试都会问哪些问题了,你看看上面那个连接里的文章,也会发现,LZ里面也基本上没有写具体的问题,原因是一样的,真的记不住啊。(就是因为记忆力的问题,导致LZ从小偏科,文科成绩一直堪忧,-_-)&/p&&p&&br&&/p&&h2&&b&社招面试如何准备&/b&&/h2&&p&&br&&/p&&p&  LZ会分为四个部分来谈论这个问题,由于LZ本身是Java出身,因此关于主语言的问题,都是与Java相关,其它语言的同学可以选择性忽略。此外,面试的时候一般面试官的问题都是环环相扣,逐渐深入的,这点在下面大家可以更明显的感受出来。&/p&&p&&br&&/p&&h2&&b&1、主语言本身以及它的高级特性。&/b&&/h2&&p&&br&&/p&&p&  主语言当然就是你平日里拿来赚钱的家伙。不要告诉LZ你没有主语言,你会N多种语言,或者是你精通N多种语言,你要非这么说的话,你可以来杭州试试,LZ保证不打死你,最多打残。&/p&&p&  LZ的主语言很显然是Java,那么对于Java来说,它的语言本身以及它的高级特性,都有哪些比较容易在面试中问到呢?&/p&&p&  一般情况下,主要有以下知识点很容易被问到。(PS:以下所列举的,都是一些Java相对而言比较高级一点的知识点,因为这里谈的是社招,而不是校招)&/p&&p&&br&&/p&&h2&&b&1)Java的数据结构相关的类实现原理,比如LinkedList,ArrayList,HashMap,TreeMap这一类的。以下简单模拟一个数据结构的连环炮。&/b&&/h2&&p&&br&&/p&&p&  比如,面试官先问你HashMap是不是有序的?&/p&&p&  你肯定回答说,不是有序的。那面试官就会继续问你,有没有有顺序的Map实现类?&/p&&p&  你如果这个时候说不知道的话,那这个问题就到此结束了。如果你说有TreeMap和LinkedHashMap。&/p&&p&  那么面试官接下来就可能会问你,TreeMap和LinkedHashMap是如何保证它的顺序的?&/p&&p&  如果你回答不上来,那么到此为止。如果你依然回答上来了,那么面试官还会继续问你,你觉得它们两个哪个的有序实现比较好?&/p&&p&  如果你依然可以回答的话,那么面试官会继续问你,你觉得还有没有比它更好或者更高效的实现方式?&/p&&p&  如果你还能说出来的话,那么就你所说的实现方式肯定依然可以问你很多问题。&/p&&p&  以上就是一个面试官一步一步提问的例子。所以,如果你了解的不多,千万不要敷衍,因为可能下一个问题你就暴露了,还不如直接说不会,把这个问题结束掉,赶紧切换到你熟悉的领域。&/p&&p&&br&&/p&&h2&&b&2)Java并发包当中的类,它们都有哪些作用,以及它们的实现原理,这些类就是java.concurrent包下面的。与上面一样,咱们也简单的模拟一个并发包的连环炮。&/b&&/h2&&p&&br&&/p&&p&  比如面试官可能会先问你,如果想实现所有的线程一起等待某个事件的发生,当某个事件发生时,所有线程一起开始往下执行的话,有什么好的办法吗?&/p&&p&  这个时候你可能会说可以用栅栏(Java的并发包中的CyclicBarrier),那么面试官就会继续问你,你知道它的实现原理吗?&/p&&p&  如果你继续回答的话,面试官可能会继续问你,你还知道其它的实现方式吗?&/p&&p&  如果你还能说出很多种实现方式的话,那么继续问你,你觉得这些方式里哪个方式更好?&/p&&p&  如果你说出来某一个方式比较好的话,面试官依然可以继续问你,那如果让你来写的话,你觉得还有比它更好的实现方式吗?&/p&&p&  如果你这个时候依然可以说出来你自己更好的实现方式,那么面试官肯定还会揪着这个继续问你。&/p&&p&  为什么说面试的时候要引导面试官,原因就在这了。因为面试官的提问很多时候都是有迹可循的,你如果抓住了他的轨迹,能够猜到他下面很可能会问什么,那你在回答的时候就可以往你想要谈的方向去说。这样面试时就会显得更加从容,更加的游刃有余。&/p&&p&&br&&/p&&h2&&b&3)IO包和NIO包中的内容。这部分里面NIO会是重点,IO包大部分都会比较熟悉,因此可能会直接略过,直接问你NIO的内容。&/b&&/h2&&p&&br&&/p&&p&  IO包和NIO包的内容相对来说不是很多,首先NIO模型要熟悉,特别是其中的selector一定要非常清楚它的职责和实现原理。其实NIO的核心是IO线程池,一定要记住这个关键点。有的时候,面试官可能也会问你IO包的设计模式(装饰器模式),为什么要这样设计?&/p&&p&  有的面试官还会问你有没有更好的设计,这个时候如果你不知道请果断说自己现在的水平有限,想不出来更好的设计,千万不要信口开河,随意YY。&/p&&p&&br&&/p&&h2&&b&4)Java的虚拟机的内容。这部分主要包括三部分,GC、类加载机制,以及内存。&/b&&/h2&&p&&br&&/p&&p&  一个GC部分简单的连环炮。&/p&&p&  面试官可以先问你什么时候一个对象会被GC?&/p&&p&  接着继续问你为什么要在这种时候对象才会被GC?&/p&&p&  接着继续问你GC策略都有哪些分类?&/p&&p&  你如果说出来了,继续问你这些策略分别都有什么优劣势?都适用于什么场景?&/p&&p&  你继续说出来了以后,给你举个实际的场景,让你选择一个GC策略?&/p&&p&  你如果选出来了,继续问你,为什么要选择这个策略?&/p&&p&  下面是关于类加载机制的简单连环炮。&/p&&p&  首先肯定是先问你Java的类加载器都有哪些?&/p&&p&  回答了这些以后,可能会问你每个类加载器都加载哪些类?&/p&&p&  说完以后,可能会问你这些类加载之间的父子关系是怎样的?&/p&&p&  你在回答的时候可能会提到双亲委派模型,那么可以继续问你什么是双亲委派模型?&/p&&p&  你解释完了以后,可能会继续问你,为什么Java的类加载器要使用双亲委派模型?&/p&&p&  你回答完以后,可能会继续问你如何自定义自己的类加载器,自己的类加载器和Java自带的类加载器关系如何处理?&/p&&p&  再来一个关于内存的连环炮。&/p&&p&  首先肯定就是问你内存分为哪几部分,这些部分分别都存储哪些数据?&/p&&p&  然后继续问你一个对象从创建到销毁都是怎么在这些部分里存活和转移的?&/p&&p&  接着可能会问你,内存的哪些部分会参与GC的回收?&/p&&p&  完事以后,可能还会问你Java的内存模型是怎么设计的?&/p&&p&  你回答了以后,还会继续问你为什么要这么设计?&/p&&p&  问完以后,还可能会让你结合内存模型的设计谈谈volatile关键字的作用?&/p&&p&  你在谈的时候,肯定会提到可见性,那么接着可见性这三个字,还可以继续问你并发的内容。&/p&&p&  基本上Java语言本身以及语言稍微高级点的内容就是以上部分,如果你能把以上四部分了解的非常透彻,那基本上Java这部分就没啥问题了,因为光以上的内容就够你跟面试官聊很久了。你聊这些聊得久了,自然问你其它问题的时间就会短点。&/p&&p&  你从LZ写这些问题的过程也应该能感受出来,很多时候,面试官都是顺着一条线一路问下去的,如果你觉得这条线你不熟悉的话,就要及时拐弯,引导面试官去问其它方面的问题。千万不要一直往下深入,直到自己跳不出来为止,那就尴了个尬了。&/p&&p&&br&&/p&&h2&&b&2、讲述自己的项目,并在中间穿插着问题&/b&&/h2&&p&&br&&/p&&p&  这一部分是面试过程中必问,也是聊得最久的一个阶段。除非你前面的语言部分非常扎实,扎实到面试官问了一两个小时,依旧没有探出你对语言本身的了解到底有多深。否则的话,你一定逃不过自己的项目这一关,而且一般情况下聊得时间不会太短。&/p&&p&  这一部分内容,一般的模式就是你自己去讲你做过的项目,然后面试官会冷不丁的让你去解释其中某一部分,比如让你解释当时为什么要这么做,或者问你现在觉得有没有更好的办法。而这些穿插的问题,大部分与你的项目所用到的技术有关。而你需要做的,就是充分、再充分的去总结自己做过的项目(尤其是最近的一两个项目),挖掘出一个甚至N个亮点,以备于到时候可以让面试官产生眼前一亮的感觉。如果你能达到这种效果的话,基本上离你成功就不远了。&/p&&p&  这部分内容由于和每个人自己的经历息息相关,因此这里也没法列举可能问到的问题。这篇文章《程序员面经:面试前到底该不该刷题以及面试前该如何准备》是LZ之前写的,里面大概讨论了下如何在面试前总结,有兴趣的可以去了解一下。&/p&&p&&br&&/p&&h2&&b&3、额外的加分项&/b&&/h2&&p&&br&&/p&&p&  上面两个阶段基本上是必问的,还有一些加分项。这些加分项中,有些内容面试官也会问你(比如TCP/IP协议、算法),但更多的是会先问你了解不了解,你了解的话再继续聊,不了解的话就直接略过了,不至于因为这种问题而直接把你打入地狱。&/p&&p&  下面LZ列举一下这些加分项,如果可以的话,这些加分项还是要争取一下的。&/p&&p&&b&1、计算机系统原理。&/b&&/p&&p&&b&2、网络通信协议(TCP/IP,HTTP等)。&/b&&/p&&p&&b&3、数据结构与算法。&/b&&/p&&p&&b&4、著名开源项目的源码。&/b&&/p&&p&&b&5、你自己有很棒的开源项目。&/b&&/p&&p&&b&6、你的个人博客。&/b&&/p&&p&  这几项当中,对于前1-3项,如果你之前就比较了解,只是由于时间问题忘记了的话,还是可以临时抱佛脚一下的。至于后面4-6项,就需要你日常的积累了,不是一时半会儿能做到的。如果你平日里没有积累,那么后面这三个加分项只能抛弃了。&/p&&p&&br&&/p&&h2&&b&4、与你职位相关的内容&/b&&/h2&&p&&br&&/p&&p&  其实这最后一项是对前面三项的补充,你应该尽量去主攻和你面试的职位相关的内容。比如你面试一个实时计算的职位,那么你的算法最好要厉害,对于著名的实时计算开源项目要熟悉,最好阅读过源码,而且还要对分布式系统有一定的见解。&/p&&p&  因此,这个第4部分没有具体的内容,只是提醒你,如果你很明确自己的面试职位,最好在面试前准备的时候,尽量朝职位的需求方向靠拢,这样成功的可能性更大。&/p&&p&&br&&/p&&h2&&b&对于Java程序猿学习的建议&/b&&/h2&&p&&br&&/p&&p&  这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是LZ你是如何学习Java的,能不能给点建议?&/p&&p&  今天LZ是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈每个阶段要学习的内容甚至是一些书籍。这一部分的内容,同样适用于一些希望转行到Java的同学。&/p&&p&&b&在大家看之前,LZ要先声明两点。&/b&&/p&&p&  1、由于LZ本人是Java后端开发出身,因此所推荐的学习内容是Java Web和Java后端开发的路线,非Java Web和Java后端开发的同学请适当参考其学习思想即可,切勿照搬。&/p&&p&  2、下面对于【第一部分】的推荐内容,目的是让你尽快成为一个可以参加工作的Java开发者,更适用于处于待业状态,准备转行Java的同学。如果你是在校学生,务必要在学好基础(比如计算机系统、算法、编译原理等等)的前提下,再考虑去进行下面的学习。&/p&&p&&b&第一部分:对于尚未做过Java工作的同学,包括一些在校生以及刚准备转行Java的同学。&/b&&/p&&p&&br&&/p&&h2&&b&一、Java基础&/b&&/h2&&p&&br&&/p&&p&  首先去找一个Java的基础教程学一下,这里可以推荐一个地址,或者你也可以参照这个地址上去找相应的视频,地址为&a href=&https://link.zhihu.com/?target=http%3A//www.runoob.com/java/java-tutorial.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&runoob.com/java/java-tu&/span&&span class=&invisible&&torial.html&/span&&span class=&ellipsis&&&/span&&/a&。&/p&&p&  学习Java基础的时候,应该尽量多动手,很多时候,你想当然的事情,等你写出来运行一下,你就会发现不是这么回事儿,不信你就试试。&/p&&p&  学完以上内容以后,你应该对Java有一个基本的了解了,你可以用Java语言写出一些简单的程序,并且你用的是最简单的编辑器,比如记事本。&/p&&p&  这个时候,不要急于进入下一部分,留下几天好好写一些程序,尽可能熟悉这些基础内容。&/p&&p&&br&&/p&&h2&&b&二、Web开发&/b&&/h2&&p&&br&&/p&&p&  等你写上几天程序以后,你往往会比较迷茫,因为你写的东西似乎看起来毫无用处,比如实现一个简单的计算器,读取一个文件等。这个时候你就应该去学着写一些让你觉得有意思的东西了,所以你应该学习更多的知识。&/p&&p&  这些内容主要是Web开发相关的内容,包括HTML/CSS/JS(前端页面)、Servlet/JSP(J2EE)以及Mysql(数据库)相关的知识。&/p&&p&  它们的学习顺序应该是从前到后,因此最先学习的应该是HTML/CSS/JS(前端页面),这部分内容你可以去上面的那个runoob网站上找。你可以试着自己写一些页面,当然,你可以尽你最大的努力让它变得最漂亮。这部分内容对于后端Java来说,理论上不是特别重要,但至少要达到可以自己写出一些简单页面的水平。&/p&&p&  接下来,你需要学习的是Servlet/JSP(J2EE)部分,这部分是Java后端开发必须非常精通的部分,因此这部分是这三部分中最需要花精力的,而且这个时候,你要学会使用开发工具,而不能再使用记事本了,可以选择eclipse。&/p&&p&  当你下载安装好eclipse以后,请视频中的教程一步一步去学习,一定要多动手。关于Servlet/Jsp部分视频的选择,业界比较认可马士兵的视频,因此推荐给大家。当然了,LZ本人并没有看过他的视频,所以不好说的太绝对,如果大家自己有更好的选择,可以坚持自己的,不要被LZ干扰。&/p&&p&  最后一步,你需要学会使用数据库,mysql是个不错的入门选择,而且Java领域里主流的关系型数据库就是mysql。这部分一般在你学习Servlet/Jsp的时候,就会接触到的,其中的JDBC部分就是数据库相关的部分。你不仅要学会使用JDBC操作数据库,还要学会使用数据库客户端工具,比如navicat,sqlyog,二选一即可。&/p&&p&&br&&/p&&h2&&b&三、开发框架&/b&&/h2&&p&&br&&/p&&p&  当你学会以上内容以后,这个时候你还不足以参加工作,你还需要继续深造。公司里为了提高开发的效率,会使用一些Java Web框架,因此你还需要学习一些开发框架。&/p&&p&  目前比较主流的是SSM框架,即spring、springmvc、mybatis。你需要学会这三个框架的搭建,并用它们做出一个简单的增删改查的Web项目。你可以不理解那些配置都是什么含义,以及为什么要这么做,这些留着后面你去了解。但你一定要可以快速的利用它们三个搭建出一个Web框架,你可以记录下你第一次搭建的过程,相信我,你一定会用到的。&/p&&p&  还要提一句的是,你在搭建SSM的过程中,可能会经常接触到一个叫maven的工具。这个工具也是你以后工作当中几乎是必须要使用的工具,所以你在搭建SSM的过程中,也可以顺便了解一下maven的知识。在你目前这个阶段,你只需要在网络上了解一下maven基本的使用方法即可,一些高端的用法随着你工作经验的增加,会逐渐接触到的。&/p&&p&  关于学习SSM框架的地址给大家推荐一个,这里面有视频,大家可以去观看,地址是&a href=&https://link.zhihu.com/?target=http%3A//edu.51cto.com/lesson/id-76468.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&edu.51cto.com/lesson/id&/span&&span class=&invisible&&-76468.html&/span&&span class=&ellipsis&&&/span&&/a&。&/p&&p&&br&&/p&&h2&&b&四、找工作&/b&&/h2&&p&&br&&/p&&p&  当你完成开发框架的学习以后,你就该找工作了,在校的找实习,毕业的找全职。与此同时,在找工作的同时,你不应该停下你的学习,准确的说,是你在以后都不能停下学习。&/p&&p&  上面这些内容你只是囫囵吞枣的学会了使用,你可以逐步尝试着去了解更多的东西,网络是你最重要的老师。&/p&&p&&b&第二部分:对于参加工作一年以内的同学。&/b&&/p&&p&  恭喜你,这个时候,你已经拥有了一份Java的工作。这个阶段是你成长极快的阶段,而且你可能会经常加班。&/p&&p&  但是加班不代表你就可以松懈了,永远记得LZ说的那句话,从你入行那一刻起,你就要不停的学习。在这一年里,你至少需要看完《Java编程思想》这本书。这本书的内容是帮助你对于Java有一个更加深入的了解,是Java基础的升级版。&/p&&p&  这本书很厚,当初看这本书,LZ花了整整三个月。正常速度的话,应该可以在半年左右看完。LZ这里不要求过高,只要你在一年以内把这本书看完即可。当然了,LZ所说的看完,是充分吸收,而不是读一遍就完事了,因此有些内容你可能会看不止一遍。&/p&&p&  总而言之,这个阶段的核心学习思想就是,在工作中实践,并且更加深入的了解Java基础。&/p&&p&&b&第三部分:对于参加工作1年到2年的同学。&/b&&/p&&p&  这部分时间段的同学,已经对Java有了一个更加深入的了解。但是对于面向对象的体会可能还不够深刻,编程的时候还停留在完成功能的层次,很少会去考虑设计的问题。&/p&&p&  于是这个时候,设计模式就来了。LZ当时看的是《大话设计模式》这本书,并且写了完整版的设计模式博客。因此,LZ要求大家,最多在你工作一年的时候,必须开始写博客,而设计模式就是你博客的开端。&/p&&p&  请记住,LZ所提的基本都是最低要求,因此不要有任何松懈的心理,否则五年后,你不要去羡慕别人高于你的工资,也不要去羡慕别人进入了某公司。&/p&&p&  这一年,你必须对于设计模式了如指掌,《大话设计模式》可以作为你的开端。当然了,你也可以去看LZ的个人公众号:&b&java技术学习之道&/b&。我会经常分享一些技术文章,希望对你有帮助。&/p&&p&  此外,设计模式并不是你这一年唯一的任务,你还需要看一些关于代码编写优化的书。比如《重构 改善既有代码的设计》,《effective java》。&/p&&p&  总而言之,这个阶段,你的核心任务就是提高你的代码能力,要能写出一手优雅的代码。&/p&&p&&b&第四部分:对于参加工作2年到3年的同学&/b&&/p&&p&  有的同学在这个时候觉得自己已经很牛逼了,于是忍不住开始慢慢松懈。请记住,你还嫩的多。&/p&&p&  这个阶段,有一本书是你必须看的,它叫做《深入理解Java虚拟机》。这本书绝对是Java开发者最重要的书,没有之一。在LZ眼里,这本书的重要性还要高于《Java编程思想》。&/p&&p&  这本书的内容是帮助你全面的了解Java虚拟机,在这个阶段,你一定已经知道Java是运行在JVM之上的。所以,对于JVM,你没有任何理由不了解它。&/p&&p&  另外,在过去2年的工作当中,你肯定或多或少接触过并发。这个时候,你应该去更加深入的了解并发相关的知识,而这部分内容,LZ比较推荐《Java并发编程实战》这本书。只要你把这本书啃下来了,并发的部分基本已经了解了十之六七。&/p&&p&  与此同时,这个阶段你要做的事情还远不止如此。这个时候,你应该对于你所使用的框架应该有了更深入的了解,对于Java的类库也有了更深入的了解。因此,你需要去看一些JDK中的类的源码,也包括你所使用的框架的源码。&/p&&p&  这些源码能看懂的前提是,你必须对设计模式非常了解。否则的话,你看源码的过程中,永远会有这样那样的疑问,这段代码为什么要这么写?为什么要定义这个接口,它看起来好像很多余?&/p&&p&  由此也可以看出,这些学习的过程是环环相扣的,如果你任何一个阶段拉下来了,那么你就真的跟不上了,或者说是一步慢步步慢。而且LZ很负责的告诉你,LZ在这个阶段的时候,所学习的东西远多于这里所罗列出来的。因此千万不要觉得你已经学的很多了,LZ所说的这些都只是最低要求,不光是LZ,很多人在这个时间段所学习的内容都远超本文的范围。&/p&&p&  如果你不能跟上节奏的话,若干年后,如果不是程序猿市场还不错的话,你很可能不仅仅是工资比别人低,公司没别人好,而是根本就找不到工作。&/p&&p&  总而言之,这个阶段,你需要做的是深入了解Java底层和Java类库(比如并发那本书就是Java并发包java.concurrent的内容),也就是JVM和JDK的相关内容。而且还要更深入的去了解你所使用的框架,方式比较推荐看源码或者看官方文档。&/p&&p&  另外,还有一种学习的方式,在2年这个阶段,也应该启用了,那就是造轮子。&/p&&p&  不要听信那套“不要重复造轮子”的论调,那是公司为了节省时间成本编造出来的。重复造轮子或许对别人没有价值,因为你造的轮子可能早就有了,而且一般情况下你造出来的轮子还没有现存的好。但是对别人没有价值,不代表对你自己没有价值。&/p&&p&  一个造轮子的过程,是一个从无到有的过程。这个过程可以对你进行系统的锻炼,它不仅考察你的编码能力,还考察你的框架设计能力,你需要让你的轮子拥有足够好的扩展性、健壮性。&/p&&p&  而且在造轮子的过程中,你会遇到各种各样的难题,这些难题往往又是你学习的契机。当你把轮子造好的时候,你一定会发现,其实你自己收获了很多。&/p&&p&  所以,这个阶段,除了上面提到的了解JVM、JDK和框架源码以外,也请你根据别人优秀的源码,去造一个任何你能够想象出来的轮子。&/p&&p&&b&第五部分:参加工作3年到4年的同学&/b&&/p&&p&  这个阶段的同学,提升已经是很难了,而且这个阶段的学习往往会比较多样化。&/p&&p&  因为在前3年的过程中,你肯定或多或少接触过一些其它的技术,比如大数据、分布式缓存、分布式消息服务、分布式计算、软负载均衡等等。这些技术,你能精通任何一项,都将是你未来面试时巨大的优势,因此如果你对某一项技术感兴趣的话,这个时候可以深入去研究一下。这项技术不一定是你工作所用到的,但一定是相关的。&/p&&p&  而且在研究一门新技术时,切忌朝三暮四。有的同学今天去整整大数据,搞搞Hadoop、hbase一类的东西。过不了一段时间,就觉得没意思,又去研究分布式缓存,比如redis。然后又过不了一段时间,又去研究分布式计算,比如整整Mapreduce或者storm。&/p&&p&  结果到最后,搞得自己好像什么都会一样,在简历上大言不惭的写上大数据、分布式缓存、分布式计算都了解,其实任何一个都只是浮于表面。到时候面试官随便一问,就把你给识破了。&/p&&p&  一定要记住,作为一个程序猿,平日里所接触的技术可能会很多,但是想要让一门技术成为你的优势,那么一定是你对这门技术的了解强过绝大多数人才行。&/p&&p&  因此在这个阶段,你就不能再简单的去学习前3年的内容了,虽然前面的学习如果还不够深入的话依旧要继续,但这个时候你应该更多的考虑建立你的优势,也可以称为差异性。&/p&&p&  差异性相信不难理解,就是让你自己变得与众不同。你前面三年的学习足够你成为一名基本合格的Java开发者,但你离成为一名优秀的Java开发者还有很大的距离。&/p&&p&  所谓优秀,即能别人所不能。而你前三年所学习的内容,是很多做过几年的Java开发都能够掌握的。那么为了让自己有差异性,你就需要另辟蹊径,找一个方向深入研究下去,以期在将来,你能够成为这个领域的专家,比如分布式计算领域的专家,大数据领域的专家,并发领域的专家等等。&/p&&p&  此外,你除了建立你的差异性之外,还要去弥补你基础上的不足,直到现在,LZ都没有提及基础知识。原因是基础是很枯燥无味的,学的太早不仅容易懵逼,而且懵逼的同时还容易产生心理阴影,以至于以后再不想去研究这些基础。但基础又是你深入研究一些领域时所必须掌握的,比如你去研究分布式计算,你不懂算法你玩个毛毛?比如你去做分布式缓存,你对计算机系统的内存不了解,你如何去做缓存?&/p&&p&  如果你的基础本来就非常强,那么恭喜你,相信你在之前的工作中已经充分体会到了这些基础对你的帮助。但LZ相信大部分人的基础都很薄弱,哪怕是科班毕业的人,很多人也不敢说自己当初的基础学的多么强大,比如算法、计算机系统原理、编译原理这些。&/p&&p&  但是每个人时间都是有限的,而且这些基础的书籍每一本读下来,没个一年半载的,还真拿不下来,因此还是要有所抉择的。虽然艺多不压身,但问题是艺多是有代价的,是需要你付出时间和精力的,而LZ个人更赞成在同等代价的情况下获取最大的收获。&/p&&p&  首先,LZ比较推崇的基础书籍有三本,分别是《深入理解计算机系统》,《tcp/ip详解 卷一、二、三》,《数据结构与算法》。其中TCP/IP有三本书,但我们这里把这三本看成是一本大书。&/p&&p&  这三本分别适合三种人,《深入理解计算机系统》比较适合一直从事Java Web开发和APP后端开发工作的人群。《tcp/ip详解 卷一、二、三》比较适合做网络编程的人群,比如你使用netty去开发的话,那么就要对TCP/IP有更深入的了解。而《数据结构与算法》这本书,则比较适合做计算研究工作的人,比如刚才提到的分布式计算。&/p&&p&  另外,LZ要强调的是,这里所说的适合,并不是其它两本对你就没有用。比如你做Java Web和APP后端开发,《tcp/ip详解 卷一、二、三》这本书对你的作用也是很大的。这里只是分出个主次关系而已,你要是时间足够的话,能把三本都精读那当然最好不过了。但如果时间有限的话,那么就先挑对你帮助最大的书去读。&/p&&p&  理论上来讲,这一年你能把这三本其中一本精读下来,就已经非常厉害了。有了基础,有了前面的工作经验,你就可以去开拓属于你的领域了。&/p&&p&  在这一年里,一定要规划好自己的领域,建立好自己的优势,制造出差异性。如果你对自己的领域不够清晰的话,随着你工作的时间日益增多,你接触的技术会越来越多,这个时候,你很容易被淹死在技术的海洋里,看似接触的技术越来越多,会用的也越来越多,但你毫无优势。&/p&&p&  有的同学可能会问,“LZ,我也不知道我的领域是什么啊?怎么办呢?”&/p&&p&  对于这种人,LZ只想说,“卧槽,这还问我?要不干脆我替你学习得了,好不好?”&/p&&p&&b&第六部分:参加工作4年到5年的同学&/b&&/p&&p&  经过前面一年的历练,相信你在自己所钻研的领域已经有了自己一定的见解,这个时候,技术上你应该已经遇到瓶颈了。&/p&&p&  这个时候不要着急提高自己的技术,已经是时候提高你的影响力了,你可以尝试去一些知名的公司去提高你的背景,你可以发表一些文章去影响更多的人。当然,你也可以去Github创建一个属于你的开源项目,去打造自己的产品。这次的开源项目不同于之前的造轮子,你这个时候是真的要去尽量尝试造出来真正对别人有价值的轮子。&/p&&p&  技术学到这个阶段,很容易遇到瓶颈,而且往往达到一定程度后,你再深入下去的收效就真的微乎其微了,除非你是专门搞学术研究的。然而很可惜,大部分程序猿做不到这一步,那是科学家做的事情。&/p&&p&  这个时候提高影响力不仅仅是因为技术上容易遇到瓶颈,更多的是影响力可以给你创造更多的机会。程序猿在某种程度上和明星很像,一个好的电视剧和电影就可以成就一批明星,程序猿有的时候也是,一个好的项目就可以成就一群程序猿。&/p&&p&  比如国内几个脍炙人口的项目,像淘宝、支付宝、QQ、百度、微信等等。这每一个项目,都成就了一批程序猿。LZ敢说,这里面任何一个项目,如果你是它的核心开发,光是这样一个Title,就已经是你非常大的优势。更何况还不止如此,Title说到底也是个名头,更重要的是,这种项目在做的时候,对你的历练一定也是非常给力的。&/p&&p&  而你如果想要参与这样的项目,除了靠运气之外,影响力也是很重要的一个手段。比如你在分布式计算领域有一定的影响力,那么如果有什么好的关于分布式计算的项目,对方就很可能会邀请你。就算人家不邀请你,你自己主动去面试的时候,对方如果知道你在这个领域的影响力,也肯定会起到很大的作用,而这个作用,甚至可能会超过你现在的技术能力。&/p&&p&  所以,在这个阶段,你最大的任务是提高自己的影响力,为自己未来的十年工作生涯那一天做准备。如果你能够靠你的影响力和以前积累的技术,参与到一个伟大的项目当中,那么你后面的五年也就有着落了。&/p&&p&  当然了,LZ现在满打满算,做程序猿也就4年半不到,因此关于4年到5年这一部分,LZ的见解不一定是对的,就算是对的,也不一定是适合任何人的。所以,希望大家自己有的判断力,去决定到底该如何度过这一年。&/p&&p&&br&&/p&&h2&&b&结语&/b&&/h2&&p&&br&&/p&&p&  本文到此就基本结束了,整篇文章很长,但其实主要就说了两部分内容,一个是社招面试的准备,一个是Java生涯的学习。&/p&&p&  关于这两部分,LZ已经给出了自己的见解,但是还是那句话,每个人吸收知识的时候,都要有抽取精华,去除糟粕的能力。LZ所说的,可能有些是对的,有些是错的,有些是适合你的,有些是不太适合你的,你要自己能够判断。&/p&&p&  其实你在生活和工作当中也是一样的,你身边的人形形色色,有的人你喜欢,有的人你很讨厌。但其实你喜欢的人也有缺点,你讨厌的人也有优点。你要学会从你讨厌的人身上学会他的优点,千万不要一棒子打死,这只会让你失去很多学习成长的机会。&/p&&p&  好了,说了这么多了,就到此为止吧,希望本文可以帮助到作为程序猿或即将成为程序猿的你。&/p&&p&&b&欢迎大家关注我的公众号:java技术学习之道(javajsxxzd),长期分享各种技术文章。&/b&&/p&
作者 : 左潇龙 | 来源 : 博客园 引言 其实本来真的没打算写这篇文章,主要是LZ得记忆力不是很好,不像一些记忆力强的人,面试完以后,几乎能把自己和面试官的对话都给记下来。LZ自己当初面试完以后,除了记住一些聊过的知识点以外,具体的内容基本上忘得…
&p&Android应用会遇到各种各样的漏洞,如何从细节上了解各种安全隐患,积极采取适当的防御措施便变得尤为重要。为了让大家对Android漏洞有一个非常全面的认识,小编专门邀请&a href=&//link.zhihu.com/?target=https%3A//www.163yun.com/product-secure%3Ftag%3DM_zhihu_& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网易云易盾&/a&资深安全工程师徐从祥为大家详细解读九大常见的Android漏洞,供各位参考。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-c16d1fac605ab14dc6d7e0_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&278& data-rawheight=&254& class=&content_image& width=&278&&&/figure&&h2&&b&第一大类:Android Manifest配置相关的风险或漏洞&/b&&/h2&&p&&b&程序可被任意调试&/b&&/p&&p&
风险详情:安卓应用apk配置文件Android Manifest.xml中android:debuggable=true,调试开关被打开。&/p&&p&
危害情况:App可以被调试。&/p&&p&
修复建议:把Android Manifest.xml配置文件中调试开关属性关掉,即设置android:Debugable=&false&。&/p&&p&&b&程序数据任意备份&/b&&/p&&p&
风险详情:安卓应用apk配置文件AndroidManifest.xml中android:allowBackup=true,数据备份开关被打开。&/p&&p&
危害情况:App应用数据可被备份导出。&/p&&p&
修复建议:把AndroidManifest.xml配置文件备份开关关掉,即设置android:allowBackup=&false&。&/p&&p&组件暴露:建议使用android:protectionLevel=&signature&验证调用来源。&/p&&p&&b&Activity组件暴露&/b&&/p&&p&
风险详情:Activity组件的属性exported被设置为true或是未设置exported值但IntentFilter不为空时,activity被认为是导出的,可通过设置相应的Intent唤起activity。&/p&&p&
危害情况:黑客可能构造恶意数据针对导出activity组件实施越权攻击。&/p&&p&
修复建议:如果组件不需要与其他App共享数据或交互,请将AndroidManifest.xml 配置文件中设置该组件为exported = “False”。如果组件需要与其他App共享数据或交互, 请对组件进行权限控制和参数校验。&/p&&p&&b&Service组件暴露&/b&&/p&&p&
风险详情:Service组件的属性exported被设置为true或是未设置exported值但IntentFilter不为空时,Service被认为是导出的,可通过设置相应的Intent唤起Service。&/p&&p&
危害情况:黑客可能构造恶意数据针对导出Service组件实施越权攻击。&/p&&p&
修复建议:如果组件不需要与其他App共享数据或交互,请将AndroidManifest.xml 配置文件中设置该组件为exported = “False”。如果组件需要与其他App共享数据或交互, 请对组件进行权限控制和参数校验。&/p&&p&&b&ContentProvider组件暴露&/b&&/p&&p&
风险详情:Content Provider组件的属性exported被设置为true或是Android API&=16时,Content Provider被认为是导出的。&/p&&p&
危害情况:黑客可能访问到应用本身不想共享的数据或文件。&/p&&p&
修复建议:如果组件不需要与其他App共享数据或交互,请将AndroidManifest.xml 配置文件中设置该组件为exported = “False”。如果组件需要与其他App共享数据或交互, 请对组件进行权限控制和参数校验。&/p&&p&&b&BroadcastReceiver组件暴露&/b&&/p&&p&
风险详情:BroadcastReceiver组件的属性exported被设置为true或是未设置exported值但IntentFilter不为空时,BroadcastReceiver被认为是导出的。&/p&&p&
危害情况:导出的广播可以导致数据泄漏或者是越权。&/p&&p&
修复建议:如果组件不需要与其他App共享数据或交互,请将AndroidManifest.xml 配置文件中设置该组件为exported = “False”。如果组件需要与其他App共享数据或交互, 请对组件进行权限控制和参数校验。&/p&&p&&b&Intent Scheme URLs攻击&/b&&/p&&p&
风险详情:在AndroidManifast.xml设置Scheme协议之后,可以通过浏览器打开对应的Activity。&/p&&p&
危害情况:攻击者通过访问浏览器构造Intent语法唤起App相应组件,轻则引起拒绝服务,重则可能演变对App进行越权调用甚至升级为提权漏洞。&/p&&p&
修复建议:App对外部调用过程和传输数据进行安全检查或检验,配置category filter, 添加android.intent.category.BROWSABLE方式规避风险&/p&&h2&&b&第二大类:WebView组件及与服务器通信相关的风险或漏洞&/b&&/h2&&p&&b&Webview存在本地Java接口&/b&&/p&&p&
风险详情:android的webView组件有一个非常特殊的接口函数addJavascriptInterface,能实现本地java与js之间交互。&/p&&p&
危害情况:在targetSdkVersion小于17时,攻击者利用addJavascriptInterface这个接口添加的函数,可以远程执行任意代码。&/p&&p&
修复建议:建议开发者不要使用addJavascriptInterface,使用注入javascript和第三方协议的替代方案。&/p&&p&&b&Webview组件远程代码执行(调用getClassLoader)&/b&&/p&&p&
风险详情:使用低于17的targetSDKVersion,并且在Context子类中使用addJavascriptInterface绑定this对象。&/p&&p&
危害情况:通过调用getClassLoader可以绕过google底层对getClass方法的限制。&/p&&p&
修复建议:targetSDKVersion使用大于17的版本。&/p&&p&&b&WebView忽略SSL证书错误&/b&&/p&&p&
风险详情:WebView调用onReceivedSslError方法时,直接执行handler.proceed()来忽略该证书错误。&/p&&p&
危害情况:忽略SSL证书错误可能引起中间人攻击。&/p&&p&
修复建议:不要重写onReceivedSslError方法, 或者对于SSL证书错误问题按照业务场景判断,避免造成数据明文传输情况。&/p&&p&&b&webview启用访问文件数据&/b&&/p&&p&
风险详情:Webview中使用setAllowFileAccess(true),App可通过webview访问私有目录下的文件数据。&/p&&p&
危害情况:在Android中,mWebView.setAllowFileAccess(true)为默认设置。当setAllowFileAccess(true)时,在File域下,可执行任意的JavaScript代码,如果绕过同源策略能够对私有目录文件进行访问,导致用户隐私泄漏。&/p&&p&
修复建议:使用WebView.getSettings().setAllowFileAccess(false)来禁止访问私有文件数据。&/p&&p&&b&SSL通信服务端检测信任任意证书&/b&&/p&&p&
风险详情:自定义SSL x509 TrustManager,重写checkServerTrusted方法,方法内不做任何服务端的证书校验。&/p&&p&
危害情况:黑客可以使用中间人攻击获取加密内容。&/p&&p&
修复建议:严格判断服务端和客户端证书校验,对于异常事件禁止return 空或者null。&/p&&p&&b&HTTPS关闭主机名验证&/b&&/p&&p&
风险详情:构造HttpClient时,设置HostnameVerifier时参数使用ALLOW_ALL_HOSTNAME_VERIFIER或空的HostnameVerifier。&/p&&p&
危害情况:关闭主机名校验可以导致黑客使用中间人攻击获取加密内容。&/p&&p&
修复建议:APP在使用SSL时没有对证书的主机名进行校验,信任任意主机名下的合法的证书,导致加密通信可被还原成明文通信,加密传输遭到破坏。&/p&&p&&b&SSL通信客户端检测信任任意证书&/b&&/p&&p&
风险详情:自定义SSL x509 TrustManager,重写checkClientTrusted方法,方法内不做任何服务端的证书校验。&/p&&p&
危害情况:黑客可以使用中间人攻击获取加密内容。&/p&&p&
修复建议:严格判断服务端和客户端证书校验,对于异常事件禁止return 空或者null。&/p&&p&&b&开放socket端口&/b&&/p&&p&
风险详情:App绑定端口进行监听,建立连接后可接收外部发送的数据。&/p&&p&
危害情况:攻击者可构造恶意数据对端口进行测试,对于绑定了IP 0.0.0.0的App可发起远程攻击。&/p&&p&
修复建议:如无必要,只绑定本地ip127.0.0.1,并且对接收的数据进行过滤、验证。&/p&&h2&&b&第三大类:数据安全风险&/b&&/h2&&p&&b&数据存储&/b&&/p&&p&&b&SD卡数据被第三方程序访问&/b&&/p&&p&
漏洞描述:发现调用getExternalStorageDirectory,存储内容到SD卡可以被任意程序访问,存在安全隐患。&/p&&p&
安全建议:建议存储敏感信息到程序私有目录,并对敏感数据加密&/p&&p&&b&全局File可读写漏洞-openFileOutput&/b&&/p&&p&
风险详情:openFileOutput(String name,int mode)方法创建内部文件时,将文件设置了全局的可读权限MODE_WORLD_READABLE。&/p&&p&
危害情况:攻击者恶意读取文件内容,获取敏感信息。&/p&&p&
修复建议:请开发者确认该文件是否存储敏感数据,如存在相关数据,请去掉文件全局可读属性。&/p&&p&&b&全局文件可写&/b&&/p&&p&
风险详情:openFileOutput(String name,int mode)方法创建内部文件时,将文件设置了全局的可写权限MODE_WORLD_WRITEABLE。&/p&&p&
危害情况:攻击者恶意写文件内容破坏APP的完整性。&/p&&p&
修复建议:请开发者确认该文件是否存储敏感数据,如存在相关数据,请去掉文件全局可写属性。&/p&&p&&b&全局文件可读可写&/b&&/p&&p&
风险详情:openFileOutput(String name,int mode)方法创建内部文件时,将文件设置了全局的可读写权限。&/p&&p&
危害情况:攻击者恶意写文件内容或者,破坏APP的完整性,或者是攻击者恶意读取文件内容,获取敏感信息。&/p&&p&
修复建议:请开发者确认该文件是否存储敏感数据,如存在相关数据,请去掉文件全局可写、写属性。&/p&&p&&b&私有文件泄露风险-getSharedPreferences&/b&&/p&&p&&b&配置文件可读&/b&&/p&&p&
风险详情:使用getSharedPreferences打开文件时第二个参数设置为MODE_WORLD_READABLE。&/p&&p&
危害情况:文件可以被其他应用读取导致信息泄漏。&/p&&p&
修复建议:如果必须设置为全局可读模式供其他程序使用,请保证存储的数据非隐私数据或是加密后存储。&/p&&p&&b&配置文件可写&/b&&/p&&p&
风险详情:使用getSharedPreferences打开文件时第二个参数设置为MODE_WORLD_WRITEABLE。&/p&&p&
危害情况:文件可以被其他应用写入导致文件内容被篡改,可能导致影响应用程序的正常运行或更严重的问题。&/p&&p&
修复建议:使用getSharedPreferences时第二个参数设置为MODE_PRIVATE即可。&/p&&p&&b&配置文件可读可写&/b&&/p&&p&
风险详情:使用getSharedPreferences打开文件时,如将第二个参数设置为MODE_WORLD_READABLE 或MODE_WORLD_WRITEABLE。&/p&&p&
危害情况:当前文件可以被其他应用读取和写入,导致信息泄漏、文件内容被篡改,影响应用程序的正常运行或更严重的问题。&/p&&p&
修复建议:使用getSharedPreferences时第二个参数设置为MODE_PRIVATE。禁止使用MODE_WORLD_READABLE | MODE_WORLD_WRITEABLE模式。&/p&&p&&b&数据加密&/b&&/p&&p&
明文数字证书漏洞:&/p&&p&
Apk使用的数字证书可被用来校验服务器的合法身份,以及在与服务器进行通信的过程中对传输数据进行加密、解密运算,保证传输数据的保密性、完整性。&/p&&p&
明文存储的数字证书如果被篡改,客户端可能连接到假冒的服务端上,导致用户名、密码等信息被窃取;如果明文证书被盗取,可能造成传输数据被截获解密,用户信息泄露,或者伪造客户端向服务器发送请求,篡改服务器中的用户数据或造成服务器响应异常。&/p&&p&&b&AES弱加密&/b&&/p&&p&
风险详情:在AES加密时,使用“AES/ECB/NoPadding”或“AES/ECB/PKCS5padding”的模式。&/p&&p&
危害情况:ECB是将文件分块后对文件块做同一加密,破解加密只需要针对一个文件块进行解密,降低了破解难度和文件安全性。&/p&&p&
修复建议:禁止使用AES加密的ECB模式,显式指定加密算法为:CBC或CFB模式,可带上PKCS5Padding填充。AES密钥长度最少是128位,推荐使用256位。&/p&&p&&b&随机数不安全使用&/b&&/p&&p&
风险详情:调用SecureRandom类中的setSeed方法。&/p&&p&
危害情况:生成的随机数具有确定性,存在被破解的可能性。&/p&&p&
修复建议:用/dev/urandom或/dev/random来初始化伪随机数生成器。&/p&&p&&b&AES/DES硬编码密钥&/b&&/p&&p&
风险详情:使用AES或DES加解密时,密钥采用硬编码在程序中。&/p&&p&
危害情况:通过反编译获取密钥可以轻易解密APP通信数据。&/p&&p&
修复建议:密钥加密存储或变形后进行加解密运算,不要硬编码到代码中。&/p&&p&
数据传输:与上面的重复了,也可以把webview系列的漏洞归入这一小类。 &/p&&h2&&b&第四大类:文件目录遍历类漏洞&/b&&/h2&&p&&b&Provider文件目录遍历&/b&&/p&&p&
风险详情:当Provider被导出且覆写了openFile方法时,没有对Content Query Uri进行有效判断或过滤。&/p&&p&危害情况:攻击者可以利用openFile()接口进行文件目录遍历以达到访问任意可读文件的目的。&/p&&p&
修复建议:一般情况下无需覆写openFile方法,如果必要,对提交的参数进行“../”目录跳转符或其他安全校验。&/p&&p&&b&unzip解压缩漏洞&/b&&/p&&p&
风险详情:解压zip文件,使用getName()获取压缩文件名后未对名称进行校验。&/p&&p&
危害情况:攻击者可构造恶意zip文件,被解压的文件将会进行目录跳转被解压到其他目录,覆盖相应文件导致任意代码执行。&/p&&p&
修复建议:解压文件时,判断文件名是否有../特殊字符。 &/p&&h2&&b&第五大类:文件格式解析类漏洞&/b&&/h2&&p&&b&FFmpeg文件读取&/b&&/p&&p&
风险详情:使用了低版本的FFmpeg库进行视频解码。&/p&&p&
危害情况:在FFmpeg的某些版本中可能存在本地文件读取漏洞,可以通过构造恶意文件获取本地文件内容。&/p&&p&
修复建议:升级FFmpeg库到最新版。&/p&&p&&b&安卓“Janus”漏洞&/b&&/p&&p&
漏洞详情:向原始的App APK的前部添加一个攻击的classes.dex文件(A文件),安卓系统在校验时计算了A文件的hash值,并以”classes.dex”字符串做为key保存, 然后安卓计算原始的classes.dex文件(B),并再次以”classes.dex”字符串做为key保存,这次保存会覆盖掉A文件的hash值,导致Android系统认为APK没有被修改,完成安装,APK程序运行时,系统优先以先找到的A文件执行,忽略了B,导致漏洞的产生。&/p&&p&
危害情况:该漏洞可以让攻击者绕过安卓系统的signature scheme V1签名机制,进而直接对App进行篡改。而且由于安卓系统的其他安全机制也是建立在签名和校验基础之上,该漏洞相当于绕过了安卓系统的整个安全机制。&/p&&p&
修复建议:禁止安装有多个同名ZipEntry的APK文件。 &/p&&h2&&b&第六大类:内存堆栈类漏洞&/b&&/h2&&p&&b&未使用编译器堆栈保护技术&/b&&/p&&p&
风险详情:为了检测栈中的溢出,引入了Stack Canaries漏洞缓解技术。在所有函数调用发生时,向栈帧内压入一个额外的被称作canary的随机数,当栈中发生溢出时,canary将被首先覆盖,之后才是EBP和返回地址。在函数返回之前,系统将执行一个额外的安全验证操作,将栈帧中原先存放的canary和.data中副本的值进行比较,如果两者不吻合,说明发生了栈溢出。&/p&&p&
危害情况:不使用Stack Canaries栈保护技术,发生栈溢出时系统并不会对程序进行保护。&/p&&p&
修复建议:使用NDK编译so时,在Android.mk文件中添加:LOCAL_CFLAGS := -Wall -O2 -U_FORTIFY_SOURCE -fstack-protector-all&/p&&p&&b&未使用地址空间随机化技术&/b&&/p&&p&
风险详情:PIE全称Position Independent Executables,是一种地址空间随机化技术。当so被加载时,在内存里的地址是随机分配的。&/p&&p&
危害情况:不使用PIE,将会使得shellcode的执行难度降低,攻击成功率增加。&/p&&p&
修复建议:NDK编译so时,加入LOCAL_CFLAGS := -fpie -pie开启对PIE的支持。&/p&&p&&b&libupnp栈溢出漏洞&/b&&/p&&p&
风险详情:使用了低于1.6.18版本的libupnp库文件。&/p&&p&
危害情况:构造恶意数据包可造成缓冲区溢出,造成代码执行。&/p&&p&
修复建议:升级libupnp库到1.6.18版本或以上。 &/p&&h2&&b&第七大类:动态类漏洞&/b&&/h2&&p&&b&DEX文件动态加载&/b&&/p&&p&
风险详情:使用DexClassLoader加载外部的apk、jar 或dex文件,当外部文件的来源无法控制时或是被篡改,此时无法保证加载的文件是否安全。&/p&&p&
危害情况:加载恶意的dex文件将会导致任意命令的执行。&/p&&p&
修复建议:加载外部文件前,必须使用校验签名或MD5等方式确认外部文件的安全性。&/p&&p&&b&动态注册广播&/b&&/p&&p&
风险详情:使用registerReceiver动态注册的广播在组件的生命周期里是默认导出的。&/p&&p&
危害情况:导出的广播可以导致拒绝服务、数据泄漏或是越权调用。&/p&&p&
修复建议:使用带权限检验的registerReceiver API进行动态广播的注册。&/p&&h2&&b&第八大类:校验或限定不严导致的风险或漏洞&/b&&/h2&&p&&b&Fragment注入&/b&&/p&&p&
风险详情:通过导出的PreferenceActivity的子类,没有正确处理Intent的extra值。&/p&&p&
危害情况:攻击者可绕过限制访问未授权的界面。&/p&&p&
修复建议:当targetSdk大于等于19时,强制实现了isValidFragment方法;小于19时,在PreferenceActivity的子类中都要加入isValidFragment ,两种情况下在isValidFragment方法中进行fragment名的合法性校验。&/p&&p&&b&隐式意图调用&/b&&/p&&p&
风险详情:封装Intent时采用隐式设置,只设定action,未限定具体的接收对象,导致Intent可被其他应用获取并读取其中数据。&/p&&p&
危害情况:Intent隐式调用发送的意图可被第三方劫持,导致内部隐私数据泄露。&/p&&p&
修复建议:可将隐式调用改为显式调用。 &/p&&h2&&b&第九大类:命令行调用类相关的风险或漏洞&/b&&/h2&&p&&b&动态链接库中包含执行命令函数:&/b&&/p&&p&风险详情:在native程序中,有时需要执行系统命令,在接收外部传入的参数执行命令时没有做过滤或检验。&/p&&p&
危害情况:攻击者传入任意命令,导致恶意命令的执行。&/p&&p&
修复建议:对传入的参数进行严格的过滤。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-d1c9c289a5be6f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&225& data-rawheight=&225& class=&content_image& width=&225&&&/figure&&p&利益相关:如果看完以上干货意犹未尽,欢迎&a href=&//link.zhihu.com/?target=https%3A//www.163yun.com/product/android-protect%3Ftag%3DM_zhihu_& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&免费试用网易云易盾Android 应用加固产品&/a&,保证解决你的安全难题。&/p&
Android应用会遇到各种各样的漏洞,如何从细节上了解各种安全隐患,积极采取适当的防御措施便变得尤为重要。为了让大家对Android漏洞有一个非常全面的认识,小编专门邀请资深安全工程师徐从祥为大家详细解读九大常见的Android漏洞,供各位参考。…
&figure&&img src=&https://pic4.zhimg.com/v2-7a55ed87be2fd85f4577f_b.jpg& data-rawwidth=&550& data-rawheight=&289& class=&origin_image zh-lightbox-thumb& width=&550& data-original=&https://pic4.zhimg.com/v2-7a55ed87be2fd85f4577f_r.jpg&&&/figure&&p&本系列文章引用了腾讯技术专家樊华恒《海量之道系列文章之弱联网优化 &a href=&http://link.zhihu.com/?target=http%3A//gad.qq.com/article/detail/29546& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&gad.qq.com/article/deta&/span&&span class=&invisible&&il/29546&/span&&span class=&ellipsis&&&/span&&/a&》的章节,感谢原作者。&/p&&p&&br&&/p&&h2&1、前言&/h2&&p&&br&&/p&&p&本文接上篇《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”&/a&》,关于移动网络的主要特性,在上篇中已进行过详细地阐述,&u&本文将针对上篇中提到的特性,结合我们的实践经验,总结了四个方法来追求极致的“爽快”:快链路、轻往复、强监控、多异步,从理论讲到实践、从技术讲到产品,理论联系实际,举一反三,希望给您带来启发&/u&。&/p&&p&如果您还未阅读完上篇《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”&/a&》,建议您先行读完后再续本文。&/p&&p&本篇的目的,就是希望以通俗易懂的语言,帮助移动端IM开发者更好地针对性优化移动网络的各种特性,使得开发出的功能给用户带来更好的使用体验。&/p&&p&本文乃全网同类文章中,唯一内容最全、“粪”量最重者,请做好心理准备耐心读下去,不要辜负作者已打上石膏的双手和用废的键盘。&/p&&p&另外,《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障&/a&》这篇文章也提到了本文所阐述的相关内容,强烈建议阅读。&/p&&p&&b&学习交流:&/b&&/p&&blockquote&- 即时通讯开发交流3群:&a href=&http://link.zhihu.com/?target=https%3A//link.jianshu.com/%3Ft%3Dhttp%253A%252F%252Fshang.qq.com%252Fwpa%252Fqunwpa%253Fidkey%253D051ed62f79eaf622dd5b1c87b26bedb890b068be79dd2006fc80ccf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&&/a&[推荐]&br&- 移动端IM开发入门文章:《&a href=&http://link.zhihu.com/?target=https%3A//link.jianshu.com/%3Ft%3Dhttp%3A//www.52im.net/thread-464-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&新手入门一篇就够:从零开发移动端IM&/a&》&/blockquote&&p&(本文同步发布于:&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&52im.net/thread-1588-1-&/span&&span class=&invisible&&1.html&/span&&span class=&ellipsis&&&/span&&/a&)&/p&&p&&br&&/p&&h2&2、系列文章&/h2&&p&&br&&/p&&p&&b&▼&/b& &b&本文是《移动端IM开发者必读》系列文章的第2篇:&/b&&/p&&ul&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”&/a&》&/li&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&移动端IM开发者必读(二):史上最全移动弱网络优化方法总结&/a&》(本文)&br&&/li&&/ul&&p&如果您是IM开发初学者,强烈建议首先阅读《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-464-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&新手入门一篇就够:从零开发移动端IM&/a&》。&/p&&h2&3、相关文章&/h2&&p&&br&&/p&&p&&b&1)关于网络通信的基础文章:&/b&&/p&&ul&&li&如果您对网络通信知识了解甚少,建议阅读《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网络编程懒人入门系列文章&/a&》,更高深的网络通信文章可以阅读《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&不为人知的网络编程系列文章&/a&》。&br&&/li&&/ul&&p&&br&&/p&&p&&b&2)涉及移动端网络特性的文章:&/b&&/p&&ul&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障&/a&》&/li&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-282-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&谈谈移动端 IM 开发中登录请求的优化&/a&》&/li&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-133-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&移动端IM开发需要面对的技术问题(含通信协议选择)&/a&》&/li&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-289-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&简述移动端IM开发的那些坑:架构设计、通信协议和客户端&/a&》&/li&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-195-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&微信对网络影响的技术试验及分析(论文全文)&/a&》&/li&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-675-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率&/a&》&/li&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-696-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(上篇)&/a&》&/li&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-697-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)&/a&》&/li&&li&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-684-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源&/a&》&br&&/li&&/ul&&p&&br&&/p&&h2&4、优化方法一:“快链路”&/h2&&p&&br&&/p&&p&我们需要有一条(相对)快速、(相对)顺畅、(相对)稳定的网络通道承载业务数据的传输,这条路的最好是传输快、不拥堵、带宽大、收费少。生活中做个类比,我们计划驱车从深圳到广州,如果想当然走广深高速十之八九要杯具,首先这个高速略显破败更像省道,路况不佳不敢提速;其次这条路上的车时常如过江之鲫,如果身材不好操控不便,根本就快不起来;最后双向六车道虽然勉强可以接受,但收费居然比广深沿江高速双向八车道还贵;正确的选路方案目前看是走沿江高速,虽然可能要多跑一段里程,但是通行更畅快。&/p&&p&实际上,真实情况要更复杂,就如同上篇中&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&【图二 有线互联网和移动互联网网络质量差异】&/a&所示(就是下图),漫漫征途中常常会在高速、国道、省道、田间小道上切换。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-f4b9fcca41cd636b24ec3a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&748& data-rawheight=&247& class=&origin_image zh-lightbox-thumb& width=&748& data-original=&https://pic3.zhimg.com/v2-f4b9fcca41cd636b24ec3a_r.jpg&&&/figure&&h2&4.1TCP/IP协议栈参数调优&/h2&&p&&br&&/p&&p&纯技术活,直接上建议得了,每个子项争取能大致有个背景交待,如果没说清楚,可以先看看以下资料:&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/topic-tcpipvol1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&TCP/IP详解&/a& - &a href=&http://link.zhihu.com/?target=http%3A//docs.52im.net/extend/docs/book/tcpip/vol1/17/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&第17章·TCP:传输控制协议&/a&》&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/topic-tcpipvol1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&TCP/IP详解&/a& - &a href=&http://link.zhihu.com/?target=http%3A//docs.52im.net/extend/docs/book/tcpip/vol1/18/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&第18章·TCP连接的建立与终止&/a&》&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/topic-tcpipvol1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&TCP/IP详解&/a& - &a href=&http://link.zhihu.com/?target=http%3A//docs.52im.net/extend/docs/book/tcpip/vol1/21/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&第21章·TCP的超时与重传&/a&》&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-513-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&通俗易懂-深入理解TCP协议(上):理论基础&/a&》&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-515-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&通俗易懂-深入理解TCP协议(下):RTT、滑动窗口、拥塞处理&/a&》&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-258-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&理论经典:TCP协议的3次握手与4次挥手过程详解&/a&》&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&不为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)&/a&》&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&不为人知的网络编程(二):浅析TCP协议中的疑难杂症(下篇)&/a&》&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&不为人知的网络编程(三):关闭TCP连接时为什么会TIME_WAIT、CLOSE_WAIT&/a&》&br&《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网络编程懒人入门(三):快速理解TCP协议一篇就够&/a&》&/p&&p&&b&① 控制传输包大小&/b&&/p&&p&控制传输包的大小在1400字节以下。暂时不讲为什么这样建议,先举个例子来类比一下,比如一辆大卡车满载肥猪正在高速上赶路,猪笼高高层叠好不壮观,这时前方突然出现一个隧道限高标识,司机发现卡车超限了,这下咋整。方案一,停车调头重新找路,而且十之八九找不到,最后只能哪来回哪;方案二,把其中一群猪卸下来放本地找人代养,到达目的地卸完货回来再取,你别说,这个机制在TCP/IP协议栈中也有,学名“IP分片”,后面会专门介绍。这个故事侧面证实美国计算机科学家也曾经蹲在高速路边观察生猪超载运输的过程,并饱受启发。且慢,每次遇到问题,想到一些方案后我们都应该再扪心自问:“还有没有更好的办法呢?”。当然有,参照最近流行的说法,找个台风眼,把猪都赶过去,飞一会就到了,此情此景想想也是醉了。&/p&&p&回归正题,概括的说,我们设定1400这个阈值,目的是减少往复,提高效能。因为TCP/IP网络中也有类似高速限高的规定,如果在超限时想要继续顺畅传输,要么做IP分片要么把应用数据拆分为多个数据报文(意指因为应用层客户端或服务器向对端发送的请求或响应数据太大时,TCP/IP协议栈控制机制自动将其拆分为若干独立数据报文发送的情况,后面为简化讨论,都以IP分片这个分支为代表,相关过程分析和结论归纳对二者均适用)。而一旦一个数据报文发生了IP分片,便会在数据链路层引入多次的传输和确认,加上报文的拆分和拼接开销,令得整个数据包的发送时延大大增加,并且,IP分片机制中,任何一个分片出现丢失时还会带来整个IP数据报文从最初的发起端重传的消耗。有点枯燥了,更深入的理解,请参见:《&a href=&http://link.zhihu.com/?target=https%3A//cloud.tencent.com/developer/article/1005367& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&海量之道系列文章之弱联网优化 (二)&/a&》。&/p&&p&我们可以得出如下结论,TCP/IP数据报文大小超过物理网络层的限制时,会引发IP分片,从而增加时空开销。&/p&&p&因此,设定合理的MSS至关重要,对于以太网MSS值建议是1400字节。什么,你的数学是体育老师教的吗?前面说以太网最大的传输数据大小是1500字节,IP数据报文包头是20字节,TCP报文包头是20字节,算出来MSS怎么也得是1460字节呀。如果回答是因为很多路由设备比如CISCO路由器把MSS设定为1400字节,大伙肯定不干,回忆一下IP和TCP的数据报包头都各有40字节的可选项,MTU中还需要为这些可选项留出空间,也就压缩了MSS的空间。要是再追问为啥这个值不是1380字节,那就有点过分了。&/p&&p&&b&知识加油站:什么是MSS?&/b&&/p&&p&TCP MSS(TCP Maximum Segment Size,TCP最大报文段长度,后面均简称MSS)表示TCP/IP协议栈一次可以传往另一端的最大TCP数据长度,注意这个长度是指TCP报文中的有效“数据”(即应用层发出的业务数据)部分,它不包括TCP报文包头部分,我们可以把它理解为卡车能装运生猪的最大数量或重量。它是TCP选项中最经常出现,也是最早出现的选项,占4字节空间。&br&&br&MSS是在建立TCP链接的三次握手过程中协商的,每一方都会在SYN或SYN/ACK数据报文中通告其期望接收数据报文的MSS(MSS也只能出现在SYN或SYN/ACK数据报中),说是协商,其实也没太多回旋的余地,原因一会讲。如果协商过程中一方不接受另一方的MSS值,则TCP/IP协议栈会选择使用默认值:536字节。&/p&&p&&br&&/p&&p&那么问题来了,控制“限高”哪种方案才最强。我们尝试探讨一下。&/p&&p&首先,可以在我们自己IDC内将各种路由交换设备的MSS设定小于或等于1400字节,并积极参与TCP三次握手时的MSS协商过程,期望达到自动控制服务器收发数据报文大小不超过路径最小MTU从而避免IP分片。这个方案的问题是如果路由路径上其它设备不积极参与协商活动,而它的MTU(或MSS设置值)又比较low,那就白干了。这就好比国家制定了一个高速沿途隧道限高公示通告标准,但是某些地方政府就是不告诉你,没辙。&/p&&p&其次,可以在业务服务中控制应用数据请求/响应的大小在1400字节以下(注:也无法根本避免前述方案中间路由MTU/MSS low的问题),在应用层数据写入时就避免往返数据包大小超过协商确定的MSS。但是,归根到底,在出发前就把数据拆分为多个数据报文,同IP分片机制本质是相同的,交互响应开销增加是必然的。考虑到人在江湖,安全第一,本方案从源头上控制,显得更实际一些。&/p&&p&当然,最靠谱的还是做简法,控制传输数据的欲望,用曼妙的身姿腾挪有致,相关的内容放到轻往复章节探讨。&/p&&p&对应到前面的快乐运猪案例,就是要么在生猪装车之前咱们按照这条路上的最低限高来装车(问题是怎么能知道整个路上的最低限高是多少),要么按照国家标准规定允许的最小限高来装车,到这里,肥猪们终于可以愉快的上路了,风和日丽,通行无阻,嗯,真的吗?&/p&&p&&b&② 放大TCP拥塞窗口&/b&&/p&&p&把TCP拥塞窗口(cwnd)初始值设为10,这也是目前Linux Kernel中TCP/IP协议栈的缺省值。放大TCP拥塞窗口是一项有理有据的重要优化措施,对移动网络尤其重要,我们同样从一些基本理论开始逐步深入理解它。&/p&&p&TCP是个传输控制协议,体现控制的两个关键机制分别是基于滑动窗口的端到端之间的流量控制和基于RTT/RTO测算的端到网络之间的拥塞控制。&/p&&p&流量控制目标是为了避免数据发送太快对端应用层处理不过来造成SOCKET缓存溢出,就像一次发了N车肥猪,买家那边来不及处理,然后临时囤货的猪圈又已客满,只好拒收/抛弃,相关概念和细节我们不展开了,有兴趣可以研读《TCP/IP详解 卷一:协议》。&/p&&p&拥塞控制目标是在拥塞发生时能及时发现并通过减少数据报文进入网络的速率和数量,达到防止网络拥塞的目的,这种机制可以确保网络大部分时间是可用的。拥塞控制的前提在于能发现有网络拥塞的迹象,TCP/IP协议栈的算法是通过分组丢失来判断网络上某处可能有拥塞情况发生,评判的具体指标为分组发送超时和收到对端对某个分组的重复ACK。在有线网络时代,丢包发生确实能比较确定的表明网络中某个交换设备故障或因为网络端口流量过大,路由设备转发处理不及时造成本地缓存溢出而丢弃数据报文,但在移动网络中,丢包的情况就变得非常复杂,其它因素影响和干扰造成丢包的概率远远大于中间路由交换设备的故障或过载。比如短时间的信号干扰、进入一个信号屏蔽的区域、从空闲基站切换到繁忙基站或者移动网络类型切换等等。网络中增加了这么多不确定的影响因素,这在TCP拥塞控制算法最初设计时,是无法预见的,同时,我们也确信未来会有更完善的解决方案。这是题外话,如有兴趣可以找些资料深入研究(详见:《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/topic-tcpipvol1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&TCP/IP详解&/a& - &a href=&http://link.zhihu.com/?target=http%3A//docs.52im.net/extend/docs/book/tcpip/vol1/21/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&第21章·TCP的超时与重传&/a&》、《&a href=&http://link.zhihu.com/?target=http%3A//www.52im.net/thread-515-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&通俗易懂-深入理解TCP协议(下):RTT、滑动窗口、拥塞处理&/a&》、《&a href=&http://link.zhihu.com/?target=https%3A//cloud.tencent.com/developer/article/1005368& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&海量之道系列文章之弱联网优化 (三)&/a&》)。&/p&&p&拥塞控制是TCP/IP协议栈最经典的和最复杂的设计之一,互联网自我牺牲的利他精神表露无遗,设计者认为,在拥塞发生时,我们应该减少数据报文进入网络的速率和数量,主动让出道路,令网络能尽快调整恢复至正常水平。&/p&&p&&b&③ 调大SOCKET读写缓冲区&/b&&/p&&p&把SOCKET的读缓冲区(亦可称为发送缓冲区)和写缓冲区(亦可称为接收缓冲区)大小设置为64KB。在Linux平台上,可以通过 setsockopt 函数设置SO_RCVBUF和SO_SNDBUF选项来分别调整SOCKET读缓冲区和写缓冲区的大小。&/p&&p&这两个缓冲区跟我们的TCP/IP协议栈到底有怎么样的关联呢。我们回忆一下TCP数据报格式及首部中的各字段里面有个16位窗口大小(见下图),还有我们前面提到的流量控制机制和滑动窗口的概念,大幕徐徐拉开,主角纷纷粉墨登场。在正式详细介绍之前,按照传统,我们还是先站在猪场老板的角度看一下,读缓冲区就好比买家用来囤货的临时猪圈,如果货到了买家使用部门来不及处理,就先在这里临时囤着,写缓冲区就好比养猪场根据订单装好车准备发货,如果买家说我现在可以收货便可速度发出,有点明白了吧。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-1cbedcd64c96b6_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&649& data-rawheight=&435& class=&origin_image zh-lightbox-thumb& width=&649& data-original=&https://pic3.zhimg.com/v2-1cbedcd64c96b6_r.jpg&&&/figure&&p&&b&④ 调大RTO(Retransmission TimeOut)初始值&/b&&/p&&p&将RTO(Retransmission TimeOut)初始值设为3s。&/p&&p&TCP为每一个报文段都设定了一个定时器,称为重传定时器(RTO),当RTO超时且该报文段还没有收到接收端的ACK确认,此时TCP就会对该报文段进行重传。当TCP链路发生超时时,意味着很可能某个报文段在网络路由路径的某处丢失了,也因此判断此时网络出现拥塞的可能性变得很大,TCP会积极反应,马上启动拥塞控制机制。&/p&&p&RTO初始值设为3s,这也是目前Linux Kernel版本中TCP/IP协议栈的缺省值,在链路传输过程中,TCP协议栈会根据RTT动态重新计算RTO,以适应当前网络的状况。有很多的网络调优方案建议把这个值尽量调小,但是,我们开篇介绍移动网络的特点之一是高时延,这也意味着在一个RTT比较大的网络上传输数据时,如果RTO初始值过小,很可能发生不必要的重传,并且还会因为这个事件引起TCP协议栈的过激反应,大炮一响,拥塞控制闪亮登场。&/p&&p&猪场老板的态度是什么样的呢:曾经有一份按时发货的合同摆在我的面前,我没有去注意,等到重新发了货才追悔莫及,尘世间最痛苦的事莫过于此,如果上天能给我一个再来一次的机会,我希望对甲方说耐心点,如果非要给这个耐心加一个期限的话,我希望是一万年。&br&&br&&b&⑤ 禁用TCP快速回收&/b&&/p&&p&TCP快速回收是一种链接资源快速回收和重用的机制,当TCP链接进入到TIME_WAIT状态时,通常需要等待2MSL的时长,但是一旦启用TCP快速回收,则只需等待一个重传时间(RTO)后就能够快速的释放这个链接,以被重新使用。&/p&&p&&b&Linux Kernel的TCP/IP协议栈提供了一组控制参数用于配置TCP端口的快速回收重用,当把它们的值设置为1时表示启用该选项:&/b&&/p&&ul&&li&1)
net.ipv4.tcp_tw_reuse = 1&/li&&li&2) net.ipv4.tcp_tw_recycle = 1&/li&&li&3)
net.ipv4.tcp_timestamps = 1(tcp_tw_recycle启用时必须同时启用本项,反之则不然,timestamps用于RTT计算,在TCP报文头部的可选项中传输,包括两个参数,分别为发送方发送TCP报文时的时间戳和接收方收到TCP报文响应时的时间戳。Linux系统和移动设备上的Android、iOS都缺省开启了此选项,建议不要随意关闭)&br&&/li&&/ul&&p&&br&&/p&&p&以上参数中tw是TIME_WAIT的缩写,TIME_WAIT与TCP层的链接关闭状态机相关。具体TIME_WAIT是谁,从哪里来,往哪里去,可以详见:《&a href=&http://link.zhihu.com/?target=https%3A//cloud.tencent.com/developer/article/1005370& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&海量之道系列文章之弱联网优化 (四)&/a&》。&/p&&p&&b&⑥ HTTP协议:打开SOCKET的TCP_NODELAY选项&/b&&/p&&p&TCP/IP协议栈为了提升传输效率,避免大量小的数据报文在网络中流窜造成拥塞,设计了一套相互协同的机制,那就是Nagle's Algorithm和TCP Delayed Acknoledgement。&/p&&p&Nagle算法(Nagle's Algorithm)是以发明人John Nagle的名字来命名。John Nagle在1984年首次用这个算法来尝试解决福特汽车公司的网络拥塞问题(RFC 896),该问题的具体描述是:如果我们的应用程序一次产生1个字节的数据(典型的如telnet、XWindows等应用),而这个1个字节数据又以网络数据包的形式发送到远端服务器,那么就很容易使网络中有太多微小分组而导致过载。&/p&&p&因为传输1个字节有效数据的微小分组却需花费40个字节的额外开销(即IP包头20字节 + TCP包头20字节),这种有效载荷利用率极其低下的情况被统称为愚蠢窗口症候群(Silly Window Syndrome),前面我们在谈MSS时也提到过,如果为一头猪开个大卡车跑一趟,也够愚钝的。对于轻负载广域网或者局域网来说,尚可接受,但是对于重负载的广域网而言,就极有可能引起网络拥塞导致瘫痪。&/p&&p&现代TCP/IP 协议栈默认几乎都启用了这两个功能。&/p&&p&我们在移动APP的设计实现中,请求大部分都很轻(数据大小不超过MSS),为了避免上述分析的问题,建议开启SOCKET的TCP_NODELAY选项,同时,我们在编程时对写数据尤其要注意,一个有效指令做到一次完整写入(后面会讲协议合并,是多个指令一次完整写入的设计思想),这样服务器会马上有响应数据返回,顺便也就捎上ACK了。&/p&&h2&4.2接入调度&/h2&&p&&br&&/p&&p&&b&① 就快接入&/b&&/p&&p&在客户端接入服务器调度策略的演化过程中,我们最早采用了“就近接入”的策略,在距离客户端更近的地方部署服务器或使用CDN,期望通过减少RTT来提高网络交互响应性能。这个策略在国内的落地执行还需要加一个前缀:“分省分运营商”,这就给广大负责IDC建设的同学带来了巨大的精神和肉体折磨。&/p&&p&在持续运营的过程中,根据观察到的数据,发现并非物理距离最近的就是最快的。回忆一下前面谈到的吞吐量指标BDP,它与链路带宽和RTT成正比关系,而RTT是受物理距离、网络拥塞程度、IDC吞吐量、跨网时延等诸多因素综合影响的,单纯的就近显然不够精细了。&/p&&p&“就快接入”在“就近接入”策略的基础上改善提升,它利用客户端测速和报告机制,通过后台大数据分析,形成与客户端接入IP按就快原则匹配接入服务器的经验调度策略库,令客户端总能优先选择到最快的服务器接入点。&/p&&p&有关就快接入的更详细方案,请参见:《&a href=&http://link.zhihu.com/?target=https%3A//cloud.tencent.com/developer/article/1005371& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&海量之道系列文章之弱联网优化(五)&/a&》一文的“3.1.2节”。&/p&&p&&b&② 去DNS的IP直连&/b&&/p&&p&DNS不但需要1个RTT的时间消耗,而且移动网络下的DNS还存在很多其它问题:&/p&&ul&&li&1) 部分DNS承载全网用户40%以上的查询请求,负载重,一旦故障,影响巨大,这样的案例在PC互联网也有很多,Google一下即可感受触目惊心的效果;&/li&&li&2) 山寨、水货、刷ROM等移动设备的LOCAL DNS设置错误;&/li&&li&3) 终端DNS解析滥用,导致解析成功率低;&/li&&li&4) 某些运营商DNS有域名劫持问题,实际上有线ISP也存在类似问题。域名劫持对安全危害极大,产品设计时要注意服务端返回数据的安全校验(如果协议已经建立在安全通道上时则不用考虑,安全通道可以基于HTTPS或者私有安全体系)。对于劫持的判断需要客户端报告实际拉取服务数据的目标地址IP等信息;&/li&&li&5) DNS污染、老化、脆弱。&br&&/li&&/ul&&p&&br&&/p&&p&综上就是在前述就快接入小节中,接入调度FSM会优先使用动态服务器列表的原因。&/p&&p&&b&③ 网络可达性探测&/b&&/p&&p&在连接建立过程中如果出现连接失败的现象,而终端系统提供的网络状态接口反馈网络可用时,我们需要做网络可达性探测(即向预埋的URL或者IP地址发起连接尝试),以区别网络异常和接入服务异常的情况,为定位问题,优化后台接入调度做数据支持。&/p&&p&探测数据可以异步报告到服务器,至少应该包含以下字段:&/p&&ul&&li&1) 探测事件ID,要求全局唯一不重复;&/li&&li&2) 探测发生时间;&/li&&li&3) 探测发生时网络类型和其它网络信息(比如WIFI时的SSID等);&/li&&li&4) 本地调度的接入服务器集合类型;&/li&&li&5) 本地调度的接入服务器IP(如使用域名接入,可忽略);&/li&&li&6) 探测的目标URL或IP地址&/li&&li&7) 本次探测的耗时。&br&&/li&&/ul&&p&&br&&/p&&h2&4.3链路管理&/h2&&p&&br&&/p&&p&链路就是运肥猪的高速路,就快接入是选路,链路管理就是如何高效的使用这条路。下面是一些实践总结:&/p&&p&&b&① 链路复用&/b&&/p&&p&我们在开篇讨论无线网络为什么慢的时候,提到了链接建立时三次握手的成本,在无线网络高时延、频抖动、窄带宽的环境下,用户使用趋于碎片化、高频度,且请求响应又一次性往返居多、较频繁发起等特征,建链成本显得尤其显著。&/p&&p&因此,我们建议在链路创建后可以保持一段时间,比如HTTP短链接可以通过HTTP Keep-Alive,私有协议可以通过心跳等方式来保持链路。&/p&&p&具体要点建议如下:&/p&&ul&&li&1) 链路复用时,如果服务端按就快策略机制下发了新的接入动态服务器列表,则应该按照接入调度FSM的状态变迁,在本次交互数据完成后,重建与新的接入服务器的IP链路,有三个切换方案和时机可选择:&br&
- a. 关闭原有链接,暂停网络通讯,同时开始建立与新接入服务器的TCP链路,成功后恢复与服务器的网络交互;&br&
- b. 关闭原有链接,暂停网络通讯,待有网络交互需求时开始建立与新接入服务器的IP链路;&br&
- c. 原有链接继续工作,并同时开始建立与新接入服务器的TCP链路,成功后新的请求切换到新建链路上,这个方式或可称为预建链接,原链接在空闲时关闭。&/li&&li&2) 链路复用时区分轻重数据通道,对于业务逻辑等相关的信令类轻数据通道建议复用,对于富媒体拉取等重数据通道就不必了;&/li&&li&3) 链路复用时,如与协议合并(后面会讨论)结合使用,效果更佳。&br&&/li&&/ul&&p&&br&&/p&&p&&b&② 区分网络类型的超时管理&/b&&/p&&p&在不同的网络类型时,我们的链路超时管理要做精细化的区别对待。链路管理中共有三类超时,分别是连接超时、IO超时和任务超时。&/p&&p&我们有一些经验建议,提出来共同探讨:&/p&&ul&&li&1) 连接超时:2G/3G/4G下5 ~ 10秒,WIFI下5秒(给TCP三次握手留下1次超时重传的机会,可以研究一下《TCP/IP详解 卷一:协议》中TC P的超时与重传部分);&/li&&li&2) IO超时:2G/3G/4G下15 ~ 20秒(无线网络不稳定,给抖动留下必要的恢复和超时重传时间),WIFI下15秒(1个MSL);&/li&&li&3) 任务超时:根据业务特征不同而差异化处理,总的原则是前端面向用户交互界
面的任务超时要短一些(尽量控制在30秒内并有及时的反馈),后台任务可以长一些,轻数据可以短一些,重数据可以长一些;&/li&&li&4) 超时总是伴随着重试,我们要谨慎小心的重试,后面会讨论。&

我要回帖

更多关于 撤回邮件没有收到提示 的文章

 

随机推荐