案例實(shí)戰(zhàn):實(shí)現(xiàn)互聯(lián)網(wǎng)驗(yàn)證碼保護(hù)服務(wù)
? ?通過(guò)對(duì)前面的線程池理論的學(xué)習(xí),我們通過(guò)一步一圖配合源碼,層層遞進(jìn)的方式對(duì)線程池進(jìn)行了抽絲剝繭式的剖析。想必你對(duì)線程池已經(jīng)建立了深入全面的認(rèn)識(shí),并且想要在實(shí)戰(zhàn)中應(yīng)用線程池解決實(shí)際問(wèn)題了。那么我們本節(jié)就滿足你的想法,讓我們利用線程池實(shí)現(xiàn)互聯(lián)網(wǎng)驗(yàn)證碼保護(hù)服務(wù)。
業(yè)務(wù)背景與實(shí)現(xiàn)思路
???????? 首先介紹一下業(yè)務(wù)背景,假設(shè)我們的系統(tǒng)是一個(gè)短視頻播放網(wǎng)站,每個(gè)新加入的用戶都需要注冊(cè)賬號(hào)并綁定手機(jī)號(hào)。為了驗(yàn)證用戶身份的可靠性實(shí)現(xiàn)手機(jī)號(hào)綁定,我們的系統(tǒng)會(huì)發(fā)送一條驗(yàn)證碼到用戶注冊(cè)時(shí)填寫(xiě)的手機(jī)上,用戶在有效期內(nèi)填寫(xiě)驗(yàn)證碼進(jìn)行認(rèn)證,通過(guò)認(rèn)證之后即綁定該手機(jī)號(hào)到用戶注冊(cè)的賬號(hào)上。完整的業(yè)務(wù)流程如圖1所示。

圖1
當(dāng)用戶注冊(cè)賬戶成功之后,需要發(fā)送短信驗(yàn)證碼,因此賬戶注冊(cè)流程中會(huì)調(diào)用驗(yàn)證碼發(fā)送模塊提供的驗(yàn)證碼發(fā)送服務(wù)。因此我們實(shí)現(xiàn)一個(gè)名為AsyncSmsVerificationCodePusher的服務(wù),對(duì)外提供驗(yàn)證碼生成和響應(yīng)的短信下發(fā)能力。最終調(diào)用第三方的短信推送服務(wù),觸達(dá)用戶。這里要注意的是,對(duì)接第三方短信推送服務(wù),需要提供接收短信的用戶手機(jī)號(hào)、驗(yàn)證碼內(nèi)容等信息,如圖2所示。

圖2
由于用戶注冊(cè)流程中,不止發(fā)送短信,還可能執(zhí)行其他的業(yè)務(wù)流程。并且發(fā)送短信本身屬于跨網(wǎng)絡(luò)服務(wù)調(diào)用,本質(zhì)上是一種網(wǎng)絡(luò)I/O操作,因此如果直接在業(yè)務(wù)主線程上直接同步阻塞式的調(diào)用驗(yàn)證碼發(fā)送模塊的發(fā)送短信接口,會(huì)影響到整個(gè)業(yè)務(wù)流程的處理效率,如果單位時(shí)間內(nèi)大量用戶涌入,會(huì)造成注冊(cè)接口響應(yīng)緩慢。這種情況肯定是會(huì)引起大量客訴的,這對(duì)于一個(gè)處于用戶拉新階段的視頻網(wǎng)站來(lái)說(shuō)是一個(gè)比較嚴(yán)重的事件,需要極力去避免。同步方式發(fā)送短信驗(yàn)證碼的業(yè)務(wù)流程如圖3所示。

圖3
因此我們考慮通過(guò)異步方式去進(jìn)行驗(yàn)證碼發(fā)送,在AsyncSmsVerificationCodePusher類(lèi)中通過(guò)定義一個(gè)專(zhuān)門(mén)的驗(yàn)證碼發(fā)送線程池來(lái)實(shí)現(xiàn)驗(yàn)證碼短信的發(fā)送。為了提高效率,我們定義一個(gè)專(zhuān)門(mén)的驗(yàn)證碼發(fā)送任務(wù)SmsVerificationCodeTask來(lái)實(shí)現(xiàn)驗(yàn)證碼生成、以及發(fā)送業(yè)務(wù)。代碼調(diào)用過(guò)程如圖4所示。

圖4
???對(duì)流程熟悉了之后,我們就開(kāi)始編寫(xiě)代碼實(shí)現(xiàn)這個(gè)業(yè)務(wù)流程吧。首先定義驗(yàn)證碼短信發(fā)送線程池,命名為SMS_SEND_THREAD_POOL,如圖5所示。
??

圖5
上圖5中,我們定義了一個(gè)自定義線程池,設(shè)置核心線程數(shù)為CPU個(gè)數(shù),最大線程數(shù)為50,這么設(shè)置的原因在于發(fā)送短信是一個(gè)I/O密集型的業(yè)務(wù)。
我們還定義了方法sendSmsVerificationCode,通過(guò)線程池提交短信驗(yàn)證碼發(fā)送任務(wù)SmsVerificationCodeTask。接著看一下SmsVerificationCodeTask的代碼實(shí)現(xiàn)。

圖6
圖6中SmsVerificationCodeTask實(shí)現(xiàn)了Runnable接口,在run方法中,我們實(shí)現(xiàn)了驗(yàn)證碼發(fā)送業(yè)務(wù)邏輯:
首先通過(guò)ThreadLocalRandom線程安全方式生成6位隨機(jī)數(shù),然后格式化為字符串;然后通過(guò)sendMessage方法將短信發(fā)送至對(duì)應(yīng)的手機(jī)號(hào),并進(jìn)行日志打印。
我們接著編寫(xiě)業(yè)務(wù)代碼調(diào)用短信發(fā)送服務(wù)模擬發(fā)送短信驗(yàn)證碼,代碼如圖7所示。

圖7
我們先創(chuàng)建了一個(gè)AsyncSmsVerificationCodePusher實(shí)例對(duì)象,然后生成了3個(gè)SmsVerificationCodeTask驗(yàn)證碼發(fā)送任務(wù),最后通過(guò)調(diào)用asyncSmsVerificationCodePusher對(duì)象引用的sendSmsVerificationCode方法通過(guò)自定義線程池提交了短信驗(yàn)證碼發(fā)送任務(wù)。日志打印如圖8所示。

圖8
???????? 到此為止,我們就通過(guò)線程池實(shí)現(xiàn)了發(fā)送互聯(lián)網(wǎng)短信驗(yàn)證碼保護(hù)服務(wù)。核心就是通過(guò)自定義線程池,異步提交驗(yàn)證碼發(fā)送任務(wù),實(shí)現(xiàn)了業(yè)務(wù)流程與驗(yàn)證碼發(fā)送流程的解耦,這種開(kāi)發(fā)方式在實(shí)戰(zhàn)中極為常用,希望你能夠掌握并靈活運(yùn)用。
