程序设计(一)

本篇博客记录一些在软件开发过程中遇到的问题及思考,持续更新。。。

协议, 原生 API 和第三方框架(或工具包)

  • 协议

    有些程序组件,比如LDAP,同时提供协议访问方式和 API 方式,协议方式直接操作数据,但是也是组件软件迭代时最可能变化的,可根据应用场景进行取舍。

  • 原生 API

    1、使用原生 API 有助于加深对基础架构的理解和增强自己的代码能力。

    2、使用原生 API 操作复杂。

  • 第三方框架(或工具包)

    1、使用第三方框架(或工具包)可以避免基础组件版本变化带来的 API 变化,第三方框架去屏蔽版本差异,可以保持程序的稳定性。

    2、如果第三方框架(或工具包)封装的不够好或者有太多 bug,就会增加程序风险。

API 调用

1、假如在一个函数中既循环调用了外部 API,又要进行本地循环处理,那么将调用外部 API 的循环放置在外层,将本地处理的循环放置在内层,可以有效提高程序运行效率,因为调用外部 API 网络延时较长,本地处理速度快。

2、除非迫不得已,否则绝对不使用用户名和密码的方式调用 API。

3、对于 Access Key 和 Secret Key 这种东西,绝对不要直接写在代码中,要保存在本地文件中。

思考事项

1、在编写代码时,需要考虑数据量,从而考虑网络、计算和存储的分离。

问题

微服务设计

整个系统进行了拆分,但是各个服务使用的数据模型有重合(有些完全重合,有些部分重合)的部分,使用 ORM 框架后,如果彼此之间引用私有仓库的包,会出问题,但是放在公有专门的存放仓库之后,代码散乱,组织结构复杂,可读性会降低,如何优雅地处理这个问题?

目前是将数据模型复制到需要使用的地方,基本可以解决问题,但是同时,如果公用的数据模型发生变动,其他各处可能需要同步修改,否则会出错误。

错误处理

在 web 开发中,是使用 HTTP 的响应状态码响应请求,还是在 HTTP 的响应状态码之内,再包裹一个自定义的状态码及错误信息,在什么场景下采用哪种方式好些?

在采取后者的情况下,往往会存在以下问题:

  • 状态码不是全局统一和集中管理的,从而是所有服务公用一套的,导致有和没有一个样,甚至更加混乱,给解决错误带来更大的困扰,实际上解决错误时还是老一套。
  • 状态码的制定规则,是针对具体错误制定,还是针对某个服务来制定?
  • 在响应中混用自定义状态码和 HTTP 状态码,导致前端无法统一处理错误。

生产环境和测试环境分离

系统开发一段时间后,逐渐地,测试环境和生产环境产生了分离,其实主要是后台数据库数据的差异(完全的前后端分离架构),导致一些线上环境中产生的错误,无法在测试环境中复现或修改后也无法在测试环境中进行测试,从而往往会在生产环境中进行小测试,如之奈何?

1、将生产数据库中除用户信息之外的其他数据每隔一段时间复制到测试数据库中

2、在测试环境中使用生产环境的 API 接口。

真理

  • 好的架构不是设计出来的,是演进出来的。

待考虑问题

2019年11月15日

1、设置 GitLab 保护,禁止向工程的 master 分支直接推送代码,只能从其他分支合并到 master 分支。

2、考虑到将 DDLDML 写在一个文件中时,在一些 SQL 管理工具中打开整个文件后不小心执行了整个文件,可能会造成不良后果。建议工程的根目录下建立 sql 目录,内含 工程名_ddl.sql工程名_dml.sql 两个文件,要求 工程名_ddl.sql 可以直接整个文件执行,平时进行的 DML 语句写在 工程名_dml.sql 中。

3、考虑到这样一种常用的使用场景,也是我们自己最常用的新应用部署场景,将 DeploymentServiceConfigMap 全部写在一个文件 mainfest.yaml 中,使用 kubectl create -f mainfest.yaml 来创建该应用及相关常用资源,完善新应用部署功能。目前只能部署单独的 Deployment,配置其相应的 Service

4、已有 ConfigMap 落库问题,目前只有通过页面增加的 ConfigMap 落库,其他已经手工创建的 ConfigMap 尚未落库,也不能在页面中修改。

5、DeploymentServiceConfigMap 等资源定期落库。

2020年01月08日

1、基于 AlertManager 的报警数据落库问题,为后续统计数据和优化提供数据支撑。

诡异问题记录

2019年01月03日

公司的内部系统用户认证突然出了问题,直接使用 LDAP 协议的第三方系统中有些不能访问,修改密码后,可以访问,原因是密码过期。但是使用我们自己开发的 LDAP 接口的第三方系统,却还是不能访问。

后来,重启了 LDAP 接口服务后,调用接口的第三方系统终于可以访问了。

查看 LDAP 接口代码,代码中在程序启动时初始化了 LDAP 连接对象,其后的操作都是使用该对象进行的。然而,当 LDAP 服务重启后,程序中初始化的连接将会断掉

1
LDAP Result Code 200 \"Network Error"\: ldap: connection closed

此时,凡是通过接口访问的,都会出现网络错误。

此时,先解决问题,重启 LDAP 接口服务

很多第三方的库或框架,会使用连接池技术,在这种情况下,可以在程序启动时,初始化一个连接对象,用于后续对资源的访问,连接对象由连接池来管理。

但是,当没有提供连接池时,这样做却可能会出现问题,就像我们所遇到的,连接的对端服务重启了,导致该连接失效,但是客户端代码还是使用的该连接,于是会报出来网络错误等。

在预估接口 QPS 不是很大的情况下,可以采用如下两种方式来解决:

1、为每次请求创建一个客户端连接对象,响应完后关闭该连接对象。

2、初始化一个连接对象,但是每次请求时先检测该连接是否还存活,如果存活着,再处理请求;如果已经无法连接服务,再次创建该连接对象,然后处理请求。

updatedupdated2019-07-092019-07-09
加载评论