愛鋒貝

 找回密碼
 立即注冊(cè)

只需一步,快速開始

扫一扫,极速登录

查看: 1545|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

筆記-1.0版本

[復(fù)制鏈接]

1386

主題

1450

帖子

5798

積分

Rank: 8Rank: 8

跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2023-4-16 23:41:01 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式

一鍵注冊(cè),加入手機(jī)圈

您需要 登錄 才可以下載或查看,沒有帳號(hào)?立即注冊(cè)   

x
關(guān)于本篇文章

第一次書寫時(shí)間:2017/12/19/9:08

第二次書寫時(shí)間:2017/12/19/14:07

第三次書寫時(shí)間:2017/12/19:20

第四次書寫時(shí)間:2017/12/19/22:55

第五次書寫時(shí)間:2017/12/20/10:31

第六次書寫時(shí)間:2017/12/21/8:32架構(gòu)設(shè)計(jì)

整體工程

概略圖:



頂部層:

( NETFLIX|OSS =>Spring Cloud )和 Spring Boot 以及 docker
NETFLIX|OSS =>Spring Cloud:

屬于aws那種以前的方式,Spring Cloud很大一部分都是基于NETFLIX |OSS,對(duì)于java開發(fā)者并且不在aws上部署服務(wù)來說可以幾乎等同于Spring Cloud,以下也是基于Spring Cloud來講述的

隨著項(xiàng)目工程的越來越龐大、開發(fā)語言的差異漸大、業(yè)務(wù)閉環(huán)組合敏捷開發(fā)帶來的指引,我們進(jìn)入了多系統(tǒng)多部署[分布式]的時(shí)期,一個(gè)組合業(yè)務(wù)的系統(tǒng)劃分成多個(gè)單獨(dú)業(yè)務(wù)的系統(tǒng)并且每一個(gè)業(yè)務(wù)都可以通過部署在多臺(tái)服務(wù)器來大大增加或者增強(qiáng)后臺(tái)的響應(yīng)速度、并發(fā)量、業(yè)務(wù)回環(huán)速度、系統(tǒng)穩(wěn)定性等等。

同時(shí)這些一些問題必須急切的被解決: 服務(wù)注冊(cè)及發(fā)現(xiàn)、負(fù)載均衡、調(diào)用鏈容錯(cuò)、統(tǒng)一路由、配置及依賴管理、多語言并存而統(tǒng)一調(diào)用聲明、可視化運(yùn)行狀態(tài)監(jiān)控。

服務(wù)注冊(cè)及發(fā)現(xiàn):運(yùn)行在多臺(tái)服務(wù)器上的同一個(gè)業(yè)務(wù)各自的所在ip不同,對(duì)于調(diào)用者或者說是服務(wù)消費(fèi)者來說服務(wù)提供者是透明的,''我''需要引用特定而不需要明確指定具體調(diào)用的的提供者的最終ip,因?yàn)楹苡锌赡茉谀承┣闆r下,那臺(tái)服務(wù)提供者因?yàn)橐恍┰蛸Y源占用率過高而無法服務(wù),因?yàn)闆]有哪種實(shí)現(xiàn)思路可以明確知道前臺(tái)業(yè)務(wù)上使用者的資源消耗是多少,也有可能是某一臺(tái)服務(wù)提供者的所在真實(shí)物理機(jī)器宕機(jī)了,此時(shí)如果是依賴的具體Ip就會(huì)導(dǎo)致無法獲取服務(wù),或許會(huì)說,就算這臺(tái)服務(wù)器掛了,我換一臺(tái)不就行了?確實(shí)是可以的,但是你如何得到下一個(gè)屬于可用狀態(tài)且不會(huì)再并發(fā)嚴(yán)重情況下獲取可用物理ip地址呢?此時(shí)就會(huì)先需要一個(gè)數(shù)據(jù)庫來記錄、修改、刪除、查詢這些可用的屬于你所依賴服務(wù)的服務(wù)器ip,Eureka Server 就是這么做的,一個(gè)較為完整的流程是:當(dāng)服務(wù)提供者開啟的時(shí)候?qū)⒆陨韎p和所屬業(yè)務(wù)提交給eureka server,eureka server會(huì)將當(dāng)前節(jié)點(diǎn)添加到它的內(nèi)置數(shù)據(jù)庫中,而且很完善的是eureka server會(huì)自動(dòng)定時(shí)的去監(jiān)測注冊(cè)到它上面的服務(wù)提供者,同時(shí)也是需要服務(wù)器提供者配合,通過內(nèi)部心跳機(jī)制向eureka server證明自己還活著,否則在超過一定時(shí)間后,eureka server就會(huì)將這臺(tái)服務(wù)器提供者從數(shù)據(jù)庫中移除,移除之后,其他消費(fèi)者就不能引用到它了,通過這樣的機(jī)制,服務(wù)提供者對(duì)于服務(wù)消費(fèi)者來說是高可用的,任何一臺(tái)服務(wù)提供者下線之后對(duì)整個(gè)服務(wù)提供者是無影響的,消費(fèi)者是無感知的,但是會(huì)提高負(fù)載。但是也是有一個(gè)問題,eureka server此時(shí)就成了瓶頸了,eureka server能否工作以及是否流暢影響著整個(gè)系統(tǒng)的可用以及性能,對(duì)于一個(gè)系統(tǒng)來說維持這樣一個(gè)其實(shí)還屬于可容范圍,但是如果宕機(jī)了就不能了所以其實(shí)eureka server有備份節(jié)點(diǎn)的,當(dāng)其他節(jié)點(diǎn)發(fā)現(xiàn)當(dāng)前工作節(jié)點(diǎn)已經(jīng)無響應(yīng)了,就會(huì)取代原節(jié)點(diǎn)繼續(xù)工作,這里用分布式系統(tǒng)的組件來描述就是zookeeper分布式協(xié)調(diào)組件 和 redis 哨兵機(jī)制

負(fù)載均衡:一個(gè)系統(tǒng)能否流暢工作一個(gè)是取決于系統(tǒng)本身是否能容下業(yè)務(wù)所需資源,另一個(gè)是資源是否能分配合理,過多的資源壓力會(huì)導(dǎo)致機(jī)器過早疲憊甚至宕機(jī),當(dāng)有機(jī)器無法負(fù)載而無法提供服務(wù)時(shí),整個(gè)服務(wù)就會(huì)的平均負(fù)載就會(huì)提高導(dǎo)致滾雪球版崩潰,或許有人會(huì)說,有幾臺(tái)機(jī)器宕機(jī)了,我就再加幾臺(tái)機(jī)器不就行了嗎?但是你要知道根本原因不解決好,再加進(jìn)來的服務(wù)器一樣會(huì)再次奔潰,然后原來的機(jī)器由于較少壓力導(dǎo)致一直處于空閑狀態(tài),微服務(wù)集群中看起來有5份效率正常輸入服務(wù)其實(shí)有可能是3:7  / 2的關(guān)系,而且頻繁上線下線機(jī)器會(huì)導(dǎo)致服務(wù)管理者的效率下降從而是整個(gè)集群過早崩潰,常用的負(fù)載有隨機(jī)分配RandomRule、輪詢獲取RoundRobinRule(默認(rèn))、試探性獲取RetryRule、權(quán)重分析WeightedResponseTimeRule等等,在不考慮自身消耗且確實(shí)有可用的情況下,試探性獲取是最有效果的實(shí)現(xiàn),但是其實(shí)獲取其他機(jī)器的負(fù)載情況是需要消耗性能的,尤其是在多次獲取無果的情況下是非常浪費(fèi)性能的,但是如果最終無果,那就該考慮實(shí)現(xiàn)自動(dòng)擴(kuò)容及自動(dòng)收縮了,也就是說在集群變動(dòng)情況較大情況下,是不太可取的,隨機(jī)分配在剛開始時(shí)是可用且消耗低的,但是隨著集群運(yùn)行量及負(fù)載量達(dá)到一定程度時(shí),隨機(jī)分配是萬萬不可取的,輪詢獲取,是消耗低較為中性的,但是考慮到最終客戶端的消耗可能大多不一樣,可能會(huì)導(dǎo)致在分配圈中總是分配某一臺(tái)或者某一些機(jī)器,此時(shí)就是不太好的,但是也可以通過非對(duì)距圈性關(guān)系來持續(xù)輪詢,那樣就不會(huì)導(dǎo)致持續(xù)磨損某一臺(tái)機(jī)器了,最后的權(quán)重分析是屬于統(tǒng)計(jì)的結(jié)果,server端每隔30秒統(tǒng)計(jì)一次給出權(quán)重,一個(gè)是多個(gè)業(yè)務(wù)情況下對(duì)server負(fù)載增加壓力而且當(dāng)某一個(gè)時(shí)間激增的情況下,可能激增的時(shí)間小于30S秒,此時(shí)這個(gè)算法就是難以切合實(shí)際的

調(diào)用鏈容錯(cuò):從一開始的切分業(yè)務(wù)到最終組合業(yè)務(wù)可能會(huì)形長大距離的多分化的線路[鏈路],當(dāng)某一個(gè)服務(wù)提供點(diǎn)出現(xiàn)問題并且依賴其服務(wù)的其他消費(fèi)者存在調(diào)用鏈時(shí),這條調(diào)用鏈就可能會(huì)造成失敗,并且是級(jí)聯(lián)失敗。我們以前的做法是拋出異常讓最終捕獲做出處理,但是呢?一個(gè)花費(fèi)了很大資源的操作因?yàn)橐恍┛赡懿皇呛苤匾冶仨毜牟僮鞫?,最后的結(jié)果為Null,其實(shí)有些操作我們可以實(shí)現(xiàn)一個(gè)后備數(shù)據(jù),有些操作即使沒有真實(shí)數(shù)據(jù)其實(shí)也是合理的,比如說我要買10個(gè)東西,結(jié)果第5個(gè)的時(shí)候出錯(cuò)了,不能購買,以往的做法是直接報(bào)錯(cuò),整條鏈路返回,但是也是資源消耗極重的,spring cloud 模式的判斷規(guī)則是5秒鐘內(nèi)失敗20次表示此節(jié)點(diǎn)可以進(jìn)入熔斷模式了,也稱為保護(hù)路模式。

統(tǒng)一路由:在一個(gè)十分龐大的分布式的業(yè)務(wù)系統(tǒng)中,其中對(duì)外暴露的功能是非常復(fù)雜以及繁瑣的,如果是每個(gè)子系統(tǒng)各有一套聲明規(guī)則,最終在組合成api文檔時(shí),這個(gè)文檔的調(diào)用者肯定內(nèi)心幾乎是崩潰的,一會(huì)是REST風(fēng)格,一會(huì)是帶參風(fēng)格,況且每一個(gè)系統(tǒng)的著重點(diǎn)不同,**微服務(wù)最大的特點(diǎn)是架構(gòu)再怎么變對(duì)整個(gè)系統(tǒng)來說都是無感知的**,在互聯(lián)網(wǎng)的時(shí)代,項(xiàng)目整體架構(gòu)風(fēng)格是不斷迭代的,就像樂高積木,在做好了這些基礎(chǔ)的方塊之后,后面組合的形狀取決于業(yè)務(wù)發(fā)展,也可以稱為業(yè)務(wù)驅(qū)動(dòng),典型代表為淘寶,使用路由的思想,由路由入口打開流量入口,對(duì)外來說整個(gè)項(xiàng)目完全像是一個(gè)系統(tǒng)一樣,接口文檔的風(fēng)格完全統(tǒng)一,對(duì)于不同業(yè)務(wù)系統(tǒng)的負(fù)載均衡策略也不同也是很容易實(shí)現(xiàn)的,對(duì)于像swagger這種項(xiàng)目動(dòng)態(tài)文檔肯定也是放在路由上的,對(duì)內(nèi)實(shí)現(xiàn)為zull根據(jù)負(fù)載均衡策略轉(zhuǎn)發(fā)請(qǐng)求到具體的實(shí)現(xiàn)者上.

配置及依賴管理:微服務(wù)雖說是各自系統(tǒng)維護(hù)各自功能,但是很多配置文件還是需要統(tǒng)一的,并且伴隨中整體系統(tǒng)的升級(jí),這樣的全局配置變量如果是各自固定日寫死的話,后面的改動(dòng)就那么容易了.畢竟一個(gè)幾十個(gè)系統(tǒng)能夠非常迅速的改動(dòng)同一個(gè)配置常量也是非常困難的,在eureka server中實(shí)現(xiàn)可以使用spring cloud configure,而在consul中是內(nèi)部已經(jīng)實(shí)現(xiàn)了,其實(shí)這樣的配置中心只不過是一個(gè)微型的k-v數(shù)據(jù)庫而已,當(dāng)項(xiàng)目子服務(wù)系統(tǒng)中配置了配置中心時(shí),在配置文件中引用變量會(huì)導(dǎo)致加載配置文件時(shí)動(dòng)態(tài)從配置中心拉去數(shù)據(jù)并填充.與maven的思想有點(diǎn)類似.依賴管理使用的是maven來做到的,其實(shí)spring cloud 的實(shí)現(xiàn)一般都是maven項(xiàng)目,同時(shí)spring cloud官方推薦的是spring boot的基礎(chǔ)項(xiàng)目構(gòu)造.maven可以理解為一個(gè)特殊的能為你的功能導(dǎo)入jar庫文件的軟件,這個(gè)軟件是apche下的一個(gè)優(yōu)秀項(xiàng)目,項(xiàng)目受到開發(fā)人員的贊賞至今.這些具體的jar庫文件會(huì)默認(rèn)在你本地的c:/用戶/用戶名/.m2/repository下,以導(dǎo)入org.springframework.boot包的spring-boot舉例,在repository下會(huì)有一個(gè)org的文件夾,其實(shí)就是以.分隔,每一個(gè)分隔的值都是一層目錄,這里為org/springframework/boot/spring-boot文件夾,在之之下為各種版本號(hào)名稱的文件夾,例如1.5.8.RELEASE/2.0.0.M3/...,在這之下為具體依賴的庫文件了,例如:spring-boot-1.5.8.RELEASE.jar/spring-boot-1.5.8.RELEASE.pom/spring-boot-1.5.8.RELEASE-sources.jar/...,在項(xiàng)目的pom.xml文件依賴庫文件的時(shí)候需要指定依賴的組織名和工程名和版本號(hào),版本號(hào)會(huì)和這里的文件夾的版本號(hào)名一致,默認(rèn)會(huì)導(dǎo)入運(yùn)行依賴jar而不是source源碼jar.同時(shí)在定義導(dǎo)入規(guī)則時(shí)可能不止3個(gè),可能會(huì)有依賴環(huán)境,例如編譯期compiler/測試期test/...,還有可能會(huì)到項(xiàng)目本地文件夾中依賴jar包,那么就需要使用systemPath標(biāo)簽填入${project.basedir}/lib/xxx名稱-版本號(hào).jar,這些jar庫文件一般都是來自于maven的外部庫,例如maven的中心庫或者是其他公司的私有庫,當(dāng)然我們也可以搭建私有庫,使用nexus搭建,一般在linux搭建服務(wù)的流程為下載文件,解壓,配置配置文件,加入系統(tǒng)自啟之類的環(huán)境變量文件中,使用給定的啟動(dòng)文件和參數(shù)啟動(dòng)服務(wù).至于nexus的水平擴(kuò)容,我暫時(shí)還沒有做過.

多語言并存而統(tǒng)一調(diào)用聲明:使用注解方式標(biāo)注網(wǎng)絡(luò)請(qǐng)求url來標(biāo)注當(dāng)前類為服務(wù)接口調(diào)用類,與以前使用的dubbo很相似,只不過dubbo是需要配置文件指明接口類對(duì)應(yīng)的url,沒有擴(kuò)容功能,開發(fā)也并非簡介,與spring boot的基于注解特點(diǎn)相違背,以前像這種都是將接口文件安裝到nexus中,服務(wù)調(diào)用者需要先依賴該接口文件然后配置再調(diào)用即可,由于是基于http網(wǎng)絡(luò)接口的,所以擁有跨語言的強(qiáng)大功能,調(diào)用遠(yuǎn)程服務(wù)就像調(diào)用本地功能一般,當(dāng)然也有一些屬于正常范圍的限制,比如說超時(shí)機(jī)制,比如說序列化效率低、效率不如dubbo/protocol buff/thrift.

在spring cloud中,這些問題的實(shí)現(xiàn)者為:服務(wù)注冊(cè)及發(fā)現(xiàn)(Eueka Server/Consul+Eureka Client)、負(fù)載均衡(Ribbon)、調(diào)用鏈容錯(cuò)(hystrix)、統(tǒng)一路由(Zuul)、配置及依賴管理(Configure Server)、多語言并存而統(tǒng)一調(diào)用聲明(Feign)、可視化運(yùn)行狀態(tài)監(jiān)控(Metrix)。

值得一提的幾個(gè)問題:

    1、微服務(wù)與單體架構(gòu)?最初項(xiàng)目由面向過程編程的c語言轉(zhuǎn)向面向?qū)ο蟮膉ava/c#編程,java以其一處編譯處處運(yùn)行,伴隨著世界上最主流的服務(wù)器系統(tǒng)linux打敗了其他語言,人們以為這是以后的趨勢了,其實(shí)不然其實(shí)這才是開始,java工程通常對(duì)應(yīng)小型企業(yè)來說是運(yùn)行在tomcat上,中間或者會(huì)使用nginx做代理服務(wù)器來達(dá)到水平擴(kuò)容,但是算一個(gè)數(shù)字,tomcat的并發(fā)量為300,不過新版本的tomcat的實(shí)現(xiàn)使用netty線程模型,可容并發(fā)量大大提升,但也是差不多,在通常情況下tomcat要實(shí)現(xiàn)業(yè)務(wù)的水平擴(kuò)容必須實(shí)現(xiàn)session 共享,眾所周知session 節(jié)點(diǎn)不能超過8臺(tái),否則此集群光是同步session所消耗的資源就已經(jīng)將所有帶寬都給占滿了.這時(shí)候前面的nginx反向代理服務(wù)器難道就可以了嗎?其實(shí)nginx并發(fā)量也是有限制的,畢竟nginx是無法反向代理的,理論上nginx的并發(fā)量為50000+,而實(shí)際并發(fā)量為30000+,一個(gè)系統(tǒng)難道十年前3W并發(fā)夠了,今天還是3W并發(fā)量就夠了嗎?每一年的并發(fā)量都在指數(shù)級(jí)的增長,所以**單體工程的容載量很難增長**, 而微服務(wù)架構(gòu)下的容載量就很容易提升了,以為服務(wù)之間的依賴是通過依賴服務(wù)實(shí)例名稱的,而對(duì)外接口是網(wǎng)關(guān)分配可用實(shí)例的,微服務(wù)下不會(huì)直接使用session,所以對(duì)外來說使用哪一個(gè)正在運(yùn)行中的實(shí)例都是沒有很多區(qū)別的,而對(duì)于像是登錄這種特殊操作,通常服務(wù)器都是會(huì)保存登錄的客戶端狀態(tài)的,對(duì)此,我們往往使用SSO(single sign on)或者oauth2.0協(xié)議下的uaa系統(tǒng).對(duì)于很早之前的互聯(lián)網(wǎng)時(shí)代,需求都是來自分析的積累,剛開始的的項(xiàng)目都是幾乎新生的,項(xiàng)目開始者需要面對(duì)于市場的風(fēng)險(xiǎn)、同類產(chǎn)品的競爭危機(jī)、工程技術(shù)的回避風(fēng)險(xiǎn),在反復(fù)推打過程中就最終確定了項(xiàng)目的原型了,由于當(dāng)時(shí)的IT項(xiàng)目的體驗(yàn)還是比較新鮮的,在新項(xiàng)目剛開始的一段時(shí)間,用戶也是出于摸索階段,項(xiàng)目的推廣使用也是非常緩慢的,系統(tǒng)的維護(hù)時(shí)間還是非常充足的,找一個(gè)深更半夜停了再發(fā)布也是無足緊要的,但是,現(xiàn)在就不太一樣了,用戶量的海量增長,需求的迅速開發(fā)發(fā)布,如果是按照以往的方式,可能需要每幾個(gè)小時(shí)整個(gè)系統(tǒng)都是需要重啟的,而對(duì)于越來越龐大的代碼量,越來越大的遺留問題,部署時(shí)間和開發(fā)時(shí)間越來越長,這樣的系統(tǒng)最終會(huì)倒下,甚至?xí)偸窃诿τ诮鉀Q以往問題而無法解決新問題的。很慶幸,如果你使用微服務(wù)架構(gòu),你的系統(tǒng)的功能架構(gòu)依舊不變,但是代碼會(huì)拆分成多個(gè)子系統(tǒng),子系統(tǒng)可以隨意水平擴(kuò)容,在有新需求的時(shí)候,如果是已有系統(tǒng)的功能增長,那么會(huì)在已有系統(tǒng)的基礎(chǔ)上繼續(xù)開發(fā)新功能,如果這個(gè)功能達(dá)到一定程度,這個(gè)時(shí)候子系統(tǒng)是可以繼續(xù)切分的,此時(shí)開發(fā)人員是可以由內(nèi)調(diào)或者外招的,各個(gè)系統(tǒng)的交互使用HTTP協(xié)議進(jìn)行通訊,無論是java/c#/go開發(fā)的系統(tǒng),整個(gè)系統(tǒng)都是高度兼容的.**單體架構(gòu)的push周期或者業(yè)務(wù)回環(huán)周期過長而由于微服務(wù)各部分是實(shí)現(xiàn)上的互不影響的,每次修改都是添加功能,不會(huì)影響其他模塊,所以可以調(diào)高效率** .

    2、微服務(wù)與分布式? 分布式是微服務(wù)的前生,分布式達(dá)到了一個(gè)大型項(xiàng)目的規(guī)模、兼容性和效率,但是其管理開發(fā)過程過于重量化,過于依賴運(yùn)維沒有統(tǒng)一實(shí)現(xiàn)、很多都是零零碎碎的拼接起來的,在服務(wù)注冊(cè)與發(fā)現(xiàn)中使用的是RPC框架,比如說Dubbo和Zookeeper注冊(cè)中心,在負(fù)載均衡上依賴Zookeeper或者nginx的實(shí)現(xiàn),對(duì)于開發(fā)人員來說可用功能過于簡單,在調(diào)用上過于依賴語言特點(diǎn),例如: Java服務(wù)如果使用Dubbo的話就只能被java服務(wù)調(diào)用,配置文件過于零碎,難以管理,因?yàn)榫退闶且蕾嚬芾硎褂昧薽aven以及私有庫,但是配置文件的部分值也是很難實(shí)現(xiàn)的,而且分布式一致性在分布式項(xiàng)目中的實(shí)現(xiàn)并非是直接實(shí)現(xiàn)的,而在微服務(wù)spring cloud中確實(shí)很容易實(shí)現(xiàn)的,常見的實(shí)現(xiàn)者為consul.RPC框架一般都是基于二進(jìn)制流(自定義序列化),所以在跨RPC框架的實(shí)現(xiàn)上也是比較難的,而微服務(wù)是基于HTTP協(xié)議的,兼容性更高,但是實(shí)際運(yùn)行效率是更低的.在功能的劃分上,分布式的粒度更大,因?yàn)樗侵亓考?jí)的,粒度過小對(duì)整個(gè)系統(tǒng)來說是災(zāi)難性的,而微服務(wù)粒度更小,因?yàn)楦髯苑?wù)是自治的并且有網(wǎng)關(guān)在流量入口把握.Spring Boot:

一個(gè)經(jīng)過整合過的輕量級(jí)的spring 框架,通篇項(xiàng)目中避免使用xml文件而是用注解來簡化項(xiàng)目,提高開發(fā)效率.基于spring 4.x實(shí)現(xiàn)了項(xiàng)目依賴動(dòng)態(tài)掃描達(dá)到動(dòng)態(tài)配置,項(xiàng)目可自帶運(yùn)行容器環(huán)境,經(jīng)過maven打包成jar包后可直接啟動(dòng),在實(shí)際項(xiàng)目中啟動(dòng)命令可為 nohup java -jar xxx.jar & ,同時(shí)基于spring boot的maven依賴文件一般為spring-boot-xxx-starter,spring boot官方已經(jīng)提供了很多starter依賴,例如:data-jpa/web/....同時(shí)非常適合作為spring cloud的 基礎(chǔ)架構(gòu),spring boot的web依賴默認(rèn)為spring mvc作為控制層處理框架,使用thymeleaf作為前端模板框架,同時(shí)效率比傳統(tǒng)servlet工程的jsp的效率要高,在使用上接近于jsp和freemearker的面向?qū)ο?同時(shí)擁有jsp/freemarker的邏輯控制功能,作為固定填充數(shù)據(jù)非常容易.在spring boot工程中通常由標(biāo)注了@SpringBootApplication的類的main啟動(dòng)加載整個(gè)項(xiàng)目,初始化spring 容器,生成被標(biāo)注了組件的類的bean,docker:

一個(gè)容器技術(shù),容器技術(shù)并非近些年的新技術(shù),而是很早之前已經(jīng)投入大規(guī)模實(shí)際生產(chǎn)的,早幾年前,有openstack等等商用容器化技術(shù),而作為新技術(shù)docker與openstack的區(qū)別在于docker使用了中心鏡像倉庫,使得很多原本安裝在linux的服務(wù)可以通過從中心鏡像倉庫pull下來后直接運(yùn)行而無需再次重復(fù)進(jìn)項(xiàng)常規(guī)的linux運(yùn)維操作,甚至在結(jié)合k8s或者swarm之后,可以迅速的大規(guī)模的水平擴(kuò)容,這在過去無容器技術(shù)時(shí)是想都想不到的.同時(shí)docker是基于linux宿主機(jī)的內(nèi)核的,是基于進(jìn)程的隔離,所以docker的啟動(dòng)時(shí)秒級(jí)別的,但是openstack呢?分鐘級(jí)別,openstack也有鏡像的概念,但是這個(gè)鏡像與docker聯(lián)合鏡像文件有些不一樣,docker的aufs可以基于鏡像分層,使得很多鏡像可以共享鏡像基礎(chǔ)層,與openstack不同的是運(yùn)行中的docker容器是基于覆蓋鏡像文件達(dá)到修改的操作的,所以不同容器的運(yùn)行狀態(tài)可以不同卻共享基礎(chǔ)鏡像文件.再看oepnstack的使用,繁瑣的配置文件,復(fù)雜的運(yùn)維,docker基于shell式的交互,提供了pull鏡像,運(yùn)行鏡像,停止容器,重啟容器,刪除容器,通過-v參數(shù)指定數(shù)據(jù)卷的掛載位置實(shí)現(xiàn)持續(xù)的使用.同時(shí)作為容器常用功能可以映射端口或者隨機(jī)ip到宿主機(jī)中,通常一般都是使用-P指定固定端口,docker輕量級(jí)、高效率、眾多免費(fèi)鏡像可用、支持大規(guī)模集群.同時(shí)docker的安裝也是非常簡單的幾乎不怎么需要修改配置文件,安裝時(shí)也只是一條yum指令就可以了,其實(shí)docker也是有一些不足之處的,比如說docker的安全性并不是特別高,集群間的網(wǎng)絡(luò)傳輸效率也不是很高,配置容器的一些環(huán)境變量時(shí)并非特別方便,記得很典型的一個(gè)問題,docker-mysql中,針對(duì)時(shí)區(qū)的配置,為何不默認(rèn)直接掛載宿主機(jī)的時(shí)區(qū)配置文件呢?中間層:

使用spring cloud 作為微服務(wù)實(shí)現(xiàn)框架,所以首先需要確定服務(wù)注冊(cè)中心服務(wù),對(duì)于spring cloud來說,實(shí)現(xiàn)可以為:consul或者eureka server,對(duì)于配置中心服務(wù)器,consul已經(jīng)內(nèi)置了,而eureka server需要另外搭配config server,對(duì)于這樣的注冊(cè)中心,默認(rèn)端口為8761,同時(shí)eureka server和consul不能共存.而在正式系統(tǒng)中,為了保持一致性以及系統(tǒng)功能簡化,使用gateway網(wǎng)關(guān)系統(tǒng),通常實(shí)現(xiàn)為zull,以前我也不理解為什么需要一個(gè)多余的網(wǎng)關(guān),但是后來才慢慢理解到,對(duì)于一個(gè)不斷復(fù)雜的微服務(wù)系統(tǒng),網(wǎng)關(guān)的作用是非常重要的,節(jié)點(diǎn)擴(kuò)充后,外部不能直接訪問固定的ip而是需要訪問一個(gè)代理去獲取所有可用的可用ip然后調(diào)用具體的ip的功能,獲取可用ip列表是eureka server 或者consul可以做到的,但是這兩個(gè)卻無法直接調(diào)用ip的功能,所以需要一個(gè)能夠調(diào)用轉(zhuǎn)發(fā)的功能,這就是zull的一個(gè)特點(diǎn),同時(shí)對(duì)于swagger這種動(dòng)態(tài)接口文檔,我們也是將其放到網(wǎng)關(guān)上的.簡而言之就是瀏覽器直接訪問gateway,gateway轉(zhuǎn)發(fā)到具體微服務(wù)系統(tǒng)上去指定調(diào)用功能.但是也是有一些問題的,并非所有的轉(zhuǎn)發(fā)都是有意義的,比如說有權(quán)限認(rèn)證的系統(tǒng),需要進(jìn)行訪問控制'Access Control',具體使用基于oauth2.0標(biāo)準(zhǔn)的uaa系統(tǒng),而這個(gè)系統(tǒng)需要使用用戶權(quán)限規(guī)則的聲明,另外一個(gè)問題就是對(duì)于一次調(diào)用的負(fù)載均衡也是在網(wǎng)關(guān)上做到,所以眾所周知zull的starter依賴中默認(rèn)都是有ribbon的.然后內(nèi)部子系統(tǒng)直接首先需要配置注冊(cè)中心所在ip位置然后直接依賴服務(wù)生產(chǎn)方的聲明的名稱在配置了ribbon的負(fù)載均衡之后會(huì)在每次消費(fèi)服務(wù)接口時(shí)進(jìn)行相應(yīng)規(guī)則的負(fù)載均衡.底部層:

著名的日志收集分析框架-->ELK,分別是ElasticSearch、Logstash、Kibana的簡稱.elasticsearch簡稱es,是一個(gè)分布式的擁有獨(dú)立部署能力、多線程等特點(diǎn)的搜索引擎,與Luccen的區(qū)別?Luccen是一個(gè)文檔搜索的開發(fā)包,并沒有部署能力,同時(shí)在一個(gè)項(xiàng)目中如果繼承了搜索功能,那是絕對(duì)不會(huì)將搜索功能內(nèi)嵌到項(xiàng)目中的,因?yàn)樗阉鞴δ艿呢?fù)載也是非常大的,同時(shí)文檔庫的聲明、持續(xù)使用、備份等操作與傳統(tǒng)項(xiàng)目是相背道的.與Solr的區(qū)別?Solr是一個(gè)搜索引擎,實(shí)現(xiàn)也是使用luccen,其擁有部署能力,但是Solr的部署能力也是非常有限制的,Solr天生并不支持集群,在我以往開發(fā)過程中雖然也是搭建了Solr集群,但是借助apache的另一個(gè)項(xiàng)目:Zookeeper,雖然最終可以實(shí)現(xiàn)分布式,但是依然是有很多問題,一個(gè)是搭建復(fù)雜,依賴運(yùn)維操作,一個(gè)是最終文件的一致性問題.而es不一樣,es天生支持分布式,在使用docker鏡像搭建es集群時(shí),強(qiáng)烈建議配置內(nèi)存大小至少分配4G以上,不過或許這也是solr的一個(gè)優(yōu)點(diǎn)吧,占用資源更少一點(diǎn).而logstash是日志的分析、kibana是將數(shù)據(jù)可視化了,使用了metrix技術(shù)技術(shù)總結(jié)

在實(shí)現(xiàn)具體子微服務(wù)系統(tǒng)中,使用以下技術(shù):spring boot

作為每個(gè)子系統(tǒng)工程的承載者,以基于注解簡化開發(fā)出名.基于spring 4.x,而spring 是現(xiàn)今java 網(wǎng)站開發(fā)的趨勢框架.由原來的重量級(jí)的EJB框架到現(xiàn)在無人不認(rèn)同的輕量級(jí)Spring框架.Spring并非強(qiáng)制規(guī)定了整個(gè)系統(tǒng)的開發(fā)流程,而是提供了輔助功能,在針對(duì)傳統(tǒng)網(wǎng)站的輸入->處理->輸出抽象成了MVC的架構(gòu)思想,控制數(shù)據(jù)輸入輸出->獲取數(shù)據(jù)->獨(dú)立界面層開發(fā),spring一直起著輔助整個(gè)作用,剛開始面對(duì)使用strux/strux2的使用者,spring 的整合是非常優(yōu)秀的,spring定義了項(xiàng)目的啟動(dòng),即必須先加載spring容器,在依賴的strux是會(huì)加載配置文件配置的action類,在依賴了hibernate時(shí)會(huì)加載配置文件中配置的dao類,等等諸如此類,spring提出了依賴注入(DI[Depency inject])的思想來做到松耦合的效果,然后上面的加載操作也就是new bean的操作,我們稱之為IOC控制反轉(zhuǎn),每一個(gè)模塊中只需要使用@Autowired之類的注解即可在調(diào)用階段獲取已經(jīng)實(shí)例化的bean,所以spring項(xiàng)目啟動(dòng)時(shí)十分漫長的.而且在開發(fā)階段使用tomcat的時(shí)候還很可能造成啟動(dòng)失敗的現(xiàn)象,那個(gè)時(shí)候需要將啟動(dòng)超時(shí)時(shí)間設(shè)置更長一點(diǎn)即可.spring boot默認(rèn)搭配的是maven,與傳統(tǒng)maven依賴不同的是spring boot的pom.xml中是肯定會(huì)依賴一個(gè)spring-boot-parent的parent的,而且就算當(dāng)前parent不是spring-boot-parent,但是肯定也是有一層的parent是指定parent為springBoot特定的parent,在我寫這篇文章的時(shí)候,springboot官方推薦的版本為1.5.9,但是更大一點(diǎn)的里程碑版本2.x也快出來了,而且2.x是基于spring5.x的,其中spring5.x是可以使用spring webflux的,對(duì)于喜歡使用異步框架寫網(wǎng)絡(luò)相關(guān)代碼是非常好的,畢竟reactor是非常好的.在涉及到異步線程模型的時(shí)候傳統(tǒng)方式是阻塞式的非常不利于實(shí)現(xiàn)實(shí)際運(yùn)行過程中由于延遲造成的一系列問題.springboot唯一的配置文件為application[-xxx].properties/yml,其中yml是基于對(duì)象屬性的書寫配置文件的一種新方式,在觀賞性和排列性上是非常高的,當(dāng)然書寫也是比較麻煩的,還好我使用的是idea工具,有配置提示功能.在標(biāo)注了@SpringBootApplication的類即為啟動(dòng)類,這個(gè)啟動(dòng)類起到加載springboot的作用,同時(shí)也可以配置通用參數(shù)或者bean,而取決了以往配置在配置xml文件的是@Configuration注解,在標(biāo)注了該注解的類中書寫標(biāo)注@Bean的方法返回特定的需要依賴的Bean對(duì)象,在這個(gè)方法里面一般都是自己手動(dòng)的new的.Spring boot web

通過這個(gè)starter從而可以獲取一系列的依賴,如spring mvc相關(guān),structs2的框架是幾年前項(xiàng)目的標(biāo)配了,而現(xiàn)在大部分項(xiàng)目都是使用spring mvc了,spring mvc使用@Controller規(guī)定了控制層的入口,類似的為@RestController(這個(gè)注解相當(dāng)于組合@ResponseBody,但是ResponseEntity對(duì)象也是不需要@ResponseBody也是可以返回實(shí)際數(shù)據(jù)的),同時(shí)通過@RequestMapping,或者@GetMapping或者PostMapping等等,標(biāo)注實(shí)際映射的url,這里有一個(gè)坑,以往的系統(tǒng)系統(tǒng)動(dòng)不動(dòng)就用特殊的請(qǐng)求參數(shù)來分別功能,這在實(shí)際使用中一個(gè)是不夠直觀,一個(gè)是是控制層平白無故多出代碼,另外一個(gè)偽靜態(tài)化操作,我們現(xiàn)在普遍使用的是REST風(fēng)格的url,在返回前端界面時(shí)使用返回String類型的數(shù)據(jù),并且保證標(biāo)注在類上的一定是@Controller而不是@RestController,該方法上一定沒有@ResponseBody注解,return 的數(shù)據(jù)為"[或有或無的文件夾名]模板名稱[或有或無的后綴]",當(dāng)然這是forward轉(zhuǎn)發(fā)請(qǐng)求的寫法,當(dāng)需要寫重定向的時(shí)候需要在前面加上"redirect:"字符串,其實(shí)默認(rèn)是"forward:",這是省略的寫法.在控制層上我們一般做獲取請(qǐng)求參數(shù),這些參數(shù)有點(diǎn)隱藏的rest里面,使用@PathVariable獲取,隱藏在parameter里面使用@Parameter獲取,隱藏在body里面,使用@RequestBody獲取,還有點(diǎn)可能隱藏在cookie里面,這些參數(shù)的數(shù)據(jù)都是需要控制層去獲取能封裝盡量封裝到對(duì)象里面.同時(shí)也對(duì)于可以直接校驗(yàn)的對(duì)象中的參數(shù)可以使用校驗(yàn)框架,在形參簽名標(biāo)注@Valid注解.在控制層一般都是注入業(yè)務(wù)層的接口,有些復(fù)雜操作通常需要組合多個(gè)業(yè)務(wù)的功能才能實(shí)現(xiàn),當(dāng)然這是非常司空見慣的,在一個(gè)系統(tǒng)中,通常不管如何,控制層的異常是絕對(duì)不能向上拋出的,這里涉及到向上傳參的方法,業(yè)務(wù)層如何向控制層傳遞參數(shù)呢?一個(gè)是返回值、一個(gè)是傳入引用值對(duì)象、一個(gè)是ThreadLocal對(duì)象,一個(gè)是向上拋出業(yè)務(wù)層及其下層的業(yè)務(wù)異常,我們通常規(guī)定好業(yè)務(wù)層出現(xiàn)異常通常都是向上拋出的,不做任何捕獲,直到控制層的捕獲,通常如果有異常的話最后向調(diào)用者表達(dá)出異常的詳細(xì)原因,此時(shí)一般會(huì)單獨(dú)寫一個(gè)枚舉類、寫一個(gè)常量類,當(dāng)然、如果項(xiàng)目文檔如果足夠強(qiáng)大,程序員足夠細(xì)心、開發(fā)周期非常短而沒有時(shí)間寫的話,一般我們都是會(huì)去寫的,這個(gè)常量類其實(shí)是一個(gè)接口類,因?yàn)楸緛韮H僅是只需要放置一些屬性就可以了,而接口類中默認(rèn)的訪問類型就是public,而且是static修飾的.最后有一個(gè)非常重要的概念:aop,面向切面編程,在spring boot中也是基于注解實(shí)現(xiàn)的,使用的是@Advice注解,組合@PointCut等注解Spring data jpa

在現(xiàn)如今的面向?qū)ο箝_發(fā)中,提起萬事萬物皆對(duì)象,在數(shù)據(jù)庫層開發(fā)中,通常會(huì)使用hibernate,而spring data jpa是hibernate的簡化升級(jí)版,其特點(diǎn)為標(biāo)注一個(gè)為@Repository,并且這個(gè)類需要實(shí)現(xiàn)JpaRepository<實(shí)體類型,主鍵類型>,這里的實(shí)體類在Jpa中也并發(fā)由于是hibernate就要是配置,我們使用@Entity注解標(biāo)注一個(gè)類為類與表映射,使用@Table映射數(shù)據(jù)庫服務(wù)器中實(shí)際表名,使用@Id標(biāo)注當(dāng)前字段為主鍵,同時(shí)對(duì)于可自增的字段使用@GenereteVlaue標(biāo)注,而在一些特殊操作,需要標(biāo)注當(dāng)前實(shí)體類為@DynamicUpdate或者@DynamicCreate,這在使用Timestampt類型的參數(shù)是比較好用,然后我也理解到timestampt是存儲(chǔ)庫,localDateTime是工具類,同時(shí)我的項(xiàng)目中使用了Lombok,這個(gè)框架可以使用注解為實(shí)體類生成getter和setter以及constructor方法.在項(xiàng)目初始開發(fā)階段推薦使用,同時(shí)這個(gè)需要配置ide,由于我的是idea所以配置還是比較簡單的,安裝插件即可,在實(shí)體類上加上@Data注解,對(duì)于空參構(gòu)造使用@NoArgsConstructor和@AllConstructor注解.對(duì)于實(shí)體類中屬性名和數(shù)據(jù)庫中表中列名不一致的問題,一般使用@Columne注解即可.一般主鍵的類型為String或者Long,Long的承載量更小,運(yùn)算速度更快,拓展性小,可自增,而String加上UUID這種全局唯一之后實(shí)現(xiàn)承載量更大,當(dāng)然對(duì)于Long可承載量來說其實(shí)也是很大的,其實(shí)一般項(xiàng)目使用Long其實(shí)也是可以的.Spring Data Jpa默認(rèn)已經(jīng)提供好了基于直接插入整個(gè)對(duì)象、修改指定id值的對(duì)象、刪除指定Id值的對(duì)象、查找所有對(duì)象、查找指定id值的對(duì)象,同時(shí)基于查詢提供了Pageable接口的傳入?yún)?shù),在業(yè)務(wù)層可自由組合size和page實(shí)現(xiàn)分頁操作,但是有一個(gè)bug就是分頁并非那么容易的時(shí)候spring data jpa定義的pageable就不是那么容易使用了,反而mysql的limit參數(shù)確實(shí)那么的好用,同時(shí)也可以指定sort規(guī)則,這些都是簡單的,更加復(fù)雜的在于根據(jù)指定條件查找/刪除/修改,然后有些查詢的優(yōu)化在于使用@Query注解實(shí)現(xiàn),一些自定義的修改規(guī)則在于使用@Update注解,總體來說spring data jpa的使用是非常簡單的.Spring data mybatis

mybatis作為以執(zhí)行效率為主要的框架,與spring data jpa不同的是,spring data mybatis是基于具體sql語句的.依賴于具體數(shù)據(jù)庫,多個(gè)系統(tǒng)之間的dao層代碼無法融合起來,在升級(jí)數(shù)據(jù)庫的時(shí)候整個(gè)系統(tǒng)會(huì)有短暫的疲憊期.同時(shí)也會(huì)出現(xiàn)由于切換數(shù)據(jù)庫導(dǎo)致的數(shù)據(jù)的兼容性問題,在大數(shù)據(jù)量遷移方面也是一個(gè)比較麻煩的問題.對(duì)于開發(fā)者來說,一部分掌握sql語言能非常流暢的優(yōu)化來自sql語句的執(zhí)行效率的人來說mybatis是極為好用的,但是另外一部分不那么流暢的人來說就為困難了,當(dāng)然也可以請(qǐng)專門的寫sql語言的dba來寫或者優(yōu)化sql語句.但是比spring data jpa這種對(duì)象關(guān)系映射的ORM框架不同的是,mybatis的操作多表的效率是非常高的.而jpa的多表會(huì)有執(zhí)行的冗雜性,同時(shí)jpa的優(yōu)化執(zhí)行語句是非常困難的.雖然jpa的@Query可以直接強(qiáng)制執(zhí)行對(duì)象SQL語句.spring data mybatis與直接使用mybatis不同的是,其使用起來也是以注解使用較多,雖然都是使用接口類,但是其盡量使用@Mapper類對(duì)dao類進(jìn)行標(biāo)注,使用@Insert、@Delete@、@Update+@Param、@Selete+@Reuslts進(jìn)行crud語句的操作,至于其他的與進(jìn)行jdbc語句差不多,mybatis其實(shí)也只是做了那么兩件事情,結(jié)合書寫的sql語句將參數(shù)設(shè)置進(jìn)去,對(duì)查詢結(jié)果數(shù)據(jù)屬性將數(shù)據(jù)取出.通常在對(duì)于效率要求很高的項(xiàng)目中都是使用mybatis的,因?yàn)閷?duì)于一個(gè)項(xiàng)目來說在現(xiàn)如今每提升一點(diǎn)系統(tǒng)性能對(duì)于經(jīng)濟(jì)的獲取也是非常大的,另外其實(shí)項(xiàng)目中是可以使用兩套持久化技術(shù)的.前期使用spring data jpa實(shí)現(xiàn),后期切換成mybatis其實(shí)也是可以的.Thymeleaf

java網(wǎng)站開發(fā)從剛一開始的將頁面冗雜到servelt中到提出mvc思想后將視圖層單獨(dú)出去,其中獲取好處也是非常多的,由于將界面層作為三分之一,這樣的前端可以直接由前端人員進(jìn)行開發(fā)維護(hù),剛開始的時(shí)候使用的是jsp技術(shù),那個(gè)的時(shí)候的開發(fā)人員并非很多,網(wǎng)站承載量并非特別大,網(wǎng)頁前端業(yè)務(wù)也并不復(fù)雜,所以導(dǎo)致對(duì)性能的要求不是很高,jsp的運(yùn)行流程為轉(zhuǎn)譯編譯運(yùn)行,其中消耗的時(shí)間內(nèi)在當(dāng)初是并非很多的,但是對(duì)于現(xiàn)在來說這種消耗是很高的,這是導(dǎo)致我們棄用jsp的一個(gè)原因,還有一個(gè)非常重要的原因就是jsp非常依賴java servlet,這就使得jsp只能作為后端專屬語言了,后來隨著分布的口號(hào),我們逐漸意識(shí)到前端渲染的重要性,那個(gè)時(shí)候我們使用的是Freeemarker網(wǎng)頁靜態(tài)化技術(shù),這在當(dāng)年還有一些類似的技術(shù),例如:velocity,但是velocity的性能不如freemarker,后來網(wǎng)頁靜態(tài)化技術(shù)成了標(biāo)準(zhǔn)技術(shù)了,網(wǎng)頁靜態(tài)化技術(shù)為將傳入數(shù)據(jù)傳入模板中通過特點(diǎn)標(biāo)簽將數(shù)據(jù)填充到指定位置最后生成html文件,在一些高并發(fā)訪問的網(wǎng)頁使用這種靜態(tài)化技術(shù)遠(yuǎn)遠(yuǎn)比動(dòng)態(tài)化技術(shù)要好的多,典型代表為:淘寶,當(dāng)年是什么支持了淘寶在那么用戶沖擊下服務(wù)器依然很流暢,一部分是cdn一部分就是靜態(tài)化技術(shù),另外的化就是其獨(dú)特的架構(gòu)了,要知道當(dāng)前國內(nèi)第一家開源RPC框架Dubbo就是阿里的.spring團(tuán)隊(duì)對(duì)市場上有先進(jìn)性的技術(shù)都很感興趣.比如struts2/hibernate,這些到現(xiàn)在逐漸變成了spring mvc以及最新基于reactor異步架構(gòu)的spring wbflux和spring data jpa及其系列,甚至可以說freemarker就是thymeleaf的前生,同時(shí)spring 自家的spring mvc框架對(duì)thymleaf非常支持.同時(shí)thmeleaf對(duì)于面向?qū)ο笏枷胫С值姆浅5轿?將原本需要冗雜的標(biāo)簽改為屬性,使得將html文件改為thymeleaf模板文件非常方便.Spring data redis

redis是一個(gè)單線程基于內(nèi)存支持分布式部署的服務(wù).通常我們項(xiàng)目中使用redis一個(gè)是為了使用其基于內(nèi)存的特點(diǎn)實(shí)現(xiàn)緩存,另一個(gè)是使用其單線程及其執(zhí)行指令強(qiáng)原子性的特點(diǎn)實(shí)現(xiàn)并發(fā)鎖機(jī)制.在項(xiàng)目中很多地方都會(huì)使用緩存,一個(gè)是用戶登錄信息token存入redis,而這在以往稱之為單點(diǎn)登錄.另外為業(yè)務(wù)數(shù)據(jù)緩存,如果是自己使用StringRedisTemplate實(shí)現(xiàn)緩存操作,那么這個(gè)業(yè)務(wù)的代碼量又會(huì)平白增加很多了,在spring boot2.x中,我們通常是使用@Cache注解實(shí)現(xiàn)對(duì)緩存的操作,這個(gè)注解包含了獲取緩存,清除緩存,修改緩存(當(dāng)觸發(fā)某種條件時(shí)),這種注解需要標(biāo)注在方法名上,對(duì)于不同的方法實(shí)現(xiàn)不同的操作.其實(shí)redis一個(gè)更加重要的作用是作為并發(fā)鎖,通常的秒殺操作都是能夠使用這種并發(fā)鎖達(dá)到單機(jī)程序鎖所達(dá)不到的效率,因?yàn)檫@種鎖是不會(huì)阻塞本地線程的.實(shí)現(xiàn)原理是因?yàn)橐淮蜗騬edis請(qǐng)求的指令為一組同時(shí)存取的原子操作,一次只能有一個(gè)操作成功,同時(shí)通常會(huì)在存數(shù)據(jù)的時(shí)候會(huì)設(shè)置過期時(shí)間,而取出數(shù)據(jù)時(shí)通常會(huì)使用時(shí)間戳做鎖,將本機(jī)時(shí)間作為鎖.而解鎖的過程為將指定key的value移除掉.Spring data ElasticSearch

在項(xiàng)目集成了搜索引擎之后,傳統(tǒng)操作索引庫是比較復(fù)雜的,但是功能最為完善,但是其實(shí)有些時(shí)候并不是需要那么完善的功能的,比如說高亮操作,這個(gè)時(shí)候我們通常是為了簡化操作而封裝一個(gè)通用方法,其實(shí)現(xiàn)在spring data 系列已經(jīng)對(duì)es有了這種操作的支持了,使用spring data elasticsearch 可以非常簡單的實(shí)現(xiàn)對(duì)索引庫的CRUD操作,但是首先你需要定義一個(gè)文檔類,使用@Document("文檔名稱,通常類名也行"), 寫一個(gè)接口類實(shí)現(xiàn)ElasticSearchRepository<文檔庫類,類中主鍵類型>.其使用方式與spring data jpa一致.Logback

對(duì)于一個(gè)項(xiàng)目來說,日志是非常重要的,日志常用來分析程序漏洞、性能瓶頸、實(shí)際調(diào)用頻率,同時(shí)對(duì)于自動(dòng)化測試來說,沒有日志就幾乎是等于白測試了,因?yàn)橛袝r(shí)候就算是自動(dòng)化測試工具通過了,但是在實(shí)際運(yùn)行過程中還是會(huì)遇到一些奇怪現(xiàn)象導(dǎo)致產(chǎn)生奇怪的數(shù)據(jù),比如說就算是AssertNotNull(data)通過了,但是不代表這個(gè)data就是合理的了.現(xiàn)在可用的日志框架很多,比如說Log4j、Log4j2等等,它們都實(shí)現(xiàn)了同樣的一些功能:以后臺(tái)方式將運(yùn)行時(shí)期的由開發(fā)人調(diào)制的數(shù)據(jù)和上下文信息通過靈活簡便的配置(如日志輸出格式、日志輸出位置等等)實(shí)現(xiàn)非常高效的輸出.但是log4j2由于過于先進(jìn),一些框架都還未支持,所以我們選擇使用Logback框架,其實(shí)日志還有一個(gè)比較重要的作用是mybatis默認(rèn)情況下不會(huì)輸出執(zhí)行語句,而是需要將mapper下的日志級(jí)別設(shè)置到dubug或者trace級(jí)別.Swagger2

對(duì)一個(gè)web項(xiàng)目來說,接口文檔是非常重要的.以前也有接口文檔,但是以前的文檔時(shí)有專門的維護(hù)人員或者開發(fā)人員去書寫的,只是作為有哪些對(duì)外接口的文字描述,測試的時(shí)候需要測試人員再次復(fù)制黏貼Url并填入復(fù)雜的請(qǐng)求參數(shù),同時(shí)這種測試是低效率的,對(duì)于多個(gè)復(fù)雜接口一起組合使用,是很實(shí)現(xiàn)的.多模塊或者多子系統(tǒng)并行開發(fā)時(shí),這種文檔還影響著項(xiàng)目開發(fā)的進(jìn)度,因?yàn)橄到y(tǒng)直接會(huì)有其他系統(tǒng)功能的依賴,swagger2打破了這一僵局,swagger2會(huì)掃描項(xiàng)目中所有加了@Controller或者@RestController的類,將這些類的映射路徑分別收集起來在請(qǐng)求swagger暴露的REST API界面時(shí)會(huì)將這些映射路徑分別隱藏在各自的Controller類中,同時(shí)可以手動(dòng)指定Controller類的名稱和方法名稱以及請(qǐng)求參數(shù)聲明.如果點(diǎn)進(jìn)去會(huì)進(jìn)入一個(gè)具體的請(qǐng)求url中,swagger會(huì)展示URL調(diào)用時(shí)需要傳入哪些參數(shù),哪些是必須的,參數(shù)的基本類型,如果再點(diǎn)擊"Try it out",會(huì)直接調(diào)用這個(gè)rest 的url,同時(shí)由于這個(gè)界面都是折疊效果做的,所以不必?fù)?dān)心當(dāng)前測試沒有做完就去做下面或者上面的其他而導(dǎo)致丟失參數(shù).總結(jié)來說:swagger的使用比較簡單、而且測試非常方便Apache ab

對(duì)于一個(gè)微服務(wù)的項(xiàng)目來說,如果你不測試它的并發(fā)量、容載量,那跟單體工程還有不同?Apache ab是一個(gè)命令行的可以測試并發(fā)效果的工具.至于使用是很簡單的.ActiveMQ/Kafka

對(duì)于一個(gè)中大型項(xiàng)目來說,任何的直接操作數(shù)據(jù)都有可能有未知原因?qū)е虏僮魇?對(duì)于一些模塊或者叫做系統(tǒng)來說,有些數(shù)據(jù)是不能丟失的,比如說訂單系統(tǒng),支付系統(tǒng).分布式的項(xiàng)目常遇到的數(shù)據(jù)一致性問題都可以使用消息隊(duì)列來解決.消息隊(duì)列有AMQP和JMS兩類,主流常見的消息隊(duì)列服務(wù)有  ActiveMQ/RabbitMQ/Kafka,其性能大致都差不多,但是ActiveMQ不支持集群,如果需要集群的話需要借助Zookeeper.RabbitMQ天生支持分布式,Kafka在大數(shù)據(jù)生產(chǎn)環(huán)境中經(jīng)常用到,所以在對(duì)于消息隊(duì)列的話,功能最強(qiáng)的是Kafka,使用最簡單的為ActiveMQ,同時(shí)由于spring整合的非常好,在使用Spring Kafka或者Spring Boot ActiveMQ,接受消息一般都是將一個(gè)方法上加上@XXXListener注解,在spring kafka中,傳入?yún)?shù)為具體需求,返回參數(shù)的類型為Void,而在@XXXListener上需要標(biāo)明id,topic等信息.而在發(fā)送消息使用@SendTo注解,并在注解中聲明發(fā)送到的topic,topic中可以使用EL表達(dá)式從配置文件中獲取話題名稱.Spring boot websocket

socket意思為套接字,一般用來維持長連接,使用長連接一般可以用作在線聊天,在spring boot框架下,有jetty/tomcat/undertow三種,如果是使用tomcat的話,由于已經(jīng)內(nèi)置了spring-boot-starter-tomcat所以不需要再次依賴,但是如果是使用的是jetty,那還需要spring-boot-starter-jetty.在使用中需要依賴spring-boot-starter-websocket并且清除掉spring-boot-starter-tomcat,寫一個(gè)類繼承TextWebSocket.重寫handleTextMessage(處理消息)、afterConnectionEstablished(當(dāng)消息處理之后)、afterConnectionClosed(連接關(guān)閉之后)、HandleTransportError(傳輸異常)方法,發(fā)送數(shù)據(jù)使用的是session的sendMessage方法,接受消息用的是TextMessage.Docker

容器技術(shù),安裝一個(gè)mysql對(duì)于docker來說,僅僅只是查看一下文檔,在dockerhub.com中查找mysql相關(guān)鏡像,理解文檔之后,按照他的pull指令在已經(jīng)安裝了docker的服務(wù)器中運(yùn)行即可得到鏡像,我一般都是用記事本將啟動(dòng)鏡像需要的參數(shù)組織起來,在覺得OK之后再復(fù)制黏貼到SSH工具,如secureCRT軟件,在鏡像運(yùn)行之后我一般會(huì)使用docker ps -a去查看容器運(yùn)行情況,有點(diǎn)時(shí)候即使是當(dāng)時(shí)啟動(dòng)成功了,后面也不一定能啟動(dòng)起來,當(dāng)發(fā)現(xiàn)描述為EXIT時(shí)我都會(huì)查看一下啟動(dòng)參數(shù)和配置,而當(dāng)運(yùn)行一段時(shí)間之后為UP之后,這樣的容器才有可能是認(rèn)為是啟動(dòng)成功了.對(duì)于如何查看容器的基礎(chǔ)信息,使用docker inspect.然后就是停止容器運(yùn)行:docker stop 容器id,刪除容器:docker rm 容器id,刪除鏡像而為本地文件系統(tǒng)騰出空間:docker rmi 鏡像id,而對(duì)于如何查看容器id使用docker ps -a ,查看鏡像id使用docker images.一個(gè)常見問題是容器內(nèi)部時(shí)區(qū)問題,通??梢允褂?e參數(shù)指定時(shí)區(qū).另一個(gè)常見問題是docker中心庫拉去鏡像速度過慢問題,通常是需要配置加速器的,一般的加速器都很貴,但是阿里云有一個(gè)加速器速度非??於颐赓M(fèi).進(jìn)入容器中使用docker exec -it 容器id /bin/bash.功能

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-6fDgKvyY-1577344034026)(C:\Users\tanSh\Desktop\需求驅(qū)動(dòng)響應(yīng)的商城平臺(tái)\資源\代優(yōu)匯商城功能設(shè)計(jì)圖4.png)]
賣家能夠增加商品,修改商品(包括商品下架),刪除商品,查找指定商品,搜索商品,查找所有商品并分頁顯示

買家能夠根據(jù)商品的特征進(jìn)行搜索商品,比如說紅色手機(jī),特征為紅色和手機(jī).

買家能夠進(jìn)行活動(dòng)中的秒殺商品操作

平臺(tái)會(huì)根據(jù)商品實(shí)際分類將商品進(jìn)行分類顯示給賣家,分類是一種多層次關(guān)系,比如說智能家電、床上用品

買家能夠查看商品詳情并且能夠?qū)⒃撋唐芳尤?amp;amp;#34;收藏"/"到貨通知"/"購物車"/"訂單"

買家能夠?qū)ξ粗Ц队唵沃Ц?或者在下訂單的時(shí)候進(jìn)行付款,買家能夠使用支付寶或者微信支付,在App中用戶能夠提示打開微信或者支付寶進(jìn)行支付,而在網(wǎng)頁中,會(huì)跳轉(zhuǎn)到支付寶或者非微信的支付界面,支付成功即為下單成功

賣家會(huì)能夠及時(shí)的得到買家下的訂單,這里我們使用websocket長連接,并及時(shí)進(jìn)行發(fā)貨等操作,并且能夠選擇物流的公司,并且在物流公司確認(rèn)發(fā)貨之后會(huì)告訴賣家開始發(fā)貨,買家會(huì)通知買家已經(jīng)開始發(fā)貨了

買家能夠支付關(guān)注到物流情況,這里我們集成了物流公司的實(shí)現(xiàn)查詢接口API

有反饋系統(tǒng),買家和賣家都可以直接向系統(tǒng)提出意見和建議

**------------------------>如果只有上面的功能,那么這個(gè)項(xiàng)目將是毫無意義的--------------->下面的才是開始:**

    隨著社會(huì)的高速發(fā)展,生產(chǎn)力已經(jīng)超過了過去十年的總和,IT時(shí)代的到來,我們漸漸意識(shí)到經(jīng)濟(jì)發(fā)展的規(guī)律,不管是淘寶還是京東,其核心功能為為生產(chǎn)力分配價(jià)值、加速流通,十年前淘寶是如此,今天還是如此,十年前人們覺得淘寶是多余的,覺得線下商店就夠了,但是從第一座城市建立開始到現(xiàn)在,沒有哪一家商店能夠站在城市的角度思考生產(chǎn)力的分配,淘寶做到了,哪怕是十座城市的人口流量還是一百座都是同一個(gè)入口,同一家商城,淘寶利用其分層的思想將適合的商品送到合適的人手中,對(duì)外部看來淘寶就像是一個(gè)巨型的商店,甚至比線下商店更加專業(yè),因?yàn)樗臄?shù)據(jù)是統(tǒng)一的,用戶需要看到商品、用戶需要拿到商品、用戶需要付款、用戶需要退貨等等.淘寶真的很牛逼,如果管理一個(gè)市中心的商店是有難度的話,中國那么多的線上商店的管理那將是指數(shù)級(jí)別難度的增長.十多年前淘寶以商家進(jìn)入線上出售商品、物流公司將商品發(fā)送為驅(qū)動(dòng),利用互聯(lián)網(wǎng)流通快、消耗小、入口統(tǒng)一的特點(diǎn)在中國消費(fèi)者市場站穩(wěn),淘寶的盈利模式為商家管理費(fèi)用,至于費(fèi)用細(xì)節(jié)這里就不細(xì)談了.

    漸漸的,買家覺得購買的東西不夠好,淘寶推出了已購買者的評(píng)價(jià)功能,淘寶平臺(tái)以為這樣就可以有效抑制差貨現(xiàn)象,其實(shí)不然,在推出這個(gè)功能之后沒過多久,大規(guī)模的刷單浪潮掀起,一單刷單,評(píng)論的質(zhì)量就無法保障,一單這個(gè)的質(zhì)量無法保障,買家在購買東西的時(shí)候?qū)⑹菦]有任何的可信性,刷單的流程一般為互聯(lián)網(wǎng)中隨意的一名買家在購買這件商品之后發(fā)布好評(píng),商家不發(fā)貨或者接受退貨,刷手不收貨或者退貨,這樣的虛假交易帶來的好評(píng)對(duì)其他消費(fèi)者是一種誤導(dǎo)甚至是坑騙,至于刷手的利益是什么?是來自商家額外的獎(jiǎng)勵(lì),在退還本金之后額外一些小費(fèi),由于網(wǎng)絡(luò)交易幾乎不存在阻塞性,刷手很可能就是靠這種方便一天為幾百家商店刷單.其實(shí)這不能怪刷手,這是平臺(tái)的漏洞導(dǎo)致的.再看用戶購買的操作,我相信很多剛開始用淘寶的買家可能會(huì)有同一種情況,由于新鮮感會(huì)抑制不住想買點(diǎn)新鮮東西,其實(shí)實(shí)際并非實(shí)用的東西,在經(jīng)濟(jì)繁榮時(shí)期這是正常的,后來才開始后悔,特別是結(jié)合花唄之后導(dǎo)致的迅速購買帶來的償還期,對(duì)于平臺(tái)來說這并沒有什么,甚至是越多購買記錄越好,但是這也是我為了改進(jìn)這種而想做這個(gè)項(xiàng)目的一個(gè)原因.

    有人說,淘寶上的二手商店是不是太多了?確實(shí)是很多,因?yàn)槠脚_(tái)對(duì)于這種二手并不感覺有什么疑問,因?yàn)閷?duì)于他來說,越多的商家越好,但是對(duì)于整個(gè)交易過程中來說,每多一個(gè)二手商店,買家的付出價(jià)值越加沉重,每多一個(gè)二手商店,在買家的付出價(jià)值不變的情況下,質(zhì)量更加低下,其實(shí)我曾經(jīng)一度在想如何消滅二手商店,在我想到答案之后,我又陷入了如何去驗(yàn)證這個(gè)答案的艱難境地,直到共享單車的出現(xiàn),經(jīng)過這樣的驗(yàn)證我明白了我的答案是對(duì)的.

    在商品繁雜的今天,如何在一個(gè)已知的已經(jīng)是很詳細(xì)的列表里面找到最適合自己的.在過去,淘寶是沒有這件事情,僅僅是展示一個(gè)商品列表又是有什么用呢?后來淘寶推出了個(gè)性推薦、同類歷史記錄推薦,當(dāng)然這是在結(jié)合大數(shù)據(jù)和人工智能分析之后的成果,其中如何去獲取數(shù)據(jù),一個(gè)是歷史記錄數(shù)據(jù),如果你瀏覽了或者搜索了某一跨商品,我堅(jiān)信在能夠推薦的地方,淘寶都會(huì)推薦相關(guān)商品給你,一個(gè)相同行為軌跡的推薦,如果你購買了手機(jī),恨與可能推薦其他眾多用戶在購買手機(jī)之后再次購買的充電寶給你,其實(shí)很多都有數(shù)據(jù),只不多淘寶僅僅是一個(gè)交易平臺(tái),甚至是如果我想買一個(gè)東西我都無法找到相關(guān)功能去與我交流,交流的意思為買家不斷輸出數(shù)據(jù),平臺(tái)捕獲數(shù)據(jù)并分析得到商品特征,而淘寶有的僅僅是一個(gè)搜索功能,當(dāng)買家知道要買個(gè)什么東西的時(shí)候需要搜索干嘛?不知道要買個(gè)什么東西的時(shí)候如何搜索?搜索得到的眾多商品怎么去選擇最適合自己的.

    關(guān)于假貨問題,也就是商品描述與實(shí)際商品不符合.甚至是很多東西都是買了很長時(shí)間之后才知道這個(gè)商品是否有質(zhì)量問題.如何去區(qū)分呢?靠買家評(píng)價(jià),完全靠不住的.靠平臺(tái)打分?那也只是個(gè)數(shù)據(jù),其實(shí)就我來說,最靠得住的是生產(chǎn)鏈,這是我前面畫那張圖中明確強(qiáng)調(diào)的部分.只有完全真實(shí)透明的生產(chǎn)鏈才能保證商品的質(zhì)量.對(duì)于工程來說質(zhì)量=測試,但是在實(shí)際實(shí)際中,很多東西都沒有那么簡單.只有靠消滅二手,公開生產(chǎn)鏈.然后我發(fā)現(xiàn)淘寶和實(shí)際生產(chǎn)廠家是分開的.所以要連接起來其中必定要多加上一個(gè)二手.所以我們的平臺(tái)必須要講生產(chǎn)廠家搬到線上,但是真實(shí)情況是很多廠家都是只是生產(chǎn)一個(gè)部分的商品,難道對(duì)于一個(gè)買家來說就是只買一個(gè)部件嗎?例如我要買手機(jī),難道只是買一個(gè)高通的處理器嗎?所以針對(duì)這一點(diǎn),里面還有一個(gè)轉(zhuǎn)折點(diǎn),部件也是商品,但是不是給普遍的消費(fèi)者買的,而是給需要這種部件的買家買的,我們將所有的買家抽象成需求者,需求者有不用的身份,需求者在需求商品的時(shí)候可以指明自己的身份,也可以使用存留在平臺(tái)的身份.過去的ERP只是作為企業(yè)內(nèi)部的管理,企業(yè)外部即企業(yè)與企業(yè)之間的聯(lián)系幾乎還是原來的模式,企業(yè)的選擇依然是人工的,不過有些大企業(yè)會(huì)有依賴資源分析系統(tǒng),對(duì),這也是我們要做的,這一點(diǎn)與普通消費(fèi)者的購買心理一致,所以抽象起來,幾乎所有的需求者都是同一種的需求心理,當(dāng)然普通人的需求心理我們可以分析出來,因?yàn)橛凶銐蚨嗟臄?shù)據(jù),企業(yè)就不一定了,對(duì)此也只是將數(shù)據(jù)排行展示而已.企業(yè)在生產(chǎn)過程中有內(nèi)部依賴需求即自己a部門生產(chǎn)的東西會(huì)被b部門依賴,也有外部依賴需求即a公司會(huì)依賴b公司的技術(shù)、商品等等,在我感覺的理想狀態(tài)是,同一種企業(yè)應(yīng)該將下層生產(chǎn)力融合起來,對(duì)于技術(shù)應(yīng)該在充分實(shí)踐之后讓落后公司學(xué)習(xí)更加先進(jìn)公司的技術(shù),這就存在著一個(gè)肯學(xué)、一個(gè)肯教的問題了,至于下層生產(chǎn)力融合起來可以理解為公司將自己的處于生產(chǎn)層員工向這樣的處于同一生產(chǎn)類型的人力資源池填充,當(dāng)需要多少資源時(shí)向資源池中獲取多少資源,當(dāng)多了就填充,少了就向其他公司平臺(tái)管理或者各公司聯(lián)合管理申請(qǐng),如果這樣做了,整個(gè)行業(yè)就容易把握了,員工不再有公司限制,有的只是屬于自己實(shí)際經(jīng)驗(yàn)的充分發(fā)揮.更容易的對(duì)社會(huì)進(jìn)行管理.在這樣的模型下生產(chǎn)力將大幅度提升.

    其實(shí)交易從古至今一直由三部分構(gòu)成,需求者,響應(yīng)者,價(jià)值,平臺(tái)其實(shí)也是只需要根據(jù)這三個(gè)抽象對(duì)象展開業(yè)務(wù)即可,傳統(tǒng)的有囤貨開店直銷、現(xiàn)代的有基于商家管理然后由商家自己管理顧客.對(duì)于需求者來說,獲取自身相關(guān)的需要的商品,平臺(tái)能更加理解需求者想要的東西,能向需求者推薦意想不到的商品,需求者能夠花更少的錢而獲取更好的貨,需求者收到的貨物有更好的質(zhì)量,而對(duì)于響應(yīng)者來說,能夠?qū)⒆约旱呢浳锼偷较胍降男枨笳呤种?,?dāng)市場更好的時(shí)候能夠更容易擴(kuò)大自己的生產(chǎn)力,能夠簡化生產(chǎn)模型并和互聯(lián)網(wǎng)融合,能向經(jīng)營或者技術(shù)更好的同類響應(yīng)者學(xué)習(xí),能夠免費(fèi)使用商用ERP并隨著時(shí)代前進(jìn)而前進(jìn)即有人能夠?qū)⒎腔ヂ?lián)網(wǎng)的響應(yīng)者持續(xù)的帶入互聯(lián)網(wǎng)并不需要錢.而對(duì)于價(jià)值來說,能夠有永久的記錄保存(就像區(qū)塊鏈)、能夠迅速的流通并發(fā)揮到需要的地方(小額貸),能夠不受社會(huì)的動(dòng)蕩抑制而是由商品的消耗價(jià)值決定,所有的需求都能直接用某一種價(jià)值進(jìn)行衡量而不受限.

    如何認(rèn)為是需響成功?需求者從瀏覽商品然后下單、平臺(tái)分析推送,當(dāng)需求者付出響應(yīng)價(jià)值、平臺(tái)保存價(jià)值、響應(yīng)價(jià)值分發(fā)響應(yīng)者、響應(yīng)者發(fā)出商品,需求者確認(rèn)響應(yīng)成功,對(duì)于剩余價(jià)值,響應(yīng)者回購已售商品殘余價(jià)值,需求者出售已購商品殘余價(jià)值。

    需求者在當(dāng)前平臺(tái)與其他平臺(tái)的區(qū)別?需求者直接發(fā)布+需求者對(duì)話提煉,需求者行為軌跡,在響應(yīng)庫中主流需求與需求者吻合,其他需求者推薦.需求者直接發(fā)布可以理解為搜索功能或者向需求庫中添加一條需求,響應(yīng)者會(huì)在收到來自平臺(tái)與之匹配的需求記錄,需求者對(duì)話提煉,會(huì)使用人工智能中的人機(jī)對(duì)象,然后從對(duì)話中提取出所需商品的特征,然后當(dāng)需求者認(rèn)為描述清楚之后向需求者展示匹配的商品列表.需求者行為軌跡可以理解為根據(jù)用戶歷史購買物品推斷出還將會(huì)購買的東西,這是屬于大數(shù)據(jù)分析或者人工智能分析的實(shí)現(xiàn)技術(shù),當(dāng)需求者符合某一系列特征后會(huì)將屬于這一特征的一些更加符合需求者實(shí)際情況的東西推薦給需求者.朋友的直接推薦.

    響應(yīng)者在當(dāng)前平臺(tái)與其他平臺(tái)的區(qū)別?響應(yīng)者可以直接發(fā)布商品,能夠免費(fèi)使用統(tǒng)一的ERP系統(tǒng),能夠從友站鏈入,響應(yīng)者可以作為一個(gè)成熟商品的一部分部件進(jìn)行發(fā)布商品,這樣的部件可以理解為商品,而且當(dāng)前公司很有可能會(huì)依賴其他公司的部件的商品.之所以只用統(tǒng)一的ERP系統(tǒng),一個(gè)是為了將這些企業(yè)聯(lián)合起來,一個(gè)是為了整合數(shù)據(jù)時(shí)更容易.還有很多功能以后再補(bǔ)充.實(shí)現(xiàn)

在這個(gè)項(xiàng)目初期分為3個(gè)系統(tǒng)1個(gè)輔助服務(wù)進(jìn)行開發(fā),分別是了需求者系統(tǒng)、響應(yīng)者系統(tǒng)、服務(wù)網(wǎng)關(guān)、注冊(cè)中心,在需求者系統(tǒng)上實(shí)現(xiàn)了買家系統(tǒng)、需求分析系統(tǒng),買家系統(tǒng)中能夠進(jìn)行常規(guī)的用戶登錄、注冊(cè)、修改密碼、忘記密碼、修改用戶信息、人臉識(shí)別登錄功能,需求分析系統(tǒng)中有人機(jī)對(duì)話功能、需求記錄、支付寶和微信支付功能、關(guān)于文件管理使用了阿里云的OSS服務(wù).響應(yīng)者系統(tǒng)中有響應(yīng)者登錄、注冊(cè)、修改密碼、忘記密碼、修改用戶信息、還有商品管理模塊,關(guān)于商品模塊支持響應(yīng)者進(jìn)行div操作,實(shí)際上也是字符串替換而已,訂單管理系統(tǒng),物流管理系統(tǒng)、支持從淘寶或者京東直接導(dǎo)入商品,能夠加入生產(chǎn)鏈作為完整商品中的一個(gè)模塊,能夠發(fā)起生產(chǎn)鏈,支持免費(fèi)使用統(tǒng)一抽象的ERP(企業(yè)資源管理)+OA(辦公自動(dòng)化)+EMS(制造執(zhí)行)系統(tǒng).針對(duì)發(fā)布商品或者生產(chǎn)鏈有智能檢測模塊保證平臺(tái)合法經(jīng)營.

對(duì)于項(xiàng)目中的注冊(cè)用戶功能,我們使用了阿里云的短信接口服務(wù),當(dāng)用戶注冊(cè)時(shí)需要先請(qǐng)求專門的發(fā)送短信的接口,此接口內(nèi)實(shí)現(xiàn)較為簡單,無dao層操作,無需涉及到數(shù)據(jù)庫的操作,但是需要集成阿里云短信java版的maven依賴(官網(wǎng)提示沒有依賴而是需要自己在自己的私有庫上去安裝),在封裝了簡單的發(fā)送短信的工具類后,使用發(fā)送短信是非常簡單的,在開始集成阿里云短信接口服務(wù)時(shí),需要申請(qǐng)短信模塊和短信簽名,這兩個(gè)申請(qǐng)還是很簡單的.將參數(shù)配置進(jìn)去后,將固定參數(shù)配置到application.yml中,當(dāng)然也可以使用application.properties,對(duì)于這兩者的區(qū)別在于yml更加面向?qū)ο?在ide工具中,如idea中修改時(shí)很簡單的,但是在記事本或者notepad++中就不容易了.其實(shí)影響也不大.還是推薦使用application.yml.在需要使用的方式使用@Value("${xxx}")注解進(jìn)行注入.如果用戶是使用了正確的手機(jī)號(hào)碼進(jìn)行注冊(cè),當(dāng)然我們后臺(tái)也會(huì)進(jìn)行基于正則表達(dá)式的檢查傳入的手機(jī)號(hào)碼.用戶手機(jī)會(huì)在1-2分鐘內(nèi)受到短信通知,而對(duì)于短信丟失率,官網(wǎng)給出的數(shù)據(jù)是99%.再調(diào)用短信接口時(shí),我會(huì)先生成0-9的6位數(shù)字的隨機(jī)值,然后將此值放入redis中,因?yàn)轫?xiàng)目中使用的是spring boot框架,所以集成一個(gè)spring data reids還會(huì)很簡單的.而通過在業(yè)務(wù)層使用@Autowired StringRedisTemplate stringRedisTemplate; 注入redis操作對(duì)象,而通過這個(gè)對(duì)象可以將手機(jī)號(hào)碼和0-9的6為隨機(jī)數(shù)字放入redis中。當(dāng)然在實(shí)際項(xiàng)目中是這樣做的,聲明一個(gè)業(yè)務(wù)常量接口類,在里面聲明一個(gè)常量,因?yàn)閕nterface類里面所以的屬性都是public static final 修飾的,所以可以使得更加貼合實(shí)際.我會(huì)聲明一個(gè)redis中直接存放的string的key的前綴,例如為'requester_regist_';然后后面再直接拼接上手機(jī)號(hào)碼,這樣就是直接是'requester_regist_123456',通過添加到redis并設(shè)置過期時(shí)間,過期時(shí)間默認(rèn)為30分鐘.當(dāng)用戶來注冊(cè)的時(shí)候回?cái)y帶手機(jī)號(hào)碼,這個(gè)時(shí)候需要校驗(yàn)是否有效,還是需要注冊(cè)redis操作對(duì)象并調(diào)用取數(shù)據(jù)的方法,從常量類中取出注冊(cè)前綴以及傳入的手機(jī)號(hào)碼,如果取出的值不為空并且與傳入的verificationCode一致,則給與注冊(cè).同時(shí)對(duì)于賬號(hào)名是否有效會(huì)進(jìn)行校驗(yàn),比如說是否與正則表達(dá)式符合,同時(shí)還會(huì)校驗(yàn)用戶名是否已經(jīng)存在,如果存在則不給予注冊(cè).在返回?cái)?shù)據(jù)對(duì)象會(huì)封裝一個(gè)抽象響應(yīng)對(duì)象.需要封裝一些必須的屬性,例如:響應(yīng)嗎、數(shù)據(jù)(類型為泛型T,以為不管是返回單個(gè)pojo對(duì)象還是page對(duì)象還是list對(duì)象都是可行的)、消息內(nèi)容,通常還會(huì)聲明一個(gè)用戶注冊(cè)的枚舉類,該類中必須設(shè)置int code和stirng msg,對(duì)于這樣封裝,雖然是增加了代碼量,但是很好維護(hù),代碼格式很優(yōu)美.就此客戶端,不管是pc的html還是手機(jī)app都是可以通過判斷code表示是否注冊(cè)成功.對(duì)于數(shù)據(jù)校驗(yàn)成功之后就可以開始寫入數(shù)據(jù)庫了,本項(xiàng)目中使用的是mysql,并且將mysql是通過docker進(jìn)項(xiàng)安裝了,在啟動(dòng)時(shí)固定了映射端口為3306,其實(shí)個(gè)人感覺最好不要隨機(jī)映射端口或者ip,原因也是很簡單的,因?yàn)橄麓螁?dòng)的時(shí)候服務(wù)的訪問地址都改變了,對(duì)于項(xiàng)目來說就是災(zāi)難性的了,同時(shí)在啟動(dòng)容器時(shí)指定數(shù)據(jù)卷,以便數(shù)據(jù)備份導(dǎo)出以及持續(xù)使用.同時(shí)對(duì)于mysql鏡像一個(gè)bug就是時(shí)區(qū)問題,這是我在使用timestamp類型的列才發(fā)現(xiàn)的,通過查資料才發(fā)現(xiàn)是容器內(nèi)部時(shí)區(qū)問題,我隨即登錄宿主機(jī)使用date指令查看了宿主機(jī)時(shí)間及時(shí)區(qū),同時(shí)通過docker exec -it 容器id /bin/bash 指令進(jìn)入了容器內(nèi)部,在同樣使用了date指定之后發(fā)現(xiàn)時(shí)區(qū)果然不對(duì),相差8個(gè)小時(shí),隨機(jī)我再次查閱官方文檔,解決方法有兩種,一種是掛載宿主機(jī)時(shí)區(qū)文件,一個(gè)是同時(shí)-e攜帶參數(shù)指定容器時(shí)區(qū).至此最終解決問題.在項(xiàng)目中使用的是spring data jpa,spring data系列框架都是很容易被開發(fā)人員接受的,spring data jpa 是基于hibernate 實(shí)現(xiàn)的,在拋棄了hibernte冗雜的配置文件.并基于接口類實(shí)現(xiàn)基于的crud,同時(shí)提供了高級(jí)查詢對(duì)象,在spring data jpa中,表與類的映射關(guān)系只是幾個(gè)注解接口解決.@Entity,@Table@Column@Id@GenerateValue,在接口層,異常都是需要寫一堆代碼,同時(shí)對(duì)于分頁操作也是不夠簡潔,jpa 中只是需要聲明一個(gè)接口類繼承JpaRepository<實(shí)體類類型,主鍵類型>,在實(shí)際的多條數(shù)據(jù)查詢中使用pageable對(duì)象,封住了size和page和sort對(duì)象,分頁查詢時(shí)同時(shí)指定page第幾頁,size一頁多少條,sort:以哪些字段排序以什么屬性排序.通常注冊(cè)只需要返回id即可.同時(shí)既然是注冊(cè),密碼的安全性也是非常高的.使用3倍md5并且加鹽實(shí)現(xiàn)了加密明文操作,同時(shí)將加密方法封裝起來,因?yàn)楫?dāng)用戶使用明文密碼登錄是還是需要使用該加密類實(shí)現(xiàn)加密再比對(duì)才能校驗(yàn)是否密碼正確.

對(duì)于項(xiàng)目中最基礎(chǔ)的登錄功能,我們實(shí)現(xiàn)的是SSO,英文名為single sign on,稱為單點(diǎn)登錄.當(dāng)用戶首次完整登錄成功,業(yè)務(wù)層會(huì)生成全局唯一的字符串,而這個(gè)操作使用uuid即可完成,在java中生成一個(gè)UUID值是非常簡單的,使用UUID類調(diào)用randomUUID即可返回一個(gè)32+4位的字符串,同時(shí)將該字符串中所有的'-'替換為''即可.將此字符串即token(令牌)存入redis中,至于key,還是可以像前面一樣在接口類中聲明前綴,例如"requester_login_",然后再加上用戶的id,因?yàn)榈卿浄绞娇梢杂卸喾N,但是id確實(shí)唯一的.同時(shí)在業(yè)務(wù)層注入redis操作類,同時(shí)調(diào)用設(shè)置值的方法將key和token存入redis中并設(shè)置默認(rèn)過期時(shí)間為2個(gè)小時(shí).因?yàn)閟pring data redis的stringRedsiTemplate.opsForValue的存值方法支持指定時(shí)間單位,所以可以不需要講毫秒值換算為2小時(shí),而是2,TimeUnit.Hour即可。對(duì)于pc的html/html5可以直接通過session對(duì)象操作cookie對(duì)象即可,而對(duì)于像手機(jī)app這種,可以將token直接作為返回參數(shù)返回,html5的本地存儲(chǔ),安卓的sqlite這些都是可行的存儲(chǔ)方案.在下一次請(qǐng)求登錄時(shí),如果對(duì)于該賬號(hào)的token有效不為空,并且與傳入的token一致,即可認(rèn)為是sso登錄,在多平臺(tái)的時(shí)代,sso登錄有著重要意義.

對(duì)于項(xiàng)目中的修改密碼,首先要確保用戶現(xiàn)在是登錄狀態(tài),然后與注冊(cè)用戶差不多,但是在使用spring data jpa進(jìn)行修改操作時(shí)需要使用@Update注解標(biāo)注修改,同時(shí)在@Query("sql語句")使用ddl語句進(jìn)行修改指定密碼類的值.

對(duì)于項(xiàng)目中的忘記密碼,實(shí)現(xiàn)與注冊(cè)有公共之處,即為忘記密碼需要驗(yàn)證手機(jī)驗(yàn)證碼.然后與修改密碼類似

修改用戶信息與修改密碼類似

關(guān)于項(xiàng)目中的人臉識(shí)別功能的實(shí)現(xiàn),由于大數(shù)據(jù)耗費(fèi)資源較重,所以對(duì)于一些市場上已經(jīng)有的第三方云服務(wù),這里就直接集成了,比如說人臉識(shí)別,在剛開始集成的時(shí)候這個(gè)東西應(yīng)該很難,實(shí)際上很容易,因?yàn)槲以诎⒗镌粕嫌虚L時(shí)間的時(shí)間經(jīng)歷,所以我剛開始的時(shí)候是選擇阿里云的人臉識(shí)別服務(wù),阿里云的人臉識(shí)別是基于兩個(gè)圖片的比對(duì)的,對(duì)于像當(dāng)前這樣的系統(tǒng)來說,我直接拋棄了,因?yàn)樯蟼鲀蓮垐D片文件的代價(jià)是比較大的,雖然也可以改進(jìn)為一張從客戶端上傳,其他的從OSS對(duì)象文件存儲(chǔ)中使用內(nèi)網(wǎng)進(jìn)行傳輸,但是由于實(shí)現(xiàn)起來確實(shí)很麻煩,后來我找了一些的服務(wù)商,都沒有符合我的業(yè)務(wù),直到碰到百度云的人臉識(shí)別,百度云的人臉識(shí)別從一開始就是瞄準(zhǔn)的團(tuán)體型,幾個(gè)核心的接口分別為:上傳用戶圖片到用戶組中,從用戶組中比對(duì)傳入圖片,從圖片組中刪除指定用戶圖片,所以事情就簡單了,在用戶開啟人臉識(shí)別并至少上傳了一張圖片,登錄時(shí)只需要打開攝像頭,拍攝一張圖片并調(diào)用接口到服務(wù)器,然后調(diào)用從用戶組中比對(duì)用戶的接口將圖片.返回結(jié)果為一系列的比對(duì)結(jié)果數(shù)組,同時(shí)可以指定返回的結(jié)果數(shù)組的大小,但是也有默認(rèn)值,返回的第一條數(shù)據(jù)為相似度最高的,可以獲取之前上傳用戶圖片時(shí)額外指定的用戶id字符串,判斷相似度是否高于85,如果高于85數(shù)據(jù)即為合理,重新刷新token,實(shí)現(xiàn)與用戶登錄類似.

關(guān)于項(xiàng)目中的需求記錄,當(dāng)用戶搜索時(shí)將搜索值提取分析保存到需求記錄表中,平臺(tái)會(huì)使用hadoop平臺(tái)定時(shí)每一天8點(diǎn)到9點(diǎn)分析所有的搜索記錄表,將數(shù)據(jù)提取到hdfs文件系統(tǒng)中,通過對(duì)標(biāo)簽的匹配,將一部分需求記錄發(fā)送給響應(yīng)者的查詢接口.因?yàn)檫@個(gè)對(duì)實(shí)時(shí)性和效率并不是要求特別高,所以是hadoop是極好的,因?yàn)樵谠品?wù)器中硬盤的性價(jià)比比內(nèi)存的性價(jià)比低的多.
關(guān)于項(xiàng)目中的文件管理使用了阿里云的OSS服務(wù),因?yàn)槠胀ㄎ募到y(tǒng)有著帶寬抑制、性價(jià)比更低、影響服務(wù)器性能、擴(kuò)容復(fù)雜,在思考之后決定使用OSS 對(duì)象存儲(chǔ)服務(wù),OSS還支持CDN加速,影音文件讀取加速等特點(diǎn),但是這也有一個(gè)缺點(diǎn),文件刪除策略過于死板,文件刪除標(biāo)準(zhǔn)應(yīng)該為文件與項(xiàng)目無關(guān)聯(lián),實(shí)現(xiàn)這個(gè)并不復(fù)雜,甚至是很簡單,但是涉及到安全問題其實(shí)阿里云OSS也是不容易做的,所以我們可以自己做,寫一個(gè)數(shù)據(jù)庫文件列的管理模塊,能夠在輸入連接數(shù)據(jù)庫的參數(shù):Url、數(shù)據(jù)庫類型、用戶名、密碼后連接實(shí)際數(shù)據(jù)庫得到所有表,管理人員在通過驗(yàn)證后展開表,勾選字段,在勾選了所有的有文件名稱引用的表的字段后,將這些數(shù)據(jù)上傳,這樣我們就可以得到所有需要提取數(shù)據(jù)的位置了,這里我并不是使用的spring data jpa而是jdbc,因?yàn)檫@個(gè)屬于過于靈活的操作,jpa做不到,在得到這些表及其字段名后,將這些數(shù)據(jù)存入記錄表中,方便管理,使用quat    Z實(shí)現(xiàn)定時(shí)服務(wù),當(dāng)開始調(diào)用分析功能時(shí),我一個(gè)是需要將所有的數(shù)據(jù)從哪些列中查出,一個(gè)是要講oss文件中當(dāng)前項(xiàng)目的bucket中的所有的文件名稱獲取出來,這里的數(shù)據(jù)量的級(jí)別已經(jīng)達(dá)到了大數(shù)據(jù)的范疇了,獲取數(shù)據(jù)之后的處理很簡單就是將sso文件庫中的文件名逐個(gè)與數(shù)據(jù)庫中的列中的文件名進(jìn)行比較,如果發(fā)現(xiàn)sso文件庫中的文件名不存在于mysql數(shù)據(jù)庫中的指定列名中,那么這個(gè)文件就是可以刪除掉的,但是具體實(shí)現(xiàn)我才發(fā)現(xiàn)并不是那么理想,在上傳數(shù)據(jù)時(shí)會(huì)有干擾因素,因此,我想出了將上傳數(shù)據(jù)庫中的文件名的操作分為3個(gè)操作,一個(gè)聲明開始上傳,一個(gè)多次上傳數(shù)據(jù),最后聲明確認(rèn)上傳接受、甚至需要管理員輸入手機(jī)驗(yàn)證碼.當(dāng)然在刪除操作進(jìn)行前會(huì)進(jìn)行備份操作.這個(gè)功能的系統(tǒng)容載量可以很容易擴(kuò)容。
-----------------------------
精選高品質(zhì)二手iPhone,上愛鋒貝APP
您需要登錄后才可以回帖 登錄 | 立即注冊(cè)   

本版積分規(guī)則

QQ|Archiver|手機(jī)版|小黑屋|愛鋒貝 ( 粵ICP備16041312號(hào)-5 )

GMT+8, 2025-2-6 23:25

Powered by Discuz! X3.4

© 2001-2013 Discuz Team. 技術(shù)支持 by 巔峰設(shè)計(jì).

快速回復(fù) 返回頂部 返回列表