2020华为软件精英挑战赛

    题意:给定一个有向图,求出图中所有长度在[3,7]之间的环。
    输入:格式为[IDU,IDV,Weight]的边表,ID为32位无符号整数(当然题目说明了,小于2^31,所以int32就好),边最多28W条,不重复,结点平均度数小于10。环中同一个ID不可以重复出现(若大环包括小环,则需要分开统计),环的个数不大于300W。
    输出:环的个数,按照1.环长度;2.环的数字字典序输出所有环。
    1.用fscanf和fprintf

    将所有入度为0的顶点入队,计数,记录当前已经输出的顶点数,从队列中取出一个顶点, 输出该顶点,将所有v指向的顶点的入度减1,并将入度减为0的顶点入栈,若入度为0,则入栈。

    算法优化
    从最初的单向DFS找环改成双向DFS。生成逆向图。
    拓扑排序过滤掉一些点,能在拓扑排序上的点一定不会在环上。
    链式前向星优化存储结构,O(n+m),核心是四个数组,head,to,edge和next。head长度为|V|, 后面三个数组长度都是|E|。

    io优化,
    从文件读取,因为是数字,所以最开始用的fscanf,后面改成getchar来读。
    我们在读id进来以后,输出的时候还得从数字转回字符串,所以加了一个缓存。相当于记录了从数字到字符串的映射,这样输出的时候不需要转,直接用系统调用write。
    用了mmap和分页预读以及字节对齐的技术。64位处理器,一次读8个字节是最合适的。
    mmap就是内存映射,文件磁盘地址和进程虚拟地址一一对应,只要操作指针,自动回写脏页面到对应的磁盘。
    多线程优化,因为处理器是4核的,所以设为5个线程。为什么多一个,因为偶尔有线程发送缺页故障暂停,额外的这个线程可以确保cpu跑满。
    考虑写一个线程池,但是因为这是计算密集型的,所以没有线程池,直接按照不同的数据范围来处理。主要是多线程处理字符串转数字和排序。
    还有循环展开。循环展开最常用来降低循环开销,为具有多核处理器提供指令级并行。也有利于指令流水线的调度。

    1. bool Graph::topological_sort(){
    2. for(int i=0; i<V; ++i)
    3. if(indegree[i] == 0)
    4. q.push(i); // 将所有入度为0的顶点入队
    5. int count = 0; // 计数,记录当前已经输出的顶点数
    6. while(!q.empty())
    7. {
    8. int v = q.front(); // 从队列中取出一个顶点
    9. q.pop();
    10. cout << v << " "; // 输出该顶点
    11. ++count;
    12. // 将所有v指向的顶点的入度减1,并将入度减为0的顶点入栈
    13. list<int>::iterator beg = adj[v].begin();
    14. for( ; beg!=adj[v].end(); ++beg)
    15. if(!(--indegree[*beg]))
    16. q.push(*beg); // 若入度为0,则入栈
    17. }
    18. if(count < V)
    19. return false; // 没有输出全部顶点,有向图中有回路
    20. else
    21. return true; // 拓扑排序成功
    22. }

    日报系统
    这个系统是最开始就是让导师更方便地管理学生,针对学生的汇报提供各种查询和统计,并对一些异常情况进行推送。后来又提供了一些日程提醒,以及研究生周期管理,它就是根据高年级的同学的汇报生成一些关键的时间节点,然后提供给低年级的学生使用,在一些关键节点(比如说该准备找实习了,该开始写论文了等等)做一些提醒。目前每天大概有100多个用户在上面填写汇报,用的是前后端分离,前端用的是vue,后端是Spring Cloud微服务,后端分了几个模块,汇报模块(包括了系统的核心功能,如汇报,统计分析,日程提醒),微信模块(负责与微信服务器通信),用户模块(管理系统的用户信息,群信息),然后还运行着一些中间件,比如Redis,Nacos,RocketMQ,Dubbo等。Redis我们这个团队后端一个是3个人,然后主要是按照功能划分职责。微信模块是我独立负责的,微信模块的功能就是和微信服务器交互,使用微信提供的接口获取用户信息,扫码,发送微信消息推送等。汇报模块我负责的主要是主页的加载这一块优化,之前主页不是我负责开发,然后每天用的时候发现主页加载很慢,通过使用Chrome自带的开发者工具查看加载时间,然后发现一些请求需要的时间超过了1s,然后优化了前端的CDN,以及把一些经常请求接口做了缓存。缓存用的redis。还有就是写了一个自动化部署的脚本。

    面试官好,我叫盘昊,我是四川大学计算机学院计算机专业研二学生,我在研究生期间获得了三等奖学金,参加过一场华为软件挑战赛获得了二等奖,最后是本科生获得过校级三等奖学金。目前我的技术栈主要是Java,另外我对Redis、MySQL、并发等比较熟悉。我在研究生所做的项目是这样的,我将按照背景、任务、行动和结果进行描述。

    最开始我们是每天都需要发送自己每天的工作学习汇报到导师管理的一个微信群里,他每天都要在群内查看各个学生的汇报,从而了解学生的学习情况。后来呢,我们导师觉得这样不便于管理,就让我们开发一个汇报管理的web系统。它分为学生端和导师端,在导师端,导师可以根据不同时间范围查看学生的汇报、甚至是项目进度、设备管理等,大幅减少导师的工作量。同时也为学生提供了更加人性化的汇报填写界面以及定时提醒,帮助学生养成自律的习惯。

    它首先解决了汇报内容的可追溯、可量化、可比较的问题,其次融入任务计划管理使汇报更具意义,最后我们还准备加入研究生全生命周期管理(从研究生入学到毕业各个重大事件,定为里程碑事件,将这些事件融入我们的系统,到一个时间节点之前,对他进行备忘和进度提醒,比如说要找实习的时间节点,根据汇报内容来判定,你的当前完成进度是多少),来帮助培养更优质的研究生。

    我在这个项目中是一个产品经理兼架构师的角色。

    我负责与导师进行沟通,询问这个系统的需求和痛点,并尝试以导师的角度理解这个系统需要是一个什么样子的,才能吸引其他的实验室使用。与此同时,我还要与组员们一起交流如何去设计实现,和怎么做才能让用户体验更好等。
    我在项目中做了以下四点:

    • 一是负责了项目架构设计,将项目分成了三个模块,用户模块、汇报模块以及微信模块。
    • 二是技术选型,选择了MySQL和Redis作为数据库和缓存。
    • 三是性能优化,如对主页的进行了显著的优化,将主页打开时间缩短了5倍。
    • 四是运维。

    我在这个项目中,经历了一个web项目从0到1的构建过程,经历多次重构,从单体服务变成微服务。还提高了团队协作能力和管理经验。

    Mybatis优势

    • MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
    • MyBatis容易掌握,而Hibernate门槛较高。

    四种常用线程池:
    Java通过Executors提供四种线程池,分别为:
    newCachedThreadPool
    创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    newFixedThreadPool
    创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
    newScheduledThreadPool
    创建一个定长线程池,支持定时及周期性任务执行。
    newSingleThreadExecutor
    创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

    • 情境(situation):描述工作的背景,HR想知道为什么你会去做这件事?

    最开始我们是每天都需要发送自己每天的工作学习汇报到导师管理的一个微信群里,他每天都要在群内查看各个学生每日的汇报,从而了解学生的学习情况。我们导师觉得这样不便于管理,就让我们开发一个汇报管理的web系统。它分为学生端和导师端,在导师端,导师可以根据不同时间范围查看学生的汇报、甚至是项目进度、设备管理等,大幅减少导师的工作量。同时也为学生提供了更加人性化的汇报填写界面以及定时提醒,帮助学生养成自律的习惯。

    • 任务(task):你当时的任务是什么?HR想知道你是怎样在上述情境下明确自己的任务的。

    我在这个项目中是一个产品经理兼架构师的角色。

    • 行动(action):你做了什么?HR要知道你为上边的任务所付出的行动,为什么这么做?还有其他方案吗?

    我负责与导师进行沟通,询问这个系统的需求和痛点,并尝试以导师的角度理解这个系统需要是一个什么样子的,才能吸引其他的实验室使用。与此同时,我还要与组员们一起交流如何去设计实现,和怎么做才能让用户体验更好等。
    我在项目中做了以下四点:
    一是负责了项目架构设计,将项目分成了三个模块,用户模块、汇报模块以及微信模块。
    二是技术选型,选择了MySQL和Redis作为数据库和缓存
    三是性能优化,如对主页的进行了显著的优化,将主页打开时间缩短了5倍。
    四是运维。比如在一次用户推广以后,系统用户量暴增10倍到达500人,系统就立马崩溃了。通过谷歌搜索、请教师兄以及查阅技术书籍,我尝试过查看日志,发现日志没有什么异常。然后了解到利用jstack这个程序可以查看线程堆栈信息。发现线程阻塞在一个登陆接口的地方,具体原因是因为数据库连接池的连接使用以后没有被释放,最后导致请求阻塞,整个系统都无法正常登陆。我在druid的github仓库找到一个issue中,一个类似的情况,才知道是数据库连接池的一个bug。后来就换成了c3p0。 还有另一个情况,就是一些用户在群里反馈系统时不时崩溃,持续时间在一分钟内。这个时候我立马反应过来是系统的重启的时候需要几十秒,在这个启动过程中,连接是无法快速地正确响应的。通过和师兄的交流以及看网上的博客,考虑到nginx的高性能和nginx本身就作为前端的服务器,最终选择了用Nginx实现负载均衡,在重启的过程中,用户的请求由备用服务器进行处理,达到了一个高可用的状态。

    • 结果(result):结果怎样?从你的行动中,得到了什么?有没有完成目标呢?你获得了那些经验教训呢?之后有没有再用到那些经验呢?

    我再总结一下这个系统,它主要解决了两方面的问题:
    对于导师,查看学生的最近学习、项目情况。
    对于学生,系统提供更加丰富的汇报填写方式,方便的汇报回顾以及自律提醒等。
    我在这个项目中,经历了一个web项目从0到1的构建过程,经历多次重构,从单体服务变成微服务。还提高了团队协作能力和管理经验。
    反问:
    您觉得我在来到公司实习以前,还需要补哪些所需的知识或者能力?

    1.迎接挑战
    请分享一件自己最初并不擅长,但后来居上的事情。
    x`观察要点:如何面对不利局面/弱点,是否渴望成功,是否主动挑战高目标和跳出舒适圈。

    我说一下唱歌这个事情吧,我从最开始的不敢唱,经历我的努力,到后面大家都觉得唱的不错。
    有一次年底聚会的时候,一个朋友给大家唱了一首歌,大家都沉浸进去了,直到唱完,大家都发出了欢呼。那一刻我感受到了会唱歌是一件多么有魅力的事情。
    默默下决心努力练习,下一次上台惊艳大家。我选择学习粤语的歌,一是因为粤语的旋律很带感,其次是因为具有一定难度,更能体现出我的厉害。
    我学一首歌就是先把每个字的音读准,再是两三天的单曲循环,把曲调刻在脑子里,直到不需要意识的哼出来就差不多了。第三点是体会歌词描述的场景,有感情地唱出来。
    还记得第一次我去ktv拿起麦克风唱歌的时候,我的手都一直在发抖,甚至唱歌的声音也会发抖。不过慢慢的进入状态以后,就放开了。朋友们都说我唱的很好,是隐藏的高手。
    那一刻我明白了不能把自己框住,觉得自己不擅长什么东西,而是一定要去努力尝试,说不定这还正是自己擅长的事情。

    2.坚持不懈
    请回想你在工作学习中“啃硬骨头”的一次经历?前前后后具体经历了什么?
    追问:在这个过程中遇到了哪些困难?为了最后的结果,具体做了哪些事情?
    观察要点:遇到难点时,有想过放弃吗?什么原因让你坚持攻克困难?

    我刚决定转专业考计算机的研究生的时候,计算机基础非常薄弱。我只会用c++和数据结构算法,对计算机的操作系统、网络、数据库等一窍不通。
    我当时想转计算机的原因,就是因为我觉得在写代码的时候,时间会过的很快。每次做完一道题或者是写出一个小工具,都会有特别强的成就感。
    经过几个月的学习,我补了大量的计算机基础。在临近考研的时候,我压力特别大,因为如果没考上研究生,我也没脸面对父母了。
    很多次我也想,哎,就这样放弃吧,轻松一点有什么不好呢。但是每当这么想,内心都会有一种无形的力量推动着自己,告诉自己这不是我想要的。这样做对不起当初高考的时候那种心无旁骛的自己。这就是我一直坚持努力下去的原因。

    3.从他人批判与成功中学习
    请你分享一次最让你印象深刻的受到批评的事件?在这个过程中具体经历了什么?
    追问:这件事情是如何发生的?你是如何评价他人对你的批评?事后你采取了什么行动?
    观察要点:是否会忽视他人批评中的合理反馈?能否站在个人成长的角度评价他人的负面反馈?能否采取行动避免类似事件?

    有一次我朋友说我在讨论技术的时候,语气太激动,容易伤人自尊。
    当时事情是这样的,我们实验室的学习氛围特别好,经常一起交流学习问题。我在大家心里的形象一直以来都是一个技术爱好者,一开始大家都喜欢和我交流技术问题。
    后面渐渐我感觉大家好像都不怎么喜欢和我交流了。我就很疑惑,直到我问了一个特别好的朋友,她跟我说,我有时候遇到意见不统一的时候,说话语气太过激烈,不太会考虑别人的感受,说话也太直接,容易伤到别人的自尊心。听到这个我很震惊,因为我一直我是没有意识的,觉得大家就事论事罢了。从那以后我就开始有意识地控制自己说话的语气,提高自控力。并通过看书和一些视频学习提高说服别人的能力。

    4.非权力影响
    请分享一次团队任务陷入僵局或遇到困难的情况,当时你是如何扭转局面、推动进展的?
    追问:是否有关键成员想要退出或反对原来的计划,你是如何处理的?假设有关键成员想要退出,你如何处理?
    观察要点:是否能够激励和支持他人,是否能够开放地接受不同意见,是否能影响团队成员达成共识。

    刚来到实验室,我们在做导师分配的项目的时候,我是作为一个模块的组长。师兄给我们组分配了一系列分时间节点的任务。我给他们也私下单独细分了任务,与他们沟通确定任务能按时完成。
    然而在某一个节点眼看时间就要截止了,我去问我手下的两个组员,他们的工作进度。这才发现他们还没有开始,我就紧急召开了一个远程会议,询问他们所遇到的困难。他们也是第一次做Web项目,虽然学过编程,但是对Web项目的开发流程和工具的使用不太熟悉。那天晚上我给他们开了一个远程桌面给讲解了一下大致的做法,并用例子演示。最终大家一起熬夜到1点才完成任务。

    经过这个事件,我明白了以下四点:
    首先是明确组员的技术栈,细分任务确保他们可以完成。
    其次是需要继续细分任务,定期跟进项目进度。
    任务分配需要公开透明,分配到个人。

    我们组之前有一个成员一度想退出这个项目组,然后我问他为什么,答学不到什么东西,反复做一些无用功,出不了成果的。
    我跟他说了几点:
    首先我给他讲我们这个项目的核心价值,让他认同这是一个有价值的项目。
    其次,我说了他能从这个项目中得到什么。比如说,将各种从书上学到的知识和技术,应用到这个项目中,比如在以后找工作经常被问到的Spring,Redis,MySQL等工具,加深对知识的理解。
    最后,就是当离开这个项目,然后接手下一个项目,需要面临什么,大概率还是和目前所做的差不多,Java Web那一套。

    5.你曾经做过的比较有挑战的一个项目是什么?遇到了什么难题,怎么解决的,你的收获和思考是什么?下次可以做的更好吗?

    • 情境(situation):描述工作的背景,HR想知道为什么你会去做这件事?

    最开始我们是每天都需要发送自己每天的工作学习汇报到导师管理的一个微信群里,他每天都要在群内查看各个学生每日的汇报,从而了解学生的学习情况。我们导师觉得这样不便于管理,就让我们开发一个汇报管理的web系统。它分为学生端和导师端,在导师端,导师可以根据不同时间范围查看学生的汇报、甚至是项目进度、设备管理等,大幅减少导师的工作量。同时也为学生提供了更加人性化的汇报填写界面以及定时提醒,帮助学生养成自律的习惯。

    • 任务(task):你当时的任务是什么?HR想知道你是怎样在上述情境下明确自己的任务的。

    我在这个项目中是一个产品经理兼架构师的角色。

    • 行动(action):你做了什么?HR要知道你为上边的任务所付出的行动,为什么这么做?还有其他方案吗?

    我负责与导师进行沟通,询问这个系统的需求和痛点,并尝试以导师的角度理解这个系统需要是一个什么样子的,才能吸引其他的实验室使用。与此同时,我还要与组员们一起交流如何去设计实现,和怎么做才能让用户体验更好等。
    我在项目中做了以下四点:
    一是负责了项目架构设计,将项目分成了三个模块,用户模块、汇报模块以及微信模块。
    二是技术选型,选择了MySQL和Redis作为数据库和缓存
    三是性能优化,如对主页的进行了显著的优化,将主页打开时间缩短了5倍。
    四是运维。比如在一次用户推广以后,系统用户量暴增10倍到达500人,系统就立马崩溃了。通过谷歌搜索、请教师兄以及查阅技术书籍,我尝试过查看日志,发现日志没有什么异常。然后了解到利用jstack这个程序可以查看线程堆栈信息。发现线程阻塞在一个登陆接口的地方,具体原因是因为数据库连接池的连接使用以后没有被释放,最后导致请求阻塞,整个系统都无法正常登陆。我在druid的github仓库找到一个issue中,一个类似的情况,才知道是数据库连接池的一个bug。后来就换成了c3p0。 还有另一个情况,就是一些用户在群里反馈系统时不时崩溃,持续时间在一分钟内。这个时候我立马反应过来是系统的重启的时候需要几十秒,在这个启动过程中,连接是无法快速地正确响应的。通过和师兄的交流以及看网上的博客,考虑到nginx的高性能和nginx本身就作为前端的服务器,最终选择了用Nginx实现负载均衡,在重启的过程中,用户的请求由备用服务器进行处理,达到了一个高可用的状态。

    • 结果(result):结果怎样?从你的行动中,得到了什么?有没有完成目标呢?你获得了那些经验教训呢?之后有没有再用到那些经验呢?

    这个系统解决了两方面的问题:
    对于导师,查看学生的最近学习、项目情况。
    对于学生,系统提供更加丰富的汇报填写方式,方便的汇报回顾以及自律提醒等。
    在这个项目中我经历了一个web项目从0到1的构建过程,经历多次重构,从单体服务变成微服务。还提高了团队协作能力和管理经验。

    6.你觉得你最大的优势是什么?有哪些不足的地方?

    优势
    精力旺盛,经常一整天坐在电脑前写代码。
    乐于助人,经常帮助实验室同学解决问题。
    项目中遇到问题会深入,通过看源码,官方文档,看博客和书籍,最终解决问题,达到一个知其然并且知其所以然的程度。
    我对敲代码和技术有一种执着和热情,我会把它当成一种兴趣,我空闲的时间也会自己琢磨一些东西。比如会用计算机技术实现自动化工具,举例两个例子。
    还有在之前我读英文的资料的时候,有的时候读起来觉得不太方便,还开发过一个截图翻译的小程序。
    做过一个天天基金的爬虫,从天天基金爬取每天基金实时的涨跌幅,监听到涨跌幅超过某个阈值就发微信提醒我进行操作。

    比如说其中一个,我在项目中负责运维,然后每次都需要手动去进行打包上传部署这套流程,然后我使用shell脚本实现了这个流程。

    不足:
    表达能力不太强,所以我平时也更喜欢在业余时间来增加自己技术的广度和深度。我相信人无完人,主要是我在这方面得到的训练也比较少,将来如果公司需要我这方面的能力,我也完全愿意努力去提高。
    在生活中的自控力不太强。
    在学校中觉得有很多同学和师兄们技术能力比较强,觉得自己这方面还有很多不足,做项目越多,就越觉得自己技术栈不是很完善,导致时间不用。
    我经常觉得自己不够厉害,在休息时间也不能全身心放松,经常感受到紧迫感,为此有一些焦虑,觉得不太能控制好这个度。

    7.你对未来的职业规划是什么?你为此付出了什么努力?

    首先是继续学习计算机基础知识,并在项目中应用和实践。
    其次,我觉得阿里是Java工程师的天堂,所以需要努力获得工作机会。
    然后在阿里积累业务知识和技术知识,并在解决问题中加深理解。
    最后就是,进一步学习中间件、分布式、数据库等知识,构建完整的知识体系。

    你觉得你的技术栈是什么样的?

    我的主要技术栈是Java后端,我用Java做过Web项目,同时深入学习过Redis、MySQL和Spring,甚至还用Java做过图形界面。在我学习计算机的过程中,语言的使用顺序是C、C++、Python、C#再到Java,用他们都做过大大小小的项目。最后我选择Java是因为它的代码风格非常的工整,看源码的时候也更加容易理解,javadoc看着也更加的方便,这些都是我在其他几个语言中没有的体验。

    你是电子科大的,为什么要去四川大学读研?
    一、我女朋友在成都,所以我也希望在成都读研。
    二、四川大学是一所综合性大学,注重人文教育的培养,希望来到四川大学感受一下。

    公司在杭州,你以后怎么打算?
    1、首先杭州是阿里的总部,意味着有更多的挑战和机会。
    2、我觉得杭州是一个宜居的城市,以后也有在杭州定居的打算。

    查看日志的方法
    less log.log

    shift + G 命令到文件尾部 然后输入 ?加上你要搜索的关键字例如 ?1213

    按 n 向上查找关键字

    shift+n 反向查找关键字

    Nginx负载均衡 健康检查
    nginx自带健康检查的缺陷:

    1. Nginx只有当有访问时后,才发起对后端节点探测。
    2. 如果本次请求中,节点正好出现故障,Nginx依然将请求转交给故障的节点,然后再转交给健康的节点处理。所以不会影响到这次请求的正常进行。但是会影响效率,因为多了一次转发
    3. 自带模块无法做到预警
    4. 被动健康检查

    使用第三访模块nginx_upstream_check_module:

    1. 区别于nginx自带的非主动式的心跳检测,淘宝开发的tengine自带了一个提供主动式后端服务器心跳检测模块
    2. 若健康检查包类型为http,在开启健康检查功能后,nginx会根据设置的间隔向指定的后端服务器端口发送健康检查包,并根据期望的HTTP回复状态码来判断服务是否健康。
    3. 后端真实节点不可用,则请求不会转发到故障节点
    4. 故障节点恢复后,请求正常转发

    最终一致性是分布式计算里的一种内存一致性模型,它指对于已改变写的数据的读取,最终都能取得已更新的数据,但不完全保证能立即取得已更新的数据。 这种模型通常可以实现较高的可用性。 最终一致性,通过乐观复制,或称延迟复制(lazy replication)实现。

    复制是导致出现数据一致性问题的唯一原因。

    UDP报文长度:65535-8(UDP报头)-20(数据链路层)

    分布式锁:
    Redis的set key

    Minor GC触发条件:
    当Eden区满时,触发Minor GC。
    Full GC触发条件:

    • System.gc()方法的调用
    • 老年代空间不足
    • 方法区空间不足
    • 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
    • 由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

    Java内存空间

    • 程序计数器
      • 如果执行的是Java方法,记录正在执行的字节码指令地址。如果是native方法,值为空
    • 虚拟机栈
      • 生命周期和线程相同
      • 每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
      • 栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口。
      • 局部变量表所需的内存空间在编译期间完成分配。所以有两种异常,栈深度太大, StackOverflowError。如果栈可以动态扩展,内存不够时会 OutOfMemoryError。
    • 本地方法栈
      • 与虚拟机栈类似,但是服务native方法。
      • 新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor空间等
    • 方法区(永久代)
      • 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

    (1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中;
    (2)通过序列化以字节流的形式使对象在网络中进行传递和接收;
    (3)通过序列化在进程间传递对象;
    3、序列化算法一般会按步骤做如下事情:
    (1)将对象实例相关的类元数据输出。
    (2)递归地输出类的超类描述直到不再有超类。
    (3)类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。
    (4)从上至下递归输出实例的数据

    还有那些地方需要提高?
    推荐一些书籍?

    读写分离,分库分表、数据分区。
    数据分区是一种物理数据库的设计技术,它的目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。 分区并不是生成新的数据表,而是将表的数据均衡分摊到不同的硬盘,系统或是不同服务器存储介子中,实际上还是一张表。

    阿里巴巴分库分表的几个原则:
    数据尽可能的平均拆分

    1. 尽可能的减少事务边界 所谓的事务边界 指单个SQL语句在后端数据库上同时执行的数量。因为事务边界越大,系统的锁冲突概率就越高,系统越难以扩展,整体性能越低。
    2. 异构索引表尽量降低全表扫描频率 这个是针对假如数据是按订单id进行分拆,当用户想查看自己的订单时,针对这种场景,常采用异构索引表来解决,即采用异步机制将原表内的每一次创建或更新,都换另一个维度保存一份完整的数据表或索引表。本质上这是互联网公司很多时候采用的一个解决思路:拿空间换时间 。

    STAR法则
    讲东西的连贯性
    系统性层面的思考

    OAuth2的思路:
    (A)用户打开客户端以后,客户端要求用户给予授权。
    (B)用户同意给予客户端授权。
    (C)客户端使用上一步获得的授权,向认证服务器申请令牌。
    (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
    (E)客户端使用令牌,向资源服务器申请获取资源。
    (F)资源服务器确认令牌无误,同意向客户端开放资源。
    Dubbo的调用关系:

    • 服务容器负责启动,加载,运行服务提供者。
    • 服务提供者在启动时,向注册中心注册自己提供的服务。
    • 服务消费者在启动时,向注册中心订阅自己所需的服务。
    • 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
    • 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
    • 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心Monitor。

    RocketMQ工作流程:
    1)首先启动NameServer。NameServer启动后监听端口,等待Broker、Producer以及Consumer连上来
    2)启动Broker。启动之后,会跟所有的NameServer建立并保持一个长连接,定时发送心跳包。心跳包中包含当前Broker信息(ip、port等)、Topic信息以及Borker与Topic的映射关系
    3)创建Topic。创建时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic
    4)Producer发送消息。启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic所在的Broker;然后从队列列表中轮询选择一个队列,与队列所在的Broker建立长连接,进行消息的发送
    5)Consumer消费消息。跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,进行消息的消费

    RocketMq如何负载均衡?
    1)producer发送消息的负载均衡:默认会轮询向Topic的所有queue发送消息,以达到消息平均落到不同的queue上;而由于queue可以落在不同的broker上,就可以发到不同broker上(当然也可以指定发送到某个特定的queue上)
    2)consumer订阅消息的负载均衡:假设有5个队列,两个消费者,则第一个消费者消费3个队列,第二个则消费2个队列,以达到平均消费的效果。而需要注意的是,当consumer的数量大于队列的数量的话,根据rocketMq的机制,多出来的队列不会去消费数据,因此建议consumer的数量小于或者等于queue的数量,避免不必要的浪费

    拦截器和过滤器的区别。

    • 使用范围不同。Filter 是Servlet 规定的.只能用于web 程序。而拦截器既可以用于Web 程序,也可以用于Apllicatioon,Swing程序中。
    • 规范不同。Filter是在Servlet 规范定义的,是Servlet容器支持的。而拦截器是在Spring 容器内的,Spring 框架所支持的。
    • 使用资源不同:同其他代码块一样,拦截器也是一个Spring的组件,归Spring 管理。配置在Spring 中,因此能使用Spring 中的任何资源,对象,例如Service对象,数据源,事务管理等。通过Ioc注入到拦截器即可。而filter 则不能。
    • 深度不同。Filter 只在Servlet前后起作用,而拦截器能深入到方法前后,异常抛出前后因而拦截器的使用具有更大的弹性,所以在spring 中优先使用拦截器。