技术走查提纲分析
基本走查
- 编制技术列表图。列出系统中所使用的所有技术及相关版本,主页等,方便安全更新的跟踪。
- 确保配置库使用。全部上配置库:全部代码/全部文档/全部脚本(SQL建表,SQL基础数据,SHELL 等)/全部配置(系统配置, 中间件配置)/与系统设计开发运行维护相关的一切。
- 编制系统部署图。包括测试环境部署和生产环境部署。识别:是否存在单点,是否为热数据准备缓存,是否有降级设置。
- 编制系统进程图。系统启动后,会有多少进程,进程之间的关系,内存 CPU 可能的占用情况。
- 编制系统维护表。包括但不限定于: a)业务健康状况如何体现?b)日志如何处理与归档?c)系统监控情况?d)数据库备份策略 e)常见问题处置方式等。
- 程序日志打印记录,包括但不限定于:
- 程序产生的异常
- 程序执行的 SQL(绑定变量的 SQL 及绑定变量,及组合变量后的 SQL)
- 日志中包含当前会话 ID,以便于日志跟踪
- API调用的日志
- 重要业务的步骤日志
- 全新项目,除了在测试环境部署外,同时在生产环境部署联调(注意暂时关闭外部访问)。
代码走查
- 编制代码模块/包划分说明。模块划分有原则可依(比如按不同业务划分,按业务与技术划分等)。数量控制在7个以内。
- 基本代码风格要统一。使用 google format,统一格式化。
- 使用 SonarQube 来构建可视化的代码质量,消除严重的代码缺陷。
- 定期开展 CodeReview 活动,来在小组内推行代码的回顾与学习。
- 编制系统债务列表。列出当前存在的技术债务,包括但不限定于:
- 应当配置的,写死了
- 应当认真设计的,使用了权宜之计的
- 应当分离业务与技术,或者子业务A与子业务B,而当前夹杂在一起的,使得代码难以理解的。
- 依赖于某个具体技术人员的部分(只有他能改,别人不敢改)
- 编制系统输出。将一些公共的技术,剥离出公共组件和工具,对于一些好的范式,则形成最佳实践。为后续项目奠定基础。
表设计
- 指定数据库设计的总负责人,负责审核校验表设计的合理性与合规性,并对表设计做出最终解释。
- 表 ID 字段,禁止使用 UUID,使用 BIGINT UNSIGNED 类型(MySQL),同时采用 Snowflake 算法生成全局 ID。
- 表枚举型字段,使用 tinyint/char(1) 来表示各种不同的状态。
- 建表时,表注释和字段注释要书写完整。对于枚举型的字段(例如状态),要说明各种不同取值的含义。
- 不同表中,相同含义的字段,必须在命名/类型/注释上保持一致。
- 识别大表(持续增长的表),审查大表的索引设置。
- 敏感信息在库加密存储。包括但不限定于:用户密码、信用卡、住址等。
- 不使用外键。
SQL 执行
- SQL 执行时,严格限定拼接变量取值(容易造成SQL注入),尽量使用绑定变量的方式。
- 不允许在 SQL 中,使用类似于
where 1=1
的写法,防止在动态条件下,条件全部丢失(500万数据全部查出,即使内存不爆满,业务系统界面也要挂掉了)。 - 操作主要/核心业务流程,在日志中捕获执行的 SQL 语句(包括原始 SQL,绑定变量列表,及替换变量后的 SQL),逐条审核 SQL 的写法,分析潜在的问题。
- 对于预期业务增长规模的表,制造一定规模的测试数据量(比如 500万),检查系统运行情况,特别是核心业务流程的响应。
- 审查大表关键的查询 SQL。
- 其它注意事项:
- 单条查询时尽量使用ID,或者唯一索引
- 多条查询时,必须携带limit限定返回条数,同时限定查询条件,避免全量查询
- 更新,必须单表单条更新,或者单表批量更新
- 避免硬删除,使用软删除(deleted_at字段)
系统安全
- 网络请求参数传递,是否在后端进行了强度合适的校验,包括但不限于:
- 基本校验:非空、最大/小长度、类型、范围、最大/小值、正规等
- 业务校验:是否符合业务要求,比如:订单号,就要求订单是存在的,是状态正常的,是属于当前登录人的等。
- 前端(Web端)存储数据原则
- 尽量存储乱序的KEY,具体数据则存储在后端缓存中;
- 存储进行加密,并且添加失效期,避免篡改。
- 授权采用白名单原则。如菜单链接,默认(没有显式授权)是401 Unauthorized。
- 采用无状态设计。 避免使用 Session 保存会话。
系统优化
- 是否有需要批量操作。大量类似操作的地方,可以转化为批量操作。
- 是否有需要异步操作。慢逻辑避免放在客户请求线程中。业务高峰时,可以采用队列模式,削峰填谷。
- 业务服务是否可以划分不同的优先级。在忙时,低优先级的可以降级。
- 识别过度设计,特别是为
夸夸其谈的可能未来业务
的设计。保持KISS原则。 - 避免过度优化。在清晰性和可读性原则的前提下,适度优化。优化必须有实际数据对比作为支撑。如果优化效果不明显,但是复杂性上升了,清晰性和可读性下降了,则放弃优化。
- 系统是否存在不必要的依赖。包括静态代码库依赖和动态环境依赖等。
- 是否存在绝对目录的依赖。
- 是否存在特定时间的依赖。
- 在 Chrome 浏览器中,打开 DevTools 跟踪请求,查看数据交互及耗时,分析合理性以及可能的问题。
系统风险
- 调用外部 API(非本系统内部调用)的风险。
- 设置超时与重试机制
- 详细的调用日志留存备查
- 慢SQL监控。
- 慢操作监控。
- 其它可能存在的风险。
表 ID 字段
一个基础的 UUID 是这个样子的:70E2E8DE-500E-4630-B3CB-166131D35C21, 字符串对待,比如 varchar(36)。
随机数排序十分困难, 因为 UUIDs 是随机的,做哈希后跨度太大,容易引起 Btree 的 rebalance,插入性能很低。
如果 Snowflake 所运行的那些机器时钟有大的偏差时, 整个 Snowflake 系统不能正常工作(偏差得越多, 分配新 ID 时等待的时间越久)
百度开源的分布式唯一ID生成器UidGenerator,解决了时钟回拨问题
避免复杂的 SQL 查询
复杂 SQL 的坏处:
- 难以维护
- 难以复用
SELECT t.did, t.ecnum, t.dname, t.ecvalidity, t.watermark, t.processtype, t.senderid, t.sendername, t.totalsign, t.currentsign, t.status, t.sendtime, t.orgid, t.sendtype, t.note, update_by, t.create_time, t.signatorys, t.template_id, isposition FROM sc_ecdocument t WHERE 1 = 1 AND t.did IN (SELECT ss.ecdocumentid FROM sc_ecdocument_signatory ss WHERE 1 = 1 AND ss.orgid = 'ae3d085e0242f3018ae53e85a0f152f5' AND ss.signstate = '2' AND ss.signtype = '0' AND ss.dnumsignname LIKE CONCAT('%', '%', '%')) AND t.status = '1' AND t.sendtime >= DATE_FORMAT('2019-05-28', '%y%m%d') AND DATE_FORMAT(t.sendtime, '%y%m%d') <= DATE_FORMAT('2019-06-27', '%y%m%d') ORDER BY sendtime DESC LIMIT 0 , 5
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论