中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

小程序設(shè)計(jì)開(kāi)發(fā)國(guó)內(nèi)seo公司排名

小程序設(shè)計(jì)開(kāi)發(fā),國(guó)內(nèi)seo公司排名,app排名前100,網(wǎng)站管理方案目錄 一 協(xié)程的概述1.1 并行與并發(fā)1.2 線程1.3 新的思路1.4 Goroutine 二 第一個(gè)入門程序 一 協(xié)程的概述 我查看了網(wǎng)上的一些協(xié)程的資料,發(fā)現(xiàn)每個(gè)人對(duì)協(xié)程的概念都不一樣,但是我認(rèn)可的一種說(shuō)法是:協(xié)程就是一種輕量級(jí)的線程框架(K…

目錄

  • 一 協(xié)程的概述
    • 1.1 并行與并發(fā)
    • 1.2 線程
    • 1.3 新的思路
    • 1.4 Goroutine
  • 二 第一個(gè)入門程序

一 協(xié)程的概述

我查看了網(wǎng)上的一些協(xié)程的資料,發(fā)現(xiàn)每個(gè)人對(duì)協(xié)程的概念都不一樣,但是我認(rèn)可的一種說(shuō)法是:協(xié)程就是一種輕量級(jí)的線程框架(Kotlin),在我之前學(xué)到Akka框架,都是為了解決線程在高并發(fā)下能力不足的問(wèn)題,這里參考了一下大神的文章《并發(fā)之痛 Thread,Goroutine,Actor》,也許你會(huì)有更深的理解。
文章地址:并發(fā)之痛 Thread,Goroutine,Actor

1.1 并行與并發(fā)

image.png

  • 并發(fā)(concurrency) 并發(fā)的關(guān)注點(diǎn)在于任務(wù)切分。舉例來(lái)說(shuō),你是一個(gè)創(chuàng)業(yè)公司的CEO,開(kāi)始只有你一個(gè)人,你一人分飾多角,一會(huì)做產(chǎn)品規(guī)劃,一會(huì)寫代碼,一會(huì)見(jiàn)客戶,雖然你不能見(jiàn)客戶的同時(shí)寫代碼,但由于你切分了任務(wù),分配了時(shí)間片,表現(xiàn)出來(lái)好像是多個(gè)任務(wù)一起在執(zhí)行。
  • 并行(parallelism) 并行的關(guān)注點(diǎn)在于同時(shí)執(zhí)行。還是上面的例子,你發(fā)現(xiàn)你自己太忙了,時(shí)間分配不過(guò)來(lái),于是請(qǐng)了工程師,產(chǎn)品經(jīng)理,市場(chǎng)總監(jiān),各司一職,這時(shí)候多個(gè)任務(wù)可以同時(shí)執(zhí)行了。
  • 所以總結(jié)下,并發(fā)并不要求必須并行,可以用時(shí)間片切分的方式模擬,比如單核cpu上的多任務(wù)系統(tǒng),并發(fā)的要求是任務(wù)能切分成獨(dú)立執(zhí)行的片段。而并行關(guān)注的是同時(shí)執(zhí)行,必須是多(核)cpu,要能并行的程序必須是支持并發(fā)的。本文大多數(shù)情況下不會(huì)嚴(yán)格區(qū)分這兩個(gè)概念,默認(rèn)并發(fā)就是指并行機(jī)制下的并發(fā)。

1.2 線程

開(kāi)始我們的程序是面向過(guò)程的,數(shù)據(jù)結(jié)構(gòu)+func。后來(lái)有了面向?qū)ο?#xff0c;對(duì)象組合了數(shù)結(jié)構(gòu)和func,我們想用模擬現(xiàn)實(shí)世界的方式,抽象出對(duì)象,有狀態(tài)和行為。但無(wú)論是面向過(guò)程的func還是面向?qū)ο蟮膄unc,本質(zhì)上都是代碼塊的組織單元,本身并沒(méi)有包含代碼塊的并發(fā)策略的定義。于是為了解決并發(fā)的需求,引入了Thread(線程)的概念。
線程(Thread)

  1. 系統(tǒng)內(nèi)核態(tài),更輕量的進(jìn)程
  2. 由系統(tǒng)內(nèi)核進(jìn)行調(diào)度
  3. 同一進(jìn)程的多個(gè)線程可共享資源
  • 線程的出現(xiàn)解決了兩個(gè)問(wèn)題,一個(gè)是GUI出現(xiàn)后急切需要并發(fā)機(jī)制來(lái)保證用戶界面的響應(yīng)。第二是互聯(lián)網(wǎng)發(fā)展后帶來(lái)的多用戶問(wèn)題。
  • 最早的CGI程序很簡(jiǎn)單,將通過(guò)腳本將原來(lái)單機(jī)版的程序包裝在一個(gè)進(jìn)程里,來(lái)一個(gè)用戶就啟動(dòng)一個(gè)進(jìn)程。但明顯這樣承載不了多少用戶,并且如果進(jìn)程間需要共享資源還得通過(guò)進(jìn)程間的通信機(jī)制,線程的出現(xiàn)緩解了這個(gè)問(wèn)題。
  • 線程的使用比較簡(jiǎn)單,如果你覺(jué)得這塊代碼需要并發(fā),就把它放在單獨(dú)的線程里執(zhí)行,由系統(tǒng)負(fù)責(zé)調(diào)度,具體什么時(shí)候使用線程,要用多少個(gè)線程,由調(diào)用方?jīng)Q定,但定義方并不清楚調(diào)用方會(huì)如何使用自己的代碼,很多并發(fā)問(wèn)題都是因?yàn)檎`用導(dǎo)致的,比如Go中的map以及Java的HashMap都不是并發(fā)安全的,誤用在多線程環(huán)境就會(huì)導(dǎo)致問(wèn)題。另外也帶來(lái)復(fù)雜度:
  1. 競(jìng)態(tài)條件(race conditions) 如果每個(gè)任務(wù)都是獨(dú)立的,不需要共享任何資源,那線程也就非常簡(jiǎn)單。但世界往往是復(fù)雜的,總有一些資源需要共享,比如前面的例子,開(kāi)發(fā)人員和市場(chǎng)人員同時(shí)需要和CEO商量一個(gè)方案,這時(shí)候CEO就成了競(jìng)態(tài)條件。
  2. 依賴關(guān)系以及執(zhí)行順序 如果線程之間的任務(wù)有依賴關(guān)系,需要等待以及通知機(jī)制來(lái)進(jìn)行協(xié)調(diào)。比如前面的例子,如果產(chǎn)品和CEO討論的方案依賴于市場(chǎng)和CEO討論的方案,這時(shí)候就需要協(xié)調(diào)機(jī)制保證順序。

為了解決上述問(wèn)題,我們引入了許多復(fù)雜機(jī)制來(lái)保證:

  • Mutex(Lock) (Go里的sync包, Java的concurrent包)通過(guò)互斥量來(lái)保護(hù)數(shù)據(jù),但有了鎖,明顯就降低了并發(fā)度。
  • semaphore 通過(guò)信號(hào)量來(lái)控制并發(fā)度或者作為線程間信號(hào)(signal)通知。
  • volatile Java專門引入了volatile關(guān)鍵詞來(lái),來(lái)降低只讀情況下的鎖的使用。
  • compare-and-swap 通過(guò)硬件提供的CAS機(jī)制保證原子性(atomic),也是降低鎖的成本的機(jī)制。

如果說(shuō)上面兩個(gè)問(wèn)題只是增加了復(fù)雜度,我們通過(guò)深入學(xué)習(xí),嚴(yán)謹(jǐn)?shù)腃odeReview,全面的并發(fā)測(cè)試(比如Go語(yǔ)言中單元測(cè)試的時(shí)候加上-race參數(shù)),一定程度上能解決(當(dāng)然這個(gè)也是有爭(zhēng)議的,有論文認(rèn)為當(dāng)前的大多數(shù)并發(fā)程序沒(méi)出問(wèn)題只是并發(fā)度不夠,如果CPU核數(shù)繼續(xù)增加,程序運(yùn)行的時(shí)間更長(zhǎng),很難保證不出問(wèn)題)。但最讓人頭痛的還是下面這個(gè)問(wèn)題:
系統(tǒng)里到底需要多少線程?
這個(gè)問(wèn)題我們先從硬件資源入手,考慮下線程的成本:

  • 內(nèi)存(線程的棧空間) 每個(gè)線程都需要一個(gè)棧(Stack)空間來(lái)保存掛起(suspending)時(shí)的狀態(tài)。Java的??臻g(64位VM)默認(rèn)是1024k,不算別的內(nèi)存,只是棧空間,啟動(dòng)1024個(gè)線程就要1G內(nèi)存。雖然可以用-Xss參數(shù)控制,但由于線程是本質(zhì)上也是進(jìn)程,系統(tǒng)假定是要長(zhǎng)期運(yùn)行的,棧空間太小會(huì)導(dǎo)致稍復(fù)雜的遞歸調(diào)用(比如復(fù)雜點(diǎn)的正則表達(dá)式匹配)導(dǎo)致棧溢出。所以調(diào)整參數(shù)治標(biāo)不治本。
  • 調(diào)度成本(context-switch) 我在個(gè)人電腦上做的一個(gè)非嚴(yán)格測(cè)試,模擬兩個(gè)線程互相喚醒輪流掛起,線程切換成本大約6000納秒/次。這個(gè)還沒(méi)考慮棧空間大小的影響。國(guó)外一篇論文專門分析線程切換的成本,基本上得出的結(jié)論是切換成本和棧空間使用大小直接相關(guān)。image.png
  • CPU使用率 我們搞并發(fā)最主要的一個(gè)目標(biāo)就是我們有了多核,想提高CPU利用率,最大限度的壓榨硬件資源,從這個(gè)角度考慮,我們應(yīng)該用多少線程呢?image.png這個(gè)我們可以通過(guò)一個(gè)公式計(jì)算出來(lái),100/(15+5)*4=20,用20個(gè)線程最合適。但一方面網(wǎng)絡(luò)的時(shí)間不是固定的,另外一方面,如果考慮到其他瓶頸資源呢?比如鎖,比如數(shù)據(jù)庫(kù)連接池,就會(huì)更復(fù)雜。

作為一個(gè)1歲多孩子的父親,認(rèn)為這個(gè)問(wèn)題的難度好比你要寫個(gè)給孩子喂飯的程序,需要考慮『給孩子喂多少飯合適?』,這個(gè)問(wèn)題有以下回答以及策略:

  • 孩子不吃了就好了(但孩子貪玩,不吃了可能是想去玩了)
  • 孩子吃飽了就好了(廢話,你怎么知道孩子吃飽了?孩子又不會(huì)說(shuō)話)
  • 逐漸增量,長(zhǎng)期觀察,然后計(jì)算一個(gè)平均值(這可能是我們調(diào)整線程常用的策略,但增量增加到多少合適呢?)
  • 孩子吃吐了就別喂了(如果用逐漸增量的模式,通過(guò)外部觀察,可能會(huì)到達(dá)這個(gè)邊界條件。系統(tǒng)性能如果因?yàn)榫€程的增加倒退了,就別增加線程了)
  • 沒(méi)控制好邊界,把孩子給給撐壞了 (這熊爸爸也太恐怖了。但調(diào)整線程的時(shí)候往往不小心可能就把系統(tǒng)搞掛了)

通過(guò)這個(gè)例子我們可以看出,從外部系統(tǒng)來(lái)觀察,或者以經(jīng)驗(yàn)的方式進(jìn)行計(jì)算,都是非常困難的。于是結(jié)論是:
讓孩子會(huì)說(shuō)話,吃飽了自己說(shuō),自己學(xué)會(huì)吃飯,自管理是最佳方案。
然并卵,計(jì)算機(jī)不會(huì)自己說(shuō)話,如何自管理?
但我們從以上的討論可以得出一個(gè)結(jié)論:

  • 線程的成本較高(內(nèi)存,調(diào)度)不可能大規(guī)模創(chuàng)建
  • 應(yīng)該由語(yǔ)言或者框架動(dòng)態(tài)解決這個(gè)問(wèn)題

線程池方案


Java1.5后,Doug Lea的Executor系列被包含在默認(rèn)的JDK內(nèi),是典型的線程池方案。
線程池一定程度上控制了線程的數(shù)量,實(shí)現(xiàn)了線程復(fù)用,降低了線程的使用成本。但還是沒(méi)有解決數(shù)量的問(wèn)題,線程池初始化的時(shí)候還是要設(shè)置一個(gè)最小和最大線程數(shù),以及任務(wù)隊(duì)列的長(zhǎng)度,自管理只是在設(shè)定范圍內(nèi)的動(dòng)態(tài)調(diào)整。另外不同的任務(wù)可能有不同的并發(fā)需求,為了避免互相影響可能需要多個(gè)線程池,最后導(dǎo)致的結(jié)果就是Java的系統(tǒng)里充斥了大量的線程池。

1.3 新的思路

從前面的分析我們可以看出,如果線程是一直處于運(yùn)行狀態(tài),我們只需設(shè)置和CPU核數(shù)相等的線程數(shù)即可,這樣就可以最大化的利用CPU,并且降低切換成本以及內(nèi)存使用。但如何做到這一點(diǎn)呢?
陳力就列,不能者止
這句話是說(shuō),能干活的代碼片段就放在線程里,如果干不了活(需要等待,被阻塞等),就摘下來(lái)。通俗的說(shuō)就是不要占著茅坑不拉屎,如果拉不出來(lái),需要醞釀下,先把茅坑讓出來(lái),因?yàn)槊┛邮窍∪辟Y源。
要做到這點(diǎn)一般有兩種方案:

  1. 異步回調(diào)方案 典型如NodeJS,遇到阻塞的情況,比如網(wǎng)絡(luò)調(diào)用,則注冊(cè)一個(gè)回調(diào)方法(其實(shí)還包括了一些上下文數(shù)據(jù)對(duì)象)給IO調(diào)度器(linux下是libev,調(diào)度器在另外的線程里),當(dāng)前線程就被釋放了,去干別的事情了。等數(shù)據(jù)準(zhǔn)備好,調(diào)度器會(huì)將結(jié)果傳遞給回調(diào)方法然后執(zhí)行,執(zhí)行其實(shí)不在原來(lái)發(fā)起請(qǐng)求的線程里了,但對(duì)用戶來(lái)說(shuō)無(wú)感知。但這種方式的問(wèn)題就是很容易遇到callback hell,因?yàn)樗械淖枞僮鞫急仨毊惒?#xff0c;否則系統(tǒng)就卡死了。還有就是異步的方式有點(diǎn)違反人類思維習(xí)慣,人類還是習(xí)慣同步的方式。
  2. GreenThread/Coroutine/Fiber方案 這種方案其實(shí)和上面的方案本質(zhì)上區(qū)別不大,關(guān)鍵在于回調(diào)上下文的保存以及執(zhí)行機(jī)制。為了解決回調(diào)方法帶來(lái)的難題,這種方案的思路是寫代碼的時(shí)候還是按順序?qū)?#xff0c;但遇到IO等阻塞調(diào)用時(shí),將當(dāng)前的代碼片段暫停,保存上下文,讓出當(dāng)前線程。等IO事件回來(lái),然后再找個(gè)線程讓當(dāng)前代碼片段恢復(fù)上下文繼續(xù)執(zhí)行,寫代碼的時(shí)候感覺(jué)好像是同步的,仿佛在同一個(gè)線程完成的,但實(shí)際上系統(tǒng)可能切換了線程,但對(duì)程序無(wú)感。

GreenThread

  • 用戶空間 首先是在用戶空間,避免內(nèi)核態(tài)和用戶態(tài)的切換導(dǎo)致的成本。
  • 由語(yǔ)言或者框架層調(diào)度
  • 更小的??臻g允許創(chuàng)建大量實(shí)例(百萬(wàn)級(jí)別)

幾個(gè)概念

  • Continuation 這個(gè)概念不熟悉FP編程的人可能不太熟悉,不過(guò)這里可以簡(jiǎn)單的顧名思義,可以理解為讓我們的程序可以暫停,然后下次調(diào)用繼續(xù)(contine)從上次暫停的地方開(kāi)始的一種機(jī)制。相當(dāng)于程序調(diào)用多了一種入口。
  • Coroutine 是Continuation的一種實(shí)現(xiàn),一般表現(xiàn)為語(yǔ)言層面的組件或者類庫(kù)。主要提供yield,resume機(jī)制。
  • Fiber 和Coroutine其實(shí)是一體兩面的,主要是從系統(tǒng)層面描述,可以理解成Coroutine運(yùn)行之后的東西就是Fiber。

1.4 Goroutine


Goroutine其實(shí)就是前面GreenThread系列解決方案的一種演進(jìn)和實(shí)現(xiàn)。

  • 首先,它內(nèi)置了Coroutine機(jī)制。因?yàn)橐脩魬B(tài)的調(diào)度,必須有可以讓代碼片段可以暫停/繼續(xù)的機(jī)制。
  • 其次,它內(nèi)置了一個(gè)調(diào)度器,實(shí)現(xiàn)了Coroutine的多線程并行調(diào)度,同時(shí)通過(guò)對(duì)網(wǎng)絡(luò)等庫(kù)的封裝,對(duì)用戶屏蔽了調(diào)度細(xì)節(jié)。
  • 最后,提供了Channel機(jī)制,用于Goroutine之間通信,實(shí)現(xiàn)CSP并發(fā)模型(Communicating Sequential Processes)。
  • 因?yàn)镚o的Channel是通過(guò)語(yǔ)法關(guān)鍵詞提供的,對(duì)用戶屏蔽了許多細(xì)節(jié)。其實(shí)Go的Channel和Java中的SynchronousQueue是一樣的機(jī)制,如果有buffer其實(shí)就是ArrayBlockQueue。

Goroutine調(diào)度器
image.png
這個(gè)圖一般講Goroutine調(diào)度器的地方都會(huì)引用,想要仔細(xì)了解的可以看看原博客。這里只說(shuō)明幾點(diǎn):

  1. M代表系統(tǒng)線程,P代表處理器(核),G代表Goroutine。Go實(shí)現(xiàn)了M:N的調(diào)度,也就是說(shuō)線程和Goroutine之間是多對(duì)多的關(guān)系。這點(diǎn)在許多GreenThread/Coroutine的調(diào)度器并沒(méi)有實(shí)現(xiàn)。比如Java1.1版本之前的線程其實(shí)是GreenThread(這個(gè)詞就來(lái)源于Java),但由于沒(méi)實(shí)現(xiàn)多對(duì)多的調(diào)度,也就是沒(méi)有真正實(shí)現(xiàn)并行,發(fā)揮不了多核的優(yōu)勢(shì),所以后來(lái)改成基于系統(tǒng)內(nèi)核的Thread實(shí)現(xiàn)了。
  2. 某個(gè)系統(tǒng)線程如果被阻塞,排列在該線程上的Goroutine會(huì)被遷移。當(dāng)然還有其他機(jī)制,比如M空閑了,如果全局隊(duì)列沒(méi)有任務(wù),可能會(huì)從其他M偷任務(wù)執(zhí)行,相當(dāng)于一種rebalance機(jī)制。這里不再細(xì)說(shuō),有需要看專門的分析文章。
  3. 具體的實(shí)現(xiàn)策略和我們前面分析的機(jī)制類似。系統(tǒng)啟動(dòng)時(shí),會(huì)啟動(dòng)一個(gè)獨(dú)立的后臺(tái)線程(不在Goroutine的調(diào)度線程池里),啟動(dòng)netpoll的輪詢。當(dāng)有Goroutine發(fā)起網(wǎng)絡(luò)請(qǐng)求時(shí),網(wǎng)絡(luò)庫(kù)會(huì)將fd(文件描述符)和pollDesc(用于描述netpoll的結(jié)構(gòu)體,包含因?yàn)樽x/寫這個(gè)fd而阻塞的Goroutine)關(guān)聯(lián)起來(lái),然后調(diào)用runtime.gopark方法,掛起當(dāng)前的Goroutine。當(dāng)后臺(tái)的netpoll輪詢獲取到epoll(linux環(huán)境下)的event,會(huì)將event中的pollDesc取出來(lái),找到關(guān)聯(lián)的阻塞Goroutine,并進(jìn)行恢復(fù)。

Goroutine是銀彈么?
Goroutine很大程度上降低了并發(fā)的開(kāi)發(fā)成本,是不是我們所有需要并發(fā)的地方直接go func就搞定了呢?
Go通過(guò)Goroutine的調(diào)度解決了CPU利用率的問(wèn)題。但遇到其他的瓶頸資源如何處理?比如帶鎖的共享資源,比如數(shù)據(jù)庫(kù)連接等?;ヂ?lián)網(wǎng)在線應(yīng)用場(chǎng)景下,如果每個(gè)請(qǐng)求都扔到一個(gè)Goroutine里,當(dāng)資源出現(xiàn)瓶頸的時(shí)候,會(huì)導(dǎo)致大量的Goroutine阻塞,最后用戶請(qǐng)求超時(shí)。這時(shí)候就需要用Goroutine池來(lái)進(jìn)行控流,同時(shí)問(wèn)題又來(lái)了:池子里設(shè)置多少個(gè)Goroutine合適?

二 第一個(gè)入門程序

  • https://github.com/Kotlin/kotlinx.coroutines

maven

<dependency><groupId>org.jetbrains.kotlinx</groupId><artifactId>kotlinx-coroutines-core</artifactId><version>1.7.3</version>
</dependency>
  • 測(cè)試案例
/*** @description:* @author: shu* @createDate: 2023/8/10 20:32* @version: 1.0*/
import kotlinx.coroutines.*@OptIn(DelicateCoroutinesApi::class)
fun main() {GlobalScope.launch {// 在后臺(tái)啟動(dòng)一個(gè)新協(xié)程,并繼續(xù)執(zhí)行之后的代碼delay(1000L)// 非阻塞式地延遲一秒println("World!")// 延遲結(jié)束后打印}println("Hello,")//主線程繼續(xù)執(zhí)行,不受協(xié)程 delay 所影響Thread.sleep(2000L)
// 主線程阻塞式睡眠2秒,以此來(lái)保證JVM存活
}

在這里插入圖片描述

協(xié)程在 CoroutineScope (協(xié)程作用域)的上下文中通過(guò) launch、async 等協(xié)程構(gòu)造器(coroutine builder)來(lái)啟動(dòng),哈哈第一個(gè)入門程序我們就寫完了,看起來(lái)還是特別簡(jiǎn)單,這里推薦一個(gè)視頻來(lái)了解攜程

  • https://www.bilibili.com/video/BV1KJ41137E9(凱哥)
http://www.risenshineclean.com/news/30008.html

相關(guān)文章:

  • 免費(fèi)做電腦網(wǎng)站網(wǎng)站視頻
  • 零基礎(chǔ)怎么開(kāi)網(wǎng)店seo短視頻網(wǎng)頁(yè)入口引流下載
  • wordpress多賬號(hào)權(quán)限天津seo優(yōu)化
  • 網(wǎng)站建設(shè)用哪種語(yǔ)言最好深圳網(wǎng)絡(luò)營(yíng)銷怎么推廣
  • 什么叫網(wǎng)站建設(shè)手機(jī)怎么建網(wǎng)站
  • 網(wǎng)站架設(shè)客服QQ百度熱搜 百度指數(shù)
  • 教育企業(yè)重慶網(wǎng)站建設(shè)動(dòng)態(tài)網(wǎng)站設(shè)計(jì)畢業(yè)論文
  • 鄂爾多斯網(wǎng)站建設(shè)百度提交網(wǎng)站入口
  • 城鄉(xiāng)建設(shè)網(wǎng)站報(bào)建需要什么網(wǎng)絡(luò)產(chǎn)品及其推廣方法
  • 搭建網(wǎng)站找什么公司銷售網(wǎng)站排名
  • 網(wǎng)站建設(shè) 關(guān)于我們百度 seo 工具
  • 專業(yè)網(wǎng)站建設(shè)好不好越秀seo搜索引擎優(yōu)化
  • 滄州哪里可以做網(wǎng)站中山seo排名
  • 網(wǎng)站url改版百度推廣年費(fèi)多少錢
  • 家庭寬帶 做網(wǎng)站在哪里查關(guān)鍵詞排名
  • 網(wǎng)站群建設(shè)報(bào)價(jià)seo優(yōu)化就業(yè)前景
  • 東營(yíng)做網(wǎng)站建設(shè)的公司友鏈網(wǎng)站
  • it運(yùn)維培訓(xùn)怎么做優(yōu)化關(guān)鍵詞
  • c 新手一個(gè)人做網(wǎng)站湖北seo公司
  • 民權(quán)平臺(tái)網(wǎng)站建設(shè)銷售人員培訓(xùn)課程有哪些
  • 關(guān)鍵詞優(yōu)化排名用哪個(gè)軟件比較好南京百度seo排名優(yōu)化
  • 網(wǎng)站建設(shè) 從用戶角度開(kāi)始網(wǎng)站建設(shè)及推廣優(yōu)化
  • 網(wǎng)站優(yōu)化公司 網(wǎng)絡(luò)服務(wù)產(chǎn)品運(yùn)營(yíng)推廣方案
  • 成都都江堰網(wǎng)站建設(shè)廣告媒體資源平臺(tái)
  • 重慶網(wǎng)站服務(wù)器建設(shè)推薦萬(wàn)網(wǎng)
  • 百競(jìng)(湘潭)網(wǎng)站建設(shè)網(wǎng)站seo哪家做的好
  • 網(wǎng)站小圖標(biāo)素材下載汕頭百度seo公司
  • 網(wǎng)站公司鄭州百度關(guān)鍵詞優(yōu)化公司
  • 上海平臺(tái)有限公司seo的公司排名
  • 世界做詭異的地方網(wǎng)站站長(zhǎng)工具seo綜合查詢收費(fèi)嗎