一、技术总结


(1)App/JavaWeb后台系统



1.1、采用RestFul架构的SSM(Spring SpringMVC MyBatis)框架集成开发的App后台系统,将用户鉴权分离出来单独的模块,将用户鉴权登录状态Token保存到Redis内存数据库中,从而便于上层业务后台系统弹性部署,提高系统的可用性和伸缩性,也为API高并发访问提供安全基础。



1.2、后台系统尤其是Web或App后台通常由后台处理业务相关数据展示到前端页面或返回Json字符串数据到客户端。项目随着业务发展和用户数的增多通常会不断重构,采用Maven进行项目构建和作为项目管理工具,将项目制作成Maven多模块,core模块、service模块、web模块、common模块、controller模块等。



1.3、MVC模式分modle层、dao层、service层,controller层。model层用于将业务实体封装成数据模型,dao层用于操作数据库的接口层,service层用于调用dao层和外部系统的接口层,比较复杂的业务逻辑一般都按原子性操作封装在service层,controller层主要用于控制分发,将业务处理结果的Json数据或前端页面分发到客户端访问层。



1.4、工作到现在用过很多API,JSON格式和XML格式都有。总结使用经验觉得JSON格式的更好用。JSON格式通常是更为简洁的(以至于传输的数据量更小),也更容易展现复杂的对象(精确)而且能运行得像其他格式一样好。



1.5、用设备号/设备mac地址作为Token:服务端接收到该参数后,便用一个变量来接收同时将其作为Token保存在数据库,并将该Token设置到session中,客户端每次请求的时候都要统一拦截,并将客户端传递的token和服务器端session中的token进行对比,如果相同则放行,不同则拒绝。



1.6、对于一些需要异步处理的,不要直接new一个thread,应当使用线程池。使用线程池的时候应当对线程数量大小合理设置,一般最大不超过50个,当然还需要考虑你的IO和CPU。容器类变量,如果变化比较大且频繁,尽量定义的时候设置初始容量大小,减少扩容带来的消耗。分支判断if…else的时候,最常符合的条件处理放在前面。对象比较的时候常量放前面,养成好习惯,减少空指针的出现。减少synchronized中等待处理的代码,能放在外面就尽量放在外面。



1.7、关于数据,一般查询比较慢,很有可能是没有建索引或者索引没用到,多去检查一下。两个大表的关联查询,可以使用二次访问数据库替代,先查出A表的数据,利用关联字段再查B表的。不要一味想着一条sql搞定最好。坚决避免,查全表数据或者数量大的数据,返回list加载到内存中,一不小心查了100w数据,又查得比较频繁,内存的爆了。有这种风险的改成分页查询。不要select *,按需取列。多考虑避免事务里面有长连接或者长事务,如果大量这种情况出现占用数据连接,会影响性能。一些无必要的逻辑可以放到事务外执行。对字段的加减乘除处理放到sql,严格避免先get处理,然后运算在set到数据库里面,并发情况非常容易导致失真。



1.8、方法里面代码不要太长,注意封装,命名语义化,代码整洁。



(2)、基于Netty底层通信的消息推送系统的研发



2.1、NIO类库的异步通信框架架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。



2.2、提供对多种编解码框架的集成,包括谷歌的Protobuf、Jboss marshalling、Java序列化、压缩编解码、XML解码、字符串编解码等,这些编解码框架可以被用户直接使用。



2.3、提供形式多样的编解码基础类库,可以非常方便的实现私有协议栈编解码框架的二次定制和开发。



2.4、基于职责链模式的Pipeline-Handler机制,用户可以非常方便的对网络事件进行拦截和定制。



2.5、所有的IO操作都是异步的,用户可以通过Future-Listener机制主动Get结果或者由IO线程操作完成之后主动Notify结果,用户的业务线程不需要同步等待。



2.6、随着网站规模的不断扩大,系统并发访问量也越来越高,传统基于Tomcat等Web容器的垂直架构已经无法满足需求,需要拆分应用进行服务化,以提高开发和维护效率。从组网情况看,垂直的架构拆分之后,系统采用分布式部署,各个节点之间需要远程服务调用,高性能的RPC框架必不可少,Netty作为异步高性能的通信框架,往往作为基础通信组件被这些RPC框架使用。



2.7、阿里分布式服务框架Dubbo的RPC框架使用Dubbo协议进行节点间通信,Dubbo协议默认使用Netty作为基础通信组件,用于实现各进程节点之间的内部通信。其中,服务提供者和服务消费者之间,服务提供者、服务消费者和性能统计节点之间使用Netty进行异步/同步通信。除了Dubbo之外,淘宝的消息中间件RocketMQ的消息生产者和消息消费者之间,也采用Netty进行高性能、异步通信。



(3)、Jenkins持续集成



3.1、对Git、JIRA、Jenkins、GitLab、Maven等自动化的基于主干分支开发方式的持续集成,Jenkins Maven自动测试、持续构建,Jenkins持续部署,持续交付等集成工具的安装使用,及基于此基础上的项目管理和项目交付。



3.2、Git主干开发开发方式,每个人在项目经理安排的任务下,基于需求开发,此时都基于develop创建一个特勤分支,如,develop-zhanghaiyang分支下开发自己的需求,本地开发完成经测试无误合并到develop主干分支,下面可以通知测试人员测试刚开发的需求。



3.3、GitLab或开源中国Git托管或GitHub托管平台都可以设置钩子和Jenkins集成,Jenkins一旦检测到设置好的分支有推送或合并响应会重新利用Maven进行构建和自动化测试,测试通过后进行重新部署,即实现需求到开发的持续集成,开发到测试的持续测试,测试到应用交付的持续交付。



3.4、JIRA是很优秀的开源的项目Bug跟踪管理工具,从项目需求到开发测试交付的整个流程的bug跟踪,便于各个层面的人员进行协调,减少项目开发过程中开发人员与测试人员,产品经理与测试人员等沟通成本。



3.5、GitLab是类似于GitHub的代码托管软件,即Git服务器,著名的开源中国码云就是基于GitLab二次开发的优秀的Git代码托管平台。



(4)、Docker容器使用



4.1、简化配置:这是Docker公司宣传的Docker的主要使用场景。虚拟机的最大好处是能在你的硬件设施上运行各种配置不一样的平台(软件、系统),Docker在降低额外开销的情况下提供了同样的功能。它能让你将运行环境和配置放在代码中然后部署,同一个Docker的配置可以在不同的环境中使用,这样就降低了硬件要求和应用环境之间耦合度。



4.2、代码流水线(Code Pipeline)管理:前一个场景对于管理代码的流水线起到了很大的帮助。代码从开发者的机器到最终在生产环境上的部署,需要经过很多的中间环境。而每一个中间环境都有自己微小的差别,Docker给应用提供了一个从开发到上线均一致的环境,让代码的流水线变得简单不少。



4.3、提高开发效率:不同的开发环境中,我们都想把两件事做好。一是我们想让开发环境尽量贴近生产环境,二是我们想快速搭建开发环境。理想状态中,要达到第一个目标,我们需要将每一个服务都跑在独立的虚拟机中以便监控生产环境中服务的运行状态。然而,我们却不想每次都需要网络连接,每次重新编译的时候远程连接上去特别麻烦。这就是Docker做的特别好的地方,开发环境的机器通常内存比较小,之前使用虚拟的时候,我们经常需要为开发环境的机器加内存,而现在Docker可以轻易的让几十个服务在Docker中跑起来。



4.4、隔离应用:有很多种原因会让你选择在一个机器上运行不同的应用,比如之前提到的提高开发效率的场景等。我们经常需要考虑两点,一是因为要降低成本而进行服务器整合,二是将一个整体式的应用拆分成松耦合的单个服务。



4.5、整合服务器:正如通过虚拟机来整合多个应用,Docker隔离应用的能力使得Docker可以整合多个服务器以降低成本。由于没有多个操作系统的内存占用,以及能在多个实例之间共享没有使用的内存,Docker可以比虚拟机提供更好的服务器整合解决方案。



4.6、调试能力:Docker提供了很多的工具,这些工具不一定只是针对容器,但是却适用于容器。它们提供了很多的功能,包括可以为容器设置检查点、设置版本和查看两个容器之间的差别,这些特性可以帮助调试Bug。



4.7、多租户环境:使用Docker,可以为每一个租户的应用层的多个实例创建隔离的环境,这不仅简单而且成本低廉,当然这一切得益于Docker环境的启动速度和其高效的diff命令。



4.8、快速部署:在虚拟机之前,引入新的硬件资源需要消耗几天的时间。虚拟化技术(Virtualization)将这个时间缩短到了分钟级别。而Docker通过为进程仅仅创建一个容器而无需启动一个操作系统,再次将这个过程缩短到了秒级。这正是Google和Facebook都看重的特性。



(5)、网站架构设计



5.1、性能:性能是网站架构设计的一个重要方面,任何软件架构设计方案都必须考虑可能带来的性能问题。也正因为性能问题几乎无处不在,所以优化网站性能的手段也非常多:浏览器端:可以通过浏览器缓存、页面压缩传输、合理布局页面、减少Cookie传输等手段,甚至可以使用CDN加速功能。应用服务器端:可以使用服务器本地缓存和分布式缓存,也可以通过异步操作方式来加快响应,在高并发请求的情况下,可以将多台应用服务器组成一个集群共同对外服务,提高整体处理能力,改善性能。 数据库服务器端:可用使用索引、缓存、SQL性能优化等手段,还可以使用NoSQL数据库来优化数据模型、存储结构等。衡量网站性能有一系列指标,重要的有响应时间、TPS、系统性能计数器等,通过这些指标以确定系统设计是否达到目标。



5.2、可用性:可用性即能够不间断提供服务的时间。几乎所有网站都承诺7×24小时可用,但事实上任何网站都不可能达到完全的7×24,总会有一些故障时间,扣除这些故障时间,就是网站的可用时间。一些大型网站可以做到4个9以上的可用性,也就是99.99%。网站高可用的主要手段就是冗余,应用部署在多台服务器上同时提供服务,数据存储在多台服务器上相互备份,任何一台服务器都不会影响应用的整体可以,通常的实现手段即把多台服务器通过负载均衡设备组成一个集群。 衡量一个系统架构设计是否满足高可用的目标,就是假设系统中任何一台或者多台服务器宕机时,以及出现各种不可预期的问题时,系统整体是否依然可用。



5.3、伸缩性:大型网站需要面对大量用户的高并发访问和存储海量数据,网站通过集群的方式将多台服务器组成一个整体共同提供服务。所谓伸缩性是指通过不断向集群中加入服务器的手段来缓解不断整体上市用户并发访问压力和不断增长的数据存储需求。衡量架构伸缩性的主要标准就是是否可用多台服务器构建集群,是否容易向集群中添加新的服务器。加入新的服务器后是否可以提供和原来的服务器无差别的服务。集群中可容纳的总服务器数量是否有限制。



5.4、扩展性:不同于其他架构要素主要关注非功能性需求,网站的扩展性架构直接关注网站的功能需求。网站快速发展,功能不断扩展,如何设计网站的架构使其能够快速响应需求变化,是网站可扩展架构的主要目标。衡量网站架构扩展性好坏的主要标准就是在网站增加新的业务产品时,是否可以实现对现有产品透明无影响,不同产品之间是否很少耦合等。网站可扩展架构的主要手段是事件驱动架构和分布式服务。 事件驱动通常利用消息队列实现,通过这种方式将消息生产和处理逻辑分隔开。 服务器服务则是将业务和可复用服务分离开来,通过分布式服务框架调用。新增加产品可用通过调用可复用的服务来实现自身的业务逻辑,而对现有产品没有任何影响。



5.5、安全性:互联网是开放的,任何人在任何地方都可以访问网站。网站的安全架构就是保护网站不受恶意访问和攻击,保护网站的重要数据不被窃取。衡量网站安全架构的标准就是针对现存和潜在的各种攻击和窃密手段,是否有可靠的应对策略。



(6)、SQL规范与性能优化--主要针对Mysql



6.1、什么是执行计划:a.决定如何访问表数据,是否通过索引,是否排序等。b.多表关联是先访问哪个表。c.多表关联时,使用哪种连接方式,不过现在MySQL只有嵌套连接(嵌套循环,顾名思义就是将一个表为出发点,将该表全部记录逐条去遍历另外一张表的记录)。



6.2、SQL执行顺序:a.检查语法是否正确。b.检查表是否存在、权限是否满足等。c.根据统计信息(如data length,rows,index length、索引唯一度),生成较优的执行计划。d.根据执行计划,进行数据检索、过滤、合并、排序等操作。访问数据时,内存中如存在表数据,则直接进行操作;否则,从磁带读取表数据,放入内存,再进行操作;如内存不足,则内存中较冷数据涮出内存,再从内存中读取数据。



6.3、索引:查询的时候如果使用上了索引,可以提高效率,因为建立了索引后,可以理解为数据字典的结构存储,因此根据条件查询的时候更加高效。下面看一下MySQL常用的索引类型的概念。普通索引:在创建普通索引时,不附加任何限制条件。这类索引可以创建在任何数据类型中,其值是否唯一和非空由字段本身的完整性约束条件决定。建立索引以后,查询时可以通过索引进行查询。例如,在student表的stu_id字段上建立一个普通索引。查询记录时,就可以根据该索引进行查询。唯一性索引:使用UNIQUE参数可以设置索引为唯一性索引。在创建唯一性索引时,限制该索引的值必须是唯一的。例如,在student表的stu_name字段中创建唯一性索引,那么stu_name字段的值就必需是唯一的。通过唯一性索引,可以更快速地确定某条记录。主键就是一种特殊唯一性索引。单列索引:在表中的单个字段上创建索引。单列索引只根据该字段进行索引。单列索引可以是普通索引,也可以是唯一性索引,还可以是全文索引。只要保证该索引只对应一个字段 即可。多列索引:多列索引是在表的多个字段上创建一个索引。该索引指向创建时对应的多个字段,可以通过这几个字段进行查询。但是,只有查询条件中使用了这些字段中第一个字段时,索引才会被使用。例如,在表中的id、name和sex字段上建立一个多列索引,那么,只有查询条件使用了id字段时该索引才会被使用。



6.4、一般一张表索引不要超过5个,而且避免重复索引,而且也不是建了索引,根据索引字段条件查询,索引就会起作用。



6.5、一般哪些场景会导致索引失效:a.使用like关键字匹配字符串第一个为”%”的场景。b.条件中包含or、in、not in、<>关键字,默认不走索引的。c.访问表上的数据行超出表总记录数30%,变成全表扫描。d.查询条件使用函数在索引列上,或者对索引列进行运算。e.多列索引中,第一个索引列使用范围查询,只能用到部份或无法使用索引。f.多列索引中,第一个查询条件不是最左索引列,上面多列索引概念中也有提到。



6.6、不能同时使用两个索引,一个过滤数据,一个用于排序(主键除外)。DML语句如果使用索引,会导致lock全表;如果使用了非唯一索引,可能只是锁住一定范围。对此,建议更新/删除数据尽量用上索引,如果可以最好用上主键或唯一索引,另外事务要及时提交。



6.7、关于事务:a.日志记录尽量放在独立事务里面,避免后面的异常发生导致日志丢失。b.上面已经几次提到,尽早提交事务,避免事务过长,因此写代码的时候,一些可以不放到事务的逻辑可以移到外面,长事务看能否拆成两个事务。



二、工作心得



(1)、和同事多维度沟通;学会使用笔记本如云笔记本记录日常工作过程和会议重点;经常总结思考理解思路;着重学习和工作效率,效率第一,质量第一。



(2)、多听其他同事和老板上司的意见。



(3)、用发展的眼光和变化的眼光看待公司的业务和自己的掌握的技术及手头上的工作。



(4)、心态决定一切,工作的价值在于自己的心态的控制和调节。



三、职业发展及2017规划



(1)、先博而后渊:感觉自己的技术点还是理解的蛮多的,但感觉很多都不够深入,未来是互联网+时代,社会变迁很快,尤其是信息爆炸的今天,东西太多,不肯能都学的很通。所以未来应该偏向实用驱动,即如果在实际实用场景需要某个技术再去深入学习,边学边用更能体现学以致用!



(2)、重视业务,积累业务和管理经验:技术再牛不能解决实际业务问题都是啥流氓。另外对业务更理解有利于自己对项目管理工作更加顺利的开展。作为项目管理人员,项目的人员协调与时间安排规划,责任越大,思考的问题就越多,遇到的问题处理经验就越丰富。把控能力也比较强。



(3)、学会和更多的同学同事交朋友:业余时间多和同事大学同学等交流共享,更有利于自己的多元化发展,及适当的拓展自己的朋友圈。



(4)、对不懂的东西保持学习心态:学习最能集中注意力的情况是有着比较强的好奇心和求知欲。所以一般一些技术分享或者老员工讨论的问题,可能很多概念知识你都不懂,这时候你就可以去学习了解这些知识。或者你工作中遇到的问题,尽量刨根问底的去弄清楚是什么原因导致的,不要一些老司机帮忙解决了就一了了之。或者是其他同事遇到的问题,你都可以去了解一下。



(5)、2017注重技术的运用:技术和业务的结合,向项目资深管理方向迈进!在项目管理和技术方向上“五五分账”,尤其是多关注大公司资深管理方面的书籍和经验。



(6)、2017技术类书单:



《重构》



《代码整洁之道》



《Java并发编程的艺术》



《高性能Linux服务器构建实践及性能调优与集群应用》



《Java多线程编程核心技术》



《SOA与Rest》--用Rest构建企业级SOA解决方案



《Spring实践》



《CentOS Linux系统运维》



《科技之巅》



《硅谷百年史》--共3册



《VMWare虚拟化与云计算应用案例详解》



《Java常用算法手册》



《Docker生产环境实践指南》



《Docker技术入门与实践》



《DevOps实践》



《Java EE开发的颠覆者Spring Boot实战》



《算法导论》



《分布式服务框架原理与实践》



《大话数据结构》



《神经网络与机器学习》



《Redis设计与实现》



《用户体验要素》--以用户为中心的产品设计



《白话大数据与机器学习》



《高性能MySQL》



《Hadoop权威指南》



《数据挖掘与数据化运营实战 思路、方法、技巧与应用》



《深入理解计算机系统》



《数据结构与算法分析:Java语言描述》



《Spring技术内幕:深入解析Spring架构与设计原理》



《机器学习》