1 应用分层
1.1 【推荐】推荐分层
图中默认上层依赖于下层,箭头关系可表示直接依赖,如:开放接口层可以依赖于Web层,也可以直接依赖于 Service 层,依此类推:

-
开放接口层:
-
终端显示层
各个端的模板渲染并执行显示的层。当前主要是 velocity渲染、js渲染、jsp渲染、移动端展示、小程序等。
-
Web 层:
主要是对访问控制进行转发,各类基本参数校验,或者不服用的业务简单处理等。
-
Service 层:
相对具体的业务逻辑服务层。
-
Manage 层:通用业务处理层,它具有以下特征:
- 对第三方平台封装的层,预处理返回结果及转化异常信息。
- 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理。
- 与 DAO层交互,对多个 DAO 的组合复用。
-
DAO 层:
数据访问层,与底层 MySQL、Oracle、Hbase 等进行数据交互。
-
外部接口或第三方平台:
包括其他部门 RPC 开放接口,基础平台,其他公司的 HTTP 接口。
1.2 【参考】封层异常处理规约
- 在 Dao 层,产生的异常类型很多,无法使用细粒度的异常进行 catch,可使用
Exception e
的方式,返回给上层 Manager/Service。
- 在 Serivice 层出现异常时,必须记录出错日志到磁盘,尽可能带上参数信息,相当与保护案发现场。
- 如果 Manager 层与 Service 同机部署,日志方式与 DAO 层处理一致;如果是单独部署,则采用与 Service 一致的方式。
- Web 层:不可以继续往上抛异常,因为已经处于顶层,如果意识到这个异常将导致页面无法正常渲染,那么就应该直接跳转到友好错误页面,加上用户容易理解的错误提示信息。
- 开放接口层要将异常处理成错误码和错误信息并返回。
2 二方库依赖
2.1【强制】定义 GAV 遵从以下规则:
(1)GroupID 格式:
com.{公司/BU}.业务线.[子业务线]
,最多四级。
# 正例
com.couragesteak.blog
com.couragesteak.dubbo.register
(2)ArtifactID 格式:
- 产品线名 - 模块名。
- 语义不重复不遗漏,先到中央仓库去查证一下。
# 正例
dubbo-client
fastjson-api
jstorm-tool
couragesteak-api
(3)Version:
2.2【强制】二方库版本号命名方式
格式:主版本号.此版本号.修订号
(1)主版本号:产品方向改变,或者大规模 API 不兼容,或者架构不兼容升级。
(2)此版本号:保持相对兼容性,增加主要功能特性,影响范围极小的 API 不兼容修改。
(3)修订号:保持完全兼容,修复 BUG、新增次要功能特性等。
说明:
主要版本起始版本号必须为:1.0.0,而不是 0.0.1,正式发布的类库必须先去中央仓库进行查证,使版本号有连续性,正式版本号不允许覆盖升级。如当前版本:1.3.3,那么下一个合理的版本号:1.3.4 或 1.4.0 或 2.0.0
# 正例
1.0.0 # 最低版本号
1.0.1
2.3【强制】requirement.txt
必须声明所有依赖的版本号,避免自动下载最新依赖导致的不兼容。
# 正例
SQLAlchemy==1.4.43
aiomysql==0.1.1
2.4【参考】二方库 发布原则
(1)精简可控原则。
移除一切不需要的 API 和依赖,只包含 Service API、必要的领域模型对象、Utils类、常量、枚举等、如果依赖其他二方库,尽量是 provided 引入,让二方库使用者去依赖具体版本号;
无 log 具体实现,值依赖日志框架。
(2)稳定可追溯原则。
每个版本的变化应该被记录,二方库由谁维护,源码在哪里,都需要能方便查到。除非用户主动升级版本,否则公共二方库的行为不应该发生变化。
3 服务器
3.1【推荐】高并发服务器超时时间
说明:操作系统默认 240 秒后,才会关闭处于 time_wait 状态的连接,在高并发访问下,服务端会因为 time_wait 的连接数过多,可能无法建立新的连接,所以需要再服务器上调小此等待值。
# 正例
# 在 linux 服务器上通过变更 /etc/sysctl.conf 文件去修改该缺省值
net.ipv4.tcp_fin_timeout = 30
3.2 调大服务器所支持的最大文件句柄数
调大服务器所支持的最大文件句柄数(File Descriptor,简写为 fd)。
说明:主流操作系统的设计是将 TCP/UDP 连接采用与连接文件一样的方式去管理,即一个连接对应于一个 fd。主流的 linux 服务器默认所支持最大 fd 数量为1024,到那个并发连接数很大时很容易因为 fd 不足而出现 “open too many files” 错误,导致新的连接无法建立。建议将 linux 服务器所支持的最大句柄数调到最高数倍(与服务器的内存数量无关)。
3.3 【参考】重定向
服务器内部重定向使用 forward;外部重定向地址使用 URL 拼装工具类来生成,否则会带来 URL 维护不一致的问题和潜在的安全风险。
<h2><a id="1__0"></a>1 应用分层</h2>
<h3><a id="11__2"></a>1.1 【推荐】推荐分层</h3>
<p>图中默认上层依赖于下层,箭头关系可表示直接依赖,如:开放接口层可以依赖于Web层,也可以直接依赖于 Service 层,依此类推:</p>
<p><img src="https://static.couragesteak.com/article/0cd4f4933dd2fd2a2256563649ed9bca.png" alt="应用开发工程分层" /></p>
<ul>
<li>
<p>开放接口层:</p>
<ul>
<li>
<p>可以直接封装 Service 方法暴露成RPC接口;</p>
</li>
<li>
<p>通过Web封装成 http 接口;</p>
</li>
<li>
<p>进行网关安全控制、流量控制等</p>
</li>
</ul>
</li>
<li>
<p>终端显示层</p>
<p>各个端的模板渲染并执行显示的层。当前主要是 velocity渲染、js渲染、jsp渲染、移动端展示、小程序等。</p>
</li>
<li>
<p>Web 层:</p>
<p>主要是对访问控制进行转发,各类基本参数校验,或者不服用的业务简单处理等。</p>
</li>
<li>
<p>Service 层:</p>
<p>相对具体的业务逻辑服务层。</p>
</li>
<li>
<p>Manage 层:通用业务处理层,它具有以下特征:</p>
<ul>
<li>对第三方平台封装的层,预处理返回结果及转化异常信息。</li>
<li>对 Service 层通用能力的下沉,如缓存方案、中间件通用处理。</li>
<li>与 DAO层交互,对多个 DAO 的组合复用。</li>
</ul>
</li>
<li>
<p>DAO 层:</p>
<p>数据访问层,与底层 MySQL、Oracle、Hbase 等进行数据交互。</p>
</li>
<li>
<p>外部接口或第三方平台:</p>
<p>包括其他部门 RPC 开放接口,基础平台,其他公司的 HTTP 接口。</p>
</li>
</ul>
<h3><a id="12__44"></a>1.2 【参考】封层异常处理规约</h3>
<ul>
<li>在 Dao 层,产生的异常类型很多,无法使用细粒度的异常进行 catch,可使用 <code>Exception e</code> 的方式,返回给上层 Manager/Service。</li>
<li>在 Serivice 层出现异常时,必须记录出错日志到磁盘,尽可能带上参数信息,相当与保护案发现场。</li>
<li>如果 Manager 层与 Service 同机部署,日志方式与 DAO 层处理一致;如果是单独部署,则采用与 Service 一致的方式。</li>
<li>Web 层:不可以继续往上抛异常,因为已经处于顶层,如果意识到这个异常将导致页面无法正常渲染,那么就应该直接跳转到友好错误页面,加上用户容易理解的错误提示信息。</li>
<li>开放接口层要将异常处理成错误码和错误信息并返回。</li>
</ul>
<h2><a id="2__52"></a>2 二方库依赖</h2>
<h3><a id="21_GAV__54"></a>2.1【强制】定义 GAV 遵从以下规则:</h3>
<p>(1)GroupID 格式:</p>
<ul>
<li><code>com.{公司/BU}.业务线.[子业务线]</code>,最多四级。</li>
</ul>
<pre><div class="hljs"><code class="lang-shell"><span class="hljs-meta"># </span><span class="language-bash">正例</span>
com.couragesteak.blog
com.couragesteak.dubbo.register
</code></div></pre>
<p>(2)ArtifactID 格式:</p>
<ul>
<li>产品线名 - 模块名。</li>
<li>语义不重复不遗漏,先到中央仓库去查证一下。</li>
</ul>
<pre><div class="hljs"><code class="lang-shell"><span class="hljs-meta"># </span><span class="language-bash">正例</span>
dubbo-client
fastjson-api
jstorm-tool
couragesteak-api
</code></div></pre>
<p>(3)Version:</p>
<ul>
<li>详细规定参考下方</li>
</ul>
<h3><a id="22_83"></a>2.2【强制】二方库版本号命名方式</h3>
<p>格式:<code>主版本号.此版本号.修订号</code></p>
<p>(1)主版本号:产品方向改变,或者大规模 API 不兼容,或者架构不兼容升级。</p>
<p>(2)此版本号:保持相对兼容性,增加主要功能特性,影响范围极小的 API 不兼容修改。</p>
<p>(3)修订号:保持完全兼容,修复 BUG、新增次要功能特性等。</p>
<p>说明:</p>
<p>主要版本起始版本号必须为:1.0.0,而不是 0.0.1,正式发布的类库必须先去中央仓库进行查证,使版本号有连续性,正式版本号不允许覆盖升级。如当前版本:1.3.3,那么下一个合理的版本号:1.3.4 或 1.4.0 或 2.0.0</p>
<pre><div class="hljs"><code class="lang-shell"><span class="hljs-meta"># </span><span class="language-bash">正例</span>
1.0.0 # 最低版本号
1.0.1
</code></div></pre>
<h3><a id="23requirementtxt_103"></a>2.3【强制】requirement.txt</h3>
<p>必须声明所有依赖的版本号,避免自动下载最新依赖导致的不兼容。</p>
<pre><div class="hljs"><code class="lang-shell"><span class="hljs-meta"># </span><span class="language-bash">正例</span>
SQLAlchemy==1.4.43
aiomysql==0.1.1
</code></div></pre>
<h3><a id="24__113"></a>2.4【参考】二方库 发布原则</h3>
<p>(1)精简可控原则。</p>
<p>移除一切不需要的 API 和依赖,只包含 Service API、必要的领域模型对象、Utils类、常量、枚举等、如果依赖其他二方库,尽量是 provided 引入,让二方库使用者去依赖具体版本号;</p>
<p>无 log 具体实现,值依赖日志框架。</p>
<p>(2)稳定可追溯原则。</p>
<p>每个版本的变化应该被记录,二方库由谁维护,源码在哪里,都需要能方便查到。除非用户主动升级版本,否则公共二方库的行为不应该发生变化。</p>
<h2><a id="3__125"></a>3 服务器</h2>
<h3><a id="31_127"></a>3.1【推荐】高并发服务器超时时间</h3>
<p>说明:操作系统默认 240 秒后,才会关闭处于 time_wait 状态的连接,在高并发访问下,服务端会因为 time_wait 的连接数过多,可能无法建立新的连接,所以需要再服务器上调小此等待值。</p>
<pre><div class="hljs"><code class="lang-shell"><span class="hljs-meta"># </span><span class="language-bash">正例</span>
<span class="hljs-meta"># </span><span class="language-bash">在 linux 服务器上通过变更 /etc/sysctl.conf 文件去修改该缺省值</span>
net.ipv4.tcp_fin_timeout = 30
</code></div></pre>
<h3><a id="32__137"></a>3.2 调大服务器所支持的最大文件句柄数</h3>
<p>调大服务器所支持的最大文件句柄数(File Descriptor,简写为 fd)。</p>
<p>说明:主流操作系统的设计是将 TCP/UDP 连接采用与连接文件一样的方式去管理,即一个连接对应于一个 fd。主流的 linux 服务器默认所支持最大 fd 数量为1024,到那个并发连接数很大时很容易因为 fd 不足而出现 “open too many files” 错误,导致新的连接无法建立。建议将 linux 服务器所支持的最大句柄数调到最高数倍(与服务器的内存数量无关)。</p>
<h3><a id="33__143"></a>3.3 【参考】重定向</h3>
<p>服务器内部重定向使用 forward;外部重定向地址使用 URL 拼装工具类来生成,否则会带来 URL 维护不一致的问题和潜在的安全风险。</p>
留言