Base62x编解码开源类库增加C++版本

2020年以来近两个月来,新冠肺炎 疫情肆虐中华大地,九洲同悲,四海恐慌,唯望炎黄子孙同仇敌忾,将传染性病毒早日隔离并捕获进牢笼,打入十八层地狱,永世不得翻身!

自我囚禁之余,安排时间对 -Base62x 编解码程序进行翻阅,同时考虑并增加了 Base62x 编解码程序的 C++版本。

这是继2016年增加 Base62x in Java, 2017年增加 Base62x in JavaScript, 2018年增加 Base62x in Perl, 2019年增加 Base62x in Python之后的又一个新语言版本,此后,C++的应用项目,可以直接下载使用即可。Base62x 编解码的实现,首先是C语言版本。

距离上次新增并完善 Base62x in Python 已经有差不多一年的时间,在这期间, Base62x 得到更广泛的应用和部署,也在 -Github 上获得更多的点赞。这是令人欣慰的。

Base62x in C++ 的程序代码包括两部分:

  1. Base62x.class.hpp
    这是 Base62x 的C++版本的主体程序,用于构建 Base62x 对象及其两个主要方法: encode/decode .
    另外还有一些辅助工具方法.

  2. Base62x_test.cpp
    是为测试 Base62x in C++ 而编写的辅助程序,主要给出调用 Base62x in C++的样例。

    Base62x in C++的使用样例

    # include “Base62x.class.hpp”

    using namespace std;
    //- init.
    Base62x myb62x;
    char *input = “Hello Base62x!\n”;
    char *output;
    int ibase = 0; // zero for string
    //- encode
    output = myb62x.encode(input, ibase);
    //- decode
    int obase = ibase
    input = myb62x.decode(output, obase);

借助 C++ (C with class)的面向对象支持,Base62x in C++几乎可以借用 Base62x in Java的逻辑和 Base62x in C的代码,融合而成即可。

截止目前(2020年2月),Base62x 已经可以提供的编程语言版本包括 C, Java, PHP, JavaScript, Perl, Python, C++.
其中Base62x in JavaScript 还有两个实现, Base62x.class.js 和 npm base62x.

2019年,Base62x 的相关说明内容还没写入网上各个主要知识Wiki站点,由此也传播给更多的人。此外,Base62x 论文相关的辅助材料也发布在 -ResearchGate 上,可供免费翻阅。与此同时,还完善了 -Base62x 的官方网页,让在线编解码体验、浏览和翻阅更简便快捷。

籍此,感谢为 Base62x 的源代码和说明文档做出贡献的朋友们,他们的名字都记载在 -Github的代码库里或者知识Wiki站点里,谢谢你们!

最好的版本永远是下一个版本,继续期待 Base62x 能为技术同行们带来帮助,也期待一起修改订正,使其日益完善。



Base62x: An alternative approach to Base64 for only-alphanumeric characters in output.
Base62x is an non-symbolic Base64 encoding scheme. It can be used safely in computer file systems, programming languages for data exchange, internet communication systems, and is an ideal substitute and successor of many variants of Base64 encoding scheme.

Base62x 是一种无符号的Base64编码方案。
在计算机文件系统、编程语言数据交换、互联网络通信系统中可以安全地使用,同时是各种变种Base64编码方案的理想替代品、继任者。

base62x-algorithm

Posted in Base62x, 编程技术, 计算机技术 | Tagged , , | Leave a comment

gMIS吉密斯十年执念:Lower Costs较低成本Better Productivity较高效率

Hello 2020! 元旦快乐!今起揭开21世纪20年代的篇章.

1. gMIS吉密斯十周年

2010-2020,十年转眼已成历史,gMIS吉密斯——通用管理信息系统(general Management Information System)已经持续迭代升级、优化完善了十年之久。

从 ChinaM.com 时的 General Table到Sina weibo.com 时的Config Table,再到 People.cn 时的完整雏形,gMIS吉密斯应运而生,伴着IT需求猛增的大趋势,一路茁壮成长,从实践出发到理论提升,重新回到实践中去,再次深化和升华…

gMIS吉密斯致力于为企事业单位一线操作管控人员提供较低成本、较高效率的操控平台系统工具。一直以来,企事业单位极力逢迎讨好客户/终端用户,而对自己的员工通常要退而次之,等到安排预算改进作业系统管控操作平台时,额度又少之又少。员工不能利其器,焉能善其事?

gMIS吉密斯努力尝试使用这少得可怜的预算经费(较低成本),通过创新软件方式方法,融合前沿技术,实现便利高效的作业系统操控,提高整体管理水平和能效(较高效率),提升员工满意度、盈利水平和整体社会效益。

2. gMIS吉密斯软件架构与功能特色

小结gMIS吉密斯十余年来的发展,她与其他多数单一任务类型的管理操作后台相比,有着鲜明的特征,也正是这些特征使其发展路径看起来崎岖艰难。本质上说,管理操作后台的基本任务是将软件的基本任务——输出/输入的更具体化,大致操作动作就是“增删改查”。

gMIS吉密斯面临的挑战是,尽可能多地满足各种管理操作后台的场景,同时尽可能少地写编程代码,一直以来的努力,也是极力地在这两方面寻找某种平衡。既要功能强大,还要无需二次开发,进而达成秉持着十年的执念:Lower Costs较低成本,Better Productivity较高效率。


2.1. gMIS吉密斯软件架构

1). 基于MVC成熟的网络应用系统设计
2). 超越MVC 可对接和读写不同驱动类型的资源,如数据库、文件、远程网络资源等;
3). 支持插件式开发,易于扩展和升级
gwa2-dba-arch-201605-v2

4). 强大的多层级缓存与优化,支持服务器端、网络层和客户端三层缓存加速;
5). 页面异步通信、块状刷新让操作更流畅、高效;
6). 先进的跨区设计,以一抵十,百变应用扩展。

2.2. gMIS吉密斯功能特色

1). 先进的无Session/Cookie用户鉴权体系,轻松穿越各种网络环境;
2). 创新设计的集成站内搜索,全站数据一搜即得;
3). 媲美主流网络电商系统前端页面的点选系统,所有数据即点即得;

4). 比肩微软Office Excel的数据透视功能,让数据决策更科学、高效;
5). 创新性的数据表字段级可配置输出输入接口;
6). 层级式目录设计,无限扩展;

7). 在线网络文件轻松管理;
8). 自动跟踪日志、记账系统;
9). 字段级安全设置与管理设计;

gmis-xdirectory-201604

10). 贴心提示,输入即搜索,随时提供备选列表;
11). 高效地数据批量导出与导入功能;
12). 跨国多语言支持;

13). 便捷地数据表记录级复制;
14). 集成深度复合搜索,让检索在最小颗粒度上进行。

3. gMIS吉密斯近期更新

1) 修订了部分遗留i18n的语言包词汇;
2) 增强了针对文件上传与下载时的安全措施,进一步加固了系统安全;
3) 升级替换了 jQuery 第三方类库,1.12 –> 3.4.

4. gMIS吉密斯在线资源
 优化升级更新博客

https://ufqi.com/blog/category/computer-tech/通用信息管理系统/

 操作手册
https://wadelau.github.io/gmis/index

 


-gMIS (general Management Information System,吉密斯) 是一种基于 -GWA2 (General Web Application Architecture,吉娃兔) 的通用管理信息系统应用软件,具有可配置的输入和输出接口、开箱即用等特征。

可以在其上构建各种信息管理应用软件系统,例如:
内容管理系统(CMS), 客户资源管理(CRM), 企业资源计划管理(ERP),
办公自动化系统(OA)等,
也可以是各种行业应用管理系统软件,例如:
人力资源管理系统(HR),学生管理,档案管理,旅游管理,图书管理,
商品管理及业务运营支撑系统(BOSS)等等。
实现零代码开发、快速搭建各种管理信息系统(MIS, Management Information System).

-gMIS is a -GWA2 based Management Information System (MIS) software with characteristics like configurable input and output interfaces, open-box-to-use.
Various management application software systems can be built on it, such as
Content Management System (CMS), Customer Resource Management (CRM), Enterprise Resource Planning Management (ERP),
Office automation systems (OA), as well as different industry application management system softwares, such as
Human Resource Management System (HR), Student Management, Archive Management, Tourism Management, Book Management,
Commodity management and business operations support systems (BOSS), etc.
With zero code development, -gMIS can build a set of management information systems (MIS) software in a few minutes.

Lower Costs, 
Better Productivity.
降低成本,
提高效率.

Posted in -gMIS, 编程技术, 计算机技术 | Tagged , | Leave a comment

WebAssembly前瞻及用C/C++写HTML和Hanjst汉吉斯特

2019年12月16日,北京下了今冬第二场雪❄️,不大不小。

年终岁尾,国际上几大软件及互联网公司(Google、Microsoft、Apple和Mozilla)拉上互联网标准化机构W3C发布了 Web Assembly的推荐标准( -R/t2SS )。此举意味着,WebAssembly技术从遮遮掩掩的实验室后台走向前台,开始面向大众,尤其是开发者进行推广应用。

  1. Web Assembly推出背景猜测

Assembly 字面上的解释是,  “a group of people gathered together in one place for a common purpose”,一群人为一个共同的目标聚集到一个地方。Web Assembly的目标简略地说,就是将 C/C++/Rust 这些编程语言写的程序能够运行在上面那几大公司到网页浏览器中(Google Chrome,Microsoft Edge,Apple Safari 和 Mozilla Firefox)。目前在网页上流行的编程语言 JavaScript 将迎来或是帮手,抑或是对手的Web Assembly。

时光倒回到约10年前, HTML5 标准刚推出来时,其首要的任务是丰富 HTML 或者说 网页应用,使之能够承载其由“内容展示平台”向“应用承载平台”转变的重任(此前 -人民网 内部研究报告)。在这之前,一直是 Adoble Flash努力地奋斗着。 HTML5 贡献了一大批新颖的功能,网页告别第一代只能做内容展示的功能受限版。

HTML5 带来了浏览器/网页作为“应用承载平台”的大发展。不想中途出现了“应用商店”App的怪胎,一下子将互联网前进的步伐打回到PC单机时代,要用个什么软件都需要下载、安装,这明显与互联互通都发展趋势是相背离的。信息孤岛逐渐形成,互联网的继续发展不是加速信息的流动,相反是加剧了信息的不对称,不流通。

这既有商业层面的利益考虑,也有技术层面的制肘,网页应用计算力弱,体验不好,安全有问题等等,一时局面甚是尴尬,有几个应用商店,一个应用就需要开发几个不同的版本。信息在各个APp之间逐渐扎起篱笆,这些与互联网先驱们的让信息更加流畅地流动的理念渐行渐远。

直到  WeAssembly的推出,或许是扭转时局的契机之一。HTML5将网页由“内容展示平台”升级到“应用承载平台”,WebAssembly或将进一步升级优化”应用承载平台”,从根本上消除网页应用与本地应用之间到性能差异。从而实现“Open and Run”, 而不是 “Open 、Download、Install and Run”,实现“Write once, run anyway”, 而不是“Write once more,run once more”。

在 WebAssembly之前,也有类似的探索, 如 asm.js , 甚至上 Java的 Applet 都是希望将编译后的程序能够在浏览器中安全高效地运行,现在看之前的努力并不算成功,希望这次能有所不同而获得预期效果。 

2. WebAssembly的直觉体验

对 WebAssembly 的直觉体验:由 hello.c 到 hello.html 

$ mkdir hello
$ cd hello
$ cat << EOF > hello.c #include <stdio.h> int main(int argc, char ** argv) { printf("Hello, world!\n"); } EOF
$ emcc hello.c -o hello.html

可以预见,大量必需由 C/C++/Rust 写的程序将有可能轻松移植到浏览器以网页应用的形式交付,极大地改变了软件研发及交付的方式方法。

3. Web Assembly的发展前瞻

3.1. WebAssembly 可能不会取代 JavaScript
而只是对其的互补,在 JavaScript 短板之处寻找其发展空间,展现其优势。

3.2. 客户端软件App
单独为特定平台写App的需求将降低,网页应用将逐渐实现跨平台,并与本地应用相一致的体验和性能。有望实现网页应用一版通天下。单独写iOS客户端,Windows客户端,或者Andorid客户端的开发人员,可能需要着手学习使用 WebAssembly。

前景是美好的,预计Native App还将存在相当长时间,并存与网页应用,并逐渐转为小众领域的特定开发。

3.3. C/C++/Rust 走向前端
古老的C/C++等编程语言将应用范围扩展到前端,从而实现真正意义上到跨平台。用 C/C++等写HTML网页,将不再是互联网上的笑话。
如此以来,为解决 C/C++ 写不了网页HTML而诞生等解决方案或者编程语言等,是否也就过时了? 或者意义不大了?

如果 C/C++ 能写网页,还需要用 ASP.NET/PHP/Perl/Python或者Java 来写 HTML应用吗?或许需要,因为有大量类库已经开发,或许需要,还有其他更多完整的生态考虑。但有一点确认的是, WebAssembly的推出,引发我们对这样对问题的重新审视和思考。

3.4. 网页应用
网页应用开发人员需要熟悉新情况,有了新增的屠龙刀,也要善加利用才能将其设计功效发挥出来。

JavaScript 有了 Web Assembly的加持和增强,其性能或有进一步的提升,可供用来设计的应用软件将进一步的扩增,体验或将更好。

得益于 JavaScript进步,也得益于Web Assembly的推出,依赖于其上 Hanjst 汉吉斯特模版语言及引擎将运行更快,体验更好。我们将着手针对这些新特性进行优化。

Hanjst.js 已经投入不少使用。

Hanjst.was / Hanjst.wasm 也将开始研发,为追求更极致的性能和体验,Hanjst 或将以 C/C++/Rust 编写,然后经编译后,引入到浏览器中进行运行。

3.5. 网络应用开发框架 Web Framework

如前所述,既然Web Assembly的原生代码可以工作在服务器端,而编译后的.wasm 可以运行在客户端浏览器中,那么开发网络应用的方式方法势必要受此影响而有所改变。

因此,可以预见,通用网络应用架构GWA2,或将以此为契机进行改造升级,推出 GWA2 in Assembly 或者 GWA2 in C / GWA2 in C++, 又或者是 GWA2 in Rust. 

至于最终实现的是  GWA2 的哪个新版本,可能要结合 Web Assembly推广应用普及到一定阶段之后才能有某种趋势判断或定论。


 


Hanjst是一种基于JavaScript的模板语言及解析引擎,她运行在客户端/服务器端。

Hanjst能够表述逻辑控制,能够实现与服务器端模版语言相同的功能。

  • Hanjst当完全在客户端解析时,节省服务器端计算资源;

  • Hanjst模板语言独立,不与服务器端资源做任何绑定;

  • 纯粹的MVC,层间数据用JSON格式传递;

  • 常见模板语言功能全支持,附带复杂而强大的JavaScript编程能力;

  • 无学习成本,直接使用JavaScript书写模板语言;

  • ….

Hanjst is a JavaScript-based templating language and parsing engine that runs on both the client-side and/or server-side.

Hanjst can express logical control and achieve the same functionality as the server-side templating languages.

  • Hanjst’s Run-time in client-side, reduce computing render in server-side;

  • Hanjst is Language-independent, not-bound with back-end scripts or languages;

  • Totally-isolated between MVC, data transfer with JSON;

  • Full-support template tags with built-in logic and customized JavaScript functions;

  • No more tags languages to be learned, just JavaScript;

  • ….

 

Posted in -Hanjst/-汉吉斯特, 编程技术, 计算机技术 | Tagged , , , | Leave a comment

gMIS吉密斯i18n多语言国际化更新

gMIS吉密斯部署和使用范围日益扩大,跨国多语言版本成为迫切需要的功能,早在2018年年中就考虑要增加这一功能——在gMIS吉密斯中实现多语言版本的支持。以期实现gMIS吉密斯的跨行业、跨地区和国际化多语言的广谱应用目标。

经过一段时间的密集开发、测试,目前gMIS吉密斯i18n多语言国际化更新已经完成。其中过程比预料的长,修改完善难度比预想的大,涉及到的修改模块也较多,兹记录备忘于此。

1. 基于GWA2的多国语言包设计

gMIS的开发框架是 GWA2吉娃兔,GWA2本身有跨语言的版本实现,如GWA2 Java, GWA2PHP,GWA2Perl等编程语言版本。gMIS所依赖的GWA2的编程语言版本为GWA2PHP,所以gMIS的多语言实现也是继承和扩展了 GWA2PHP(吉娃兔的PHP版本)的多语言开发模式。

在GWA2PHP的多国语言版本多实现中,主要依靠如下设施。

语言模块对象:
mod/language.class.php
其主要方法是实例化 Language.class 并加载语言包文件;同时提供按 lang_key 进行相应翻译的操作方法;

语言包文件:
lang/language.pkg.zh_CN.json,
lang/language.pkg.en_US.json,
lang/language.pkg.ja_JP.json,

全局变量:
全局实例化 $lang 语言包对象,并在全局范围内可以访问。
同时对当前语言环境进行探测,对语言版本环境对探测又进一步地区分为有显式的语言版本参数如 “&lang=zh” 等,或者使用隐式的语言环境参数来判断当前应该加载哪种语言包。

输出 $lang 到模板引擎:
$data[‘$lang’][‘lang_key’] = $lang->get(‘lang_key’);
如此以来,便可在 模版文件中以 {$lang[‘lang_key’]} 多方式进行访问。
后面会进一步地详细描述。

2. Module类或Controler类PHP程序中调用语言包对象

在gMIS中,普通PHP文件中对多语言对象多访问形式如下:

print $lang->get(‘lang_key’);

该语句将输出按当前语言配置所加载语言包对应多 lang_key 所指向的语言版本相应的内容,其中语言对象 $lang 是全局变量,可以在任意 controller文件中进行调用。类似地,在Module模块类中,需要更多的修改,在Module模块类的声明创建和实例化时,引入全局变量语言包对象。

如在 mod/abc.class.php 的文件中,传递 $lang 对象:

public function __construct($args, $lang=null);

为后向兼容,也可以不安全或不推荐地直接使用全局变量 $ lang :

public function _myFunc(){
    return if($lang){ $lang->get(‘lang_key’); }
}

 

3. HTML模板文件中调用

gMIS 在设计和实现 GWA2 PHP 时,完整地继承了 GWA2 的 MVC,因此,作为兼容和后续扩展,gMIS的大部分视图文件,都以模版文件都方式呈现。

在国际化多语言的扩展中,我们需要在模版引擎中增加对语言对象的输出,形如:
$data[‘lang’][‘lang_key’] = ‘lang_value’;

然后在模版文件中使用如下方式增加对 lang_key 的调用:
{$lang[‘lang_key’]}

 

4. JavaScript脚本中调用

由于 gMIS 在设计上采用了高效的 Ajax 技术,页面进行了局部或部分的更新。这在多语言环境中,可能涉及到需要将相应的标签字符进行多语言翻译。
基于这种考虑,我们在 ido.php 进行加载时,输出 userinfo.$lang 全局变量,在其中以 JSON 方式将待翻译的语言标签输出到 JavaScript中,从而使得当我们需要在 JavaScript 调用相应的语言标签时,能够进行顺利的调用,进而显示合适的语言版本给终端用户。

userinfo.$lang = {“lang_key”:”lang_value”, “”:””};

在 JavaScript 实际调用中:

let buttonValue = userinfo.$lang[‘lang_key’];

 

5.  XML/JSON数据表配置文件中调用

gMIS强大对可扩展性和伸缩性依赖于我们所涉及对元数据与用户数据对隔离,而实现元数据与用户数据对融合操作对就是我们对gMIS表数据处理引擎。

在gMIS,我们针对每一张被管理的数据表创建了一个表格属性描述文件,该属性描述文件以配置文件xml格式存储在 xml子目录下。当目标数据表被加载时,数据处理引擎将读取配置文件,以属性描述文件定义的各种格式将用户数据呈现出来。

在这一过程中,显然,如果我们在属性描述文件中有关于国际化多语言的内容标签,就需要一并也要创建对应的语言版本的属性描述文件。基于这些考虑,我们将xml文件的国际化多语言修改形如下:

xml/abctbl.xml –> xml/abctbl.en_US.xml 
xml/abctbl.xml –> xml/abctbl.zh_CN.xml
xml/abctbl.xml –> xml/abctbl.ja_JP.xml
….

默认情况下,如果某个数据表efgtbl没有 xml/efgtbl.xml 属性描述文件,则使用系统默认的形式将用户数据显示出来;也是默认的,如果某个数据表 efgtbl 的某个国际化语言版本 xml/efgtbl.zh_CN.xml 没有被创建出来,系统依然鲁棒地使用默认配置将用户数据用默认语言版本呈现出来。

6. lang_key /value 的设计与规划

gMIS 国际化多语言的语言包文件的设计采用通用数据交换文件格式 JSON。在多语言标签设计时,将标签按如下分类进行设置:每个标签键名称以下划线分割的多段英文字符隔空。每段表示不同的层级。
样例如下:
navi_xxxx,
func_xxxx,
form_xxxx,
user_xxxx,
func_importxlsx,
func_importxlsx_hint,
navi_help_company,
navi_help_company_faq,
….

7. 国际化多语言使用者/开发者社区

gMIS吉密斯源码早几年前已开源在 -github 上,然而由于没有进行国际化多语言操作,开发和使用仅限于中文环境,随着这次国际化多语言的完善,gMIS的开发将迎来更多非中文开发者和使用者。

这将为gMIS吉密斯的发展壮大注入更加强大而持续的动力,为gMIS吉密斯由管理后台进化为管控操作系统做进一步地准备。

对非中文母语的开发者而言,源代码中没有了写死的常量“中文”字符, 修改代码不再有障碍;gMIS吉密斯的代码将得到全球范围内的开发者的审阅、修订和完善。

对于非中文母语的使用者而言,可以通过在首页的使用语言切换功能,快速切换为自己熟悉的语言界面. 从而为gMIS带来全世界的用户。使用范围将进一步地扩大到全球范围。

从而实现了gMIS的跨行业、跨地区和跨语言的全新时代。


2019-11-04,山东威海国际机场。


-gMIS (general Management Information System,吉密斯) 是一种基于 -GWA2 (General Web Application Architecture,吉娃兔) 的通用管理信息系统应用软件,具有可配置的输入和输出接口、开箱即用等特征。
可以在其上构建各种信息管理应用软件系统,例如:
内容管理系统(CMS), 客户资源管理(CRM), 企业资源计划管理(ERP),
办公自动化系统(OA)等, 以及各种行业应用管理系统软件,例如:
人力资源管理系统(HR),学生管理,档案管理,旅游管理,图书管理,
商品管理及业务运营支撑系统(BOSS)等等。
实现零代码开发、快速搭建各种管理信息系统(MIS, Management Information System).

-gMIS is a -GWA2 based Management Information System (MIS) software with characteristics like configurable input and output interfaces, open-box-to-use.
Various management application software systems can be built on it, such as
Content Management System (CMS), Customer Resource Management (CRM), Enterprise Resource Planning Management (ERP),
Office automation systems (OA), as well as different industry application management system softwares, such as
Human Resource Management System (HR), Student Management, Archive Management, Tourism Management, Book Management,
Commodity management and business operations support systems (BOSS), etc.
With zero code development, -gMIS can build a set of management information systems (MIS) software in a few minutes.

Lower Costs, 
Better Productivity.
降低成本,
提高效率.

 

 

Posted in -gMIS, -GWA2, 编程技术, 计算机技术 | Tagged , , , , | 2 Comments

UfqiNews有福新闻的第N+1批次更新:清晰,流畅,省电

UfqiNews有福新闻自推出以来,一直持续更新、优化升级,作为一款带来全新新闻阅读体验的资讯应用,已经日益成熟,浏览量也日渐攀升。

近日针对 UfqiNews有福新闻的升级改进包括如下方面。

1. UI调整优化,清晰易读的页面导航

改进页面导航,调整优化明晰的跳转指示:

UfqiNews利用各种方向的箭头,类似物理世界的导航一样,简单明了。
而且在不同的操作系统平台上,如 iOS, Android后者WIndows中,不同的箭头又以各自平台的UI特色显示出来,
与本地风格融合更好。
.
 

2. +分享功能,简单易用的新闻分享

为便于用户将页面分享出去,尤其是分享到各个社交网站,UfqiNews增加 ShareThis 分享按钮。

用户可以很方便地通过页面底部使用 ShareThis 将当前页面分享出去。

+  点击 AddToFav 或 Ctrl+D  52次转发  

通过 ShareThis 按钮可以直接链接到 数十种社交网站。

3. 调整缓存策略,页面加载更快,link prefetch/preload

UfqiNews在有限的计算资源和带宽资源下,尽快地加载并呈现页面,一直是我们的技术团队努力的方向。 在这方面UfqiNews近期的主要努力包括:
1) 改进资源文件:图片、样式表CSS和脚本程序Scripts的缓存机制,使得这些资源在一个会话时间段内,只需首次从服务器下载并缓存到本地后,在该时段内,后面的页面加载时,这些资源文件都将从浏览器的本地缓存中自动加载,而无需每次从服务器端下载。
这将极大地改进页面加载速度。在资源类文件的 HTTP返回中,增加如下 HTTP headers.

HTTP/1.1 200 OK
Date: Sat, 14 Sep 2019 01:36:17 GMT
Last-Modified: Mon, 30 Jul 2018 08:59:19 GMT
ETag: “e2a-57233ad3e67c0”
Cache-Control: max-age=604800
Expires: Sat, 21 Sep 2019 01:36:17 GMT

2) 使用 link preload/prefetch 指令进行预加载
在支持预加载指令的浏览器中,UfqiNews使用 link preload / prefetch 指令,对接下来即将浏览的页面或资源进行自动加载。如在 list页面,自动加载 下一个 page; 在新闻详情页面,自动加载下一个 item,如此以来,当用户进行翻阅下一页时,页面将会实现秒开。

4. 重构爬虫引擎,抓取采集更节能

UfqiNews在生产端,有一个设计复杂的新闻爬虫系统,主要负责从各大新闻站点,将当地、当天最热门的新闻条目抓取回来。抓取回来的新闻页面内容进一步地使用自然语言处理技术对这些新闻条目进行分析,然后分门别类地列如到相应的类目下,供进一步地读取调用和使用。

这一页面抓取及分析系统,是分布式的计算系统,最早的设计其内容的流转是依靠NFS系统作为页面文件的承载服务。

(UfqiNews页面抓取系统/爬虫系统)

UfqiNews的分布式系统支持将这一爬虫系统部署成为一主多从的结构,可以同时启动N多个Node,而每个Node里又可以启动M多个进程。从而形成强大的页面抓取能力,及时并行处理N*M个新闻页面。

像所有的分布式系统一样,UfqiNews需要有一种机制或者队列能保证数据的一致性,UfqiNews依赖NFS的网络文件分享机制,将内容和页面队列写入到一个NFS文件中,并且顺序读取,从而保证了页面读取的一致性。

在单个NOde上并行运行M个进程时,NFS及内容读写磁盘系统,都需要以来文件IO来实现,一个偶尔的机会,当我们观测到跑在VmWare虚拟机中的耗电量在Windows的 Task Manager 中的“Power Usage” 和 “Power usage trend” 都为“Very high”, 进一步地分析发现,导致耗电量非常高,是由于 UfqiNews的生产爬虫系统的缘故。

(UfqiNews生产系统耗电量分析)

这种耗电量的现象,我们觉得是不可接受的,既不绿色,也不环保。而且其背后更深层次的原因也好理解,频繁地文件IO读写访问,一定是要高频度地调用设备驱动,进行实际磁盘操作。

在此之前,我们在review 目前的设计时,也觉得,依赖NFS并非长久之计,也非上上之选,只是觉得应该改进优化,这次发现UfqiNews如此高耗能,成为压垮骆驼的最后一根稻草,必须对UfqiNews的文件IO及其队列做进一步的优化改进了。

最早的设计中,我们希望构建一套网络服务,用于存储在 UfqiNews运转过程中的数据,类似 AED Server这种的设计与操作。这次在对UfqiNews进行重构设计时,我们发现问题的焦点在某种服务对文件IO的接管,也即无论是页面队列,还是新闻页面内容,将写入文件的内容,存储到内存或者某个中间服务时,用完即可删除。

这种场景用 AED Server 是合适的,将页面内容或者页面队列存储到 AED Server 中去,可以满足需求,同时,也可以看到,类似的需求,与常规的”缓存“服务也很相似。

沿着这一思路,我们考虑使用 Memcached 或者 Redis 来接管真实的文件IO,或可解决目前的问题。于是我们就使用该方法对 UfqiNews的爬虫系统进行优化完善。

在凡是需要读写操作文件IO时,均改为读写 Memcached 的服务,对于页面内容,直接存取即可。 对于页面队列,则需要使用数组的形式,对其中的内容做动态更新,放入新生成的条目,同时丢弃已经处理完了的条目。

经过几周的断续修改和调整,我们逐渐将 UfqiNews 的爬虫系统中的过程内容的文件IO全部替换为读写 Memcached ,Ufqinews的运行时耗电量也从 “Very high” 逐步降低下来。

Very high — High — Moderate — Low — Very low

尽管目前没有定量的数据,但Windows系统中的这个耗电量5级划分应该是有一定的依据的,而是次优化调整,也真切地显示出来。

作为软件编程技术人员,我们一直在谈论算法改进,程序优化,但改进前后效果对比如此立竿见影天壤之别的情况,还很少见,体会也没有如此强烈。

5. +内容链接静态化,优化SEO,对搜索引擎索引更加友好

针对页面链接地址做进一步的调整,增加如下两个快捷链接到主要页面:

1)列表页面, list.123,456.html , 指向原来的 ./?pnskwordid=123,456

2) 内容详情页面, page.1234.html  , 指向原来的 ./?mod=rdr&pgid=1234

改进后,伪静态页面将根据有利于搜索引擎的抓取和页面分析。

 


ufqinews logo
有福新闻 UfqiNews

这里呈现热点全局, 尺寸间一览所有令人关注的疑点焦点;
这里表达条分缕析, 视野内一睹各个脉络清晰的故事主线.

有福新闻UfqiNews 带来全新的资讯阅览体验, 不信息过载, 亦不信息茧房.

在寻求最大社会共识和满足千人千面之间谋取平衡,
在满足广泛涉猎与追求术业专攻之间谋取平衡.

媒介插上人工智能的翅膀将如虎添翼, 与资讯比翼双飞.

新闻爱好者的良心之选, 匠心之作.

UfqiNews presents the hot spots globally, with all interesting points at a glance.
Information is organized here and there is a clear storyline within every single detail.

UfqiNews brings a brand new reading experience, no information overload and no information Cocoons,

In seeking a balance of the maximum social consensus and meeting thousands of people for each interest,
In achieving a balance between satisfying a wide range of hunting and pursuing specialization in the industry.

That media is being born with wings of the artificial intelligence will be even more powerful and the information will fly swifter than ever.

Better choices of newsreaders and the art of work from them.

 

Posted in 服务器运维, 社会生活, 编程技术, 计算机技术 | Tagged , , , , , | Leave a comment

汉吉斯特Hanjst模板语言及引擎在线文档Doc&API首发

经过一段时间的梳理总结、精心编制,汉吉斯特Hanjst在线文档和API已经完成初版,并发布在 //wadelau.github.io 上,为方便检索和使用,兹列目录如下,供查询、使用。


 

汉吉斯特Hanjst概述

Hanjst标志

Hanjst是一个Han J ava S cript T emplate,它是HTML和Web的模板语言和引擎。

“ 汉吉斯特 ”是 Hanjst 的中文名称。

入门

Hanjst是什么?为什么?

安装

配置

调试

快速开始

杂项

Hanjst为模板设计人员

基本语法

变量和修饰符

功能函数指令

内置功能

自定义功能

Hanjst在服务器端运行

Node.js

Hanjst为后端开发人员

Hanjst 对象类

服务器端替换

JSON中的数据

资源

路径

脚本

第三方类库

图片

高速缓存

随时可用样例

搜索引擎优化

标题,描述和关键字

链接

文本内容

 


在线文档目前没有中文版,只有English Version,以下是 English Version 的目录列表。


. . .


Contents in English Version


 

Hanjst Overview

Hanjst Logo

Hanjst is an Han JavaScript Template, and its language and engine for HTML and Web.

汉吉斯特” is its Chinese name.

Get Started

What is Hanjst and Why?

Installation

Configurations

Debugging

Quick Start

Misc.

Hanjst for Templates Designers

Basic Syntax

Variables and Modifiers

Functions

Built-in Functions

Custom Functions

Hanjst Run in Server-side

Node.js

Hanjst for Back-end Developers

Hanjst Class

Server-side Replacements

Data in JSON

Resources

Paths

Scripts

Third-party Libraries

Images

Caching

A Ready-to-go

Search Engine Optimization

Title, Description and Keyword

Links

Plain Contents

 




Hanjst是一种基于JavaScript的模板语言及解析引擎,她运行在客户端/服务器端。

Hanjst能够表述逻辑控制,能够实现与服务器端模块语言相同的功能。

  • Hanjst当完全在客户端解析时,节省服务器端计算资源;

  • Hanjst模板语言独立,不与服务器端资源做任何绑定;

  • 纯粹的MVC,层间数据用JSON格式传递;

  • 常见模板语言功能全支持,附带复杂而强大的JavaScript编程能力;

  • 无学习成本,直接使用JavaScript书写模板语言;

  • ….

Hanjst is a JavaScript-based templating language and parsing engine that runs on both the client-side and/or server-side.

Hanjst can express logical control and achieve the same functionality as the server-side templating languages.

  • Hanjst’s Run-time in client-side, reduce computing render in server-side;

  • Hanjst is Language-independent, not-bound with back-end scripts or languages;

  • Totally-isolated between MVC, data transfer with JSON;

  • Full-support template tags with built-in logic and customized JavaScript functions;

  • No more tags languages to be learned, just JavaScript;

  • ….

 


河北-张家口,千米高原,天高云淡,西北风烈,酒肉香混.

 

Posted in -Hanjst/-汉吉斯特, 编程技术, 计算机技术 | Tagged , , , , , | Leave a comment

☘ gMIS吉密斯优化升级:+工作区,可读性异常信息,异步删除等

“年与时驰,意与日去,遂成枯落,多不接世,悲守穷庐,将复何及!” 

—- 诸葛亮《诫子书》

gMIS吉密斯近期进行了较大幅度的优化升级,功能增强改进,感谢大家对 gMIS吉密斯开源社区的捐赠,这些支持使得 gMIS吉密斯 能够日益成熟而稳定、健壮而强大。诸葛先生的训诫之词,言犹在耳,未敢懈怠。

这批次 gMIS吉密斯的更新主要包括如下内容,记录备忘如下,以期后续结集成书时参考备查。

  • 1)增加工作区概念(workspace), 多个物理上、逻辑上相互隔离的区域,一套系统管理N多个信息管理系统;

gMIS吉密斯 自今起,开始支持工作区 workspace的功能。

工作区 Workspace 往往与项目、地区、主题等密切相关,gMIS 增加工作区的主要考虑是为了满足如下设想的工作场景。

我们认为在一个大型的企事业单位的组织中,随着数字化、信息化的不断投入与持续升级改进,其数字资产会深入地细化、细分,从一个10人团队的一个数据库开始,会逐渐升级改进扩展为2个数据库,4个数据库,10个,20个,甚至是200个数据库。

这些数据库及其数据都需要管理,管理数据信息,就需要安装 gMIS,有多少数据库要管理就安装多少套 gMIS吗?

答案显然不是。首先, gMIS 支持一套系统管理N多数据库,参考:“-gMIS 中操作同时并发操作和管理多个数据库multiple databases” (-R/x12SV )。通过这种方式, gMIS 可以轻易地管理其这些数据库。其次,平行地复制或并行多套一样的系统,对IT运维团队来说是灾难,如果有这样的需求,首选的方案应该是负载均衡等。

之所有要考虑引入WorkSpace工作区,是要管理两个以上并行的 gMIS 实例数据库,比如,在一个单位中,人事系统、财务系统、购销存系统,系统分别独立运行,而不是揉和在一个系统内。这样情况下,平行复制 gMIS 是方案,而引入工作区workspace 则是更好的方案。

gMIS 工作区(workspace)

在用户登录系统时,给出待登录的工作区选择,当用户选择给定工作区(如上图HR工作区、ERP工作区或者CRM工作区)时, gMIS按设置加载给定工作区的数据库,进行认证;用户通过权限认证后,将本次会话的工作区信息写入用户身份数据,按指定工作区加载指定的数据,进行后续数据操作工作。

  • 2)增加对只读模式下对功能菜单调整,去掉“新增”,”导入Xls”等;

gMIS吉密斯在设计时会考虑两种情况无法对一个数据表对象进行“写入”操作:1)访问权限设置系统里,如果针对当前用户或者用户组是受限的,则无法进行写入;2)数据表对象本身具有“只读”属性,比如针对所有用户,“操作日志”记录表就设置了无法删除。

针对不具有写入权限的数据表对象,程序增加了判断,去掉了那些针对当前用户和场景无法使用的菜单选项,比如“新增”,“编辑” 或者“导入Xls”等操作。这样既避免用户误操作,也让界面现得清爽。

  • 3)在 comm/tblconf 里修正对Unique index的探测;

gMIS 在装载当前数据表对象的数据之前,通常需要对该数据表的元数据进行解析。这项解析工作包括目标数据表,有哪些字段,每个字段的数据类型等,同时也检查字段之间的关系等,如哪些字段是唯一键,哪些是组合约束键等。

本次改动主要是优化改进了 MySQL 数据库作为后端数据时,检查以 MUL 为标记的组合约束键。

  • 4)列表行删除数据时,不再刷新页面进行UI更新,改进为通过JavaScript前端删除;

关于删除的改进优化,gMIS吉密斯一直未停止。

早前在2015年,我们受 Microsoft Windows 延迟删除的改进启发,增加了针对数据删除,由必需点击“确认”改进到“延迟”数秒进行无确认删除:“删除确认、删除异步及删除延时,delete confirm,aysnc and delay” (-R/62SS )。

在2015的这次改进中,被删除的数据会被打上标记,比如变灰色,等下次刷新时,整个页面再做刷新,这样做的目的是节省因为删除数据而进行一次数据请求和与服务器的通信,将数据交互的量级降到最低。

持续地改进,在多数数据操作人员眼里,删除就应该立即移除掉,而不是打上删除标记等下次页面刷新。这次改进,当数据通信与服务器通信正常时,会使用JavaScript动态的将所删除的数据行从当前UI视图中移除掉,而不进行整个页面刷新。

这样既实现了立即移除掉的目的,也再次地坚持了“降低成本、提升效率”的设计和实践原则。

  • 5)列表页选择框下拉选择即时递交,不再等复合条件查询,改一步复合查询为多步叠加条件;

gMIS 内置的增强数据表头,提供了功能强大的搜索及排序功能。

在条件设置上,列出所有可能经常用到的列表字段供筛选时使用; 同时,在每一个具体的筛选字段上,又提供数种可供操作的操作符供选择,如数值型的字段提供了等于、大于、小于和值域区间等,而字符型字段则提供了等于、包括、以其开头、以其结尾和不包括等选择项,可谓十分丰富和强大。

在组合条件设置三上,同时提供了“并且”和“或者”两种模式,前者是满足所有条件的数据,后者是满足其中一项的数据记录。

这些足以满足通常情况下数据操作人员对待检索数据的所有筛选设想。这次改进的地方是当用户选择了“选择性”的字段的某个“选择项”时,即时递交数据筛选请求,不再等待点击“并搜”或“或搜”再进行筛选条件的组合。

  • 6)输入数据异常时, 给出具体而详细的出错信息;

作为管理信息系统应用软件,录入数据是很常规的操作,对常规数据的校验,主要依赖 gMIS内置的 GTAjax在前端进行。 GTAjax 在前端页面通过 JavaScript在递交前,检查当前数据录入表单的各项是否符合预期。

这在一般情况下是够用的,但有时一些异常是在后台数据库写入时才能发现的,比如常见的写入时异常就包括,唯一键冲突;再者,在做二次定制开发时,开发人员可能没有主动意识或者要求针对某些字段需要增加基于 GTAjax的数据校验。针对这样的异常,此前 gMIS 会报错成写入失败,并请用户重试。但可供管理用户深入核对的信息不够详细。

Hanjst 更新优化报错信息定位到行数 (-R/52SQ ) 的升级优化启发,我们觉得可以在 gMIS 里也能够实现在数据保存异常时,给出详细而具体的信息定位。

于是我们改写了 act/doaddmodi 的返回输出内容,当数据报错异常发生时,通过解析数据库的返回错误代码或者程序错误代码,进一步地解读成普通数据操作人员能够理解并定位到的语句内容,通过 JSON方式返回给前端,进一步地展示给数据操作人员。

如此详细而具体的异常描述信息将有助于数据操作人员快速找到问题并解决,正是生动地实践了 gMIS吉密斯的 “降低成本、提高效率” 的初衷。

  • 7)增加 “导入Excel” 数据表功能,与此前已有的 “导出Excel” 形成闭环.

gMIS 一直希望能“降低成本、提升效率”,并将这个作为设计与研发的原则。批量操作也是这一体现,“导出Xls“ 和 “复制” 操作就是具体的实现。

在 gMIS 所管理的数据表中,可以轻易地使用“导出Xls” 将当前记录结果集下载到本地使用。 “复制” 则是在录入数据过程中,对于两条差异不大的数据,可以快速地复制一份,再稍作修改即可作为新数据进行录入。

这次改进,增加了“导入Xls”功能,与“导出Xls”,相对,形成闭环操作:即可导出,亦可导入。然而,对比“导出Xls”, “导入Xls“的操作要复杂的多,主要原因是:1)不相信用户的任何输入,2)用户输入的数据需要各种复杂的解读与格式化,没有“以一贯之”的良药。

即便如此,我们也要进行一些尝试。这些改进包括:在 导入Xls 的分步骤操作中,先给出预览,预期当前数据表可接受的数据表格式,给出表头。

如果用户按照所给出的表头进行数据准备并递交后,分步骤导入Xls中进一步地检查,并给出已解析、待录入的数据预览。

当用户确认其准备的数据经有程序校验符合预期时,再点击下一步,执行分步骤导入Xls的真正写入操作。如果在这一步中发现不符合预期,用户可以选择修改本地数据,并重新上传,循环此数据校验步骤,直到获得满意预期,再进行实际导入操作。

gMIS Import Excel Flowchart /导入 Excel 数据 流程图

为何是 Microsoft Office Excel?

  • 8)其他一些更新

gMIS 2019 发行版本是 gMIS有史以来更新幅度较大的一次,根据 -github 的版本差异统计分析,这次更新设计到数百个文件的更新。

commit 92736964b3ea3279639988cca7f172d670663d15

Showing 432 changed files with 111,925 additions and 21,134 deletions.

 


林林总总,gMIS 吉密斯在不断满足不同需求的同时,持续地丰富和改进其功能,日益成熟而稳定,健壮而强大。

这既得益于信息化发展创造的巨大需求,也得益于开源社区群体共同努力。

唯有感谢,并不忘初心,砥砺前行!


-gMIS (general Management Information System,吉密斯) 是一种基于 -GWA2 (General Web Application Architecture,吉娃兔) 的通用管理信息系统应用软件,具有可配置的输入和输出接口、开箱即用等特征。
可以在其上构建各种信息管理应用软件系统,例如:
内容管理系统(CMS), 客户资源管理(CRM), 企业资源计划管理(ERP),
办公自动化系统(OA)等, 以及各种行业应用管理系统软件,例如:
人力资源管理系统(HR),学生管理,档案管理,旅游管理,图书管理,
商品管理及业务运营支撑系统(BOSS)等等。
实现零代码开发、快速搭建各种管理信息系统(MIS, Management Information System).

-gMIS is a -GWA2 based Management Information System (MIS) software with characteristics like configurable input and output interfaces, open-box-to-use.
Various management application software systems can be built on it, such as
Content Management System (CMS), Customer Resource Management (CRM), Enterprise Resource Planning Management (ERP),
Office automation systems (OA), as well as different industry application management system softwares, such as
Human Resource Management System (HR), Student Management, Archive Management, Tourism Management, Book Management,
Commodity management and business operations support systems (BOSS), etc.
With zero code development, -gMIS can build a set of management information systems (MIS) software in a few minutes.

Lower Costs, 
Better Productivity.
降低成本,
提高效率.

Posted in -gMIS, 服务器运维, 编程技术, 计算机技术 | Tagged , , , , , | Leave a comment

汉吉斯特Hanjst+更新升级:error reporting, innerLoop和loadingLayer

过去的几个月里,汉吉斯特Hanjst进行了一些升级,有功能增强,也有性能优化,为Hanjst的生产环境部署增砖添瓦、保驾护航。为便于后续维护和持续更新改进,兹备忘于下。

* 12:48 Saturday, April 27, 2019, + readable error reporting for template erros
* 19:19 Sunday, May 19, 2019, + renderTemplateRecurse for deep-in include files.
* 18:44 Friday, May 31, 2019, + allow limited support for variables in xxxelse scope, bugfix for includeScript.
* 07:58 6/2/2019, + imprvs with _appendScript to appendScript for async call.
* 16:31 Wednesday, June 5, 2019, + imprvs with parentNode=BODY
* 19:18 Monday, June 10, 2019, + bugfix for asyncScripts.
* 22:29 Thursday, June 13, 2019, + loadingLayer. “<div id=”Hanjstloading” style=”width: 100%; height: 100%; z-index: 99;”> Xxxx Loading… 加载中… </div>” .
* 21:36 Thursday, June 20, 2019, + warning for MSIE browsers.

  1. 增加可读性错误异常报告
    当Hanjst遇到语法错误时,抛出可读性的异常代码描述,形成可以追踪的错误报告,其大致形式如下:

    Hanjst template code exec failed.

    {“stack”:”ReferenceError: $myAds2 is not defined\n at eval (eval at renderTemplate (http://example.com/view/default/js/Hanjst.js?v=201906171103:468:15), :405:1)\n at renderTemplate (http://example.com//view/default/js/Hanjst.js?v=201906171103:468:39)\n at _callRender (http://example.com//view/default/js/Hanjst.js?v=201906171103:679:9)\n at http://example.com//view/default/js/Hanjst.js?v=201906171103:698:9\n at http://example.com//view/default/js/Hanjst.js?v=201906171103:701:3″,”message”:”$myAds2 is not defined”}

    Line 404:

    Line 405: if( $myAds2[‘sadplace’]==’homepage_up_right’){

    Line 406: tpl2js.push(” <a href=\””);

    根据这些具体到行号的错误提示信息,开发者可以较快地找到出错位置并进行修正。如上所示,表明在模板引擎进行解析时,发现在第405行有未定义的 $myAds2 这样的变量未经初始化就开始使用,所以报错。

    注意!值得注意! Hanjst 全程开启 JavaScript 的 Strict mode,不允许使用未经定义的变量!

  2. 改进Hanjst循环嵌套模板的处理方法
    在初版的 Hanjst模板引擎设计中,我们假定模板的嵌套只有一层,也即一个模板中通过include 指令引入了另外一个模板内容。
    {include file=”$anotherTemplateFileContent”}

    随着 Hanjst 应用场景的复杂化,多层嵌套成为必然,有鉴于此,我们升级改进了 Hanjst,允许无限层的模板内容嵌套。也就是父页面可以引入嵌套子页面,子页面内也可以进一步的嵌套引入孙页面,如此递归不止。

  3. 增加对 forelse, foreachelse, whileelse下的模板语言支持
    通常情况下,如果循环一个数列,如果遇到轮空的情况,默认我们设计了给一个提示,如下所示。
    {foreach $myList as $l}
        //- some data
    {foreachelse}
        //- a warning…
    {/foreach}

    这次改进是在 “a warning” 部分给与有限功能的模板支持,比如允许使用变量进行替换操作等。

  4. 改进对async引入脚本的处理方法
    对嵌套页面的脚本程序引入有两种方式,一种是直接执行,另外一种方式是记账并延后进行引入。
    其中后面一种异步的async方式,对提升页面加载速度有很大帮助。所以在 Hanjst的改进中予以实现,当有非必要可以延后加载的脚本,都可以通过 async方式安排当页面首屏加载完成后再继续。
    上面是理想情况,还有非理想的情况时,当有些页面元素还为就绪时,一些依赖于其上的脚本就无法执行,这时候就是迫不得已需要等页面元素就绪后再加载脚本程序。
    根据这些,我们建议对象什么类脚本程序可以直接加载,而对对象的调用类脚本,一般都安排async异步加载为好。
    <!–
    JavaScript codes which will be run only once after Hanjst’s work,
    should be placed below here, after Hanjst, and keep in mind:
    1) ‘use strict’ mode, add comma for each sentence;
    2) src of Objects should be loaded in sync mode, e.g. jquery.min.js;
    3) invokes with Objects should be loaded in async mode, e.g. base.js;
    –>

  5. 增加对Hanjst父元素的探测
    这是改进是由于 HTM本身限制导致的,根据实验结果所示,浏览器的解析引擎进行页面渲染时,如果是放入未关闭的 div 内的脚本,默认是不执行而直接跳过的。
    如此以来,如果将 Hanjst 放入一个 div 元素,则默认随页面自动启动的 Hanjst解析引擎启动后,随后的加载嵌套页面的脚本等就无法实现了。
    有鉴于此,当 Hanjst启动时,探测如果其父元素不是默认和预期的 body 时,就抛出异常进行报错。
    待开发者进一步解决问题之后再继续。

  6. 增加loadingLayer
    当Hanjst进行编译页面时,原始代码会曝露给调用者,尽管时间是 毫秒级(ms)的,但如果碰上较慢的网速,依然有不完美的“印象”。
    为此,我们设计了当 Hanjst 工作时,前端预置一个”幕布”, loadingLayer , 显示给用户,当页面完成编译后,大幕揭开,完美呈现!
    <div id=”Hanjstloading” style=”width:100%;height:100%;z-index:99;opacity:0.92;position:absolute;background-color:#ffffff;”> Hanjst Loading… 加载中

    Hanjst loading layer默认的元素id是 Hanjstloading, 也可以通过启动参数:

    Hanjst.LoadingLayerId = ‘myLoadingLayer’;

    来指定自定义的元素Id。

  7. 增加对过时MSIE的探测
    如果浏览器太老了,比如 微软 IE浏览器,特别是8.0以前的版本,对JavaScript支持有限,无法顺利完成 Hanjst 的编译与解析,就会出错。
    为便于用户感知这些,我们改进 Hanjst 增加了对 MSIE太老版本的探测,并给用于相应的提示。



Hanjst是一种基于JavaScript的模板语言及解析引擎,她运行在客户端/服务器端。

Hanjst能够表述逻辑控制,能够实现与服务器端模块语言相同的功能。

  • Hanjst当完全在客户端解析时,节省服务器端计算资源;

  • Hanjst模板语言独立,不与服务器端资源做任何绑定;

  • 纯粹的MVC,层间数据用JSON格式传递;

  • 常见模板语言功能全支持,附带复杂而强大的JavaScript编程能力;

  • 无学习成本,直接使用JavaScript书写模板语言;

  • ….

Hanjst 在线文档 & API .

Posted in -Hanjst/-汉吉斯特, 编程技术, 计算机技术 | Tagged , , , | 2 Comments

♾好好与这个世界对话:gMIS/吉密斯更新+扩展操作行为

距离上次gMIS/吉密斯的更新差不都有半年过去了,这期间gMIS部署和使用的场景进一步扩大。最近又有新的部署并使用,在更新维护的同时,也有增加新功能,比如这次比较重要的一点是进一步地深化和加强了扩展行为操作的使用。情况较复杂,兹详述如下,以备忘。

gMIS/吉密斯 是“通用管理信息系统“软件,当我们有底气说“通用”的时候,意味着这个系统可以管理任何基于关系数据库所管理的数据,为这些数据提供面向非技术人员的人性化的操作和使用数据的途径。关系数据库,技术人员能耳熟能详地列出 Oracle、MySQL、SQLServer、SyBase等,其也是当今信息化的基础设施之一。通用的面向技术人员的,各种数据库的客户端,无论是基于命令行的还是基于GUI的(包括App和Web, 如 Navicat、PHPMyAdmin等),都有不少选择。而能够基于原始数据,直接产生能够面向非技术人员的,类似产品并不多,我们说“通用”,是我们创建了一套方法,可以针对任意指定的“字段”,无论其什么数据类型,我们都能够在gMIS/吉密斯中配置出契合其特点的输出/输入接口/界面,也即我们的 extra目录,插件式的工作,通过指定配置信息,无论这个字段是读写数据、字符串、选择项、文件、层级目录、编辑器等,均能应付自如。当一种新的数据类型、接口、界面被需要时,我们可以再通过extra方式制作并嵌入进去,这就是当我们说“通用”的底气。

一直以来,gMIS/吉密斯秉持这种“通用性”工作良好。

然而,我们深知,多样性、丰富性和复杂性才是世界的本原,我们以“通用”立命题就有某种抗自然规律的冲动,这种带有某种邪乎劲的要“包治百病”式的做法,会让人担忧,也令人不解。毕竟,这世界上没有包治百病的良药。


Fig.1 数据库数据表示层级

深度地解析,上述“通用性”是建立在对“字段”这一级别的操作上,也即,可以应对所有数据类型的字段进行操作,按照通常的数据组织结构划分 “数据库 — 数据表 — 记录 — 字段”(Fig.1),我们实现了在“字段”级的“通用性”操作。

如果多样性和丰富性的需要是针对“记录(Row)”这一级别呢?

目前针对“记录”的操作,我们有规定的动作“add、modify、view、print、delete、search(insite, pickup)、pivot、export、copy”等,如果要增加一种或多种针对“记录”的操作,该如何操作?这种需求合理吗?常见吗? 需要被满足吗? 能被满足吗? 如果能,该如何实现在“记录”层级的“通用性”?

最早我们设想,几乎所有共用的操作,针对一条数据(Row)的操作也就这么多,除了增删改查这四项基本的,我们已经很丰富地增强提供了其他多项。然而,诚如前所言,多样、丰富和复杂的客观世界,可能会有更多种针对一条数据的操作需求。这种需求是合理的,也是客观的描绘世界的必需项。这样的设计应该被满足。

初次遇到这样的需求,并令我们面对和思考这样的问题是在进行 工作流 的设计和制作上。工作流的本质也是对Row为单位的数据进行操作,但其动作已经超过了对Row本身的操作,而是Row之间发生了关系,也即一条Row可能从用户A流转到用户B,然后用户B将该Row流转到用户C等等,依此类推,而且还可能针对Row产生不同的修改。

为了满足这种需求,我们设计并实现了第一版的 ActOption 标记,这一个版本的 ActOption 在数据表的 table节点配置,并输出绑定到 act/view 界面上. 详细记录参考:
[2016] -gMIS 更新多库连接及工作流workflow
[
2018] –gMIS吉密斯更新Workflow工作流、FileMgr文件柜及GTAjax等模块

这些实践,为我们最终打开 gMIS 好好与这个世界的大门,既然 ActOption 可以一种配置文件的形式嵌入到 act/view 中,那距离出现在 list 主页面的 弹出式菜单中也只有一步之遥。如果实现了某种针对 Row级别的操作,既能出现在 act/view 的窗口,也能够出现在 list主页面的弹出式菜单中,与 常规的 add\modify\view\print等相并列,则gMIS/吉密斯就具有了好好与这个世界对话的强大话语表达能力。

于是沿着这个思路,近期我们突破了自我局限,将 ActOption 的配置通过 ido, jdo, comm/ido.js 等修改实现了自动添加到 list 主页面的 弹出式菜单,与常规操作 view/modify/print 等并列。其实现方式亦颇为曲折,大致流程可以描述为:

基于 table 的xml配置信息,配置某个 <table> 的 <actoption>,
–> gMIS 解析引擎读取 <actoption>配置,
–> act=list 时, ido 负责将 actoption 输出到 JavaScript 
–> 当 comm/ido.js: showActList 被激活时,读取 JavaScript 中的 actoption ,拼入 showActList,呈现给用户. 
–> act=view 时, act/view 负责将 actoption 读取并输出.

这既像是 gMIS/吉密斯 自身打开任督二脉,实现圆通;也像是其突破了狭隘的“通用”桎梏,如虎添翼,实现了升级,将“通用”二字的外延进一步扩大。

在此之前,我们说“通用”是可以满足通常情况下的字段级的任意方式方法的输出与输入,已经有的,随配随用,需要创新的没有的输入输出方式,我们可以创制后无缝嵌入。
今天起,我们说“通用”不但可以满足字段级的任意方式方法的输入与输出,而且也可以满足任意方式方法的记录级的操作,已经有的,随配随用,需要创新的没有的操作方式方法,我们可以创制后无缝嵌入。

所谓“通用”,不是寻求某种包治百病的神药,而是普通常见的已经就绪,随去随用;而没有的,也能够见机行事,按需定制,增强适配。如此以来,“通用”则更有底气,无论是理论基础,还是实践经验,我们都信心十足,满怀干劲;既讲求事物的普遍性,也照顾到事物的特殊性;既有由个例到共性的总结归纳,也有由抽象到具象的推导演绎(Fig.2)。也许,“通用”的意思在这里,就像有“科学的科学”——哲学一样。


Fig.2 特殊到普遍,具象到抽象

自2011年创制以来,这将是 gMIS/吉密斯 发展史上的一个标志性的更新,Latest commit e8aaaf0 . 近十年来,gMIS/吉密斯 不断茁壮成长,目前已经具有如下一些鲜明的特色功能点。

创新性的数据表字段级可配置输出输入接口;
先进的无Session用户鉴权体系
创新性强大的站内搜索功能
媲美前端的点选搜索功能
模拟Office Excel的数据透视表功能
商用级别工作流支持;
层级目录式的文件管理系统;
自动跟踪记账系统;
多层级缓存局部更新等优化高速秒开页面
….
创新的数据表记录级的可配置输入输出接口;
….


-gMIS (general Management Information System) 是一种基于 -GWA2 (General Web Application Architecture) 的通用管理信息系统应用软件,具有可配置的输入和输出接口、开箱即用等特征。
可以在其上构建各种信息管理应用软件系统,如
内容管理系统(CMS), 客户资源管理(CRM), 企业资源计划管理(ERP),
办公自动化系统(OA)等, 以及各种行业应用管理系统软件,如
人力资源管理系统(HR),学生管理,档案管理,旅游管理,图书管理,
商品管理及业务运营支撑系统(BOSS)等等。
实现零代码开发、快速搭建各种管理信息系统(MIS, Management Information System).

-gMIS is a -GWA2 based Management Information System (MIS) software with characteristics like configurable input and output interfaces, open-box-to-use.
Various management application software systems can be built on it, such as
Content Management System (CMS), Customer Resource Management (CRM), Enterprise Resource Planning Management (ERP),
Office automation systems (OA), as well as different industry application management system softwares, such as
Human Resource Management System (HR), Student Management, Archive Management, Tourism Management, Book Management,
Commodity management and business operations support systems (BOSS), etc.
With zero code development, -gMIS can build a set of management information systems (MIS) software in a few minutes.

Lower Costs, 
Better Productivity.
降低成本,
提高效率.

 

Posted in -gMIS, 编程技术, 计算机技术 | Tagged , , , , , , | Leave a comment

一例走近科学式地😥网速慢的排查

最近感觉家里的网速逐渐慢下来了,偶尔出现的timeout变成经常性的行为。尽管秉性脾气好忍受度极高也觉得有必要查一下原因,毕竟速度配不上光纤接入速度。

由于计算机网络科班出身,且懂服务器端优化,-R/P2SN ,我想从宏观和微观两个层面去排查。

宏观上分析。

由于访问的目标网站和服务器在国外,起初怀疑是太平洋底的通信光缆受最近地震影响或断了或部分的断了而导致路由表调整而降速。但这一点无法证实或证伪。

其次要考虑的是国外网站及主机受国家防火墙的限制而降速,毕竟黑白名单传了很久若有一天海外未名主机完全无法访问也是有可能的事,只是这一点也无法证实或证伪。

再次,国内路由跨电信运营商的网络之间限速也是有耳闻目睹的事,会不会我要访问的海外主机走的是电信的国际出口而我客户端在联通的网络中。有可能,只是也不容易获得确切证实或证伪的数据。而且,如果网速慢是上述一个或多个交织原因导致的结果,就让排查工作难度提升了不少。

北京城市副中心热火朝天地建设不会影响了这区县的电信网络通信吧?所住小区最近一直在人防工程保养施工,弄断了几根线缆影响了入户线路?

都有可能发生,都不容易确认。

微观上分析。

在网络链路上,网络慢排查需要进一步细化。一个常规检查网络请求处理的时间分为两大块:网路上的时间和服务器端处理请求的时间。由于是自用的服务器,我们可以清晰地看到请求处理时间都在ms毫秒级别。慢不在服务器处理时间上,而是在网络链路上.

于是上各种网络工具,数据显示时好时坏,好的时候各节点一路畅通,坏的时候第一步就走不通. 也能够观察到中间节点超时的情况。相当于链路各节点都有好坏的时候,并不有助于问题的排查。前提的确是,正常情况下ping到服务器端需要 200ms左右,好的时候 100ms,差点就直接超时了。

排查工作就觉得没思路了。于是在浏览器打开本地路由器/网管的控制台看看,居然发现打开本地路由器的控制台页面也有超时的情况。这算是异常到极致了。台式机到路由器只有一条网线,难道是浏览器坏了或者路由器本身有问题?

继续这个思路,使用另外一台mac笔记本无线连接到路由器的控制台,浏览和操控很流畅。进一步地排除了本地路由器的问题。会是台式机浏览器的问题吗?于是从新审视了最新版的Chrome浏览器并打开网络流量监控软件进行实时监测。

在这个过程中,我们又分别重启了路由器和插拔了网线接口,不想问题变得更糟糕了,台式机的网络彻底被断开了,路由器和台式机上都显示网络异常。网线有问题?!

排查路由器到台式机的网线!这跟网线穿墙里走了两个房间进入台式机,起初安装使用时,电信公司工程师拨开了外皮拆了蓝白两条用作了语音电话☎️。另外三组网线用作数据通信,而在拆开网线的部分只是简单包扎,可能来来回回的挪移路由器和牵扯网线导致接口接触不良,信号就传输异常,丢包严重。网路慢和失败就成必然结果。而最后一次的插拔和挪移将问题摆上了台面。

还没有现成可替换的网线,于是重新包扎/包装拨开的网线部分,并重新换了网口,网路恢复,网速回到可以预期的范围。实测本地台式机到本地路由器时延1-3ms,丢包率 0.001,可接受范围。

恐怖片开始、喜剧片结束了这让人哭笑不得😥的网路慢排查工作。

Posted in 服务器运维, 计算机技术 | Tagged , | Leave a comment

🍃GWA2Java新增Cmdline命令行和JavaBean运行时模式

根据业务发展需求,我们按预期新增了GWA2 Java版本的命令行运行模式和JavaBean运行模式。这是距离 GWA2 两年前发布 Perl 版本之后的另外一个主要升级版本。


(GWA2的发展路线图)

# Use GWA2Java in cmdline and/or JavaBean

## GWA2Java cmdline

### compose GWA2 in .java files

### compile them into .class files

shell> cd ./WEB-INF/classes

shell> java com.ufqi.gwa2.Index “?mod=user”

## GWA2Java in .jsp

### compose GWA2 in .java files

### compile them into .class files

### import and use in .jsp:

#### as of a single class
<@page import=”com.ufqi.gwa2.mod.User”%><%
com.ufqi.gwa2.mod.User modUser = new com.ufqi.gwa2.mod.User();
modUser.getId();
//….
%>

#### as of a JavaBean
<jsp:useBean id=”modUser” class=”com.ufqi.gwa2.mod.User” scope=”application”>
<jsp:setProperty name=”modUser” property=”param1″ value=”value1″ />
</jsp:useBean>
<%
modUser.getId();
%>

## Why Tomcat cannot compile automatically .java files under ./WEB-INF?

## as of Caucho Resin?

在此前的 GWA2Java 架构设计下,一个没有明确答案的思考时,如果使用在 .jsp 文件中定义了太多的 classes 并且每个 classes 定义太多的 methods,会不会超过 Java 的规范定义? 即便没有超过,会不会有性能上的不足?

关于第一个问题,我们能够很容易从 Java 文档中得知,一个通常的 Java class可以允许有 65535 个 inner classes,而一个 class也允许有 65535个 methods,所以即便include再多的 class在 .jsp 文件中,也很难到达这个限制。单个 Method有 64K的限制,我们在此前的研发中也的确遇到过,分拆和提炼相应的代码即可回避。

至于第二个问题,这样的class contains inner classes 会不会有性能上的不足,暂时并没有数据支持或者不支持这一说法。

即便如此,根据我们的考虑,仍应该为开发者预留比较传统的Java Servlet的调用方法,也即将单独的class单独封装起来,使用外部类,或者useBean的方式引入 GWA2 的运行时环境,进而与普通的 inner classes一样使用。

基于这样的考虑,我们也一并研制了 GWA2Java 的cmdline命令行运行时模式,这些为GWA2Java的全功能运行时模式提供了思路,继续完善、强化还需要开发者参与并举共襄。


GWA2 cmdline 运行时举例。

GWA2PHP:

shell> cd /path/to/gwa2php
shell> php index.php “?mod=user&act=list”

GWA2Perl:

shell> cd /path/to/gwa2perl
shell> perl index.pl “?mod=user&act=list”

GWA2Java:

shell> cd /path/to/gwa2java
shell> java com.ufqi.gwa2.Index “?mod=user&act=list”


截至目前,基于 GWA2 开发的各种语言版本的软件可以如下几种方式运行:

GWA2PHP
软件以GWA2PHP开发完成后,可以寄宿在Web Server中运行,也可以cmdline命令行运行。

GWA2Perl
GWA2Perl 的软件目前支持以cmdline命令行方式运行。

GWA2Java
GWA2Java 的软件开发完成后,可以寄宿到Web Server中运行,也可以cmdline命令行模式运行。


-GWA2 是”通用网络应用架构( General Web Application Architeture )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.

 

Posted in -GWA2, 编程技术, 计算机技术 | Tagged , , , , , | Leave a comment

Base62x算法改进并增加Base62x in Python

距离上次 “-Base62x 新增 -Perl 版本技术实现 Base62x.pm (-R/J2SL )”, Base62x 在时隔 6 个月后又进行了一些更新,记录一下,也再次印证,最好的版本永远是下一个版本。这次的更新包括:1)对解码算法的优化改进;2)增加Python版本的Base62x的工程实现。

1. 增加 Base62x in Python

春节一过即开工,因着技术项目需求,最近加紧编程开发了 Base62x in Python 的版本(Base62x.py)。 Python.py 版本的 Base62x 调用方法大致如下:

# import Base62x.py
from Base62x import Base62x

# initialize
base62x = Base62x();

rawstr = “abcd1234x’efg89;01”;
encstr = base62x.encode(rawstr);
decstr = base62x.decode(encstr);

Python 对面向对象的支持较好,所以直接以 OOP 方式编制了 Base62x.py , 并没有像 Base62x in Perl版本那样提供了 OOP 和 functional 两种方式。

截至目前Base62x 已经开源的编程语言版本如下: C, Java, JavaScript, PHP, Perl 和 Python. 其中 PHP的提供了三个版本:1)以PHP扩展模块形式的 ext/base62x C语言代码; 2) PHP 5版本的 Base62x.class.php; 3)PHP 7 版本的 Base62x.class.php 。
其中JavaScript 还有两个实现, Base62x.class.js 和 npm base62x 。

在实施 Base62x in Python 的编码时,我们发现 Python 语言中没有提供对自增+1的操作符 “i++” 这样的操作,而在此前所有版本的 Base62x 的算法中,均大量使用了 “i++” 或者 “++i” 的操作。

面对这样的编程语言的特性,我们不得不寻求另外的实现方法,这既是一种挑战,似乎也是一种机遇,我们在下面的一节讨论由此引发的对 Base62x 解码(decode)的优化改进。 

2. Base62x 解码算法的优化改进

2.1. 改进 if-else 顺序
将最大可能的 if 放最前面,减少每次 loop 时的运算对比次数。
改进后的代码大致如下:

if( a > 2){
     # most case
}
else if(a == 2){
     # secondary most case
}
else{
     # least case
}

改进后,有望减少计算判断,提升程序运行速度。也即如果按照通常的逻辑,如果代码写成  if(a==1){ … }else if(a==2){ … }else if(a>2){ … }, 则在每一个循环中,程序都要拿 a 跟 1, 2, 3等各个分支比对一次,然后再进入所对应的分支块。这是本次改进的主要认识之一。

2.2. 改进对自增操作符 i++ 等的调用
使用内部子循环来优化解码(decode)操作, 减掉大量循环体内的 if-else 操作,减掉 ++i 和 ++m 的操作.

如前所述,我们在编码 Base62x in Python 时,发现 Python 无法提供类似 “i++” 或者 “++i”  自增操作符,而在 Base62x 之前的很多版本的解码操作中,均有大量使用自增操作符。原算法的代码大致如下 (C语言):

switch(remaini){
case 1:
printf(“Base62x.decode: found illegal base62x input:[%s]! 1612121816.\n”, input);
break;

case 2:
if(input[i]==xtag){ tmpin[0] = bpos+bint[input[++i]]; }
else{ tmpin[0]=rb62x[input[i]]; }
if(i == maxidx){ //- may be wrapped into a func decode_by_length
c0 = (tmpin[0] << 2);
output[m]=c0;
}
else{
if(input[++i]==xtag){ tmpin[1] = bpos+bint[input[++i]]; }
else{ tmpin[1]=rb62x[input[i]]; }
c0 = tmpin[0] << 2 | tmpin[1];
output[m]=c0;
}
break;

case 3:
if(input[i]==xtag){ tmpin[0] = bpos+bint[input[++i]]; }
else{ tmpin[0]=rb62x[input[i]]; }
if(input[++i]==xtag){ tmpin[1] = bpos+bint[input[++i]]; }
else{ tmpin[1]=rb62x[input[i]]; }
if(i == maxidx){
c0 = tmpin[0] << 2 | tmpin[1];
output[m]=c0;
}
else{
if(input[++i]==xtag){ tmpin[2] = bpos+bint[input[++i]]; }
else{ tmpin[2]=rb62x[input[i]]; }
c0 = tmpin[0] << 2 | tmpin[1] >> 4;
c1 = ( ( tmpin[1] << 4) & 0xf0) | tmpin[2];
output[m]=c0;
output[++m]=c1;
}
break;

default:
if(i < last8){
if( input[i]==xtag){ tmpin[0] = bpos+bint[input[++i]]; }
else{ tmpin[0]=rb62x[input[i]]; }
if( input[++i]==xtag){ tmpin[1] = bpos+bint[input[++i]]; }
else{ tmpin[1]=rb62x[input[i]]; }
if( input[++i]==xtag){ tmpin[2] = bpos+bint[input[++i]]; }
else{ tmpin[2]=rb62x[input[i]]; }
if( input[++i]==xtag){ tmpin[3] = bpos+bint[input[++i]]; }
else{ tmpin[3]=rb62x[input[i]]; }
c0 = tmpin[0] << 2 | tmpin[1] >> 4;
c1 = ( ( tmpin[1] << 4) & 0xf0) | ( tmpin[2] >> 2 );
c2 = ( ( tmpin[2] << 6) & 0xff) | tmpin[3];
output[m]=c0;
output[++m]=c1;
output[++m]=c2;
}
else{
if(input[i]==xtag){ tmpin[0] = bpos+bint[input[++i]]; }
else{ tmpin[0]=rb62x[input[i]]; }
if(input[++i]==xtag){ tmpin[1] = bpos+bint[input[++i]]; }
else{ tmpin[1]=rb62x[input[i]]; }
if(i == maxidx){
c0 = tmpin[0] << 2 | tmpin[1];
output[m]=c0;
}
else{
if(input[++i]==xtag){ tmpin[2] = bpos+bint[input[++i]]; }
else{ tmpin[2]=rb62x[input[i]]; }
if(i == maxidx){
c0 = tmpin[0] << 2 | tmpin[1] >> 4;
c1 = ( ( tmpin[1] << 4) & 0xf0) | tmpin[2];
output[m]=c0;
output[++m]=c1;
}
else{
if(input[++i]==xtag){ tmpin[3] = bpos+bint[input[++i]]; }
else{ tmpin[3]=rb62x[input[i]]; }
c0 = tmpin[0] << 2 | tmpin[1] >> 4;
c1 = ( ( tmpin[1] << 4) & 0xf0) | ( tmpin[2] >> 2 );
c2 = ( ( tmpin[2] << 6) & 0xff) | tmpin[3];
output[m]=c0;
output[++m]=c1;
output[++m]=c2;
}
}
}
}

变量 remaini 是当前待处理的字符流的余量,算法的逻辑是对余量按每四个字符进行解码并按位操作。按余量不同,分别按4,3,2,1的长度情况使用 switch分别处理。这里首先要按 2.1. 的思路,将 余量为4 (最大可能)放第一位 if,然后再处理 i++ 和 ++m 的情况。

根据测试实验,使用一个内部的子循环可以取代 i++ (++i)和 m++ (++m) 的情况,针对C语言版本,还实现了此前处于@todo 的 decode_by_length . 该函数是用于处理 C、Java等可能出现的数据越界的安全检查等。改进后的代码大幅减少,(C语言)源代码大致如下:

if(remaini > 1){
j = 0;
do{
if(input[i] == xtag){
i+=1;
tmpin[j] = bpos+bint[input[i]];
}
else{
tmpin[j]=rb62x[input[i]];
}
i+=1; j+=1;
}
while(j < 4 && i < inputlen);
m = decode_by_length(tmpin, output, m);
}
else{ //- == 1
printf(“Base62x.decode: found illegal base62x input:[%s]! 1612121816.\n”, input);
continue;
}

从代码量上看,改进后的代码缩减至 10几行,而优化改进之前的代码足足有几十行至上百行,因此无论从体量还是从逻辑上看,改进后的代码更高效、简介。改进优化前: do{ if–else if– else if — else if — else; }while(…), 改进优化后: do{ do{ if — else; }while(…); }while(…); .

2.3. 针对所有已知编程语言版本进行升级改进
将上述在 C语言版本  base62x.c 中的算法,近测试无误后将相应地算法同样地在 Java, JavaScript, PHP, Perl 等版本中一一重新实现,并使用所对应的测试脚本对按 2.1 和 2.2 进行优化改进的算法进行测试。

测试结果显示,修改符合预期,优化改进成功。

另外还完成了 C语言、Java语言版本中的 decodeByLength 内部函数/方法的实现。

3. 持续向前兼容所有 Base62x 版本
上述 2.1. 和 2.2. 的优化改进,是 Base62x 在应用范围和算法性能上的扩展和改进。这些改进不会对现有的 Base62x 在格式、定于及语法上引起偏误,改进后的代码持续向前兼容所有 Base62x 的历史版本。

也即,此前版本Base62x 编码出来的 String,能够使用改进后的的算法准确地进行解码;使用改进版本的Base62x编码出来的String,也能够使用原来的Base62x算法原本无误地进行解码。

 

Base62x is an alternative approach to Base64 for only alphanumeric characters in output.
Base62x can be used safely in computer file systems, programming languages for data exchange, internet communication systems, and is an ideal substitute and successor of many variants of Base64 encoding scheme.
Base62x 是一种无符号的Base64编码方案。
Base62x 可以在计算机文件系统、编程语言数据交换、互联网络通信系统中安全地使用,同时是各种变种Base64编码方案的理想替代品、继任者。

 

Posted in Base62x, 编程技术, 计算机技术 | Tagged , , , , | Leave a comment

DevOps: 一例高负载多并发服务器连接池满的异常排解过程

今天是三八国际妇女节, 也是中国农历二月二/龙抬头的节日,恭祝女同胞节日快乐!恭祝中国善良的人们都抬头见喜!

好一阵子没更新Blog,今天也借这喜气冲刷一下往日的阴霾,经过多日的观察,终于找到这阵子“有福新闻”高负载多并发服务器的异常报错背后的原因之一。此前在Blog中频繁观测到 GWA2 PHP Memcached的报错,并且在代码层面进行了多次调优,问题暂时得到缓解,深层并未深究出个所以然。

“GWA2 PHP Memcached自动追加服务器连接?一例缓存服务被击穿的异常分析”, -R/52SP  。

在进行日常服务器状态巡检时,先是发现 Apache 在数日的持续运行中,会有 segmentation fault 导致的死掉,于是对 Apache 2.4.x 进行升级到最新版的操作,然而加了保护措施。尽管偶尔有 Apache child 有 segmentation fault退出,但整个服务顽强的活着.

后续几日的连续观测中,Apache暂无异常死掉,而 GWA2 PHP Memcached再次开始报错,报错信息为唯一的 127.0.0.1/11211 服务被标记为 DEAD (error code: 35). 然而在终端用 telnet 进行手工模拟时,memcached的服务又是正常的,这是为何?时好时坏,随机出错吗?

近日继续探测,在最近的一次服务器上尝试使用 ping ufqi.com 时,命令行开始报错说 sendmeg not permitted… 于是一例服务器操作系统层面的问题被曝露出来。

ping命令的无法执行,可能是网络配置或操作系统异常,循着这个思路,我们使用 journalctl -f 命令,很快看到 kernel层的报错信息:

Mar 08 04:43:06 srv21 kernel: nf_conntrack: nf_conntrack: table full, dropping packet
Mar 08 04:43:06 srv21 kernel: nf_conntrack: nf_conntrack: table full, dropping packet
Mar 08 04:43:06 srv21 kernel: nf_conntrack: nf_conntrack: table full, dropping packet

原来是系统的网络连接池出现了问题!关于 “nf_conntrack: table full, dropping packet” 这里 -R/u2SR 有详细的解释。 简单地说,操作系统集成了 Netfilter 防火墙服务,基于 iptables 的操作系统的连接管理器中,有四个 table(表) 和五个 chain(链)。


Fig1. Iptables 4 tables and 5 chains

Tables: categorized by different operations to data packets.

raw: highest priority, only appied to PREROUTING and OUTPUT chain. When we don’t need to do NAT, we can use RAW table to increase performance.

mangle: modify certain data packet

nat: NAT, port mapping, address mapping

filter: filter

Chains: categorized by different hooks.

PREROUTING: packet before going to route table

INPUT: after packet passing route table, destination is current machine

FORWARDING: after packet passing route table, destination is not current machine

OUTPUT: packet comes from current machine and to outside

POSTROUTIONG: packet before going to network interface

当操作系统处理 TCP/IP 连接相关模块出错时,所有基于连接的服务都会报出异常。这是此前在代码层无论如何优化都没办法解决OSI分层中更底层的问题。

操作系统默认的并发连接数为 65535, 通过命令:cat /proc/sys/net/netfilter/nf_conntrack_max  可以查看到。 如果通过命令 cat /proc/sys/net/netfilter/nf_conntrack_count 获得到的数字等于 max 的最大值时,此时再有新创建连接的需求就会报错,当创建连接失败时,基于其上的所有应用都将失败,而这些在代码层并不容易解决。推荐的 /proc/sys/net/netfilter/nf_conntrack_max 值的计算公式: CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (ARCH / 32) , 如 8GB RAM in x86_64 OS,  max = 8*1024^3/16384/2=262144 。

当一台繁忙的服务器的连接数超过默认值时,需要通过修改 /proc/sys/net/netfilter/nf_conntrack_max  来使得系统能够接收更多连接进来。

临时修改:
echo 524288 > /proc/sys/net/netfilter/nf_conntrack_max
or
sysctl -w net.netfilter.nf_conntrack_max=262144
永久修改:
在 /etc/rc.d/after.local  或者 /etc/rc.d/rc.local 中增加上述命令行语句。

除了增加 /proc/sys/net/netfilter/nf_conntrack_max 参数设定外,还可以通过调整 iptables 的表或者链上相关规则来进行调优,更多参考: -R/u2SR 。

“有福新闻”, “全国招投标信息中心” 等服务又可以畅快地运行并有信心地迎接下一次洪峰的到来。

小结:
1. 在代码层很难发现操作系统层的问题,可行的路线是分析应用层源码;
2. 系统层的异常,通过具有随机性,比如连接数,是一个动态变化数据,可能下一秒异常就没有了,无法确定重现的问题为 troubleshooting 带来了一定的障碍。
但是,已有的问题,在没解决之前,会再次发生,这是确定的。

Posted in -GWA2, 服务器运维, 计算机技术 | Tagged , , , , | 1 Comment

🛠️Hanjst/汉吉斯特更新加JavaScript运行时优化等

这是 Hanjst/汉吉斯特 发布以来的首个主要升级更新版本。这次的主要升级更新的内容包括移除HTML Comments注释行, 优化在 Hanjst include模板文件时的JavaScript运行时环境。

Hanjst 在设计和工程实现时,预留了模板文件嵌套功能,由于在过往的Web软件研发过程中,对模板文件的套用场景非常熟悉,所以对这一需求也感触较多,于是在最早的 Hanjst 初始发布中就预制了模板嵌套功能。

Hanst的模板嵌套采用了与 -Smarty 等模板语言类似的语法表达:

{include file=”$anEmbedTplFile”}

其中 “anEmbedTplFile” 经由服务器端读取并生成想要的表达式语言字符串。然后经由 Hanjst JSON Data 传递给 Hanjst 模板解析引擎。

Hanjst 模板引擎在解析 include 指令时,将对应的模板表达式汇入当前的页面的当前位置,从而实现对模板的嵌套。这个过程很流畅,逻辑也与服务器端模板语言一致。所不同于服务器端模板语言的是,当我们在 anEbedTplFile 里声明 JavaScript 变量及对象时,在父模板的 JavaScript运行时环境中可能找不到该变量或对象。设若, anEmbedTplFile 中包括如下内容:

<p>This is in an Embed Tpl File</p>
<script>
function embedJSFunc(varA){ console.log((new Date())+” :  call embedJSFunc with varA:”+varA); }
embedJSFunc(“I’m in embed tpl file!”);
</script>
<p>EOF.</p>

当我们将该模板以嵌套的形式进行嵌入一个 index.html 中时:

<p>This is in an Index Tpl File.</p>
{include file=”anEmbedTplFIle”}
<p>EOF.</p>

Hanjst 在解析 index 时,会将 anEmbedTplFile 的内容合并到 index 中,同时通过 _appendScript 私有方法将 embedJSFunc 注册到 index 中,同时在 index 的运行时环境执行 embedJSFunc 函数。

这次的主要升级改进就是这一流程中的细节进一步的优化提升。

1)资源冲突问题,当 index 中也有 embedJSFunc 同名函数时,会报错。
该如何处理报错信息?
可行方法是,避免在 index 和 embed 文件中同时命名相同的函数或变量、对象,以免引起冲突导致出错。
即便有开发者意外地在 index 和 embed 中同样地声明了相同的函数后者变量,Hanjst 也做了异常处理,以便整体流程能够顺利执行并完成页面渲染。

2)如果在 embed 中有 <script src=””></script>, 需要考虑引入其脚步资源。
该怎样引入较好?
路径中的变量如何处理?
Hanjst 此次改进增加了对 embed 的引入资源的支持,对资源路径中的变量进行解析,如在 anEmbedTplFile 中:

<script async src=”{$tplDir}/js/adsbygoogle.js”></script>

则 Hanjst 在将 该js引入到 index时,同时解析出 {$tplDir} 所指向的真实路径。

然而,如果是在 index 中模板中的路径,则需要在服务器端进行相应的替换,因为此时Hanjst 尚未接管对页面的渲染,尤其是不能使用带有变量的路径来引入 Hanjst.js 文件。

在服务器端对资源路径进行替换的通常做法大致过程是:A)模板开发人员,前端设计制作人员通常会使用相对资源引用路径在交付设计稿时,B)工程技术人员拿到带有相对资源引用路径时,会分割出共用头文件和尾文件,其他嵌套文件块,然后藉由模板引擎的{include}指令,重新分割、组装模板,C)工程技术人员将其中的相对引用路径替换为带有模板绝对路径的输出内容文本。相应的替换逻辑可以在 -GWA2 Java版中见到。

//- replaces in GWA2Java
String[] repTags = new String[]{“images”, “css”, “js”, “pics”};
for(int ti=0; ti<repTags.length; ti++){
    outx.append(“ti:[“+ti+”] reptag:[“+repTags[ti]+”]”);
    tplcont = tplcont.replaceAll(“\””+repTags[ti]+”/”, “\””+viewdir +”/”+repTags[ti]+”/”);
}

3)执行时序问题,如果是执行语句,绑定了相应的DOM对象,而该对象在Hanjst当前环境中还未就绪,会报错.
该如何处理?
onComplete?  window.setTimeout?

当 Hanjst 将 embed的模板内容中的脚本注入到 index 的运行时环境时,在解决了资源冲突问题之后,需要考虑执行时序,尤其是当待执行的代码需要依靠 Hanjst 后续输出的DOM 对象时,需要延后执行。

延后执行有两种思路,依靠 JavaScript的事件驱动机制event-driven, 将待执行的动作绑定到 Hanjst 的渲染方法 _renderTemplate 之后,也即 Hanjst._renderTemplate.onComplete。 第二种思路是,依靠 JavaScript的匿名函数Anonymous Function机制,既然是延后执行,则可以将待执行的命令封装到一个匿名函数,然后设定一个 window.setTimeout 过一段时间(预计 Hanjst 渲染完成 DOM)之后再触发该动作。

目前,Hanjst 采用的是后一种解决执行时序问题,也即当 embed的动作要执行时,先以一个匿名函数封装并生成一个 window.setTimeout。

执行时序问题,不单是 embed有,有时候index内的执行函数也有问题,一个常见的场景是,如果某些JavaScript调用是发生在 Hanjst引用之前,则会被调用两次(重复!)。解决这个问题的思路就是将 待执行的命令放在 Hanjst 引用之后,或者在命令设计时,允许重复执行而不影响预计效果。

这个设计及实现可以在 Hanjst的Demo页面看到。

Web模板语言及其解析引擎深入下去才发现,复杂而庞大,希望这些细节的探究及描述可以帮助更多的开发人员理解其内幕,仅一个{include}指令的编译就涉及那么多方面,一些以玩票心态用几十行代码实现一个“轮子”的想法可以考虑暂停下来了。

Hanjst 解析引擎目前已经超过600行代码,包括很多类似这样的算一行的统计:

var asyncScriptArr = []; var isAsync = false; var srcPos = -1; var endTagPos = -1; //- four lines
matchStr = match[0]; exprStr = match[1]; //- two lines
if(exprStr.indexOf(‘=’) > -1){ containsEqual = true; } //- three lines

毫无疑问,随着 Hanjst 部署的实例场景越多、兼容的异常越多、引入的模块越多和功能日趋强大,其代码会越来越长。

 


 

Hanjst/汉吉斯特 是一种基于JavaScript的模板语言及解析引擎,她运行在客户端/服务器端。Hanjst能够表述逻辑控制,能够实现与服务器端模块语言相同的功能。

Hanjst/汉吉斯特的主要特征/功能包括:

  • Hanjst当完全在客户端解析时,节省服务器端计算资源;

  • Hanjst模板语言独立,不与服务器端资源做任何绑定;

  • 纯粹的MVC,层间数据用JSON格式传递;

  • 常见模板语言功能全支持,附带复杂而强大的JavaScript编程能力;

  • 无学习成本,直接使用JavaScript书写模板语言;

  • ….

Hanjst 新增部署实例参考:
-Ufqi-Ztb ,
https://ztb.ufqi.com/?mod=ztb , 
全国招投标信息中心 .

Posted in -GWA2, -Hanjst/-汉吉斯特, 编程技术, 计算机技术 | Tagged , , , , , | Leave a comment

GWA2 PHP Memcached自动追加服务器连接?一例缓存服务被击穿的异常分析。

GWA2 PHP Memcached自动追加服务器连接? 一例缓存服务被击穿的异常分析。

最近在一次网络应用服务器巡检时,发现负载特别高,与当时的流量不成比例,于是就进一步地核查看看为何负载高。

首先发现负载高是由于数据库(-MySQL)的查询读取查询异常的多,并发连接有上百个,多数是简单的查询,可见不是数据库结构问题,而是自然流量触发的数据请求。

缓存被击穿了吗?为何这些显而易见的查询会出现那么多并发?稍微留意发现,有些查询SQL是相同的,于是可以大致推断,缓存层出问题。确认缓存被击穿,对一个线上应用来说是一件很恐怖的事情。

@memcached
进一步的诊断缓存服务(-Memcached),使用telnet 工具连接本地缓存服务,通过 stats命令查询,缓存服务正常,有正确的get/set数据,有get_hits/misses统计,缓存服务没有问题。

下一个疑点就是在代码层,PHP连接模块Memcached的地方有问题吗? 调用缓存服务的存取操作有异常吗?

打开 GWA2 PHP 的 inc/config.class 核对连接缓存服务,没有问题,基于IP地址和端口的连接配置;
打开 inc/webapp.class 显示读取缓存的成功与失败日志记录,发现有成功,有失败。
进一步地打开 inc/webapp.class 的 readObject/writeObject的日志记录;打开 inc/cachea.class, inc/memcached.class 中的 set方法的日志记录。

日志记录显示,有成功的,结果是预期的;当失败时,memcached发回的错误代码和错误消息是,35 / Server Marked Dead。

这听起来不可思议,当下的memcached服务,只有一个 127.0.0.1 基于IP的连接配置,怎么会有成功和失败的状况同时存在呢?

更进一步地输出当前 sever list发现,的确有两个缓存服务的配置:

memcached servers:a:2:{i:0;a:3:{s:4:”host”;s:9:”127.0.0.1″;s:4:”port”;i:11211;s:4:”type”;s:3:”TCP”;}i:1;a:3:{s:4:”host”;s:33:”/bin/memcached/memcached.sock”;s:4:”port”;i:11211;s:4:”type”;s:6:”SOCKET”;}}

明明在 inc/config.class 中只配置了 127.0.0.1 的一个缓存服务,而第二个 /bin/memcached/memcached.sock 从哪里来的呢?显然这个 .sock 的连接已经被标注了 DEAD 但并没有从 server list 里移除,这也让人费解,毕竟在 Memcached的连接初始化时声明了自动移除DEAD Server。

$this->mcache = new Memcached(self::persist_ConnId);
$this->mcache->setOption(Memcached::OPT_REMOVE_FAILED_SERVERS, true);
$this->mcache->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);

一种合理的解释大致是,/bin/memcached/memcached.sock 文件存在,然后Memcached 服务会自动探测,然后追加到当前的 server list里。会这样智能吗? 可能要分析PHP Memcached的扩展模块源码 和 Memcached的服务源码相应的模块才能确认。

导致存在 /bin/memcached/memcached.sock 文件并且使用 127.0.0.1 的原因是,第一次启动 Memcached服务时,指定了 -s /bin/memcached/memcached.sock 然后kill关闭,再次启动时不带 -s 而是指定了 IP/Port,这样 /bin/memcached/memcached.sock 就被遗留下来而没有用。

之所以不再使用 -s /bin/memcached/memcached.sock 模式,是由于该 Memcached服务需要在 PHP和 Java之间共享,而Java读取操作 .sock 文件相对复杂,暂时没有集成到 GWA2 Java中去。而 -s /bin/memcached/memcached.sock 与 IP/Port 在Memached服务看来又不能共存。

由于 /bin/memcached/memcached.sock 是上次启动后遗留下来的,所以其状态可能并不是 DEAD, 所以 OPT_REMOVE_FAILED_SERVERS 也未能生效?

针对这个问题,手工移除 /bin/memcached/memcached.sock , 然后重启 HTTPD ,  GWA2 PHP 再次正常运行,缓存服务不再报错,也没有缓存服务被击穿,导致数据库查询并发大,进而系统负载高的问题出现。


-GWA2 是”通用网络应用架构( General Web Application Architeture )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.

Posted in -GWA2, 编程技术, 计算机技术 | Tagged , , | 1 Comment