互联网踩坑指南

每个在互联网的人都知道互联网有两个坑,一个大家抢着占,一个得有人填,哪里有坑哪里就有程序猿!

本系列的帖子总结了笔者在互联网里踩到的或者听到的坑,总结以警示那些刚刚入行的新人,希望对他们能有所帮助,如果你填过其他的坑,也请在下面评论中分享下。

1. 一个同事使用String连接来拼凑日志的字符串很不爽,效率不高而且代码很凌乱,所以,这位同事使用String.format来构造日志字符串,不巧的是用来格式化字符串的基串是其它接口返回的,返回的串的值不可预测,有些返回值包含%,因此,String.format报不支持这样的格式错误,果断将动态返回的字符串在最后面加入到日志串中。
2. 如果你在改造一个旧项目或者重构一段代码,请参考“面向接口编程“相关知识,请保持接口的一致性在接口后方的实现开刀,保持接口一致不但要保持入口参数,出口返回值的一致,也请保持已有的错误返回等的格式,异常代码的一致性,切忌不要大肆宣扬结构清晰至上,重构至上,而忽略业务的特殊性。待实现结构清晰,可与服务的调用方共同协商改造接口上的不合理契约,切忌切忌。
3. 在改造一个项目的时候,很多开发人员容易忽略的就是数据格式的向前兼容问题,在项目中经常遇到的是缓存数据格式不能向前兼容,例如,一个项目依赖缓存存储中间状态,小B看到项目的结构非常的不合理,不清晰,不具有可扩展性等,准备重构项目,小B选择重新架构并且实现此项目,项目预览期间发现不能进行灰度验证,原因是当前项目和已有的项目缓存不一致,这知道有状态的服务请求如果跨越已有的服务和新的服务由于缓存数据格式不通用而导致失败。
4. 一个系统的关键领域模型的对象都有一个ID字段,如果在改造一个系统的时候,最好保留已有的ID生成规则,否则后患无穷。
5. 如果选择在HTTP Body里上传文件内容,并且不使用MultiPart文件格式,那么需要在请求流程中先取得请求输入流,否则先取了任何参数,请求流就会被读一遍,Sevlet容器会遍历整个请求的Body来查找参数,尽管Body里面并不包含任何参数,遍历后Body的InputStream的指针指向了尾部,之后再直接个m的时候此流为空。解决办法,可以先读取InputSteam再读取请求参数,也可以使用Multipart格式上传文件。
6. 计算MD5的API经常有人把临时对象声明成一个成员变量,看似能够提高效率,但是产生了多线程安全问题,切忌切忌。
7. 在大型互联网公司,大部分的服务接口导出都使用HTTP协议(或者RPC),那么每个公司都会封装一个HTTP Client实用客户端,客户端跟觉服务的特点可以设置超时时间,一般会提供长时间超时的一个HTTP客户端和短时间超时的客户端,在进行大文件上传等耗时的操作和短操作需要使用不同的客户端。
8. 定义DB结构和字段时一定注意字段的长度是否能满足所有的业务需要,mysql中的int(10)只代表显示的时候按照10位来显示,并不代表10个字节的int,如果需要大的整形,请使用big int类型。

9. 在DAO操作DB产生异常的时候一定打印异常堆栈,并且同时也打印SQL语句以及传入大的参数,否则排查数据库问题机器困难。
10. 在产生异常的时候,一定打印错误或者警告日志,然而,如果在计算开关操作的时候,在开关数据或者格式不合法的情况下,请别依仗产生的NullPointerException或者NumberFormatException来是用默认值,这样会让任何一个请求都增加一个警告或者错误日志,使警告和错误日志太臃肿并且不好跟踪真正的线上问题。
11.一个正在频繁增加新功能的项目需要进行架构改造,增加新功能和架构改造是两个小组并行开发的,现在改造要更改整个Web MVC框架,需要对几十个接口服务进行改造以适应新Web MVC框架的需要,如果暂停新功能的开发,专门进行架构的改造,由于几十个接口很难一次迁移完毕,而且迁移后要进行测试,仿真,上线,上线后可能还有问题,这是一个需要很长时间的过程,这时候新功能开发的停止必定会让高层不爽,所以,这个方法是行不通的,于是,模仿在线数据库扩容(双写,迁移老数据,切读,下双写),先让两个Web MVC框架并存,成批次的移植服务接口,一次移植一部分,先移植简单的并且不是很重要的接口,等框架问题修正趋于稳定了再移植复杂的和核心的接口。这样在一定程度上可以和新功能一起开发,在每次移植一批接口前和新功能开发组一起协商,避免更改同一接口,待所有接口移植完成后,再下掉老的Web MVC框架 。
12. 处理消息,消息是字符串,需要去重,消息无标志,通过在缓存保存字符串,但是字符串长度无限制,担心缓存填满,则可以把字符串放数据库或者文件系统,将hash值和数据库记录id/或者文件位置放入缓存,如果hash不同则字符串一定不同,如果hash相同再取源串对比。

发表评论