插件版本管理说明(十年磨一剑!)

十年磨一剑!

一个中台管控系统的版本化管控方案:插件版本管理说明

  • 插件系统说明
    • 当前插件系统本身是一套责任链模式系统, 插件和插件间通过约定进行功能交互. 简单以库存同步为例, A插件只要约定库存同步规则, ERP只要按这个约定给到A插件, A插件就可以完成库存同步. 叠加套餐插件, 就ERP给数据到A插件, 套餐提取ERP数据, 处理完, 再按约定给到A即可实现套餐库存同步. 后续如果叠加虚拟库存, ERP给数据, 虚拟库存插件将计算结果按约定给到套餐或直接给到A插件, 最终实现库存上传. 订单同样, 通过订单状态约定, 可无缝切换波次, 快递鸟, 菜鸟裹裹等插件, 组成各种系统, 而系统只需维护好每个插件. 但同样的, 系统对插件设计要求会比较高, 任何功能需要经过合理安排, 检查和测试才能进来, 不然一个调整疏忽将可能蹦坏各种组合成的系统, 特别是系统插件等核心插件.
  • 插件系统问题
    • 原插件系统被设计成是做成类似”微擎”,”discuz”或”odoo”类的应用平台, 打算实现各插件独立版本化管控, 这样契合各平台接口对接, 也方便各平台独立管理, 升级, 便于未来做一个开放式平台做铺垫. 但随着时间推移, 现有系统已经形成插件组合模式的系统, 本质上, 该模式已和原设计的插件平台模式不同, 大部分插件已经通过组合, 形成一个插件组合系统而非插件独立管控形式, 单一插件出问题, 将影响到各种组合构成的系统. 而原管控模式, 包括SVN只设计了主线和分支管理, 没有实现一个主系统的版本的截断, 在持续开发迭代过程中, 容易出现因考虑不足, 导致系统不稳定, 特别是系统插件等核心插件的调整. 系统已经经过快速发展期, 现在需要进入稳定管控阶段, 所以需要实现一个版本截断和管理. 并有规划的进行版本升级, 不能只认一个主线即一个”版本号”.

 

 

 

机器学习杂杂收集(最近一年一直在学习这块)

莫凡python(非常适合入门)

https://mofanpy.com/

yolov(目标检测工具)

https://pytorch.org/hub/ultralytics_yolov5/

3Blue1Brown (大神讲解神经网络原理)

https://www.3blue1brown.com/topics/neural-networks

动手学深度学习(面向中文读者、能运行、可讨论。中英文版被55个国家的300所大学用于教学。)

https://github.com/d2l-ai/d2l-zh

两年份懒人笔记…

find . -mtime 10 -name "*.php" ! -path "*cache*" ! -path "*think*" ! -path "*runtime*"
  搜索最近修改且排除目录
puppeteer 字体没有生效
  yum groupinstall "Font"
宝塔防火墙实现反响代理时提取真实IP进行安全验证
  宝塔防火墙中本身有CDN设置,开启会识别请求头中信息,有安全问题。识别具体反向服务器IP,再通过提取头部转发IP,才妥当
  /www/server/btwaf/httpd.lua
  function get_client_ip() 最后面补充下列语句
  if(client_ip=='反响代理服务器IP' and httpd.headers_in['x-forwarded-for']~= nil  and httpd.headers_in['x-forwarded-for'] ~= "")  then

		client_ip= httpd.headers_in['x-forwarded-for'];

	end
lua 使用模块
  yum install luarocks
  luarocks install inspect
  lua 文件中local inspect = require('inspect')引入
IE卸载 https://www.cnblogs.com/cang12138/p/6707307.html
统计apache 日志某天前100名
cat xxxxx | grep "16/Nov/2020"  |awk '{print $1}' | sort | uniq -c | sort -nr | head -100
  tail -n 1000000  xxxxxlog | cut -d ' ' -f 1 |sort |uniq -c | sort -nr | awk '{print $0 }' | head -n 10

lodash 按需安装
  npm install lodash.debounce
ssh 密钥登录
  https://toutiao.io/posts/popsg/preview
虚拟机网络不正常
  网络编辑器恢复默认
虚拟机VMware设置开机启动
  https://blog.51cto.com/4746316/2330911
  右键->管理->添加共享
  共享->设置->设置开机启动
oralce 触发器拦截插入
	IF :NEW.JKPT_UPLOAD_MODE in ('ADD','UPDATE') THEN

			raise_application_error ( -20101, '不允许  ADD,UPDATE' );

	END IF;
ubuntu 18 补充/etc/rc.local
  https://blog.csdn.net/qq_41782149/article/details/89001226
测试/etc/rc.local
  sudo /etc/rc.local
  观察当前会话和启动会话环境差异
  echo $PATH(两个地方输出看差异)
  export $PATH=$PATH:/xxxx(修正差异,避免开机启动时环境异常)
mysql 空用户名导致登录密码错误问题
  use mysql;delete from user where User='';  #删除账号为空的行
nodejs cluster 原理
  https://cnodejs.org/topic/56e84480833b7c8a0492e20c
mssql 多转义查询(每个查询后需要补充)
  where xx like '\_' escape '\' and xx not like '\_' escape '\' 
nsp内网穿透
  https://post.smzdm.com/p/az5emoon/
  https://ehang-io.github.io/nps/#/?id=nps
firewalld 命令
  https://wangchujiang.com/linux-command/c/firewall-cmd.html
端口转发软件(iptables,firewall 没启用...不敢直接开...)
  socat TCP4-LISTEN:12345,reuseaddr,fork TCP4:192.168.172.131:22
  后台运行:nohup xxxxx &
深入分析linux进程
  https://blog.csdn.net/FL63Zv9Zou86950w/article/details/105383294
  strace  php-fpm 输出进程所有执行过程
  pstack pid 跟踪进程
  vmstat 2 10 输出当前系统状态
  pidstat -w 5 查看进程上下文切换次数
  iostat -d -k 1 10
  -x 
svn版本 分支合并主线报缺失异常
  https://stackoverflow.com/questions/2472249/missing-ranges-error-message-when-reintegrating-a-branch-into-trunk-in-subversio
apache 日志分析神器
  apachetop 实时分析当前请求情况
  apachetop -f xxxx.log -T xxx 保留观察时间,默认30秒(方向键向右可查看地址的IP统计)
  goaccess 分析并导出日志分析内容, 非常全面
  goaccess 1000000.log  --log-format=COMBINED -o m.goaccess.html
sshfs sftp目录挂载 不补充参数会出现没有权限读取的问题
  sshfs -p 22 xxx@xxxxx.com:/ /xxxxx  -o allow_other -o reconnect
邮箱原理
  https://wiki.ubuntu.org.cn/IRedMail#iRedmail_.E7.BB.84.E4.BB.B6
剪切板过小问题
  修改系统虚拟内存.
查询window日志(按类型)
  https://blog.csdn.net/C_chuxin/article/details/84974207
php sftp 操作
  pear install 
  https://techglimpse.com/install-phpseclib-netssh2-netsftp-ppc64le-machine-centos/
  Net_SFTP 也可直接下载放到扩展,无需安装依赖.
  http://phpseclib.sourceforge.net/sftp/examples.html
phpstudy 新版本redis找不到, extention里后面少了.dll导致读取不到文件
  phpstudy 默认开启了opcache,需要关闭
mysql 复制表报错
  Specified key was too long, 索引键使用了utf8mb4导致
 puppeteer 安装 Failed to download Chromium r
 	cmd:set PUPPETEER_SKIP_DOWNLOAD=1  // 跳过chrome下载
  node ./node_modules/puppeteer/install.js // 单独下载谷歌
  record脚本:https://www.stefanjudis.com/blog/how-to-record-screen-actions-as-a-puppeteer-script/
  屏蔽特征:https://blog.xinshangshangxin.com/2019/01/01/headless-chrome-start/
svn 提交&清理报错  Failed to run the WC DB work queue associated with
  .svn/wc.db // sqlite3打开 清理WORK_QUEUE表(navicat 等工具直接打开操作即可)
redis消息订阅发布 https://www.runoob.com/redis/redis-pub-sub.html
  查询订阅状态 https://www.runoob.com/redis/pub-sub-pubsub.html
矩阵乘法证明
  http://www.ruanyifeng.com/blog/2015/09/matrix-multiplication.html
  https://nolaymanleftbehind.wordpress.com/2011/07/10/linear-algebra-what-matrices-actually-are/
pycharm " cv2 You need configured Python 2 SDK to render"
  file->setting->project->Python interpreter->齿轮->show all->添加python2.x进来(exsits environment)(python 3.x和python 2.0都要一起出现)
window 请求转发
打开cmd/powershell
首先安装IPV6(xp下IPV6必须安装,否则端口转发不可用!)
netsh interface ipv6 install
添加一个IPV4到IPV4的端口映射 (也可以直接不加listenaddress=0.0.0.0)
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=7000 connectaddress=目标IP connectport=7000
删除指定监听ip和端口
netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=7000 
可以查看存在的转发
netsh interface portproxy show all
plsql 安装+导出,导入
  配置环境变量到oracle_home
  指定exp文件
firewall ipset 控制
  https://www.cnblogs.com/architectforest/p/12973982.html
php 调试
  phpstorm:file=>settings=>languages&frameworks=>php=>cli interpreter 添加php路径
  interpreter 指定 php 路径时, 下面的xdebug文件也需要指定
  对应php.ini配置xdebug为启用
SVN 版本误删除重新找回&合并(包括重命名)
  文件浏览器(右边指定浏览到达版本), 可显示该误删除分支原完整提交日志
  合并时指定版本范围,可合并原丢失SVN版本
yum socket代理 
  /etc/yum.conf  追加  socks5h://xxxx
gcc 编辑器版本升级
  手动编译:https://blog.csdn.net/EI__Nino/article/details/100086157
  https://gist.github.com/pablomp/237ee367e4a0ac060ed83d3d40e2285a
  find / -name "libstdc++.so*"
       检查编译后版本:strings /root/local/lib64/libstdc++.so.6.0.23 | grep CXXABI

       添加lib至全局:export LD_LIBRARY_PATH=/root/local/lib64/:$LD_LIBRARY_PATH

  安装式升级编辑器:https://linuxize.com/post/how-to-install-gcc-compiler-on-centos-7/
  复制文件到 /usr/lib64/xxx下
  建立软链接:ln -s libstdc++.so.6.0.25 libstdc++.so.6

 

网络异常排查

网络异常排查

 

关键字:网络排查

PING(优先)(判断网络是否正常)

命令

ping IP/域名

示例

 

观察响应是否正常,再判断时间是否过久,正常100ms内,超过250ms会出现不稳定,超过300ms算不正常,需要从网络,运营商,路由等各方面进行排查.

判断端口是否正常

同时需要确认目标主机是否开放ping命令,如果目标主机禁止了ping,则通过tracert 判断数据包是否到达或通过telnet 观察目标端口是否可到达.

如果是ping域名不通,需要检测域名解析是否正常(获取域名实际IP后进行ping测试)

TELNET(判断目标程序是否可以访问)

命令

telnet IP/域名 端口

示例

端口异常

端口正常

端口不正常需要通过多种方式判断,优先判断目标服务主机本地是否可以TELNET或访问到服务,再依次判断内网,路由,外网(如果是云主机,需要判断安全组是否有设置)

主机正常,内网不正常,检查防火墙

主机正常,内网不正常,且存在多路由,原路由检查后,再检查延伸路由

主机正常,内网正常,外网不正常,检查外网映射;检查安全组.

补充:需要注意程序或服务是否允许外网访问,很多程序,默认是只允许本地访问,这样即使telnet通,程序也无法使用.

 

NSLOOKUP(判断域名解析是否正常)

命令

nslookup 域名

示例

正常解析

解析异常

说明

只有在ping通IP的前提下,判断域名解析才有意义.

IP正常,域名不通常见处理

通过nslookup命令判断域名解析是否正常

直接写死host文件

C:\Windows\System32\drivers\etc\hosts

注:不推荐,避免后续IP切换导致潜在异常. 需要确认好目标服务器IP是否为动态.

尝试刷新DNS

 

需要跟域名管理人确认好是否已设置解析

修改DNS

114.114.114.114

223.5.5.5

223.6.6.6

TRACERT(判断数据包到目标网络哪个线路异常)

命令

tracert IP/域名

示例

本机->内网->运营商->目标运营商->目标机房->目标内网->目标服务器

观察每次跳跃点,通过分析跳跃点,排查数据包在哪个阶段的路由跳转异常,根据实际情况处理.

 

网络异常排查

 

 

JS中的debounce与throttle

转:https://juejin.cn/post/6844903760334946312#heading-5

debounce 有一个等待时长,如果在这个等待时长内,再次调用了函数,就取消上一个定时器,并新建一个定时器。所以 debounce 适用于 input, keyup, keydown 等事件, 亦或者 click 事件需要防止用户在某个时间范围内多次点击的时候,也可以用。注:在lodash 的实现中 中并没有取消新建定时器的做法,是用时间来判断的。
throttle 也有一个等待时长,每隔一段这个等待时长,函数必须执行一次。如果在这个等待时长内,当前延迟执行没有完成,它会忽略接下来调用该函数的请求,不会去取消上一个定时器。所以 throttle 适用于 scroll, mousemove 等事件。在lodash 的实现中,还有一个等待的最大时长,这个我们分析源码时再讨论。

 

基于midwayjs编写的一个自动更新框架结构说明

midwayjs为eggjs的ts版本+依赖注入。这边由于接入的业务类型名,利用eggjs的插件形式,做成一个平台化,所有程序以插件的形式挂入的形式。所有模块单独进行模块管理。类似小程序。

  • TypeScript体系调研报告:https://juejin.im/post/59c46bc86fb9a00a4636f939
  • 淘宝开发实践:https://www.infoq.cn/article/L1yoBP2qbJ5yW*2D7Mv7
  • 语法:https://github.com/joye61/typescript-tutorial
  • javascript迁移:https://jkchao.github.io/typescript-book-chinese/typings/migrating.html
  • 装饰器:https://www.xiaoyulive.top/books/typescript/decorator-definition.html#%E8%A3%85%E9%A5%B0%E5%99%A8%E7%BB%84%E5%90%88
  • EGGJS文档:https://eggjs.org/zh-cn/intro/
  • EGGJS(typescript)文档:https://eggjs.org/zh-cn/tutorials/typescript.html
  • MIDWAY文档:https://midwayjs.org/midway/guide.html
  • MIDWAY依赖注入文档:https://midwayjs.org/injection/guide.html
  • 参考开源项目:
    只做参考,有兴趣再看

    • DoraCMS
      基于EGGJS(ES)
      一个完成度很高的CMS管理系统​
    • cool-admin
      基于EGGJS(TS)
      一个通用的后台管理系统,不过要付费。 这边有一部分源码,可以学习用。​
    • doodoo.js
      基于KOA
      一个微服务开源框架​
    • cabloy
      基于EGGJS(ES)
      一个全栈开发框架​
    • apshop
      基于EGGJS(ES)
      开源网店​
    • lin-cms-koa
      基于KOA
  • 自动更新结构说明
    • EGG 后台更新推送结构
      全部结构采用统一结构形式, 在补充后台的情况下,需要后台同时进行模块版本号的依赖管理。再推送配置列表到客户端

      • jy-tmall
        文件目录清单:
        /src/plugins/jy-tmall
        说明: 所有模块都以模块和独立的版本代号进行管理,更新,维护。在客户有特殊定制需求的情况下,可以复制,并调整名字做为一个新插件推送到客户端。在有时间的情况下,再考虑标准化。

        • version
          版本编号,不同时,则更新
        • type
          类型,暂定两种类型,一种是插件,一种是基础类型,更新形式相同,只有启动方式,程序插件需要做特殊化处理​
        • path
          压缩包解压路径
        • script
          程序初始化脚本,程序解压后,如果有指定初始化脚本,则会进行相应的初始化操作
        • download
          下载文件路径,做了权限判断,只有有权限的,才能下载到文件。​
      • jy-test
        文件目录清单:
        /src/plugins/jy-tmall

      • base_application
        文件目录清单:
        ​/src(除了/src/plugins目录)
        /​install.js
        /upgrade.js
        /common
        说明:
        系统基础程序结构,相对稳定,按需更新。​​​​​​

      • base_static
        文件目录清单:
        /public
        说明:​​
        更新频率很少​

      • base_node_modules
        文件目录清单:
        ​/node_modules
        ​/package.json
        /package-lock.json​
        说明:
        ​更新频率相对较少。同时插件目录本身也支持,也可以考虑直接在程序插件中进行特殊化管理。​

    • EGG TYPESCRIPT 自动更新结构整理
      • common
        程序相关辅助数据

        • sql
          程序建表语句

          • table
            • goods
            • test
              • mssql
                • JKPT_TEST.sql
                  建表语句,可以包含字段
                • JKPT_TEST_COLUMN_ADD_TEST.sql
                  字段扩张,相当于用于不同版本的字段修正
              • oracle
                • JKPT_TEST.sql
                • JKPT_TEST_COLUMN_ADD_TEST.sql
      • data
        系统数据,不对外, 系统生成

        • plugins
          插件相关文件数据

          • jy-tmall
          • jy-test
        • download
          下载的数据​
      • dist
        程序自动编译目录
      • local_test
        本地测试目录
      • node_modules
        node 基础模块
      • public_file
        插件相关下载,同时需要对外的数据,必须放这里

        • uploads
          • plugins
            • jy-tmall
            • jy-test
      • public
        静态资源文件,且对外。​
      • run
        ​系统运行时文件,用于分析系统当前依赖的情况
      • src
        系统源码目录,插件和系统主程序代码都放在这个目录中。插件目录移动到外面,会出现路由映射等识别不到的问题​

        • app
          • controller
            • base
              基础模块

              • BaseController.ts
                控制器命名规则:骆驼命名+Controller.ts
                ​基础控制器,其它控制器继承于这个文件
                ​内置通用频率拦截,用于当计划任务使用时或防止异常扫描时,进行数据拦截
                所有控制器,都通过声明式语法进行路由指定和控制:https://midwayjs.org/midway/guide.html#web-%E4%B8%AD%E9%97%B4%E4%BB%B6​​
          • extend
            需要声明:/src/index.d.ts
            ​框架扩展

            • context.ts
              上下文扩展
            • request.ts
              请求扩展
          • mode
            需要声明:/src/index.d.ts
            ​按需要,构建数据模型​
          • schedule
            需要声明:/src/index.d.ts
            声明结构:[{title:“标题”,url:”请求地址”}​]​
            ​通用计划任务,所有计划任务挂到/src/config/config.default.ts:config.tasks上,计划任务会以指定频率,进行异步请求,频率限制直接通过base.limitAccess(second)限制,也可考虑再补充参数到计划任务中。实现一个计划任务管理器,管理所有任务列表。​
          • view
            模板文件
          • router.ts
            路由器暂时只有socket使用。
        • config
          • config.default.ts
            配置文件,不同启动方式,可以配置不同的配置文件
          • plugin.ts
            插件配置文件,内置插件基本不用调整,需要的插件按需添加。同时做了特殊处理,会将/config.json:plugins插件列表的插件加载进来.​
        • lib
          公共代码库

          • common
            通用库,暂时是用js,主要保留js脚本需要执行特殊代码如更新和初始化时使用,同时挂到了全局​
            常用工具库​
            调用方式:
            ts:​globalThis.common​
            js:common​

            • arrayHelper.js
              数组
            • commonHelper.js
              通用函数
            • dbHelper.js
              通用数据库操作
              如果是更新脚本和初始化脚本访问数据库时,需要先common.dbHelper.getDb()进行初始化,数据库配置在:/config.json:db​​
            • fileHelper.js
              通用文件操作
            • httpHelper.js
              通用网络请求:下载,GET,POST,JSON,请求编码,请求解码
            • imgHelper.js
              通用图象处理:二维码,条码等
            • numberHelper.js
              通用数字操作:精度计算(精度计算提供了公式封装)
            • stringHelper.js
              通用字符串操作
            • timeHelper.js
              通用时间操作
        • plugins
          程序插件目录,每个程序插件,都可以做为一个独立的程序,挂到接口平台。只要在/config.json 中有,启动时会自动挂进来,并进行相关初始化。 前台可完成访问
          所有ts程序,必须放在/src目录中。​

          • jy-test
            • app
              • controller
                • GoodsController.ts
                  不同模块,控制器名可相同,需要进行@provide(‘/jy-test/GoodsController’)声明作用域
              • public
                程序插件静态资源文件,下载和上传的数据。必须放/public,不能放这里。避免更新时的覆盖。通过/src/plugins/jy-test/app.ts初始化,挂静态路径进来。
              • service
                需要进行声明
                ​不能出现同名的业务类,需要按模块,按插件,进行变量名规范。如:jyTestUser.ts
              • view
                程序插件模板目录
            • app.ts
              文档:https://eggjs.org/zh-cn/basics/app-start.html
              ​​egg初始化时,在声明周期需要进行特殊处理的地方。
              程序插件在启动初始化时,会挂菜单,挂计划任务​, 挂插件静态目录映射等,按需要调整。
            • install_plugin.js
              数据初始化脚本,当更新和安装时,如果推送的配置有指定更新脚本,则会执行。
              初始化时,尽量利用knex的兼容性(判断表,字段,视图等是否存在,以及字段长度,类型),大代码块或knex处理麻烦的以sql形式放置(建表)(knex搞太多东西,会带来一定的阅读困难),再通过knex.raw进行代码块的执行。
              ​/common/sql/table/test/mssql/JKPT_TEST.sql
              /common/sql/table/test/mssql/JKPT_TEST_COLUMN_ADD_TEST.sql​
            • package.json
              程序插件配置
          • jy-tmall
            插件目录结构相同

        • service
          • admin
            业务模块

            • AdminAdminService.ts
              命名规则:插件名+业务名+Service.ts
              ​业务类,不能出现同名,需要定个规定,按模块和插件进行业务类型命名.相关接口声明,也需要按类似形式,避免不规范导致的冲突
        • app.ts
          文档:https://eggjs.org/zh-cn/basics/app-start.html
          ​​egg初始化时,在声明周期需要进行特殊处理的地方。
          程序插件在启动初始化时,会挂菜单,挂计划任务​, 挂插件静态目录映射等,按需要调整。
        • global.d.ts
          全局声明​
        • index.d.ts
          通用声明,局部声明,需要按需单独防止。命名格式:*.d.ts
        • install_base.js
          程序初始化
          ​脚本初始化全部做了特殊处理,支持单独测试。​
      • test
        单元测试
      • config.json
        系统配置文件,由这边建立,非EGG自带。
        进行数据库配置,用户信息配置。​
        程序插件以及各模块的版本记录
        程序更新是以该文件的版本号为判断依据。同时/src/plugins的插件引入也是通过该文件读取​​
      • install.js
        脚本初始化全部做了特殊处理,支持单独测试。​
        将更新脚本独立出现,方便测试。/upgrade.js在接收到推送时,再调用该脚本​
      • upgrade.js
        程序更新脚本,会启动一个socket,并绑定后台的企业帐号。如果有推送更新,则执行/install.js脚本进行安装.

 

nodejs global的妙用

//gctx.js

//gctx.js
/**
 * global context
 * @type {{}}
 */
let gctx = {};
gctx.error = function(msg, code) {
  let error = (new Error);
  error.code = code;
  error.message = msg;
  error.file = error.stack.split('\n')[2];
  return error;
};
module.exports = gctx;

//subcall.js

let subcall = {};
subcall.call = function() {
  //调用全局报错
  //减少重复性的引用
  throw gctx.error('test', 500);
};
module.exports = subcall;

//index.js

const gctx = require('./gctx.js');
const subcall = require('./subcall.js');
//引入全局global context
global.gctx = gctx;

try {
  // throw gctx.error('test', 500);
  subcall.call();
} catch (e) {
  console.log(e.message, e.code, e.file);
}

输出:

test 500     at Object.subcall.call (....\local_test\subcall.js:4:14)

 

nodejs 优雅的抛出异常

//ctx.js
let ctx = {};
ctx.error = function (msg, code) {
    let error = (new Error);
    error.code = code;
    error.message = msg;
    error.file = error.stack.split('\n')[2];
    return error;
}
module.exports = ctx;
//test.js
const ctx = require('./ctx.js');

try {
    throw ctx.error("test", 500);
} catch (e) {
    console.log(e.message, e.code, e.file);
}
test 500 at Object.<anonymous> (F:\jy\jkpt_backend\local_test\t_error.js:9:20)

 

eggjs-框架, 最近入了nodejs的坑…写给新东家的新框架,基于eggjs

 框架结构

  • app[框架主目录]
    • controller[控制器]
      控制器已实现路由的自动装载,只需要建立具体的控制器. 具体功能业务按需建立目录. 不要将不相干的业务揉在同一模块,同一控制器里.

      • admin[业务模块]
        • admin.js[控制器]
        • system.js[控制器]
    • extend[扩展]
      扩展目录中,可以给控制器,请求类,上下文扩展通用函数(https://eggjs.org/zh-cn/basics/extend.html)
    • io[socket控制器]
      特别注意,静态资源,控制器请求以及io请求,都是同一个端口.通过特殊解析实现具体访问.

      • controller[socket控制器]
        • client[socket模块]
          保留模块, 后续新socket编写需要单独建立模块目录,并在具体动作中实现业务逻辑. 同样在egg的基础上补充了自动路由装载的实现.

          • client.js[控制器]
            这个socket控制器为保留控制器, 为兼容原客户端的socket请求以及回调的特殊处理类. 所有原socket请求都会通过映射, 跳转到/app/service/client/*里的业务类进行特殊处理,并回调.原请求方式. io.emit(‘message’,{api:’login’,param:{username:’xxx’,password:’xxx’}},function(res){})新请求方式. io.emit(‘/admin/admin/login​​’,{param:{username:’xxx’,password:’xxx’}},function(res){})需要明确注意, socket本质上是不存在回调的. 只是socket.io-client内部和服务器实现了packetid为标志的特殊实现. 其它任何语言都没有…但然. 通过原理编写也行..原理:https://www.cnblogs.com/lightsong/p/10226940.html​​
      • extend[socket扩展]
        同/app/extend
      • middleware[socket中间件]
        • connection.js[连接中间件]
          建立链接时, 可以做权限校验
        • packet.js[数据包中间件]
          数据请求过程中触发
    • lib[工具类]
      引用方式按最原始的方式引用. 不封装引用的主要目的是保留代码提示.

      • common[通用工具目录]
        • commonHelper.js[原通用类 ]
          按需要加,不需要的不要乱加进来,明确功能的.建立目录单独存放​
        • expressHelper.js[快递通用类]
          快递一些通用的获取调用, 在各自模块中实现, 并提供统一调用. 通用类,根据类型去调用具体的帮助类, 减少过程式代码, 增加代码可读性
      • cngg[功能模块目录]
        不同于业务, 一般功能模块都有其特殊实现和封装. 单独放这里. 业务功能再在业务目录里实现. 最大限度避免代码混乱. 当扩展达到一定的重复性和可用性, 可以考虑写成插件

        • cnggHelper.js[菜鸟裹裹帮助类]
      • kdn[快递鸟目录]
    • middleware[中间件]
      个人建议称为中间处理件会相对好理解, 需要先了解下洋葱模型(https://eggjs.org/zh-cn/basics/middleware.html), 类似过滤器

      • commonRequest.js[通用请求中间件]
        将常规请求进行前置处理, 如get和body合并到ctx.request.params中. 不区分get和post.
      • mwAdminUser.js[用户请求权限中间件]
        实现用户的权限判断和拦截
    • model[数据模型]
      暂时使用的数据库是mongodb, 然后暂时选用的访问方式为mongose(https://mongoosejs.com/docs/guide.html), 同时提供原访问方式, 方便快速复用原代码(尽量能写成新的写成新的…别只复制粘贴…)

      • Admin[业务模块]
        特别注意,其它目录都是小写开头, 只有数据模型的目录和类是大写开头….

        • Admin.js[数据模型类]
          数据层可复用代码,尽量复用到数据模型. 业务层复用业务模型. 尽量减少重复代码. 如可以写一个函数load(id), 找不到直接报错. 后续通用调用即可.
    • public[静态文件]
      egg-static提供静态文件访问支持​, 同端口访问时. 如果路径为/public/则会自动进入该目录​, 客户端和小访问量服务器可以直接使用. 大访问量, 需要实际压力测试看看. 最好还是走nginx做反向代理.

      • assets[静态资源目录]
      • backstage[后端静态资源目录,主要是组件类封装]
        复制原资源文件, 暂时按习惯的来
      • upload[上传文件目录]
    • router[路由配置]
      • router.dev.js
        路由实际配置脚本, 自动化脚本能满足基本路由情况, 如果需要特殊路由或者兼容原路由. 可以单独在这个地方再补充映射https://eggjs.org/zh-cn/basics/router.html
    • schedule[计划任务]
      计划任务只需要复制即可使用, 但是发现需要重启服务才会引入, 需要研究下热部署?
    • service[业务]
      需要理解下新的设计分层, 该形式接近MVC, 但是不是MVC.常规MVC是模型,视图,控制器, egg 结构层是 数据层(model), 控制器(controller), 业务(service), 视图(view), 控制器只做权限以及参数校验, 具体功能封装到业务层中. ​主要目的是实现代码的高复用性.如登陆,封装成service.user.login(username,password), 后续任何地方都是调用这个业务, 即可实现登陆. ​同时后续的单元测试, 主要是测试业务类.同时, 业务需要以抛出异常的形式代替返回值判断, 并再最外层进行异常处理. 可大大增加代码的可读写以及编写. 避免没必要的各种判断​

      • admin[业务模块]
        • adminService.js[业务类]
          结构类似控制器, 全是只为处理具体业务代码
      • client[保留模块]
        原客户端的io调用使用的方式和egg-socket不一样. 未避免冲突, 单独配置一个io路由,并将原请求动作全部映射到这里的具体业务动作. 同时兼容了socket.io-client的回调

        • enterpriseService.js[原客户端所有socket调用]
    • view[视图]
      所有页面文件以*.ejs做后缀, webstorm,vscode等格式化和开发过程中<% %>会有代码提示, 会极大的提高开发效率, 测试过程中, 也可以考虑页面代码在<%%>中测试再贴回去. 页面保存是实时更新的. nodejs其它功能模块修改在ssd的情况下, 依然需要4,5 秒的重启

      • admin[模块目录]
        • site[控制器目录]
          • login.ejs[登陆页面]
            页面对应具体的控制器
      • layout[通用页面组件]
        • layout.ejs[图层]
          包含常用的静态资源文件引入, 控制器里渲染页面时, 图层会包裹具体的页面代码, 可以方便全局性调整. 对于可复用的页面组件, 都可以考虑封装成*.ejs或者作成vue组件, 按需要来
      • 200.ejs[通用消息提示页面]
      • 500.ejs[通用错误消息提示页面]
    • router.js[路由脚本]
      用于引用/app/router里的实际路由脚本​, 路由脚本在egg的基础上加了自动配置, 只需要复制或新增控制器, 就会自动添加路由
  • test[单元测试目录]
  • local_test[自己编写的框架外的测试脚本]
  • cache[缓存目录]
    如果使用缓存, 则目标缓存会生成到该路径下, 如果服务器有多节点. 缓存必需存放到redis或数据库, 不能配置单机的fs或内存缓存. 除非是代码或页面类缓存,视具体情况选择
  • config[配置目录]
    • locale[翻译目录]
      • zh-CN.js[翻译语言配置脚本]
        egg-validate的翻译,需要在这个地方进行配置
    • config.default.js[默认配置]
    • config.dev.js[具体环境配置脚本]
      可根据启动命令不同,加载不同配置文件,方便测试
    • plugin.js[插件配置]
      框架使用插件,必须在这个地方启用, 然后如果有特殊参数配置,在/config/config.default.js里进行详细参数配置. egg默认启用的插件需要到/node_modules/eggjs 里进行查看.
  • logs[日志目录]
    • test_egg[项目名]
      • common-error.log[常规日志]
      • egg-agent.log[agent日志]
      • egg-schedule.log[计划任务日志]
      • egg-web.log[egg内部日志]
  • package.json[配置文件]
    • 启动命令
      • 启动开发环境:npm run dev
        • 实际脚本:egg-bin dev –sticky –port 7001
      • 启动生产环境:npm run start
        • 实际脚本:egg-scripts start –daemon –sticky –port 7001
    • 启动模式
      • 框架是以 Cluster 方式启动的,而 socket.io 协议实现需要 sticky 特性支持,否则在多进程模式下无法正常工作。
    • 注意事项
      • 最好指定端口, 否则开发工具崩溃后, 重新运行, 会被重新分配端口, 避免带来不必要的问题
  • 框架保留问题, 需要找时间进行优化
    • 框架文件过多(超过3w+文件…)
      • 优化方向:减少不必要的扩展.
    • 重启速度需要再进行研究优化,在ssd的情况下, 重启服务需要大概4,5秒, 较影响开发, 不过配合调试模式, 可以弥补.
      • 优化方向:考虑单独写个启动脚本, 抛弃一些特性来实现热更新, 具体再观望看看别人有没有其它实现. 尽可能实现修改后马上可见.
    • 页面组件化
      • 优化方向:无
        • 还在学习和了解中.