das 2.0开发记录
本文目前是工作过程记录的素材整理,尚未校正。
1.内存对象定义及访问
核心的内存对象描述对应的系统资源,主要包括机构,用户,服务器。
原来本地和平台是2套分别定义的。
本地:
MEM_SVR_DATA定义:common\APBase.h
SERVERINFO,USERINFO,ORGINFO定义: common\APBase.h
统一定义到:
.i_memdata2.h
文件名字不是很恰当,作用就是服务器端内存系统对象定义及接口。
.memdata.h
实现对象类定义
原来本地和平台访问内存数据分别通过IAP,IDAP接口。分别由ap,dap插件实现。
调整后统一到IMemData接口。
md_xxx是实现IMemData接口的插件统称.
md_bdb和md_mysql分别实现BerkeleyDB和MySQL的IMemData接口。
md_xxx插件的含义提供共享数据的访问,数据一般可以保存在内存中,但不是必须的。
所以,md_xxx理解为share_data_xxx更合适。
dap废除。
ap的作用:作为服务器与外部主动连接的插件,提供内存数据库访问,用户登录处理等。
ap的功能分拆到几个插件中:
。与central server的连接和通信:改为linkto框架和具体的业务插件。
。用户接入功能移到uap.
。内存数据库功能移到md_xxx中
可用于das前置机,im本地服务器(目前不实现),平台服务器与交换服务器连接。
可能存在一些差异:
如:das需要在连接后注册,配置中包含机构,服务器信息等。
2.路由框架
不同的服务器路由策略不同。
以bbox为路由模块的基础。
原来向平台发送消息(通过ap_接口来完成),则需要从代码中消除。由link_to提供路由方法。
.bbox:
---本地模式:
服务器需要与外部服务器主动通信。
GetDataProc,InquiryData,InquiryData2线程都只有在与外部服务器连接后才执行.
CanSend的含义是是否能与平台通信
---非本地模式:平台模式
只有本地服务器连接时才主动推送消息
linkto_xxx:
.一个主动连接器:代码来自ap,目标可配置,支持代理
.负责与central server(外部服务器)的通信
.连接后逻辑由具体的linkto_xx插件完成,如das的linkto_das,向服务器注册。(linkto框架通过事件与具体的模块通信)
.linkto_das的开发
im需要开发的有
.linkto_im (本地服务器连接平台)---暂时不支持
.linkto_switch:需要开发
bbox作为框架
入口消息路由:
有2种结果:(1)消息由本服务器插件处理 (2)根据消息目标转发,或者存储转发或丢弃
出口消息路由:
.这种消息不会存储,路径选择和入口消息转发处理一致。
多个插件可以登记路由处理器,根据消息的目标进行路由,
一个消息只能有一个路由出口。
多个路由处理器按登记的顺序调用,如果消息被某个路由处理器处理,则结束不再调用后面的路由处理器。
/// @return 0:未路由 >0:已路由 <0:错误
virtual int HandleInput(CWrappedMsg<> *pwm,int &action) = 0;
如果一个消息没有被任何路由处理器成功处理,则调用默认的路由处理器。
应用可以定义和登记自己的默认路由处理器。
默认路由处理器最后调用。
如果默认路由处理器也未处理,则框架输出丢弃消息的信息。
路由处理
接收路由处理
返回值:
0:由插件处理
非0:不再由插件处理(<0:错误 >0:其它情况)
int CBBoxPlugin::HandleInput(CWrappedMsg<> *pwm,void **pploc,int &action)
发送路由处理
int CBBoxPlugin::HandleSend(CMsg *msg,CWrappedMsg<> **wm)
登记消息检查函数,端点路由函数(如针对特定的类型)
路由是针对目标进行的。可以对端点类型或者具体的目标进行路由,如对机构路由,甚至对某个机构进行路由。
拦截机制:
。只要消息被一个拦截器拦截,消息就不需要再经过其它拦截器处理了。
接口定义
class IRouter {
public:///< 登记一个路由模块virtual int RegisterRouteHandler(IRouteHandler *handler) = 0;};
实现:
class CBBoxPlugin: public CQQBasePlugin,public IRouter {
publci:int RegisterRouteHandler(IRouteHandler *handler);
};
。das服务器的路由:
rto_das_server
---入口消息路由
对于目标为(8,8)的消息,交给插件处理。
默认路由处理:
。对于目标(0,0)的消息,交给插件处理
。其它的返回未路由信息
---出口消息路由
。das前置机的路由:
rto_das_ws
3.hotfox优化
是否支持时序控制可配置.
hotfox.conf增加配置项: 在<Scheduler>节点中增加
<enable_seq_ctrl>false</enable_seq_ctrl> <!--是否支持时序控制,默认:true -->
.直接路由走的消息不需要解析
.ExtAttr的低16位用做时序控制键
4.umx4支持
新特性:
1.消息头ExtAttr域无法使用问题
.利用ExtAttr的低12位作为时序键(最大4096)
可快速分发
2.消息头域的顺序调整,
版本号(1字节)+消息包长度(4字节)+其它
先读5个字节的版本号,然后读整个包.
const unsigned short UMX_INIT_READ_NUM = 5; ///< 初始读的字节数
3.PktHead效率问题:能否做性能优化(未处理)
int VarToBuffer(char *&base,const char *type_name,int offset);
int BufferToVar(char *&base,const char *type_name,int offset);
4.长度引导方式:(未实现)
行集列数据长度是按最大可能长度占用空间的,可能存在比较大的浪费.
每个字节的最高位用来区分是否是最后一个长度字节
兼容性考虑:
为了兼容现有系统(如在不全面升级的情况下,应用于现有的本地服务器),connector默认仍采用UMX3.
对于新的系统,可以通过set_prot_version设置connector的协议版本.可以在linkto_xxx中配置.
class IConnector {
public:///< 设置主动连接器协议版本virtual void set_prot_version(short version) = 0;};
5.全表覆盖支持
实现单表定时同步,与单个对象处理模式相比有2个优点:1.一次处理多个对象,效率高 2.支持删除的情况
/// 变更类型
enum OP_MODE {OM_UNSPECIFED=0, ///< 未指定:默认按新增处理OM_NEW=1, ///< 新增OM_DELETE=2, ///< 删除OM_OVERWRITE=3, ///< 全量修改OM_PK_CHANGED=4, ///< 主键修改OM_INC=5,///< 增量修改OM_SLIGHT_CHANGE=6, ///< 主表(细微)修改OM_FULL_SYNC=7, ///< 表同步
};
virtual int HandleTableChange(CMsg *msg,CSheetDealResult &sdr); ///< 处理全表更新
改名为:
virtual int HandleFullSync(CMsg *msg,CSheetDealResult &sdr); ///< 处理全表更新
该变更应用的限制:
1.对于数据汇集的情况,多个源合并到一个目标库中,只能同步源对应的部分数据而不能影响到其它源的数据. (目标库中需要一个区分源的标志字段,源数据包含该源标志,如src_orgid)。
处理方配置为合并模式处理.目前暂不实现,当出现真实应用的要求时再确定方案和实现.
---源端的消息包可以通过消息头确定源机构.
2.语义上的理解:
从整体角度,这是一种合理的数据同步,分布式环境下的数据一致性。
有危害的方面是,对于目标方这个行为是由源端决定的。
当源和目标属于不同的利益体时,这可能引发责任和风险方面的顾虑。
OM_NEW和OM_INC的处理逻辑的差别:
---增量修改时忽略主表主键冲突,适用于新增明细的情况
抽取规则属性增加:<ChangeMode>.
f023n_5606字段废弃.对应的成员变量append_mode_也废除。
dd.conf增加<do_cleanup>配置,默认:true
BillInterface修改:
v3.7 2014-8-18
int CSheet::ProcessImport(CMsg *msg,CSheetDealResult &sdr) {USEDBC(pdbor,this->dbc_name_.c_str());int result = 0;switch(op_type_) {case OM_UNSPECIFED:case OM_NEW:result = HandleNew(msg,sdr);break;case OM_DELETE:result = HandleDelete(msg,sdr);break;case OM_OVERWRITE:result = HandleUpdate(msg,sdr);break;case OM_PK_CHANGED:result = HandlePKChange(msg,sdr);break;case OM_INC:result = HandleIncChange(msg,sdr,1);break;case OM_SLIGHT_CHANGE:result = HandleSlightChange(msg,sdr);break;case OM_FULL_SYNC:result = HandleFullSync(msg,sdr);break; }return result;
}
是否存在多表的同步要求呢?
.常见的应用场景是零售商端向目标同步门店或商品资料等单表信息。
单据交换是基于数据对象的,对象分为单表对象和多表对象,多表对象对应的是多个由树形结构关系的表。
对表对象每次交换一个对象,对于单表对象为了提交处理效率,支持多个对象的组合传输与处理。
dd模式:一次批量扫描处理多个单表对象
dxi_change_log模式:app_key只能对应到一个对象,如果为空则表示表的所有对象(记录)。
dxi_change_log跟踪记录单个对象的变化,额外支持单表的全量覆盖。
这些信息是关于多个对象的。
对于单表,
dd扫描时不带任何条件,定时抽取,实现表之间的定时同步。
5.多零售商异构数据支持
。das 1.0中没有合作机构的概念,也没有使用供应商机构ID。
零售商提供的单据信息中包含供应商的MIS编号信息。
das平台内部服务器负责把零售商机构ID转换为jxj的客户编码。
jxj金融平台自己处理mis编号到客户编号的转换。
(所依赖的编码表由jxj组织和维护)
.das服务端对来自零售商的数据中的供应商MIS编号,查表确定供应商的机构ID。
在gyb2中供应商是以此机构ID访问系统的。
das 可以需要也可以不需要做此MIS编号到供应宝机构ID的转换。
对于gyb2需要,对于独立部署的das则不需要,如das 1.0的应用场合
.das 2.0服务端对数据库的支持:
---对于gyb2,需要全面支持PostgreSQL
---支持mysql(考虑支持sql server:应该是可以的,需要验证)
.动态根据单据的源机构输出到对应的数据库(仅包含业务数据的数据源)
规划部署时服务端数据库的种类不限定只有一种,这是考虑未来迁移的可能,考虑可能同时出现两种类型的数据库。
驱动采用非DSN方式,避免服务器本地对各个数据源配置DSN。
lm.conf中配置数据库驱动,连接串模板。
因这些数据库仅限于单据处理
不同实例的数据库名字相同。
<!-- 是否映射目标接收机构,默认:false-->
<map_vender_orgid>true</map_vender_orgid><!-- 多数据源模式(不同的源机构的数据存储在不同的数据库中) 0:单数据源 1:多数据源.默认: 0 -->
<multi_ds>1</multi_ds><!--数据源连接串模板 -->
<ds_connstr_template>
<database>gyb_platform_2_9_1</database>
<item>
<ds_name>mysql5.1</ds_name>
<connstr_template>{MySQL ODBC 3.51 Driver};SERVER=@server;port=@port;DATABASE=@database;USER=@user;PASSWORD=@password;OPTION=3;charset=gbk</connstr_template>
<db_ext>mysql_ext.dll</db_ext> <!--数据库扩展 -->
</item>
</ds_connstr_template>
其中,@server,@port,@user,@password运行时根据机构ID从tb_8021中获取.
机构数据源信息在服务器内存中缓存,访问后缓存,而不是初始全部加载.
tb_8021增加一个数值字段表示版本,初始为1。每次变更递增。
对于长期不使用的项予以释放。
这些机制保证了效率,资源以及动态加入,运行时调整需要的兼顾。
这种机制同样适用于tb_8022.
DRIVER={MySQL ODBC 3.51 Driver};SERVER=172.23.2.56;port=3308;DATABASE=gyb_platform_2_9_1;USER=root;PASSWORD=Admin_123;OPTION=3;charset=gbk
das对业务单据全部采用通用单据处理。
CSheet.OnReceive是接收单据的处理入口
orgid--->dbpool---->从中取得一个连接(如果没有缓存连接则创建)
hotfox提供新的接口方法:
.指定连接串,连接名(连接池名称),数据库扩展模块名创建连接对象
---连接池名称不能与hotfox中配置的冲突,采用格式:用机构ID作为连接池名称.
零售商数量不是很大时,可以简化实现,不需要回收连接对象及连接配置信息所占资源.
.动态创建和管理连接对象:
das前置机与服务器的区别:
。lm:
----<mulit_ds>为0:不需要tb_8021,tb_8022,tb_1068表
数据库表:
.mis-机构ID对照表(tb_1068)
.数据源信息(tb_8021)
.机构数据源信息(tb_8022)
///< @note 对于业务数据分库存储的情况,不能保证事务的完整性
----接收单据处理时,本地库的操作,事件机制产生的其它操作等如果跨数据库可能存在问题。 -----事件机制应用的场合也是有限制的。
***本地库上可能有写待办事宜的操作: 这种事务不一致的错误不严重的话是可以接受的。
6.其他
6.1 ICentralServer
接口原来是本地连接平台并通信的接口。
抽象为本地与外部通信的接口。仍然用此名称。
定义转移到common\i_centralserver.h文件中。
struct CCentralServer : public ICentralServer
转移到common\centralserver.h文件中。
6.2CMemDataBDB::GetAllServer
int CMemDataBDB::GetAllServer(vector<CQQ_SERVERID>& vecServer)
if(svr_data->svr_id_ != self_->GetServerID())
GetAllServer需要排除服务器自身
增加参数:except_server排除的服务器(可带多个)
int CMemDataBDB::GetAllServer(vector<CQQ_SERVERID>& vecServer,CQQ_SERVERID *except_server)
6.3 self_
self_对于本地和平台都存在此对象,表示服务器本身.
self_用IMemData的GetLocalServer代替
6.4服务器证书
用途
(1)与客户端通信时加密密码等安全信息
(2)解密会话密钥
使用的插件有:linkto_das,uap.
证书由md_xxx加载,作为共享数据访问。
7.软件包版本
原来的软件包版本编号的结构如下: 软件包分类编号组成: 包类型编号(1)+行业编码(3)+节点编码(2)
程序通过下列宏访问软件包组成信息项:
#define PKG_TYPE(v) (v/100000) ///< 包类型编号
#define PKG_DOMAIN(v) ((v%100000)/100) ///< 行业编码
#define PKG_LEVEL(v) (v%100) ///< 供应链节点编号
#define PKG_DOMAIN_LEVEL(v) (v%100000) ///< 行业编码(3)+节点编码(2)
简单的顺序编码就可以满足需要,不可能推出很多软件包.
沿用原来的编码也未尝不可!但编码方式仅用于阅读,不用于程序处理。
8.数据库
ALTER TABLE tb_0033 ADD COLUMN f016n_0033 INT DEFAULT 0;
f016n_0033为失败重做记录的服务器ID.每个服务器只处理本服务器的失败重做记录.
9.插件工程选项
General|Output Directory:..\..\..\bin\output\debug
C++|General\Addtional Directories:..\..\common\hotfox\include;..\..\source\include;..\..\common;
Linker|Output File: ..\..\..\bin\server\debug\md_bdb.dll
Linker|Debugging|Generate Programm Database File:..\..\..\bin\output\debug\md_bdb.pdb
从工程编译选项中去掉原平台的以下宏
CQQ_PLATFORM,BCQ_DEBUG,SEPSDK_AS_STATIC_LIB
10.文件增删
10.1新增文件
common\i_centralserver.h
common\centralserver.h
common\i_routehandler.h
10.2删除文件
common\i_ap.h
common\i_dap.h
common\CQQRSPBase.cpp
coomon\CQQRSPBase.h
common\APBase.cpp
common\APBase.h
common\i_apbase.cpp
common\i_apbase.h
11.todo
?UMX4:压缩特性测试(检查压缩解压是否正常)
?bool CAPBase::IsLocalOrg_(CQQ_ORGID orgid)
重新实现。利用内存数据库中机构的属性信息来区分.
原型:int IsLocalOrg(CQQ_ORGID orgid);
返回值可以区分失败.
1:是0:否 -1:失败
? tb_8021的密码(f007v_8021)是明文
? lm:
GetCoOrg优化,支持缓存.
?本地支持多SEMQ实例(从平台RTO引入)
? 升级支持:涉及uap,
?uap支持Windows域验证: m_piADAdapter (限于本地部署的IM服务器)----可暂时不实现
?uap:
// ans->AddRowset(getcoserver()); ///< @todo 不支持分离服务器
---gyb2无此场景.
(代码与gyb1统一存在此兼容性问题!!!)
? lm不支持移动应用(如移动供应链)
GetUserSvcPubList方法被屏蔽
? 原ap提供的EVENT_REACTOR可以用框架的事件反应器替代,目前使用的地方不多,产生用户下线事件由其它插件响应处理
? dd清理:
---对于集群部署,清理不能由每个服务器去执行,只能由单一的服务器承担。
对于专用的单个服务器,允许服务器自行完成清理。
清理实际上可以由清理插件完成。
---dd的清理代码注释掉!!
?trunk的dd代码的一个小错误:CDd::GetDataProc名字错误
int CDd::OnActivate() {
IDeamonTask *task = CBasePluginModule::deamon_mgr_->add(cleanup_proc,"CDd::GetDataProc",this);
task->set_timer_strategy(60);
?md_mysql ,md_bdb接口差异:
目前仍不能彼此替换,没有完全覆盖到所有方法。
接口方法的含义有差异
。md_bdb:取版本只有本地的2个包,md_mysql则包含所有包的版本信息
?linkto_das:提取基类lintobase,在此基础上可以派生出linkto_switch,linkto_im.
! 387协议
return -1; ///< @note 不再支持组件包
12.测试环境备忘
CREATE TABLE tb_jxjorgcode(orgid INT PRIMARY KEY,bizcode VARCHAR(20) NOT NULL
) ENGINE=INNODB DEFAULT CHARSET=gbk;ALTER TABLE tb_0033 ADD COLUMN f016n_0033 INT DEFAULT 0;
---tb_0044配置错误 (172.23.2.80 etl库)
<?xml version="1.0" encoding="gb2312" standalone="yes" ?>
<content>
<tables>
<table>
<name>tb_1116</name>
<cname>tb_1116</cname>
</table>
<table>
<name>tb_1106</name> tb_1106 错误的!
<cname>tb_1106</cname>
</table>
</tables>
<relations>
<relation>
tb_1116.src_orgid=tb_1118.src_orgid
</relation>
<relation>
tb_1116.sheet_id=tb_1118.sheet_id
</relation>
</relations>
</content
13.平台插件代码修改方法
//#include "CQQRSPBase.h"
#include "CQQBase.h"//class CPSMPlugin : public CCQQRSPBase
class CPSMPlugin : public CQQBasePlugin //typedef CCQQRSPBase parent;
typedef CQQBasePlugin parent;// IDAP* m_piDap;
// 使用m_piDap的地方替换为mem_data_//#pragma comment(lib,"sepsdk.lib")
#pragma comment(lib,"lssdk.lib")//USERINFO *user = dynamic_cast<USERINFO*>(this->m_piDap->GetUser(UserSerial));
IUSERINFO *user = dynamic_cast<IUSERINFO*>(this->mem_data_->GetUser(UserSerial));
das 2.0开发记录相关推荐
- Web项目实战 | 购物系统v2.0 | 开发记录(五)使用base64编码实现头像修改 | 用户个人信息修改 | JQuery动态提示
文章目录 以往记录 一.运行环境 二.实现头像修改 三.用户个人信息修改 四.Bug & DeBug 以往记录 Web项目实战 | 购物系统v2.0 | 开发记录(一)需求分析 | 技术选型 ...
- Web项目实战 | 购物系统v2.0 | 开发记录(九)Controller层返回数据的封装 | 商品批量操作 | 五表联立实现商品搜索
--若发现文章内容有误,敬请指正,望不吝赐教,感谢! 文章目录 以往记录 运行环境 一.设计Bean用于Controller层返回数据 二.商品批量操作 2.1 批量操作的前端设计 2.2 批量操作的 ...
- ASP.NET Core 1.0 开发记录
ASP.NET Core 1.0 更新比较快(可能后面更新就不大了),阅读注意时间节点,这篇博文主要记录用 ASP.NET Core 1.0 开发简单应用项目的一些记录,以备查阅. ASP.NET C ...
- Web项目实战 | 购物系统v1.0 | 开发记录(一) | 大学生闲置物品交易系统 | 选择页面模板(附资源),使用 JQuery AJAX实现注册、登陆
文章目录 运行环境 1. 前言 2. 挑选模板 2.1 前端模板 2.2 后端模板 2.3 总结 3. 实现注册与登陆 3.1 项目结构 3.2 注册 3.2.1 JDBC连接池连接 3.2.2 da ...
- 极客感十足的电子胸牌 ART-Badge V2.0开发记录!
开源地址:https://github.com/ART-Badge 前言 关注 RT-Thread 的同学肯定知道,RT-Thread为了向众多开发者展示RT-Thread的最新开发和生态建设成果,每 ...
- 个人知识管理系统 mysql_个人知识管理系统Version1.0开发记录(12)
最近碰到个问题,在五个工作日内阅读一个百万行左右代码量的新项目集合,如何解决呢? 第一个工作日,环境观察.待在那个项目组,看项目成员们在做些什么事情,开发,测试,聊天,或多或少可以收集到一些项目相关的 ...
- RDC到场礼,ART-Badge V2.0开发记录,极客感十足
开源地址:https://github.com/ART-Badge #前言 关注 RT-Thread 的同学肯定知道,RT-Thread为了向众多开发者展示RT-Thread的最新开发和生态建设成果, ...
- 个人知识管理系统 mysql_个人知识管理系统Version1.0开发记录(04)
demo model 我们采用mvc软件架构模式,方便以后用Struts2框架技术优化.重构.封装.这次主要设计一些常用的方法工具,即数据访问逻辑.工具:eclipse.oracle.sqldevel ...
- Anytime项目开发记录0
Anytime,中文名:我很忙. 开发者:孤独的猫咪神. 这个项目会持续更新,直到我决定不再维护这个APP. 2014年3月10日:近日有事,暂时断更.希望可以会尽快完事. 2014年3月27日:很抱 ...
最新文章
- 在Matlab中可视化3D体积图像数据,例如MRI图像
- oracle缩小表空间
- Powershell Module for Netapp Data Ontap
- 揭穿骗子阴谋,学会保护自己
- AbpZero之企业微信---登录(拓展第三方auth授权登录)---第一步:查看AbpZero的auth第三方登录的底层机制...
- 首次揭秘云原生Hologres存储引擎
- SAP CRM的user status和system status
- 正在启动oracle universal,oracle的常见问题与解决
- ubuntu 系统下的Caffe环境搭建
- NameError: name ‘__file__‘ is not defined的问题原因及解决方法
- android谷歌反地理,android – 谷歌地理编码服务是不可用的(协调地址)
- 2021蓝桥杯省赛c++A
- 下载并安装JDK7 教程
- Linux系统下tmux的分屏使用
- 常见Andriod游戏破解搜索关键字
- su PK sudo
- 盘点那些Wifi破解姿势(2)
- 【转】2023年Java学习路线图-黑马程序员
- HDU 6194 string string string :后缀数组+单调队列 | 后缀自动机
- 《大腕》对白之各类搞笑版