Worktile中百萬級實時消息推送服務的實現

2021-01-11 CSDN技術社區

在團隊協同工具 Worktile的使用過程中,你會發現無論是右上角的消息通知,還是在任務面板中拖動任務,還有用戶的在線狀態,都是實時刷新。Worktile中的推送服務是採用的是基於XMPP協議、Erlang語言實現的Ejabberd,並在其源碼基礎上,結合我們的業務,對源碼作了修改以適配我們自身的需求。另外,基於AMQP協議也可以作為實時消息推送的一種選擇,踢踢網就是採用 RabbitMQ+STOMP協議實現的消息推送服務。本文將結合我在Worktile和踢踢網的項目實踐,介紹下消息推送服務的具體實現。

實時推送的幾種實現方式

相較於手機端的消息推送(一般都是以Socket方式實現),WEB端是基於HTTP協議,很難像TCP一樣保持長連接。但隨著技術的發展,出現了WebSocket,Comet等新的技術可以達到類似長連接的效果,這些技術大體可分為以下幾類:

1)短輪詢。頁面端通過JS定時異步刷新,這種方式實時效果較差。

2)長輪詢。頁面端通過JS異步請求服務端,服務端在接收到請求後,如果該次請求沒有數據,則掛起這次請求,直到有數據到達或時間片(服務端設定)到,則返回本次請求,客戶端接著下一次請求。示例如下:

3)WebSocket。瀏覽器通過WebSocket協議連接服務端,實現了瀏覽器和伺服器端的全雙工通信。需要服務端和瀏覽器都支持WebSocket協議。

以上幾種方式中,方式1實現較簡單,但效率和實時效果較差。方式2對服務端實現的要求比較高,尤其是並發量大的情況下,對服務端的壓力很大。方式3效率較高,但對較低版本的瀏覽器不支持,另外服務端也需要有支持WebSocket的實現。Worktile的WEB端實時消息推送,採用的是XMPP擴展協議XEP-0124 BOSH( http://xmpp.org/extensions/xep-0124.html),本質是採用方式2長輪詢的方式。踢踢網則採用了WebSocket連接RabbitMQ的方式實現,下面我會具體介紹如何用這兩種方式實現Server Push。

運行時環境準備

服務端的實現中,無論採用Ejabberd還是RabbitMQ,都是基於Erlang語言開發的,所以必須安裝Erlang運行時環境。Erlang是一種函數式語言,具有容錯、高並發的特點,藉助OTP的函數庫,很容易構建一個健壯的分布式系統。目前,基於Erlang開發的產品有,資料庫方面:Riak(Dynamo實現)、CouchDB, Webserver方面:Cowboy、Mochiweb, 消息中間件有RabbitMQ等。對於服務端程式設計師來說,Erlang提供的高並發、容錯、熱部署等特性是其他語言無法達到的。無論在實時通信還是在遊戲程序中,用Erlang可以很容易為每一個上線用戶創建一個對應的Process,對一臺4核8個G的伺服器來說,承載上百萬個這樣的Process是非常輕鬆的事。下圖是Erlang程序發起Process的一般性示意圖:

如圖所示,Session Manager(or Gateway)負責為每個用戶(UID)創建相對應的Process, 並把這個對應關係(MAP)存放到數據表中。每個Process則對應用戶數據,並且他們之間可以相互發送消息。Erlang的優勢就是在內存足夠的情況下創建上百萬個這樣的Process,而且它的創建和銷毀比JAVA的Thread要輕量的多,兩者不是一個數量級的。

好了,我們現在開始著手Erlang環境的搭建(實驗的系統為Ubuntu 12.04, 4核8個G內存):

1、依賴庫安裝

sudo apt-get install build-essentialsudo apt-get install libncurses5-devsudo apt-get install libssl-dev libyaml-devsudo apt-get install m4sudo apt-get install unixodbc unixodbc-devsudo apt-get install freeglut3-dev libwxgtk2.8-devsudo apt-get install xsltprocsudo apt-get install fop tk8.5 libxml2-utils

2、官網下載OTP源碼包(

http://www.erlang.org/download.html

), 解壓並安裝:

tar zxvf otpsrcR16B01.tar.gzcd otpsrcR16B01configuremake & make install

至此,erlang運行環境就完成了。下面將分別介紹rabbitmq和ejabberd構建實時消息服務。

基於RabbitMQ的實時消息服務

RabbitMQ是在業界廣泛應用的消息中間件,也是對AMQP協議實現最好的一種中間件。AMQP協議中定義了Producer、 Consumer、MessageQueue、Exchange、Binding、Virtual Host等實體,他們的關係如下圖所示:


消息發布者(Producer)連接交換器(Exchange), 交換器和消息隊列(Message Queue)通過KEY進行Binding,Binding是根據Exchange的類型(分為Fanout、Direct、Topic、Header)分別對消息作不同形式的派發。Message Queue又分為Durable、Temporary、Auto-Delete三種類型,Durable Queue是持久化隊列,不會因為服務ShutDown而消失,Temporary Queue則服務重啟後會消失,Auto-Delete則是在沒有Consumer連接時自動刪除。另外RabbitMQ有很多第三方插件,可以基於AMQP協議基礎之上做出很多擴展的應用。下面我們將介紹WEB STOMP插件構建基於AMQP之上的STOMP文本協議,通過瀏覽器WebSocket達到實時的消息傳輸。系統的結構如圖:


如圖所示,WEB端我們使用STOMP.JS和SockJS.JS與RabbitMQ的WEB STOMP Plugin通信,手機端可以用STOMPj, Gozirra(Android)或者Objc-STOMP(IOS)通過STOMP協議與RabbitMQ收發消息。因為我們是實時消息系統通常都是要與已有的用戶系統結合,RabbitMQ可以通過第三方插件RabbitMQ-AYTH-Backend-HTTP來適配已有的用戶系統,這個插件可以通過HTTP接口完成用戶連接時的認證過程。當然,認證方式還有LDAP等其他方式。下面介紹具體步驟:

從官網( http://rabbitmq.com/download.html)下載最新版本的源碼包,解壓並安裝:

tar zxf rabbitmq-server-x.x.x.tar.gzcd rabbitmq-server-x.x.xmake & make install

為RabbitMQ安裝WEB-STOMP插件

cd /path/to/your/rabbitmq./sbin/rabbitmq-plugins enable rabbitmq_web_stomp./sbin/rabbitmq-plugins enable rabbitmq_web_stomp_examples./sbin/rabbitmqctl stop./sbin/rabbitmqctl start./sbin/rabbitmqctl status

將會顯示下圖所示的運行的插件列表

安裝用戶授權插件

cd /path/to/your/rabbitmq/pluginswget <a href="http://www.rabbitmq.com/community-plugins/v3.3.x/rabbitmq_auth_backend_http-3.3.x-e7ac6289.ez">http://www.rabbitmq.com/community-plugins/v3.3.x/rabbitmq_auth_backend_http-3.3.x-e7ac6289.ez</a>cd .../sbin/rabbitmq-plugins enable rabbitmq_auth_backend_http

編輯RabbitMQ.Config文件(默認存放於/ECT/RabbitMQ/下),添加:

[ ... {rabbit, [{auth_backends, [rabbit_auth_backend_http]}]}, ... {rabbitmq_auth_backend_http, [{user_path, 「http://your-server/auth/user」}, {vhost_path, 「http://your-server/auth/vhost」}, {resource_path, 「http://your-server/auth/resource」} ]} ...].

其中,User_Path是根據用戶名密碼進行校驗,VHOST_Path是校驗是否有權限訪問VHOST, Resource_Path是校驗用戶對傳入的Exchange、Queue是否有權限。我下面的代碼是用Node.js實現的這三個接口的示例:

var express = require('express'); var app = express(); app.get('/auth/user', function(req, res){ var name = req.query.username; var pass = req.query.password; console.log("name : " + name + ", pass : " + pass); if(name === 'guest' && pass === "guest"){ console.log("allow"); res.send("allow"); }else{ res.send('deny'); } }); app.get('/auth/vhost', function(req, res){ console.log("/auth/vhost"); res.send("allow"); }); app.get('/auth/resource', function(req, res){ console.log("/auth/resource"); res.send("allow"); }); app.listen(3000);

瀏覽器端JS實現,示例代碼如下:

...... var ws = new SockJS('http://' + window.location.hostname + ':15674/stomp'); var client = Stomp.over(ws); // SockJS does not support heart-beat: disable heart-beats client.heartbeat.outgoing = 0; client.heartbeat.incoming = 0; client.debug = pipe('#second'); var print_first = pipe('#first', function(data) { client.send('/exchange/feed/user_x', {"content-type":"text/plain"}, data); }); var on_connect = function(x) { id = client.subscribe("/exchange/feed/user_x", function(d) { print_first(d.body); }); }; var on_error = function() { console.log('error'); }; client.connect('guest1', 'guest1', on_connect, on_error, '/'); ......

需要說明的時,在這裡我們首先要在RabbitMQ實例中創建Feed這個Exchange,我們用STOMP.JS連接成功後,根據當前登陸用戶的ID(user_x)綁定到這個Exchange,即Subscribe(「/exchange/feed/user_x」, …) 這個操作的行為,這樣在向RabbitMQ中Feed Exchange發送消息並指定用戶ID(user_x)為KEY,頁面端就會通過WEB Socket實時接收到這條消息。

到目前為止,基於RabbitMQ+STOMP實現WEB端消息推送就已經完成,其中很多的細節需要小夥伴們親自去實踐了,這裡就不多說了。實踐過程中可以參照官方文檔:

http://rabbitmq.com/stomp.html
http://rabbitmq.com/web-stomp.html
https://github.com/simonmacmullen/rabbitmq-auth-backend-http

以上的實現是我本人在踢踢網時採用的方式,下面接著介紹一下現在在Worktile中如何通過Ejabberd實現消息推送。

基於Ejabberd的實時消息推送

與RabbitMQ不同,Ejabberd是XMPP協議的一種實現,與AMQP相比,XMPP廣泛應用於即時通信領域。XMPP協議的實現有很多種,比如JAVA的OpenFire,但相較其他實現,Ejabberd的並發性能無疑使最優秀的。XMPP協議的前身是Jabber協議,早期的Jabber協議主要包括在線狀態(Presence)、好友花名冊(Roster)、IQ(Info/Query)幾個部分。現在Jabber已經成為RFC的官方標準,如RFC2799,RFC4622,RFC6121,以及XMPP的擴展協議(XEP)。Worktile Web端的消息提醒功能就是基於XEP-0124、XEP-0206定義的BOSH擴展協議。

由於自身業務的需要,我們對Ejabberd的用戶認證和好友列表模塊的源碼進行修改,通過Redis保存用戶的在線狀態,而不是Mnesia和MySQL。另外好友這塊我們是從已有的資料庫中(MongoDB)中獲取項目或團隊的成員。Web端通過Strophe.JS來連接(HTTP-BIND),Strophe.JS可以以長輪詢和WebSocket兩種方式來連接,由於Ejabberd還沒有好的WebSocket的實現,就採用了BOSH的方式模擬長連接。整個系統的結構如下:

Web端用Strophe.JS通過HTTP-BIND進行連接Nginx代理,Nginx反向代理EjabberdCluster。iOS用XMPP-FramWork連接, Android可以用Smack直接連Ejabberd伺服器集群。這些都是現有的庫,無需對Client進行開發。在線狀態根據用戶UID作為KEY定義了在線、離線、忙等狀態存放於Redis中。好友列表從MongoDB的Project表中獲取。用戶認證直接修改了Ejabberd_Auth_Internal.erl文件,通過MongoDB驅動連接用戶庫,在線狀態等功能是新加了模塊,其部分代碼如下:

-module(wt_mod_proj). -behaviour(gen_mod). -behaviour(gen_server). -include("ejabberd.hrl"). -include("logger.hrl"). -include("jlib.hrl"). -define(SUPERVISOR, ejabberd_sup). ... -define(ONLINE, 1). -define(OFFLINE, 0). -define(BUSY, 2). -define(LEAVE, 3). ... %% API -export([start_link/2, get_proj_online_users/2]). %% gen_mod callbacks -export([start/2, stop/1]). %% gen_server callbacks -export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2, code_change/3]). %% Hook callbacks -export([user_available/1, unset_presence/3, set_presence/4]). -export([get_redis/1, remove_online_user/3, append_online_user/3]). ... -record(state,{host = <<"">>, server_host, rconn, mconn}).start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). user_available(New) -> LUser = New#jid.luser, LServer = New#jid.lserver, Proc = gen_mod:get_module_proc(LServer, ?MODULE), gen_server:cast(Proc, {user_available, LUser, LServer}).append_online_user(Uid, Proj, Host) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), gen_server:call(Proc, {append_online_user, Uid, Proj}). remove_online_user(Uid, Proj, Host) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), gen_server:call(Proc, {remove_online_user, Uid, Proj}). ... set_presence(User, Server, Resource, Packet) -> Proc = gen_mod:get_module_proc(Server, ?MODULE), gen_server:cast(Proc, {set_presence, User, Server, Resource, Packet}). ...start(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, transient, 2000, worker, [?MODULE]}, supervisor:start_child(?SUPERVISOR, ChildSpec).stop(Host) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), gen_server:call(Proc, stop), supervisor:delete_child(?SUPERVISOR, Proc).init([Host, Opts]) -> MyHost = gen_mod:get_opt_host(Host, Opts, <<"wtmuc.@HOST@">>), RedisHost = gen_mod:get_opt(redis_host, Opts, fun(B) -> B end,?REDIS_HOST), RedisPort = gen_mod:get_opt(redis_port, Opts, fun(I) when is_integer(I), I>0 -> I end, ?REDIS_PORT), ejabberd_hooks:add(set_presence_hook, Host, ?MODULE, set_presence, 100), ejabberd_hooks:add(user_available_hook, Host, ?MODULE, user_available, 50), ejabberd_hooks:add(sm_remove_connection_hook, Host, ?MODULE, unset_presence, 50), MongoHost = gen_mod:get_opt(mongo_host, Opts, fun(B) -> binary_to_list(B) end, ?MONGO_HOST), MongoPort = gen_mod:get_opt(mongo_port, Opts, fun(I) when is_integer(I), I>0 -> I end, ?MONGO_PORT), {ok, Mongo} = mongo_connection:start_link({MongoHost, MongoPort}), C = c(RedisHost, RedisPort), ejabberd_router:register_route(MyHost), {ok, #state{host = Host, server_host = MyHost, rconn = C, mconn = Mongo}}. terminate(_Reason, #state{host = Host, rconn = C, mconn = Mongo}) -> ejabberd_hooks:delete(set_presence_hook, Host, ?MODULE, set_presence, 100), ejabberd_hooks:delete(user_available_hook, Host, ?MODULE, user_available, 50), ejabberd_hooks:delete(unset_presence_hook, Host, ?MODULE, unset_presence, 50), eredis:stop(C), ok. ... handle_call({append_online_user, Uid, ProjId}, _From, State) -> C = State#state.rconn, Key = <<!--?PRE_RPOJ_ONLINE_USERS /binary, ProjId/binary-->>, Resp = eredis:q(C, ["SADD", Key, Uid]), {reply, Resp, State}; handle_call({remove_online_user, Uid, ProjId}, _From, State) -> ... handle_call({get_proj_online_users, ProjId}, _From, State) -> ... handle_cast({set_presence, User, Server, Resource, Packet}, #state{mconn = Mongo} = State) -> C = State#state.rconn, Key = <<!--?USER_PRESENCE /binary, User/binary-->>, Pids = get_user_projs(User, Mongo), Cmd = get_proj_key(Pids, ["SUNION"]), case xml:get_subtag_cdata(Packet, <<"show">>) of <<"away">> -> eredis:q(C, ["SET", Key, ?LEAVE]); <<"offline">> -> ... handle_cast(_Msg, State) -> {noreply, State}.handle_info({route, From, To, Packet}, #state{host = Host, server_host = MyHost, rconn = RedisConn, mconn = Mongo} = State) -> case catch do_route(Host, MyHost, From, To, Packet, RedisConn, Mongo) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); _ -> ok end, {noreply, State};handle_info(_Info, State) -> {noreply, State}.code_change(_OldVsn, State, _Extra) -> {ok, State}. ...

其中,User\_Available\_HOOK和SM\_Remove\_Connection\_HOOK 就是用戶上線和用戶斷開連接觸發的事件,Ejabberd 中正是由於這些HOOK,才能很容易擴展功能。

在用Tsung對Ejabberd進行壓力測試,測試機器為4核心8G內存的普通PC,以3臺客戶機模擬用戶登錄、設置在線狀態、發送一條文本消息、關閉連接操作,在同時在線達到30w時,CPU佔用不到3%,內存大概到3個G左右,隨著用戶數增多,主要內存的損耗較大。由於壓力測試比較耗時,再等到有時間的時候,會在做一些更深入的測試。

免費訂閱「CSDN雲計算(左)和CSDN大數據(右)」微信公眾號,實時掌握第一手雲中消息,了解最新的大數據進展!

CSDN發布虛擬化、Docker、OpenStack、CloudStack、數據中心等相關雲計算資訊,     分享Hadoop、Spark、NoSQL/NewSQL、HBase、Impala、內存計算、流計算、機器學習和智能算法等相關大數據觀點,提供雲計算和大數據技術、平臺、實踐和產業信息等服務。        

相關焦點

  • ...雲開發即將發布實時數據推送服務,再也不用自己搭建WebSocket了
    受訪嘉賓 | 周子傑作者 | Yonie小程序雲開發 - 實時數據推送是小程序雲開發即將發布的一個雲服務, 可以監聽雲資料庫的數據變更,實時推送到小程序端。省去了開發者搭建 WebSocket 的成本,是小程序中實時推送的高效實踐方案。
  • 集成型統一推送服務UniPush知識詳解
    UniPush是DCloud聯合個推公司推出的集成型統一推送服務,內建了蘋果、華為、小米、OPPO、VIVO、魅族、谷歌FCM等手機廠商的系統級推送和個推等第三方推送。整體架構:推送消息類型:通常推送消息分以下兩種類型:通知欄消息(推送通知)UniPush推送服務定義好的推送樣式、
  • 醫院如何設計和應用智能消息提醒中臺?|中臺|消息推送|-健康界
    ,立即發送是由事件驅動引擎驅動統一消息中臺實時發送消息,定時發送是按照預先配置的時間定時發送;回復類型配置,對需要回復的消息,配置消息窗內容。授權哪些系統可以調用AI消息引擎或統一消息發送中臺服務。消息監控。通過大屏看板展示各消息鏈、消息節點、事件、出口的數量,實時動態顯示消息服務數量變化曲線或雷達圖,動態顯示事件調用數、異常數。質控分析。消息引擎分析包括節點達標分析、節點耗時分析、節點異常分析;消息推送中臺包括消息流量分析、消息目標分析、消息異常分析。
  • 明年四川將實現全省秒級地震預警服務 老百姓手機端可收到推送
    封面新聞記者 吳冰清18日8時14分,四川資中發生5.2級地震。8秒後,四川地震烈度速報與預警系統發出報警信息,第一報4.5級,2秒後更新為4.8級,隨後2分33秒產出自動速報,4分50秒產出儀器烈度圖,有力支撐了地震應急響應處置工作。
  • 中國地震臺網中心:將向震中微博用戶自動推送速報
    中國地震臺網中心:將向震中微博用戶自動推送速報 2014-12-17 16:00:54對此,新浪微博CEO王高飛介紹,這將通過對用戶曾使用過的地理位置信息、IP位址等大數據的分析實現,準確率達到99%以上。  事實上,近年來,中國地震臺網中心不斷提升公共服務能力。去年4月1日起,中國地震臺網實現了自動地震速報,通過手機APP、微博、微信、網站等對外同步發布。
  • 高德地圖推出多方向實時路況 實現路口車道級導航
    近日,高德地圖在業內首次推出「多方向實時路況」,它實現了路口處的車道級導航能力,能對路口車輛進行更精準引導,每天可為用戶出行節約近10萬小時。  高德地圖推出的多方向實時路況打破了行業瓶頸,它實現了路口處的車道級導航能力,將路口處的路況信息從路徑級升級為車道級,路況信息精度有了大幅提升,能為用戶提供更加精準的導航服務。  比如,「多方向實時路況」推出後,高德地圖會在用戶即將接近擁堵路口前就提醒其變道或轉向,幫用戶有效避開路口擁堵。用戶可通過高德地圖的語音導航、地圖畫面獲知路口處車道級的轉向提醒。
  • 一加完成統一推送服務開發:將支持災害預警推送
    今天下午,一加官方微博宣布,一加已加入並首批完成統一推送聯盟服務開發工作,後續一加 5 及以上的機型都將支持統一推送服務。在微博中,一加還提及了一項非常重要的新信息。統一推送新增了「推必達」服務,專用於災難險情發生後,第一時間給用戶發送運營商級別的災害預警推送,並提供撤離路線導航等服務。也就是說,支持統一推送服務的手機,未來都將同時支持災害預警功能。據悉,截至 2019 年底,華為、榮耀、OPPO、realme、一加、中興、三星、vivo、iQOO 等手機品牌都已宣布支持統一推送服務。
  • 一文帶你徹底了解APP PUSH推送機制
    本文主要講解關於APP PUSH的流程、機制及相關經驗,一是為了方便大家可以針對APP迅速制定PUSH消息推送方案,實現0到1的推送功能搭建;二是可以了解下PUSH流程,對各個環節針對性地提高觸達率。
  • 【AWS移動開發公開課】第三講:實現 iOS的Amazon SNS移動推送自...
    然而通知推送的實現並不容易,目前有很多的推送平臺,包括Kindle、iOS、Android、Windows Phone/Desktop、Baidu等,其中的一個很大的挑戰就是每個平臺都給通知推送建立了不同的API和需求。
  • 搜狗輸入法誤推送「12級地震」,網友:地球都碎了
    事件起因:2月3日,部分搜狗輸入法用戶收到河北興隆發生12級地震的消息推送,隔日,搜狗輸入法官微發聲,稱河北興隆12級地震消息為錯誤推送,並對受到影響的5000名用戶致歉。搜狗輸入法目前與權威地震減災機構合作推出了地震預警功能,其目的是為了幫助其用戶在第一時間掌握地震消息,及時規避人身與財產安全。然2月3日四川成都發生5.1級地震後,搜狗輸入法技術團隊為了提高信息到達率,進行了一輪新技術測試,測試中,相關人員對伺服器進行了誤操作,因此導致錯誤推送了河北12級地震的烏龍事件。
  • 航旅縱橫緊急上線通知系統 實時推送航班疫情動態
    如有同航班的旅客確診,航旅縱橫將實時推送提醒信息:「航班發現確診患者,請您返家後暫不要外出,居家封閉隔離觀察,並第一時間到所在社區進行登記。發現異常者請立即就近到指定發熱門診就診。就診過程中要全程佩戴口罩,儘量不要乘坐公共運輸工具。」 航旅縱橫方面表示,緊急上線該系統,旨在幫助廣大旅客及時、準確了解自己乘坐航班的疫情動態,希望收到推送的旅客重視提醒,科學防範。
  • 網際網路提升預警速度 地震信息服務與地震波賽跑
    「網際網路可以結合地震部門重要信息發布的需求和社會公眾迫切需要知道震情災情的需求,實現應急信息的實時推送。」潘懷文說。2013年4月,中國地震臺網中心正式對外提供自動地震速報服務,並積極通過地震速報APP、微博、微信、網站等對外同步發布地震信息。  中國地震臺網中心地震新媒體負責人侯建民表示,地震研究是一門古老的行業,與網際網路結合能不能給地震減災工作帶來一些變化,還要等待時間的檢驗。
  • 百度新聞源收錄添利器,實時推送工具即將上線
    此次課程在去年北京首講的基礎上增加了優質新聞資源實時推送工具、資訊類站點移動化等新內容。吸引了東方網、解放網、新民網、浙江在線等50餘家上海及周邊城市的核心資訊類網站內容負責人和技術負責人參加。優質新聞資源實時推送工具,解決收錄不及時、不收原創收抄襲等多種問題此次培訓最受大家關注的內容莫過於百度即將針對優質新聞資源推出的實時推送工具。該工具可以有效解決 「新內容遲遲不被收錄」、「百度收錄競品卻不收自己網站」,以及「百度未收錄自己的原創內容,反而收錄了抄襲網站」這幾大困擾網站的問題。
  • 即刻產品分析報告:信息爆炸時代,即刻是如何實現精準推送?
    擇感興趣的主題,剩下的一切交給即刻精選優質內容源,讓你得到最好的信息服務針對不同類型的主題,隨心選擇開關推送通知你最在意的消息,第一時間推送通知你關心的,即刻告訴你!既然用戶的需求痛點在於信息爆炸和快速獲取有效信息上,即刻所做的就是由用戶定製感興趣的信息,從網上將有關信息定期發給用戶,幫助用戶高效率地從網上提取有價值的信息,這種模式其實並不陌生,這就是郵件列表推送服務。
  • 南山「5G消息」來了!給你「飛」一般政務服務速度~
    ▲多媒體化、輕量化、交互化作為5G時代最早落地的應用,「5G消息」以簡訊為入口,通過引入「消息即平臺」技術實現了消息的交互化、多媒體化、輕量化。除了自身的原生應用服務創新之外,「5G消息」還可以實現對第三方App、H5頁面的自由跳轉,與i深圳、疫情申報等平臺進行連接,實現用戶服務的無縫銜接。下一步,還將實現常規性政務服務的「能力遷移」,在內容創新、交互創新等方面實現更大應用前景的拓展。
  • 搜狗輸入法錯誤推送12級地震,凌晨下線功能,12級地震有多可怕?
    河北發生12級地震?2020年1月,搜狗輸入法官方宣稱其是「全球首個接入地震預警系統」的輸入法產品。將實時地為用戶推送及時的、準確的、權威的地震預警和相關信息。搜狗輸入法聯手@成都高新減災研究所在地震發生時快速發出預警,為數億用戶打通地震預警「最後一公裡」。
  • 手機總是會收到推送消息?關閉這3處,以後再也不怕被打擾
    手機總是收到推送消息,讓你煩不勝煩?關閉這3處才能用得更舒心手機總是受到一大堆推送消息,讓你煩不勝煩?如果你也有類似經歷,那就趕緊往下看,只用花一分鐘時間,以後手機也能變得更加趕緊清爽,只有關閉這3處手機才能用得更舒心。
  • 百度實時計算平臺的實現和應用
    百度自主研發了國內規模最大的實時計算平臺——Dstream和TM。它們各有千秋,適用於不同的業務場景。Dstream旨在面向有向無環的數據處理流,滿足高時效性要求的計算業務場景(如實時CTR計算),可達到毫秒級的響應。
  • 實時備份技術的含義
    現在通過CDP實時備份技術,可以實現到秒級的細顆粒度抓捕效果,將備份窗口已經降至可以實現的最小值,數據丟失的間隔誤差隨著備份技術的這種改進也達到秒級,與此同時,數據恢復的重要性以及存在的風險日益凸顯服務接管在主伺服器宕機以後,從備份機可以手動或者自動的接管主站的IP以及對外的相關服務,確保業務的連續性。
  • 2020第18號颱風實時最新消息 颱風莫拉菲最大風力將達到強颱風級
    38米/秒),中心最低氣壓為965百帕,七級風圈半徑220-250公裡,十級風圈半徑60公裡,十二級風圈半徑50公裡。  颱風莫拉菲最大風力將達到14級  預計,「莫拉菲」將以每小時25公裡左右的速度向偏西方向移動,強度逐漸加強,最強可達強颱風級(42-45米/秒,14級),並向越南中部沿海靠近。