治大国若过小家——写写王朝兴衰更替背后的经济账

最近在读网红历史长篇文章《晚清沧海事》( 上下卷在线连载: https://ufqi.com/news/ulongpage.1008.html  ),在其中接近尾声的部分,有一个章节叫做《 晚清沧海事:制度落后就要挨打-117:下卷六十六:光复伊犁:晚清灭亡的实情》。这个章节里剖析了晚清灭亡的真实情况,从作者的观点,晚清政府未能对外抵御强敌,对内镇压反叛势力是根本原因之一。作为两个政治想象的另外一个,意图改革儒家思想也加速了其衰落,最终走向不得不面临的大清帝国崩盘的局面。

细究起来,晚清政府之所以未能在对日本等国的作战中取得胜利,主要原因之一是晚清在勉力镇压了内部反叛势力(太平天国军、捻军等)之后,经济上受到重创,国库见底。在接下来的拮据日子里,又要面临一个子掰两半花的局面,那就是晚清著名的 海防还是疆防的大辩论。这里的海防是大清帝国的海上防务,主要是针对同时明治维新崛起的日本和欧洲列强。而并不多见于历史的疆防,则是指西北的陕甘宁和新疆、西藏等地区的内乱和外敌。内乱是穆斯林持续不断的反叛,外地是土耳其、印度(英属)和俄国等。

总结就是晚清政府由于常年征战导致经济上连年负债,越没钱越弱,越弱越遭人欺负,越没钱,死循环。一个大国的治理,竟如同一个小家过日子一样,穷死。

古圣贤者老子在名篇《道德经》里著文“治大国若烹小鲜”。由于所言极其简略,加上时日久远,解读众说纷纭。比较主流的解释有两种,一种是治国不要折腾,寓意烹小鲜不能来回翻转。还有一种解法是说,小鲜不若大鱼,不能掐头去尾删减内脏,那就几乎不剩下啥了,要原样蒸煮。这种解法寓意治国要兼收并蓄,不删减,不增殖,顺其自然。

这里本人倾向于第二种解释,顺其自然。不过结合对此前的理解,稍加改动为“治大国若过小家”。看着一个泱泱大国,治理道理的背后,竟然与寻常百姓的一家一户过日子一样,都是围绕挣取几块钱,吃上一口饭。这个观点也在斯塔夫里阿诺斯(Leften Stavros Stavrianos)的《全球通史》里被提到,王朝循环的根本原因是经济管理的循环,而造成经济循环的原因,则是帝国开支超过税收。

这是读习经济学的第三篇心得体会写作,之前两篇分别是《写写1929年美国经济大萧条与2020年美国股市大跌》( https://ufqi.com/blog/us-1929-economic-crisis-2020-stock-shock/ )和《写写🏦存款利率贷款利率和负利率》( https://ufqi.com/blog/captial-rate-and-minus-rate/ )。

简而言之,一个大国的治理,与一个小家庭过日子一样的道理,也是开门七件事,柴米油盐酱醋茶,关门七件事,吃喝拉撒睡洗刮。其核心就是一个字,钱!没有一个大国是在国库充盈的时候被击垮的,而所有王朝被覆灭的时候,都是国库亏空的。宛如家境殷实的家庭不容易离散出问题,而贫贱夫妻百事哀。

Fig 1. 王朝兴衰更替背后的经济账

一个政权(政府)初始创立,开始“今儿起我话事”,都听我的安排,给我上税(如上图)。
如果是一个允许讲道理(民主自由)的政权,基本内部就不存在起义、反叛等事件,因为允许公开有礼有节的抗辩,自然会遵循所谓市场规律,自由发展。勤快的懂得钻营的人就会获得超过平均数的收入和财富,于是有资本利得的助力,人群有贫富分化,踩着马太效应进而形成垄断,而垄断是经济危机的伏笔。

于是,政府要警惕垄断,预防经济危机,当经济危机发生时,国库可能会亏空。为避免这种情况,政府要避免经济危机发生,也就是避免垄断,也就是避免过分的贫富差距极大化。当经济危机不可避免的发生时,需要采取一切可能的手段来救助经济。如果成功了,皆大欢喜,如果不能,在野党就会翻盘上台,政府被和平更替。还有一种情况比较危险是,隔壁老王的邻国这时候趁火打劫来入侵处于经济危机时候的国家。

相反地,如果一个政权(政府)是不允许讲道理(独裁专制)的,内部起义、反叛就不可避免了。内部干架的区别主要是大的反抗和小的反抗,镇压了的反叛和镇压不了的反叛。从设立开始话事的时候起,反对派就一直在积蓄力量,政府主要收入来源的税基就像一个有蚁穴的大坝一样,潜移默化的逐渐减少。此消彼长,纳税的减少,而吃税(吃财政)的人却是反方向逐年月的增长,国库从一开始有盈余到平衡,到不可逆转的出现亏空。

反对派无法通过讲道理来实现诉求,只好战场上刀把子说话,不可避免的,持续动荡,帝国疲于应付,财政日趋紧张。周遭环伺的隔壁老王的邻国这时候也会插上一杠子,一般会正面敲竹杠,或者正面敲竹杠叠加或明或暗地支持反对派的叛军。兴盛一时的帝国无可奈何地走向了内忧外患的地步,无论是攘外必先安内,还是颠倒过来,一个锅里吃饭,就那么多米,区别不大。

晚清政府既要努力镇压西北陕甘新疆西藏穆斯林的反叛,还要对付海上来袭的日本和欧洲列强,不是不能打,实在是没钱了,生生打没钱的。据说晚清政府军队组织从中原地带运送粮草往大西北打仗,起运30担粮食,终到1担粮食,其余29担粮食在来回途中被吃掉了。从这个角度理解,国民政府时候,蒋介石面临似乎也有类似的局面。

在这个不讲道理的政府来看,无非是镇压了上一个反叛军,然后迎接下一个反叛军。在这个无休止的循环中,如果某一次反叛军胜利了,政府就彻底完蛋,另一个新政府就此设立。
如果他还是一个不讲道理的政府,就再次开启那个反抗-镇压模式的无休止地狱模式。
如果他良心发现,转为允许讲道理的政府,那就进入与经济危机做斗争的娱乐模式。

隔壁老王式的邻国是一个烦人的存在。由于国与国之间没有所谓正义,只有所谓利益,而且是无羞耻、无底线的地盘之争,所以,一旦一个政府被刺探到其国库亏空,就想一个普通百姓家庭一样,如果穷的揭不开锅,那受人欺负几乎是必然的。如果这时候有被大户财阀看得上的东西,无论是人还是财物,往往都会被使用各种手段被掠走。

家庭如此,政府国家亦然。百姓穷居闹市无人问,国家也是弱国无外交。
治大国若过小家,手中有粮,心中不慌。这背后都是经济活动,起支配作用的是经济规律。

发表在 社会生活 | 标签为 , , , | 12条评论

好奇婴幼儿中国国民党革委会中国国民党Apache Softwares

GWA2吉娃兔🐇Java中的文件上傳表單處理若干問題

在 GWA2Java 中處理文件上傳的HTML表單被稱爲是“客貨混裝”的HTTP請求處理。

文件上傳處理是HTTP Web開發中較爲特殊的應用,對開發者有一定的要求。無論是流行的PHP,Aspx或者JSP都需要一定的處理技巧。由於實在想不起來10多年前是如何赤手純代碼來處理客貨混裝的HTML文件上傳表單,這次還是詳細地記錄一次,以備再過些時日忘卻了而備查。

還有一層考慮是,在處理HTML的文件上傳表單時,需要考慮與 GWA2Java的融合,涉及到GWA2 的文件處理的核心模塊,因此也需要或者也是檢視GWA2架構設計的一次極好的機會。
對此前的 GWA2 Java項目的巡視,我們發現已經有一些項目涉及到文件上傳,但基本上多數是使用Ajax異步上次等,回避了“客貨混裝”模式,某個HTML表單只負責文件上傳,而另外一個表單再收集其他數據。

所以,這次要在 GWA2Java 中更好的整合進文件上傳,并且是客貨混裝模式——處理一個表單,裏面同時包括兩個字段:張三的姓名文字和張三的頭像圖片。

1. 瀏覽器客戶端 HTML表單中enctype

如果需要在瀏覽器客戶端的HTML表單中進行文件上傳,需要明確顯式地指定 Form元素的 enctype 屬性為 multipart/form-data 。

2. 服務器端接收處理文件上傳的第三方組件

基於 Apache Tomcat的 Java Web Server,進行服務器端的文件上傳處理,推薦使用的組件是 Apache commons-fileupload-1.4.jar , 一并的也要引入 Apache commons-io-2.7.jar。

3. HTTP Request.getParameter 失效

儅客戶端使用文件上傳的表單遞交數據時,Java Web Server中常規的 Servlet 對象 HTTPRequest的主要方法 request.getParameter 就失效。這也是普通程序無法處理客貨混裝的原因之一。

取而代之的,儅 enctype=multipart/form-data , 需要通過第三方組件獲取到相應的表單參數。
在 GWA2 中,其中的路由模塊嚴重依賴HTTP Request的參數,這時候,需要將主要路由參數放入Form的Action屬性中。
可以改進的另外一個方法是,通過引入 Apache commons-fileupload 的相關對象,便利 FormItems 對象,從而獲得表單中的常規非文件字段,文本文件字段的名稱和值。

遍歷FormItems獲得HTTP Request請求參數之後,再通過 request.setAttribute寫回到當前Request對象,如此即可巧妙地彌補 request.getParameter 失效的問題。
由於在 GWA2Java 中,獲取外部參數通常由 Wht.get 的方法進行,這個方法除了調用 request.getParameter 之外,還會進一步地的訪問 request.getAttribute , 從而實現了對 request.setAttribute 的訪問。再進一步地的 Wht.get 還會對訪問數據做一些基本的安全檢查。

樣例代碼:

ServletFileUpload sfileupld = new ServletFileUpload((new DiskFileItemFactory()));
formItems = sfileupld.parseRequest(request); // can only be parsed once!
if (formItems != null && formItems.size() > 0){
String iname, ivalue; byte[] bytes;
for (FileItem item : formItems){
// processes only fields that are common form fields
if (item.isFormField()){
bytes = item.getFieldName().getBytes(“ISO-8859-1”); // why 8859?
iname = new String(bytes, “UTF-8”);
bytes = item.getString().getBytes(“ISO-8859-1”);
ivalue = new String(bytes, “UTF-8”);
request.setAttribute(iname, ivalue);
//debug(“ctrl/item: iname:”+iname+”, ivalue:”+ivalue);
}
}
}

 

4. HTML表單上傳request 能且僅能被parse一次

上文中提到的獲取 FormItems 需要從 HTTP Request中提取,

List<FormItem> formItems = uploadInstance.parseRequest(request);

這裏的Request,只能被 parseRequest 執行一次,如果在同一次請求處理程序中,再次對這個 request 執行 parseRequest 時,就會返回異常為空的錯誤。
因此,儅我們需要在程序頂部通過便利 FormItems 設置 request.setAttribute 時,還需要保留 FormItems 作爲全局對象,在後面這裏處理實際上傳文件時使用,避免再次調用 parseRequest 產生爲空的錯誤異常。

5. 揮之不去的字符轉碼: 從 ISO-8859-1 到 UTF-8

從心裏上,我們是抗拒在代碼中進行字符集轉碼的,所以從一開始,我們在 GWA2Java 中進行了前後端統一全流程一貫地使用UTF-8字符集,從而避免在系統程序内做無謂的轉碼工作。(參考:-GWA2 Java版本的i18n/中文编码/乱码问题,https://ufqi.com/blog/gwa2-java-i18n/

偏偏這裏儅使用客貨混裝模式進行文件上傳時,通過parseRequest出來的 FormItem 其中的非ASCII字符的編碼是 ISO-8859-1 ,對於像 GWA2Java 這樣默認的 UTF-8 環境,字符集轉碼成爲迫不得已的事情。

6. 文件上傳處理方法的歸置

在 GWA2 的架構設計中,文件上傳功能,歸屬于文件模塊,引入系統的接口文件是 inc/FileA , 針對不同的文件系統,有不同的文件類來實現 inc/FileDirver , 如 默認的文件處理是 Linux 的 inc/FileSystem .

在歸屬上,這些 inc 目錄下的類及其方法是“大家閨秀”,一般不參與到具體業務處理程序的,只能通過統一界面接口 inc/WebApp 來調用。因此理想的是調用文件上傳的邏輯流程大致為:

ctrl/a.jsp –> mod/ModA –> inc/WebApp –> inc/FileA –> inc/FileSystem .

由於文件上傳,屬於非常規的“操作”需求,另外一種非標準的捷徑是,在 mod/ModA 中直接實例化 inc/FileSystem , 從而便利地觸發對 upload 方法的運用。但這只針對具體的項目可行,且不需要可移植性。比如如果宿主系統不是 Linux, 那就不能實例化 inc/FileSystem , 相應地可能需要實例化 inc/WindowsFileSystem 來處理宿主環境是 Windows 的文件上傳。

7. 有進有出,文件刪除的操作

在此之前,核心接口類 inc/WebApp 中定義了 readObject/writeObject 用來讀寫非數據庫源的數據。其中 inc/FileA 中相應地定義了 read/write 方法,只是還沒有對應的刪除方法 rm 的實現。

接著這個機會,我們歸置並實現了 inc/FileA, inc/FileDriver 和 inc/FileSystem 三個類的 rm 方法,同時改造 inc/WebApp.rmBy 方法,將上述方法進行對接。

inc/WebApp.rmBy(“file:Path_To_File”) –> inc/FileA.rm –> inc/FileSystem.rm .

 GWA2Java, GWA2 就是這樣通過一個又一個項目實踐,不斷豐富完善,日益健壯强大,儅融合和沉澱足夠多的智慧和精華,一定能取得更大的成就。我們在 UfqiWork 有福工坊 ( https://ufqi.com/work/ )上首先實現了 GWA2Java 處理文件上傳的客貨混裝模式。


-GWA2 吉娃兔 是”通用网络应用架构( General Web Application Architeture, https://ufqi.com/dev/gwa2/ )”,基于 -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, online medical services, online teaching, 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
轻松启动, 快速产出.


ufqiwork-logo

有福工坊UfqiWork 是一个在线服务交易平台。( https://ufqi.com/work/ )
有福工坊提供在线分类服务信息,致力于在线撮合服务交易的买方和卖方,并为买方、卖方提供“行准”服务,居间担保服务交易。行准服务的提供方为居间交易的第三方。有福工坊的服务交易平台为整个服务交易流程的第四方。

-R/32ST

https://ufqi.com/blog/gwa2-java-file-upload-issues/

发表在 -GWA2, -Hanjst/-汉吉斯特, 服务器运维, 编程技术, 计算机技术 | 标签为 , , , , | 一条评论

愛自己悅己容汽車老司機車載汽車老司機好奇婴幼儿

A practical analysis on $hadow$ocks

Things are getting worse even for an ordinary computer programmer to bypass the Internet walls in some countries or districts. There are quite a lot of techniques involved in making a working solution to get through the walls safely to smoothly.

Knowledge on TCP/IP is an entry for this exam. Deep understanding of the walls is an essential point and other requirements are data communications, data security, network security and data encryption.

Besides those above, programmers are also being asked what application is being deployed over the wall. The most-deployed application is HTTP, and therefore they need to understand more than usual on its protocols. Multiple operating systems and programming languages could help programmers easily get things done.

What’s more, for both sides, the battles of blocking and anti-blocking are always continually being evolved  and they just look like spear vs. shield. One working technique may fail tomorrow if it has been acquired by another side. 

Here is a workflow based on what we have learnt from $hadow$ocks, one of the most-starred repositories on GitHub.

Work flow:

–> packets plain sent (1)
–> $hadow$ocks-windows-client(2) –> obfs-local(3)
–> packets wrapped over Internet
–> obfs-server(4) –> $hadow$ocks-libev-server(5)
–> packets REQUEST & RESPONSE (6)
–> $hadow$ocks-libev-server(7) –> obfs-server(8)
–> packets wrapped over Internet
–> obfs-local(9) –> $hadow$ocks-windows-client(10)
–> packets plain recv (11)


https://ufqi.com/blog/analysis-on-hadowocks-202008/

-R/A2SP

发表在 服务器运维, 编程技术, 计算机技术 | 标签为 , , | 一条评论

愛自己悅己容2nd愛自己悅己容汽車老司機車載汽車老司機

GWA2吉娃兔🐇升級基於事件驅動的緩存處理模塊

時間過得飛快,距離上次升級改進GWA2吉娃兔🐇已經又三個月過去了。GWA2吉娃兔🐇升级模板引擎子系统( https://ufqi.com/blog/gwa2-updt-template-engine/ )。這期間,GWA2一直在進行細微改進升級,這次記錄的是改進較大的一個地方,對内置Built-in的緩存模塊進行了再次優化。其中的細節和思考值得分享,備忘於此。

GWA2吉娃兔🐇自相應體系創建以來,花了大量的時間和精力持續不斷地推進創建“更好的下一個版本”。關於緩存相關的改進,有記錄可以見于“GWA2-Java built-in cache with connection pool design/带连接池的缓存流程设计( https://ufqi.com/blog/gwa2-java-built-in-cache-with-pool-flowchat/ )”、“-GWA2 更新缓存调用built-in cache方法( https://ufqi.com/blog/gwa2-built-in-cache/ )”。



圖1. GWA2吉娃兔内置緩存機制

這些努力都是希望基於GWA2的應用系統跑得快些,再快些!待到進行到某種極緻的狀態時,往往面臨的是某種權衡和取捨。比如緩存功能,如果訪問速度更快,則預期的緩存時間越長,更新頻次越低。而對於某些改動,又需要立即更新,這就需要做出某種平衡和不同優先級的考慮。有些系統可以允許緩存一定時間再將改動提到到前端系統,有些系統則對實時性要求較高,不允許有片刻的緩存。

這樣總體考慮,大致是三種情況:1)全部用緩存,數據更新及時性次級考慮,2)全部不用緩存數據即時更新,系統效能次級考慮,3)部分查詢用緩存,平衡系統效能和數據及時性。
gMIS吉密斯 ( https://ufqi.com/dev/gmis/ ) 作爲 GWA2吉娃兔的一個應用實例,就是使用3)方式,部分查詢使用緩存,另外一部分完全不使用緩存,這樣在系統效能和數據及時性之間做tradeoff. 比如gMIS管理所訪問的當前數據表不使用緩存,數據及時性得到保證,而一些公共菜單、權限檢查等則使用了緩存,更新無法立即生效,需等待一個緩存失效的周期。

有沒有一種機制將這種實時性區分開來(第4種情況:全部使用緩存而又能保證數據的及時性, 既….又….?)?儅允許緩存時,使用默認的緩存機制,將數據緩存起來,以此來提升系統響應速度;儅需要實時性時,則立即進行相關數據的更新。經過一番探索,我們采用事件驅動機制,增加了對這些設想的工程實現。其大致思路時,儅用戶發起對系統的寫入、更新操作時,在更新系統對象狀態時,即刻觸發對緩存的更新,從而實現了按需更新想要緩存的目標,讓緩存數據與系統對象真實狀態保持高度一致性、同步性。這些改進包括如下兩個地方。

1. 改進頂級類 inc/WebApp,rmBy 方法的實現

改造之前,inc/WebApp.rmBy 的操作只支持針對數據庫接口的刪除操作。這次改進之後,inc/WebApp.rmBy 將支持形如 “cache:keyString” 的參數定義,儅接收到這樣的參數時,觸發對相應的緩存的刪除。

緩存刪除操作通過 inc/Cachea 接管后效用相應的緩存驅動,進而實現對緩存的刪除、更新操作。也即,通過改進 inc/WebApp.rmBy , 調用 inc/WebApp.writeObject , 通過寫入一個沒有緩存值的對象來發起對當前緩存的更新。這一流程中數據的流轉大致如下。

…. –> mod/ObjectInstance.setBy(execBy) –> inc/WebApp.rmBy
–> inc/WebApp.writeObject –> inc/Cachea.rm
–> inc/Memcached.rm –> …
圖2. GWA2 緩存刪除操作

相應地,不但可以在 inc/WebApp 中通過 rmBy(“cache:keyString”) 的形式調用針對緩存的清理,也可以在任何繼承或實現了 inc/WebApp 的類中調用該方法,實現對緩存的更精準的控制。比如通過圖2. 實現了對單條數據記錄字段級的更新時同步更新緩存的操作,如果針對一個具有多條數據集的操作,該如何同步進行緩存更新操作?

顯然地,需要在控制器中,顯示地調用 mod/ObjectInstance.rmBy(“cache:keyString”) 的方法來清空所涉及到的緩存對象。這是超出内置緩存的範疇,需要具體問題具體分析進行,尤其是每個cache的key不同時,如果有多條cache需求更新,還需要多次調用 rmBy(“cache:anotherKeyString”) .

2. 優化更新操作時觸發緩存操作

在此之前,按圖1.的標志,内置緩存只在數據對象讀取時發生作用,也即在 inc/WebApp.getBy/execBy 時生效,對於寫入、更新操作 inc/WebApp.setBy/execBy 時,無需調用相應的緩存功能模塊,因爲寫入數據無需進行緩存。

帶上開篇提到的問題,儅我們需要在寫入、更新操作時進行緩存更新時,采用事件驅動模式進行相應操作時,需要在寫入、更新操作 inc/WebApp.setBy/execBy 考慮一下緩存。只不過這時候考慮緩存,不是寫入緩存,而是也同步“更新緩存”。具體的改進包括如下兩項。

2.1. 改進 inc/WebApp.setBy

inc/WebApp.setBy 此前的方法中,支持第三個參數 HashMap args 形式,其主要功能是考慮需要寫入非數據庫時的需求。比如寫入緩存系統,寫入文件系統等,儅有這些發生時,需求被進一步地前傳給 inc/writeObject .

接著這個可擴展的機制,我們可以在寫入數據庫時,也通過 args 帶入需要更新的緩存keyString, 儅完成了相應的寫入數據庫的操作時,相應地發起對緩存的更新操作。其流程與圖2.描述相同。

2.2. 改進 inc/WebApp.execBy 

inc/WebApp.execBy 的情況稍微複雜一些。在目前的設計中,inc/WebApp.execBy 是為了滿足一些特定的SQL查詢語句,儅我們無法通過 getBy/setBy 實現目標SQL查詢時,execBy 就被排上用場。他甚至可以替代 getBy/setBy ( 在某些GWA2的新手,或者簡單應用中,開發者甚至只用這一種方法即可完成與數據庫的全部讀寫操作 ) ,因而需要考慮 execBy 的讀取和寫入兩種情況。

儅 execBy 執行讀取操作時,其第三個參數 HashMap args 本身就帶有 cache keyString 的參數,意在用於儅讀取成功時,通過這個cache keyString 將查詢結果緩存起來,下次再有類似查詢時,優先主動使用緩存數據。這也是 圖1. 我們的内置緩存的運行機制。

現在我們需要更多地考慮一層,儅 execBy 執行寫入、更新操作時,儅完成相應的操作后,需要進一步地考察 args 中的 cache keyString 參數,如果給定了相應的cache keyString,則我們認爲這是需要同步觸發更新緩存的操作,於是就進一步地呼叫 inc/WebApp.rm(“cache:keyString”) , 同步完成對緩存的更新。

只是,這裏如果是通過 execBy 發起對非數據庫的操作呢? 比如,通過 execBy 發起對 緩存系統,文件系統的操作呢? 目前還沒有這方面的需求,不過的確是需要再考慮的事情。@todo .


-GWA2 吉娃兔 是”通用网络应用架构( General Web Application Architeture, https://ufqi.com/dev/gwa2/ )”,基于 -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, online medical services, online teaching, 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
轻松启动, 快速产出.


GWA2吉娃兔 基於事件驅動的緩存處理機制已經在 有福工坊UfqiWork ( https://ufqi.com/work/ )上得到部署應用。

ufqiwork-logo
有福工坊UfqiWork 是一个在线服务交易平台。
有福工坊提供在线分类服务信息,致力于在线撮合服务交易的买方和卖方,并为买方、卖方提供“行准”服务,居间担保服务交易。行准服务的提供方为居间交易的第三方。有福工坊的服务交易平台为整个服务交易流程的第四方。

-R/B2SU
https://ufqi.com/blog/gwa2-updt-build-in-cache/

发表在 -GWA2, 服务器运维, 编程技术, 计算机技术 | 标签为 , , , | 留下评论

中国国民党革委会中国国民党Apache Softwares亮月亮科技

Graph圖的相似性計算的極值問題

數據集的相似性計算,其應用十分廣汎,在現有的各類人工智能的底層算法中,大多數都是基於概率(可能性)的近似計算,然後取最大可能性的近似值。參考 理解计算:从根号2到AlphaGo ——第1季 从根号谈起 ( https://ufqi.com/news/ulongpage.191.html )。 另外使用神經網絡可以模擬任意曲綫函數,A visual proof that neural nets can compute any function ( http://neuralnetworksanddeeplearning.com/chap4.html ) 。
甚至,在早期的搜索引擎的計算中,如果計算兩個段落或者兩篇文章的相似性,也有使用基於圖的算法,將每篇文章視爲一個 graph,然後使用下面的圖的相似性的算法來計算兩者之間的相似性。

從一堆圖片中找到貓的照片是類似算法,車牌識別是這種算法,人臉識別、語音識別等都是類似的應用,神經網絡、深度學習等,莫不如是。人工智能AI之外,我們看到各種基於興趣的商品推薦,在綫廣告的智能匹配等等,都有這些算法的身影。
我們曾經開展過在綫廣告點擊率預測模型,其中運用到KNN算法,其核心就用到了 Euclidean Distance的計算 ( https://www.researchgate.net/publication/330742123_A_practical_study_on_imbalanced_data_re-sampling_for_conversion_rate_of_online_advertising ) 。

Neo4j 關於圖(Graph)的相似性計算(Similarity algorithm)提供了若干算法。
https://neo4j.com/docs/graph-data-science/current/alpha-algorithms/

這些算法都有詳細的解釋説明,樣例代碼等,這裏還有對幾種不同算法的對比分析(參考:余弦距离、欧氏距离和杰卡德相似性度量的对比分析 , https://www.jianshu.com/p/c4bbad87f873 )。 其中應用較多的是 餘弦距離和歐氏距離。

cosine similarity

Cosine Similarity/餘弦距離計算公式

euclidean

Euclidean Distance/歐氏距離計算公式

在 Neo4j 的文檔中,對餘弦距離和歐氏距離的應用場景都有差不多的描述:

我们可以使用欧几里德距离算法来计算两个事物之间的相似性。然后我们可以使用计算出的相似度作为推荐查询的一部分。例如,根据用户的偏好来获得电影推荐,这些用户所給出的评分与您看过的其他电影的评分相似。
We can use the Cosine Similarity algorithm to work out the similarity between two things. We might then use the computed similarity as part of a recommendation query. For example, to get movie recommendations based on the preferences of users who have given similar ratings to other movies that you’ve seen.

Neo4j是一個開源的NoSQL的原生圖數據庫。Neo4j is an open-source, NoSQL, native graph database that provides an ACID-compliant transactional backend for your applications.
圖數據庫存儲的數據單位是節點(Node)和關係(Relations)。
通常,圖用一組數據表示,如 g1(a0, a1, a2, a3, ….), g2(b0, b1, b2, b3, ….),極值情況下,如 g1(a0), g2(b0) 如何比較和計算相似性?這是本文試圖探討的要點。我們還結合研發中的 ufqiwork-logo有福工坊UfqiWork ( https://ufqi.com/work ) 的實際應用案例對所提議的算法進行了驗證,取得了預期的效果。

將極值比如 g1(10) 和 g(100) 進行計算時,幾乎每個算法都會返回極其不相似的結果值: -1 .

如果我們想進一步地探討, g1(10) 和 g2(100) 的不相似值, 與 g2(100) 和 g3(1000) 的不相似值,有多少程度上的不同呢? 顯然上面的算法在都返回不相似的極值 -1 時,兩者的不相似是一樣的,而真實情況真的是一樣嗎?如果不一樣,怎麽來描述這種不相似的差異?

簡單而直接的做法是考察兩個數值之間的減法差值或除法商值,差值或商值的大小決定了兩個數據的差異性,正比例關係。
比如,10~100的差值是90,商值是10, 100~1000的差值是900,商值是10.

如果我們要定義或者套用一下相似性,10~100的相似性用數值表達是多少? 100~1000的相似性用數值表達是多少?如果比較差值的話,後者的差別大於前者,如果比較商值的話,前者與後者相等。從語義上來解讀,顯然使用商值較符合預期,業績兩者的差異是10倍。

使用絕對商值10來描述相似性顯然不太合適,爲了便於表述為相似性,我們還需要對其進行歸一化處理。為方便描述兩個數值的商值,我們對商值取log10對數,這樣大幅降低絕對值的範圍並提供更大的曲綫表述空間,其絕對值的細微變化能夠映射到相應的對數值上。


對數log10(x)的坐標曲綫

嘗試進行歸一化(Normalization)處理時,需要設定區間閾值。如果兩個數相等,其商值為1,取對數log10(1)時, 得到值為 0,可以認爲儅兩個數的如上這麽計算過程之後值為0時,這兩個數的相似性是 100%。

那麽,多大是不相似呢?如果做歸一化或者百分比,我們需要確定、劃定一個“不相似值”的標準,無論是取商值,還是再對商值取對數,需要一個明確而具體的數值來表示或界定完全不相似。這個數值可能最終需要靠經驗獲得,也與要考察的數據可能的取值範圍有關,比如考察人的身高時,相差一倍就有種十萬八千裏的感覺;而考察星系,十萬八千里也可能只是一倍的表述。因此,這個用以界定“不相似”的閾值 k 應該是根據經驗和應用場景而定。

於是,我們就可以寫出我們用於求值某兩個任意數的相似性值,設若k為完全不相似,則某兩個數的相似性表述區間為 [0, k] , 針對這個取值範圍,再進行歸一化處理則相對容易。最終,我們擬寫了下面這個求取兩個任意數值的相似性的函數表達式:

F(n1, n2, k) = normalize{ min[k,  log10[ max(n1, n2)/min(n1, n2)] ] };

其中n1, n2為待求取相似性的兩個數值, k為經驗常數極值(表示完全不相似值)。
其計算過程可以描述爲:
1) 比較n1, n2的大小;
2) 求取n1, n2較大值除以較小值的商;
3) 對商值取log10對數;
4) 比較對數值與常熟k的大小,如果商值的對數值大於k,取k值;
5) 對前一步數值做歸一化處理,得到預期值在 [0, 1] 之間.

由此,我們獲知,儅兩個數的商值一樣時,其相似性是一樣的。因此10~100 和 100~1000的相似性是一樣的。對商值做進一步的處理是爲了表述和運算方便。類似的算法我們在 ufqiwork-logo有福工坊UfqiWork ( https://ufqi.com/work ) 進行試用,取得了一定的預期效果。

圖的極值問題只是相似性問題中的特例,同時這些所謂的極值也是相對的,儅g1(a1), g2(a2), g3(a3)…. 等多個極值組合為一個大的圖G(a1, a2, a3….)時,其與另外一個大G(b1, b2, b3…)相比較計算相似性時,又回歸到到文檔看到提到的數據集相似性問題計算了。

 


ufqiwork-logo
UfqiWork 有福工坊 服務交易所

有福工坊UfqiWork 是一个在线服务交易平台。
有福工坊提供在线分类服务信息,致力于在线撮合服务交易的买方和卖方,并为买方、卖方提供“行准”服务,居间担保服务交易。行准服务的提供方为居间交易的第三方。有福工坊的服务交易平台为整个服务交易流程的第四方。

线上签约,线下交割。有福工坊整合服务交易的 信息流和 资金流,在线承载买卖双方的需求供给信息匹配、交易撮合,在线承担交易双方的资金拨付、担保。服务交易的 标的物在线下实施、交割。

有福工坊服务交易平台服务于提供居间交易的“行准”,通过行准服务于服务交易的买卖双方。交易标的物与其他电子商务交易不同的是其非标准性,如房屋、工作/职业、家政/维保、汽车、医疗、教育、金融、出行、时尚等等。相应地行准为房产中介,猎头中介,商品导购、推荐、带货等。
所不同于现有分类市场的地方在于:站在买方立场代表买方利益的居间服务;买方有定价权,居间服务报价。相应地,卖方也可以使用定价权雇佣代表卖方立场和利益的居间服务。

有福工坊UfqiWork 圖標中 “有” 的紅色高亮部分,既像是“房屋”(住房),也像是“凳子”(工作),寓意 有福工坊UfqiWork 致力於為用戶提供住房、工作、家政等各類信息匹配及撮合交易服務。

发表在 计算机技术 | 标签为 , , , , , | 2条评论

愛自己悅己容2nd愛自己悅己容汽車老司機車載汽車老司機

GTAjax升級:一劍🗡磨十年改進JavaScript表單遞交瀏覽器異常等

2020年7月以來,持續對 UfqiLong 有福常在 進行升級改進。
改進過程中遇到之前不曾見的問題,在使用 GTAjax進行異步遞交 有福常在UfqiLog 的文章内容時,有隨機性地出現遞交失敗。進一步的跟蹤發現,儅點擊遞交后,GTAjax接管了表單遞交動作並觸發了進度顯示並進行讀秒操作。

但是,詭異的是,GTAjax在後臺並未真的將遞交發送給服務器端後臺。於是我們決定對 GTAjax開啓 debug 模式,進行深入分析,爲何之前不曾有這樣的問題,爲何問題會是隨機性出現,而又爲何,儅第一次遞交失敗后,第二次原樣操作,卻能成功?

帶著這些問題,我們準備深入分析一下。開啓 GTAjax的debug模式相對簡單,在 運行時參數裏:

var myGTAjax = new GTAjax();
myGTAjax.set(‘isdebug’, true);

這樣即可打開 GTAjax 的過程數據輸出,從而觀測到整個通訊過程。通過分析debug日志,問題很快鎖定到 postForm.submit() 這個節點上。
也即,在使用 ForceFrame 模式進行表單遞交時,依賴 JavaScript的 HTMLFormElement.submit() 這個方法進行最終的數據遞交。

這個是 W3C、HTML DOM和 JavaScript等標準組織封裝好的方法,無法進一步地往下拆解。問題就轉化為爲何 submit() 遞交失敗呢?通過進一步地分析,我們發現在 GTAjax 接管真正的 HTML Form表單時,通常會通過 _DFM_F 方法將 onsubmit 返回一個 false,從而阻止正常的遞交,然後GTAjax 再開展一系列的準備動作之後,再遞交 postForm.submit() 進行遞交。

詭異的地方在於,Google Chrome、MS Edge等瀏覽器,之前即便對HTML Form設置了 _DFM_F, 調用 postForm.submit() 時並不會受影響,而且儅 GTAjax 通過 _RGT 方法進行初始化設置之後再次調用 _DFM_F ,然後再次 postForm.submit() 時,卻是可以通行過去,如預期地進行與服務器端的通信。

我們推測,可能是近期的Google Chrome和MS Edge瀏覽器的升級,增加了對HTML Form遞交前的JavaScript等狀態檢查,所以如果發現某個Form的onsubmit 綁定了 return false的動作,就自動終止當前的操作;相反,則繼續如常。 

定位到問題,並經過粗略的原因分析之後,解決問題的辦法也就隨之而來。如果當前被執行的HTML Form被設置了 onsubmit 的檢查,則需要對已經設置的 onsubmit 進行重寫,使之能夠覆蓋之前的設置,尤其是之前 return false 的設置,以使得後續的Form遞交操作能夠順利進行。 改進主要集中在 _SUB 這個内部調用的子函數上。

在執行postForm.submit() 之前,對當前 postForm的onsubmit 進行檢查。

//postForm.submit(); // maybe fail due to this._DFM_F . 10:42 2020-07-04
if(postForm.onsubmit == null){
    postForm.submit();
    GTAj._DBG(GTAj.vA[‘ib’], ‘this._SUB’, ‘Sync form:        [‘+postForm.name+’] is being submitted.’);
}
else{
    GTAj.currentPostFormId = postForm.name!=” ?     postForm.name : postForm.id;
    postForm.onsubmit = (function(){
        var myTimerId = window.setTimeout(function(formId){
    document.getElementById(GTAj.currentPostFormId).submit();
GTAj._DBG(GTAj.vA[‘ib’], ‘this._SUB’, ‘Async form:[‘+GTAj.currentPostFormId+’] is being submitted.’);
}, 10); //- 0.01 sec
return true;
})();
}

如果當前被執行的 postForm的onsubmit 沒有被設置過,則繼續使用之前的邏輯,直接執行 postForm.submit();

如果當前被執行的 postForm的onsubmit已經被設置過,則需要重寫onsubmit的綁定與賦值操作。經過多次實驗,我采取了JavaScript anonymous function的方式,重新對當前postForm的onsubmit進行賦值操作。初始我們將一個匿名函數賦值給當前的 postForm, 形如:

postForm.onsubmit = function(){ return true; }

在我們的實測過程中,這一匿名函數,在不同應用場景和不同的瀏覽器中,仍有一定的隨機性出現匿名函數不被執行的情況。為保全起見,我們進一步地改進這個匿名函數,不但定義了匿名函數同時隨後執行這個你們函數,將返回值賦給 postForm.onsubmit .

在匿名函數體外,我們還通過全局變量 GTAj,將當前被執行的postForm的相關信息帶入匿名函數内;在匿名函數體内,我們設定了一個隨後立即執行的新的匿名函數,這第二個内嵌的匿名函數將完成這個表單的真實遞交動作。執行的時序變成: …. 1)定義一個匿名函數A—- 2)在匿名函數A内定義另一個異步的匿名函數B—- 3)執行這個匿名函數A —- 4)將匿名函數A的返回值true賦值給 postForm.onsubmit —- 5)時間觸發執行匿名函數B —– 6)實際執行postForm.submit() 操作 —– 7)監測服務器返回值進度….

改進后,分別在 Google Chrome,MS Edge 和 Mozilla Firefox 多個瀏覽器的不同應用場景下實測,均取得預期效果,不再發生或者隨機性發生,遞交Form未被執行的情況,故障問題得到順利解決。完整程序源代碼可以在 GTAjax 主頁( https://ufqi.com/dev/gtajax/ )和 GitHub上查詢(wadelau/GTAjax)。

這可能是軟件更新史上間隔最長的一次更新,GTAjax的官網主頁記錄記錄的上次更新時間為 2011-07, 距今已經九年過去了。著實令整個軟件作者也感到時光飛逝,一方面感慨時間過得太快,同時也對 GTAjax 歷時十多年,還能夠堅强、頑强地服務于業務系統的旺盛生命力感到一陣驚喜。

這不就是那種“Best as Air(好到無形)”極好的案例嗎? 幾乎每個工作日打開的基於 gMIS 吉密斯系統,其中都有 GTAjax 工作的身影,而他總是能夠不負囑托,完成每一次基於 GTAjax 的HTTP請求。

實際上,2011年以來,GTAjax 也做過小幅的升級改進和Bug修復,根據軟件源代碼中的更新標記,至少有如下幾次。

gtajax logo

* GTAjax.js
* @abstract: General-Targeted Ajax
* @author: wadelau@hotmail.com,wadelau@gmail.com
* @since: 2006-2-17 14:04
* @code: 5.7 // a.bc , funcs added b+, errs updated c+
* @NOTICE: DO NOT USE THIS COMMERICALLY WITHOUT AUTHOR’S PAPER AUTHORIZATION
* @update: Tue Feb 1 20:47:03 GMT 2011 

* Wed Jan 26 17:31:33 GMT 2011
* Wed Jul 20 08:08:09 BST 2011
* Fri Mar 16 16:36:52 CST 2012
* 12:15 Friday, February 20, 2015
* Sun Jan 24 12:56:43 CST 2016
* Fri May 25 08:51:23 CST 2018, code format refine and cA.sort bugfix
* Wed Oct 31 21:57:26 CST 2018, +form Name validate
* 11:06 Friday, August 16, 2019, imprvs with form validate
* 11:55 2020-07-04, bugfix for submit fail with forceFrame.

GTAjax 初創于 2006年2月,距今已經有 15年的歷史了。對於日新月異的軟件及互聯網行業來説,這差不多是古董級的軟件了。然而,基於開放標準和成熟技術棧,15年后,GTAjax依然穩定運行和應用在各種Web軟件中,這不能不説是相當成功的案例。

可以設想和對比的是,在應用層軟件,有有多少能使用15年之久?不要說15年,基於私有類庫和標準而開發的軟件,可能5年、10年之後已經難以覓得蹤跡,GTAjax 伴隨 gMIS 吉密斯 等軟件能夠一直運行到現在,並繼續運行到下一個5年,10年,是一件值得慶賀的事情。

軟件的生命力或者生存周期有多久?需要多久? 摩爾定律說硬件計算速度每18個月翻倍,軟件是否也只能用18個月要改版、升級換掉,甚至是完全推導重建?

實際上,GTAjax 生存的越久,越有可能遇到“趕不上趟”的情況,畢竟技術的發展與進步,日新月異,每隔3-5年幾乎就是天翻地覆的改變。GTAjax能夠堅持其可用、好用、能用達15年之久,應該說算是某種“成功”。

幾乎同時期的很多軟件都已經銷聲匿跡了。也可以設想,如果不是使用的開放的HTML、CSS和JavaScript等標準,而是使用某一家公司的某項私有技術,其情況可能就完全無法預料,更誑論與時俱進、歷久彌新了。縱向地時間跨度看,要保護和珍視一個軟件,盡可能延遲其生命周期,保持旺盛生命力,唯一可取的方式就是使用開放的技術與標準,構建面嚮未來的軟件。

從這一方面來説,基於WEB的應用軟件已經完勝了基於某個公司或者平臺的“本地應用”。10年前,差不多是WEB軟件真大行其道的時候,以美國Apple公司的Appstore反其道而用之,强推基於其自有的平臺軟件(App),構築强大的軟件壁壘,同時引導、脅迫無數軟件開發者不斷的爲其開發軟件(App),短則數月,長則數十月,App的快速更迭,也意味著大量的新寫成的代碼,像曇花一現一般消失了。

當然,也有及其少數的本地應用App頑强地頻繁地更新升級穿越了10年以上的歲月時空,如游戲魔獸世界WoW,即時通信軟件騰訊QQ等。這其中也包括,Web軟件賴以運行的網絡瀏覽器,如MS IE,Mozilla Firefox,Google Chrome,Apple Safari,Opera等。

在人民網工作期間,儅其實我們用的基於WEB的内部辦公系統(OA)相當有些年份(5-6年?),當時覺得,爲何不升級采用新技術? 甚至是再一個5-6年之後(10多年前),這個OA系統依然在運行中。現在想來,這是一筆極大的財富,因爲軟件的本身的技術棧是公開的標準,沒有很快地被業界全部抛棄,所以企事業單位的投資,得以延用至今繼續發揮作用。

當然,也不是說公開、開發的技術標準就止步不前,相反,公開、開放、開源的技術也在不斷的改進升級,只是由於影響巨大,各方需要多輪磋商,考慮各種因素,相對於一家公司的一項技術,其進度必然是緩慢的,當然也是理性而鑒定的。

比如 GTAjax 在開發計劃中,就規劃了 GTAjax-6.x 版本,主要考慮外部因素如下:

* 12:15 Friday, February 20, 2015
* 6.x Bears
HTML 5
ECMAScript 5, 6
HTTP/2 and Event-driven,
highly-cached,
code style of high-performance and readability
* in mind

尤其是其中的 HTML5,JavaScript 6 和 HTTP2 這些是在業界公開討論多年的技術標準,日益成熟,在新應用部署時會加快采用。相信在不久的將來,GTAjax-6.x 就緒時,能夠充分利用這些新技術特徵,在兼容之前的前提下,繼續為互聯網社區做出新的貢獻,下一個 15年,30年,50年。

與之相關 GTAjax更新Blog有:1)gMIS吉密斯更新Workflow工作流、FileMgr文件柜及GTAjax等模块( https://ufqi.com/blog/gmis-workflow-filemgr-gtajax/ ),2)-gMIS, -GWA2, -GTAjax 一并更新 ( https://ufqi.com/blog/gmis-gwa2-gtajax-update/ )。

世界仍不平靜,新冠肺炎疫情仍在傳播,愿軟件開發者多開發些生命周期更長的軟件,為世界和平貢獻智慧和力量,不要讓軟件成爲快消品, 而是要讓軟件成爲耐用品、藝術品。

-R/M2SR
https://ufqi.com/blog/gtajax-updt-form-submit-202007

发表在 -GTAjax, 编程技术, 计算机技术 | 标签为 , , | 一条评论

Apache Softwares亮月亮科技OpenAI ChatGPTPdf Drive