# 更簡單,更便宜,更快:Playtomic 從.NET 遷移到 Node 和 Heroku
> 原文: [http://highscalability.com/blog/2012/10/15/simpler-cheaper-faster-playtomics-move-from-net-to-node-and.html](http://highscalability.com/blog/2012/10/15/simpler-cheaper-faster-playtomics-move-from-net-to-node-and.html)

*這是 [Playtomic](https://playtomic.com/) 首席執行官 Ben Lowry 的特邀帖子。 Playtomic 是一項游戲分析服務,每天大約有 2 千萬人在大約 8000 種移動,網絡和可下載游戲中實施。*
*這是 [Ben Lowry 在 Hacker News](http://news.ycombinator.com/item?id=4458124) :*上的一個很好的摘要語錄
> 昨天有超過 2 千萬的人點擊了我的 API 700,749,252 次,玩了我的分析平臺集成的大約 8,000 款游戲,總播放時間不到 600 年。 就是昨天 有許多不同的瓶頸在等著人們大規模經營。 在我的用例中,Heroku 和 NodeJS 最終以非常便宜的價格緩解了很多。
Playtomic 始于幾乎唯一的 Microsoft.NET 和 Windows 體系結構,該體系結構保持了 3 年,然后被 NodeJS 完全重寫所取代。 在整個生命周期中,整個平臺從單個服務器上的共享空間發展為完全專用,然后擴展到第二專用,然后將 API 服務器卸載到 VPS 提供程序和 4-6 個相當大的 VPS。 最終,API 服務器安裝在 Hivelocity 的 8 臺專用服務器上,每個服務器都具有超線程+ 8gb ram +運行 500 或 3 個 API 堆棧實例的雙 500gb 磁盤的四核。
這些服務器通常為 30,000 至 60,000 個并發游戲玩家提供服務,每秒最多接收 1500 個請求,并通過 DNS 輪詢實現負載平衡。
7 月,整個服務器群被 Heroku 托管的 NodeJS 重寫所取代,以節省大量資金。
## 使用 NodeJS 擴展 Playtomic
遷移包括兩個部分:
1. **專用于 PaaS** :優勢包括價格,便利性,利用其負載平衡和降低總體復雜性。 缺點包括沒有用于 NodeJS 的 New Relic,非常小的崩潰以及通常不成熟的平臺。
2. **.NET 到 NodeJS** :將具有本地 MongoDB 實例和服務預處理事件數據的 ASP.NET/C#體系結構切換到本地,然后將其發送到集中式服務器以完成操作; 到 Heroku + Redis 上的 NodeJS 以及 SoftLayer 上的預處理(請參見 Catalyst 程序)。
## 專用于 PaaS
復雜性的降低是顯著的; 我們在托管合作伙伴 Hivelocity 擁有 8 臺專用服務器,每臺服務器運行 3 或 4 個 API 實例。 每個人都運行一小套軟件,其中包括:
* MongoDB 實例
* 日志預處理服務
* 監視服務
* 帶有 api 網站的 IIS
部署是通過 FTP 腳本完成的,該腳本將新的 api 站點版本上載到所有服務器。 服務更討厭部署,但很少更改。
MongoDB 對于在預處理和發送日志之前臨時保存日志數據是一個糟糕的選擇。 它提供了最初只寫內存的巨大速度優勢,這意味著寫請求幾乎立即就“完成”了,這遠遠優于 Windows 上的常見消息隊列,但是它從未回收已刪除數據留下的空間,這意味著 db 大小會膨脹到 如果不定期壓縮,則超過 100 GB。
PaaS 提供商的優勢是眾所周知的,盡管它們似乎最成熟并且擁有廣泛的技術支持,但對 Heroku 和 Salesforce 的信心最容易,盡管看上去最相似。
過渡到 PaaS 的主要挑戰是,人們像在專用服務器上那樣,可以與網站一起運行輔助軟件的想法已經動搖。 大多數平臺都提供了一些可以利用的后臺工作線程,但這意味著您需要通過 3 rd 第三方服務或服務器來路由 Web 線程中的數據和任務。
我們最終選擇在 Softlayer 上的大型服務器上運行了十二個特定目的的 Redis 實例和一些中間件,而不是后臺工作程序。 Heroku 不對出站帶寬收費,而 Softlayer 不對入站帶寬收費,這巧妙地避免了所涉及的大量帶寬。
## 從.NET 切換到 NodeJS
在服務器端使用 JavaScript 是一種混合體驗。 一方面,缺乏形式和樣板正在解放。 另一方面,沒有 New Relic,也沒有編譯器錯誤,這使所有事情都變得比原本困難。
有兩個主要優點,這使得 NodeJS 對于我們的 API 極為有用。
1. **后臺工作程序**與 Web 服務器位于相同的線程和內存中
2. **與 Redis 和 mongodb 的持久共享連接**
### 后臺工作者
NodeJS 具有非常有用的功能,可以獨立于請求繼續工作,允許您預取數據和其他操作,這些操作可以讓您非常早地終止請求,然后完成對它的處理。
對于我們而言,將整個 MongoDB 集合復制到內存中(定期刷新)是特別有利的,這樣,整個工作類都可以訪問當前數據,而不必使用外部數據庫或本地/共享緩存層 。
在以下條件下,我們每秒總共節省 100 至 1000 的數據庫查詢:
* 主 api 上的游戲配置數據
* 數據導出 api 上的 API 憑據
* GameVars,開發人員用來存儲配置或其他數據以將其熱加載到他們的游戲中
* 排行榜得分表(不包括得分)
基本模型是:
> var cache = {};
>
> module.exports = function(request,response){
> response.end(cache [“ x”]);
> }
>
> 函數 refresh(){
>
> //從數據庫中獲取更新的數據,存儲在緩存對象
> 中。cache [“ x”] =“ foo”;
> setTimeout(refresh,30000);
> }
>
> refresh();
這樣做的優點是,您可以與后端數據庫建立單個連接(每個 dyno 或實例),而不是每個用戶建立一個連接,并且具有非常快的本地內存緩存,該緩存始終具有新數據。
注意事項是您的數據集必須很小,并且此線程與其他所有線程都在同一線程上運行,因此您需要意識到阻塞線程或執行過多的 CPU 工作。
### 持久連接
NodeJS 通過.NET 為我們的 API 提供的另一個巨大好處是持久性數據庫連接。 在.NET(等)中進行連接的傳統方法是打開您的連接,進行操作,然后將您的連接返回到池中,以便在短期內不再使用或不再使用時可以重新使用。
這是很常見的,除非達到很高的并發性,否則它將正常工作。 并發率很高,因此連接池無法足夠快地重用連接,這意味著它會生成新連接,數據庫服務器必須擴展這些連接才能處理。
在 Playtomic,我們通常有數十萬并發游戲玩家正在發送事件數據,這些事件數據需要被推回到不同數據中心中的 Redis 實例,而使用.NET 則需要大量 連接數量–這就是為什么我們在每臺舊專用服務器上本地運行 MongoDB 的原因。
使用 NodeJS,每個 dyno /實例具有單個連接,該連接負責推送特定 dyno 接收的所有事件數據。 它位于請求模型之外,如下所示:
> var redisclient ?= redis.createClient(….);
>
> module.exports = function(request,response){
>
> var eventdata =“ etc”;
>
> redisclient.lpush(“ events”,eventdata);
>
> }
### 最終結果
**高負載:**
最后一刻的要求
* * *
_exceptions:75 (0.01%) _ 失敗:5 (0.00%) 總計:537,151 (99.99%) data.custommetric.success:1,093 (0.20%) data.levelaveragemetric.success :2,466 (0.46%) data.views.success:105 (0.02%) events.regular .invalid_or_deleted_game#2:3,814 (0.71%) events.regular.success:527,837 (98.25%) gamevars.load.success:1,060 (0.20%) geoip.lookup.success:109 (0.02%) Leaderboards.list.success:457 (0.09%) Leaderboards.save.missing_name_or_source#201:3 (0.00%) 排行榜。保存。成功:30 (0.01%) 。
排行榜.saveandlist。成功:102 (0.02%) playerlevels.list.success:62 (0.01%) playerlevels.load.success:13 (0.00%)
* * *
此數據來自在每個實例的后臺運行的一些負載監控,將計數器推送到 Redis,然后將其匯總并存儲在 MongoDB 中,您可以在 [上查看它們的運行情況 https://api.playtomic.com/load.html](https://api.playtomic.com/load.html) 。
該數據中有幾種不同的請求類別:
* **事件** 從 MongoDB 檢查游戲配置,執行 GeoIP 查找(開源的非常快速的實現,網址為 https://github.com/benlowry/node-geoip-native) ,然后推送到 Redis
* **GameVars , 排行榜,玩家級別** 都從 MongoDB 中檢查游戲配置,然后再檢查相關的 MongoDB 數據庫
* **數據** 查找被代理到 Windows 服務器,因為 NodeJS 對存儲過程的支持不佳
The result is 100,000s of concurrent users causing spectactularly light Redis loads fo 500,000 – 700,000 lpush’s per minute (and being pulled out on the other end):
?1 ?[|| ?????????????????????????????????????????????????????????????????????????????????????1.3%] ????Tasks: 83; 4 running
?2 ?[||||||||||||||||||| ???????????????????????????????????????????????????????????????????19.0%] ????Load average: 1.28 1.20 1.19
?3 ?[|||||||||| ?????????????????????????????????????????????????????????????????????????????9.2%] ????Uptime: 12 days, 21:48:33
?4 ?[|||||||||||| ??????????????????????????????????????????????????????????????????????????11.8%]
?5 ?[|||||||||| ?????????????????????????????????????????????????????????????????????????????9.9%]
?6 ?[||||||||||||||||| ?????????????????????????????????????????????????????????????????????17.7%]
?7 ?[||||||||||||||| ???????????????????????????????????????????????????????????????????????14.6%]
?8 ?[||||||||||||||||||||| ?????????????????????????????????????????????????????????????????21.6%]
?9 ?[|||||||||||||||||| ????????????????????????????????????????????????????????????????????18.2%]
?10 [| ??????????????????????????????????????????????????????????????????????????????????????0.6%]
?11 [ ???????????????????????????????????????????????????????????????????????????????????????0.0%]
?12 [|||||||||| ?????????????????????????????????????????????????????????????????????????????9.8%]
?13 [|||||||||| ?????????????????????????????????????????????????????????????????????????????9.3%]
?14 [|||||| ?????????????????????????????????????????????????????????????????????????????????4.6%]
?15 [|||||||||||||||| ??????????????????????????????????????????????????????????????????????16.6%]
?16 [||||||||| ??????????????????????????????????????????????????????????????????????????????8.0%]
?Mem[||||||||||||||| ????????????????????????????????????????????????????????????????2009/24020MB]
?Swp[ ???????????????????????????????????????????????????????????????????????????????????0/1023MB]
?PID USER ????PRI ?NI ?VIRT ??RES ??SHR S CPU% MEM% ??TIME+ ?Command
12518 redis ????20 ??0 40048 ?7000 ??640 S ?0.0 ?0.0 ?2:21.53 ?`- /usr/local/bin/redis-server /etc/redis/analytics.conf
12513 redis ????20 ??0 72816 35776 ??736 S ?3.0 ?0.1 ?4h06:40 ?`- /usr/local/bin/redis-server /etc/redis/log7.conf
12508 redis ????20 ??0 72816 35776 ??736 S ?2.0 ?0.1 ?4h07:31 ?`- /usr/local/bin/redis-server /etc/redis/log6.conf
12494 redis ????20 ??0 72816 37824 ??736 S ?1.0 ?0.2 ?4h06:08 ?`- /usr/local/bin/redis-server /etc/redis/log5.conf
12488 redis ????20 ??0 72816 33728 ??736 S ?2.0 ?0.1 ?4h09:36 ?`- /usr/local/bin/redis-server /etc/redis/log4.conf
12481 redis ????20 ??0 72816 35776 ??736 S ?2.0 ?0.1 ?4h02:17 ?`- /usr/local/bin/redis-server /etc/redis/log3.conf
12475 redis ????20 ??0 72816 27588 ??736 S ?2.0 ?0.1 ?4h03:07 ?`- /usr/local/bin/redis-server /etc/redis/log2.conf
12460 redis ????20 ??0 72816 31680 ??736 S ?2.0 ?0.1 ?4h10:23 ?`- /usr/local/bin/redis-server /etc/redis/log1.conf
12440 redis ????20 ??0 72816 33236 ??736 S ?3.0 ?0.1 ?4h09:57 ?`- /usr/local/bin/redis-server /etc/redis/log0.conf
12435 redis ????20 ??0 40048 ?7044 ??684 S ?0.0 ?0.0 ?2:21.71 ?`- /usr/local/bin/redis-server /etc/redis/redis-servicelog.conf
12429 redis ????20 ??0 ?395M ?115M ??736 S 33.0 ?0.5 60h29:26 ?`- /usr/local/bin/redis-server /etc/redis/redis-pool.conf
12422 redis ????20 ??0 40048 ?7096 ??728 S ?0.0 ?0.0 26:17.38 ?`- /usr/local/bin/redis-server /etc/redis/redis-load.conf
12409 redis ????20 ??0 40048 ?6912 ??560 S ?0.0 ?0.0 ?2:21.50 ?`- /usr/local/bin/redis-server /etc/redis/redis-cache.conf
and very light MongoDB loads for 1800 – 2500 crud operations a minute:
insert ?query update delete getmore command flushes mapped ?vsize ???res faults locked % idx miss % ????qr|qw ??ar|aw ?netIn netOut ?conn ??????time
????2 ?????9 ?????5 ?????2 ??????0 ??????8 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????3k ????7k ??116 ??01:11:12
????1 ?????1 ?????5 ?????2 ??????0 ??????6 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????2k ????3k ??116 ??01:11:13
????0 ?????3 ?????6 ?????2 ??????0 ??????8 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????3k ????6k ??114 ??01:11:14
????0 ?????5 ?????5 ?????2 ??????0 ?????12 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????3k ????5k ??113 ??01:11:15
????1 ?????9 ?????7 ?????2 ??????0 ?????12 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????4k ????6k ??112 ??01:11:16
????1 ????10 ?????6 ?????2 ??????0 ?????15 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????1|0 ????4k ???22k ??111 ??01:11:17
????1 ?????5 ?????6 ?????2 ??????0 ?????11 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????3k ???19k ??111 ??01:11:18
????1 ?????5 ?????5 ?????2 ??????0 ?????14 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????3k ????3k ??111 ??01:11:19
????1 ?????2 ?????6 ?????2 ??????0 ??????8 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????3k ????2k ??111 ??01:11:20
????1 ?????7 ?????5 ?????2 ??????0 ??????9 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????3k ????2k ??111 ??01:11:21
insert ?query update delete getmore command flushes mapped ?vsize ???res faults locked % idx miss % ????qr|qw ??ar|aw ?netIn netOut ?conn ??????time
????2 ?????9 ?????8 ?????2 ??????0 ??????8 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????4k ????5k ??111 ??01:11:22
????3 ?????8 ?????7 ?????2 ??????0 ??????9 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????4k ????9k ??110 ??01:11:23
????2 ?????6 ?????6 ?????2 ??????0 ?????10 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????3k ????4k ??110 ??01:11:24
????2 ?????8 ?????6 ?????2 ??????0 ?????21 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????4k ???93k ??112 ??01:11:25
????1 ????10 ?????7 ?????2 ??????3 ?????16 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????4k ????4m ??112 ??01:11:26
????3 ????15 ?????7 ?????2 ??????3 ?????24 ??????0 ?6.67g ?14.8g ?1.23g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????6k ????1m ??115 ??01:11:27
????1 ?????4 ?????8 ?????2 ??????0 ?????10 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????4k ????2m ??115 ??01:11:28
????1 ?????6 ?????7 ?????2 ??????0 ?????14 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????4k ????3k ??115 ??01:11:29
????1 ?????3 ?????6 ?????2 ??????0 ?????10 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????3k ??103k ??115 ??01:11:30
????2 ?????3 ?????6 ?????2 ??????0 ??????8 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????3k ???12k ??114 ??01:11:31
insert ?query update delete getmore command flushes mapped ?vsize ???res faults locked % idx miss % ????qr|qw ??ar|aw ?netIn netOut ?conn ??????time
????0 ????12 ?????6 ?????2 ??????0 ??????9 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????4k ???31k ??113 ??01:11:32
????2 ?????4 ?????6 ?????2 ??????0 ??????8 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????3k ????9k ??111 ??01:11:33
????2 ?????9 ?????6 ?????2 ??????0 ??????7 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????3k ???21k ??111 ??01:11:34
????0 ?????8 ?????7 ?????2 ??????0 ?????14 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????4k ????9k ??111 ??01:11:35
????1 ?????4 ?????7 ?????2 ??????0 ?????11 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????3k ????5k ??109 ??01:11:36
????1 ????15 ?????6 ?????2 ??????0 ?????19 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????5k ???11k ??111 ??01:11:37
????2 ????17 ?????6 ?????2 ??????0 ?????19 ??????1 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????6k ??189k ??111 ??01:11:38
????1 ????13 ?????7 ?????2 ??????0 ?????15 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????1|0 ????5k ???42k ??110 ??01:11:39
????2 ?????7 ?????5 ?????2 ??????0 ?????77 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????2|0 ???10k ???14k ??111 ??01:11:40
????2 ????10 ?????5 ?????2 ??????0 ????181 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ???21k ???14k ??112 ??01:11:41
insert ?query update delete getmore command flushes mapped ?vsize ???res faults locked % idx miss % ????qr|qw ??ar|aw ?netIn netOut ?conn ??????time
????1 ????11 ?????5 ?????2 ??????0 ?????12 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????0|0 ????4k ???13k ??116 ??01:11:42
????1 ????11 ?????5 ?????2 ??????1 ?????33 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????3|0 ????6k ????2m ??119 ??01:11:43
????0 ?????9 ?????5 ?????2 ??????0 ?????17 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.1 ?????????0 ??????0|0 ????1|0 ????5k ???42k ??121 ??01:11:44
????1 ?????8 ?????7 ?????2 ??????0 ?????25 ??????0 ?6.67g ?14.8g ?1.22g ?????0 ?????0.2 ?????????0 ??????0|0 ????0|0 ????6k ???24k ??125 ??01:11:45
## 相關文章
* [新的 API 服務器:Heroku 和 NodeJS 與專用和.NET](https://playtomic.com/blog/post/86-the-new-api-server-heroku-an)
* [日志處理,從無到有,每天發生十億個事件](https://playtomic.com/blog/post/68-log-processing-from-nothing)
* [每天在預算范圍內實時處理超過 3 億個事件](https://playtomic.com/blog/post/53-handling-over-300-million-ev)
* [回顧 2010 年-從每月 4000 萬事件到每天 3 億](https://playtomic.com/blog/post/46-looking-back-on-2010)
* [四種讓玩家愛上您的游戲的方式](http://www.gamasutra.com/blogs/BenLowry/20111116/8914/Four_ways_to_keep_players_in_love_with_your_game.php)
* [已發布 InkTd Flash 游戲源代碼](http://www.emanueleferonato.com/2012/04/19/inktd-flash-game-source-code-released/)
* [黑客新聞主題](http://news.ycombinator.com/item?id=4615799)的相關評論
* [Heroku 成功案例頁面](http://success.heroku.com/playtomic)
* [關于黑客新聞](http://news.ycombinator.com/item?id=4655718)
Redis 和 MongoDB 嗯...。 好文章
這是一篇很棒的文章,感謝您的分享。
因此,您切換了三件事:體系結構,部署/操作模型和運行時。
多汁的標題指的是第三部分,它可能是更改的最不重要的部分,而成本最高的部分(因為它需要完全重寫)。
不要誤會我的意思-我愛我一些 node.js,并且我是 Heroku 的忠實擁護者,但是.NET impl 中指出的所有警告很容易(或不太容易,但比完全重寫要容易得多) )可尋址。 因此,您*可以*通過優化現有代碼庫(而不是重寫)并遷移到具有 AppHarbor,Azure 的易于部署的模型(或在 Heroku 上運行 Mono)來獲得類似的結果。 而且您還會有 New Relic :)
很想聽聽您對完整重寫的成本收益平衡的看法
寫得好!,我們曾經做過類似的事情。 當我們的集合太大時,Node GC 將暫停很長一段時間,并最終會因 JS 內存不足錯誤(大約 2 Gig)而崩潰。 我們最終創建了一個 NodeJS C ++插件來存儲 V8 堆之外的數據,這實際上使我們可以將駐留在內存中的緩存擴展到超過 10 個 Gig。
我對 Node.JS 不太了解,但是 devdazed 的評論提出了我無法解決的問題。 在哪個星球上,NodeJS 內置的 GC 比 JVM(或.NET)更好?
我猜不能與成功爭辯-這對他們是有用的。 但是很難相信在 JVM 或.NET 環境中無法輕松實現同一目標,在這些環境中,您不會遇到與 GC 相關的陷阱。 或者至少您發現的那些是眾所周知的。
這是一本不錯的書,但是我沒有得到一些要點:
1.后臺工作者。 通過創建一個新線程,Asp.net 可以輕松地做到這一點。 唯一應注意的事情是不會在該線程中引發未處理的異常。
2.持久連接。 為什么不僅僅擁有一個靜態的 MongoServer 實例(它是線程安全的類)呢? MongoCollection 類也是線程安全的。 所以我們甚至可以有一個靜態的集合實例
究竟是什么使您用 Node.js 取代.NET? ASP.NET 完全支持異步。 通過從.NET 切換到節點,您還可以獲得“沉重”(如 3-10 倍)的性能。 如果您的應用切換到 node.js 之后變得更快,那么您首先在.net 方面做錯了什么。
您也可以隨意處理數據庫連接。 您可以使用[ThreadStatic]或其他某種機制使每個線程保持一個打開狀態。
@Dmitry:
并不是說我是該領域的專家(也不認為 Node 是靈丹妙藥),但也許我會說一些話來為您澄清一下:
1.我不會依賴 ASP.NET 來執行后臺任務,因為該實現通常非常脆弱。 ASP.NET 根本不是為此目的而設計的,我想如果您想通過 ASP.NET 應用程序上下文中的線程 API 實現后臺工作程序,則需要一個非常非常好的理由。 我寧愿選擇 WCF 服務作為 Windows 服務托管,它更可靠。
2.的確如此,擁有靜態的 MongoServer / MongoDatabase 實例將使您在應用程序域的整個生命周期中都具有持久的連接。 最后一部分很重要,因為 ASP.NET 應用程序可以出于多種原因(計劃的應用程序池回收,web.config 或應用程序文件夾更改等)重新啟動。 而且我認為 Node 在這方面更可靠。
但總的來說,我同意其他人的觀點,即完全沒有必要完全重寫(以及移至 Node)(但我認為他們也知道自己在做什么)。
What on earth made you replace .NET with Node.js? ASP.NET supports asynchrony to the fullest. You also take a *heavy* (like 3-10x) perf hit by switching to node from .NET. If your app got faster after switching to node.js you did something wrong on the .net side in the first place.
You are also free to handle your DB connections however you want. You could have kept one open per thread for example with [ThreadStatic] or some other mechanism.
最近所有的 node.js 文章都有什么?
是的,node.js 速度很快,但是它缺少太多基本功能,因此當您重寫所有模塊時,“神奇”的速度優勢將不復存在,而且整個代碼庫將成為一堆不斷調用自身的回調 ,進行簡單的更改需要您分析整個過程,就像穿針一樣。
Node.js 令人頭疼。
我們正在將 StatsD + Graphite 與我們的企業 Node 應用一起使用。 有了它,您可以輕松免費地免費獲得 New Relic。
哇,這家伙真的很喜歡過度設計! 在 API 客戶端中使用 boost(并迫使 android 用戶使用自定義 SDK 進行編譯,這對于使用 malkade skd 的用戶而言更加痛苦)。
- LiveJournal 體系結構
- mixi.jp 體系結構
- 友誼建筑
- FeedBurner 體系結構
- GoogleTalk 架構
- ThemBid 架構
- 使用 Amazon 服務以 100 美元的價格構建無限可擴展的基礎架構
- TypePad 建筑
- 維基媒體架構
- Joost 網絡架構
- 亞馬遜建筑
- Fotolog 擴展成功的秘訣
- 普恩斯的教訓-早期
- 論文:Wikipedia 的站點內部,配置,代碼示例和管理問題
- 擴大早期創業規模
- Feedblendr 架構-使用 EC2 進行擴展
- Slashdot Architecture-互聯網的老人如何學會擴展
- Flickr 架構
- Tailrank 架構-了解如何在整個徽標范圍內跟蹤模因
- Ruby on Rails 如何在 550k 網頁瀏覽中幸存
- Mailinator 架構
- Rackspace 現在如何使用 MapReduce 和 Hadoop 查詢 TB 的數據
- Yandex 架構
- YouTube 架構
- Skype 計劃 PostgreSQL 擴展到 10 億用戶
- 易趣建筑
- FaceStat 的禍根與智慧贏得了勝利
- Flickr 的聯合會:每天進行數十億次查詢
- EVE 在線架構
- Notify.me 體系結構-同步性
- Google 架構
- 第二人生架構-網格
- MySpace 體系結構
- 擴展 Digg 和其他 Web 應用程序
- Digg 建筑
- 在 Amazon EC2 中部署大規模基礎架構的六個經驗教訓
- Wolfram | Alpha 建筑
- 為什么 Facebook,Digg 和 Twitter 很難擴展?
- 全球范圍擴展的 10 個 eBay 秘密
- BuddyPoke 如何使用 Google App Engine 在 Facebook 上擴展
- 《 FarmVille》如何擴展以每月收獲 7500 萬玩家
- Twitter 計劃分析 1000 億條推文
- MySpace 如何與 100 萬個并發用戶一起測試其實時站點
- FarmVille 如何擴展-后續
- Justin.tv 的實時視頻廣播架構
- 策略:緩存 404 在服務器時間上節省了洋蔥 66%
- Poppen.de 建筑
- MocoSpace Architecture-一個月有 30 億個移動頁面瀏覽量
- Sify.com 體系結構-每秒 3900 個請求的門戶
- 每月將 Reddit 打造為 2.7 億頁面瀏覽量時汲取的 7 個教訓
- Playfish 的社交游戲架構-每月有 5000 萬用戶并且不斷增長
- 擴展 BBC iPlayer 的 6 種策略
- Facebook 的新實時消息系統:HBase 每月可存儲 135 億條消息
- Pinboard.in Architecture-付費玩以保持系統小巧
- BankSimple 迷你架構-使用下一代工具鏈
- Riak 的 Bitcask-用于快速鍵/值數據的日志結構哈希表
- Mollom 體系結構-每秒以 100 個請求殺死超過 3.73 億個垃圾郵件
- Wordnik-MongoDB 和 Scala 上每天有 1000 萬個 API 請求
- Node.js 成為堆棧的一部分了嗎? SimpleGeo 說是的。
- 堆棧溢出體系結構更新-現在每月有 9500 萬頁面瀏覽量
- Medialets 體系結構-擊敗艱巨的移動設備數據
- Facebook 的新實時分析系統:HBase 每天處理 200 億個事件
- Microsoft Stack 是否殺死了 MySpace?
- Viddler Architecture-每天嵌入 700 萬個和 1500 Req / Sec 高峰
- Facebook:用于擴展數十億條消息的示例規范架構
- Evernote Architecture-每天有 900 萬用戶和 1.5 億個請求
- TripAdvisor 的短
- TripAdvisor 架構-4,000 萬訪客,200M 動態頁面瀏覽,30TB 數據
- ATMCash 利用虛擬化實現安全性-不變性和還原
- Google+是使用您也可以使用的工具構建的:閉包,Java Servlet,JavaScript,BigTable,Colossus,快速周轉
- 新的文物建筑-每天收集 20 億多個指標
- Peecho Architecture-鞋帶上的可擴展性
- 標記式架構-擴展到 1 億用戶,1000 臺服務器和 50 億個頁面視圖
- 論文:Akamai 網絡-70 個國家/地區的 61,000 臺服務器,1,000 個網絡
- 策略:在 S3 或 GitHub 上運行可擴展,可用且廉價的靜態站點
- Pud 是反堆棧-Windows,CFML,Dropbox,Xeround,JungleDisk,ELB
- 用于擴展 Turntable.fm 和 Labmeeting 的數百萬用戶的 17 種技術
- StackExchange 體系結構更新-平穩運行,Amazon 4x 更昂貴
- DataSift 體系結構:每秒進行 120,000 條推文的實時數據挖掘
- Instagram 架構:1400 萬用戶,1 TB 的照片,數百個實例,數十種技術
- PlentyOfFish 更新-每月 60 億次瀏覽量和 320 億張圖片
- Etsy Saga:從筒倉到開心到一個月的瀏覽量達到數十億
- 數據范圍項目-6PB 存儲,500GBytes / sec 順序 IO,20M IOPS,130TFlops
- 99designs 的設計-數以千萬計的綜合瀏覽量
- Tumblr Architecture-150 億頁面瀏覽量一個月,比 Twitter 更難擴展
- Berkeley DB 體系結構-NoSQL 很酷之前的 NoSQL
- Pixable Architecture-每天對 2000 萬張照片進行爬網,分析和排名
- LinkedIn:使用 Databus 創建低延遲更改數據捕獲系統
- 在 30 分鐘內進行 7 年的 YouTube 可擴展性課程
- YouPorn-每天定位 2 億次觀看
- Instagram 架構更新:Instagram 有何新功能?
- 搜索技術剖析:blekko 的 NoSQL 數據庫
- Pinterest 體系結構更新-1800 萬訪問者,增長 10 倍,擁有 12 名員工,410 TB 數據
- 搜索技術剖析:使用組合器爬行
- iDoneThis-從頭開始擴展基于電子郵件的應用程序
- StubHub 體系結構:全球最大的票務市場背后的驚人復雜性
- FictionPress:在網絡上發布 600 萬本小說
- Cinchcast 體系結構-每天產生 1,500 小時的音頻
- 棱柱架構-使用社交網絡上的機器學習來弄清您應該在網絡上閱讀的內容
- 棱鏡更新:基于文檔和用戶的機器學習
- Zoosk-實時通信背后的工程
- WordPress.com 使用 NGINX 服務 70,000 req / sec 和超過 15 Gbit / sec 的流量
- 史詩般的 TripAdvisor 更新:為什么不在云上運行? 盛大的實驗
- UltraDNS 如何處理數十萬個區域和數千萬條記錄
- 更簡單,更便宜,更快:Playtomic 從.NET 遷移到 Node 和 Heroku
- Spanner-關于程序員使用 NoSQL 規模的 SQL 語義構建應用程序
- BigData 使用 Erlang,C 和 Lisp 對抗移動數據海嘯
- 分析數十億筆信用卡交易并在云中提供低延遲的見解
- MongoDB 和 GridFS 用于內部和內部數據中心數據復制
- 每天處理 1 億個像素-少量競爭會導致大規模問題
- DuckDuckGo 體系結構-每天進行 100 萬次深度搜索并不斷增長
- SongPop 在 GAE 上可擴展至 100 萬活躍用戶,表明 PaaS 未通過
- Iron.io 從 Ruby 遷移到 Go:減少了 28 臺服務器并避免了巨大的 Clusterf ** ks
- 可汗學院支票簿每月在 GAE 上擴展至 600 萬用戶
- 在破壞之前先檢查自己-鱷梨的建筑演進的 5 個早期階段
- 縮放 Pinterest-兩年內每月從 0 到十億的頁面瀏覽量
- Facebook 的網絡秘密
- 神話:埃里克·布魯爾(Eric Brewer)談銀行為什么不是堿-可用性就是收入
- 一千萬個并發連接的秘密-內核是問題,而不是解決方案
- GOV.UK-不是你父親的書庫
- 縮放郵箱-在 6 周內從 0 到 100 萬用戶,每天 1 億條消息
- 在 Yelp 上利用云計算-每月訪問量為 1.02 億,評論量為 3900 萬
- 每臺服務器將 PHP 擴展到 30,000 個并發用戶的 5 條 Rockin'Tips
- Twitter 的架構用于在 5 秒內處理 1.5 億活躍用戶,300K QPS,22 MB / S Firehose 以及發送推文
- Salesforce Architecture-他們每天如何處理 13 億筆交易
- 擴大流量的設計決策
- ESPN 的架構規模-每秒以 100,000 Duh Nuh Nuhs 運行
- 如何制作無限可擴展的關系數據庫管理系統(RDBMS)
- Bazaarvoice 的架構每月發展到 500M 唯一用戶
- HipChat 如何使用 ElasticSearch 和 Redis 存儲和索引數十億條消息
- NYTimes 架構:無頭,無主控,無單點故障
- 接下來的大型聲音如何使用 Hadoop 數據版本控制系統跟蹤萬億首歌曲的播放,喜歡和更多內容
- Google 如何備份 Internet 和數十億字節的其他數據
- 從 HackerEarth 用 Apache 擴展 Python 和 Django 的 13 個簡單技巧
- AOL.com 體系結構如何發展到 99.999%的可用性,每天 800 萬的訪問者和每秒 200,000 個請求
- Facebook 以 190 億美元的價格收購了 WhatsApp 體系結構
- 使用 AWS,Scala,Akka,Play,MongoDB 和 Elasticsearch 構建社交音樂服務
- 大,小,熱還是冷-條帶,Tapad,Etsy 和 Square 的健壯數據管道示例
- WhatsApp 如何每秒吸引近 5 億用戶,11,000 內核和 7,000 萬條消息
- Disqus 如何以每秒 165K 的消息和小于 0.2 秒的延遲進行實時處理
- 關于 Disqus 的更新:它仍然是實時的,但是 Go 摧毀了 Python
- 關于 Wayback 機器如何在銀河系中存儲比明星更多的頁面的簡短說明
- 在 PagerDuty 遷移到 EC2 中的 XtraDB 群集
- 擴展世界杯-Gambify 如何與 2 人組成的團隊一起運行大型移動投注應用程序
- 一點點:建立一個可處理每月 60 億次點擊的分布式系統的經驗教訓
- StackOverflow 更新:一個月有 5.6 億次網頁瀏覽,25 臺服務器,而這一切都與性能有關
- Tumblr:哈希處理每秒 23,000 個博客請求的方式
- 使用 HAProxy,PHP,Redis 和 MySQL 處理 10 億個請求的簡便方法來構建成長型啟動架構
- MixRadio 體系結構-兼顧各種服務
- Twitter 如何使用 Redis 進行擴展-105TB RAM,39MM QPS,10,000 多個實例
- 正確處理事情:通過即時重放查看集中式系統與分散式系統
- Instagram 提高了其應用程序的性能。 這是如何做。
- Clay.io 如何使用 AWS,Docker,HAProxy 和 Lots 建立其 10 倍架構
- 英雄聯盟如何將聊天擴大到 7000 萬玩家-需要很多小兵。
- Wix 的 Nifty Architecture 技巧-大規模構建發布平臺
- Aeron:我們真的需要另一個消息傳遞系統嗎?
- 機器:惠普基于憶阻器的新型數據中心規模計算機-一切仍在變化
- AWS 的驚人規模及其對云的未來意味著什么
- Vinted 體系結構:每天部署數百次,以保持繁忙的門戶穩定
- 將 Kim Kardashian 擴展到 1 億個頁面
- HappyPancake:建立簡單可擴展基金會的回顧
- 阿爾及利亞分布式搜索網絡的體系結構
- AppLovin:通過每天處理 300 億個請求向全球移動消費者進行營銷
- Swiftype 如何以及為何從 EC2 遷移到真實硬件
- 我們如何擴展 VividCortex 的后端系統
- Appknox 架構-從 AWS 切換到 Google Cloud
- 阿爾及利亞通往全球 API 的憤怒之路
- 阿爾及利亞通往全球 API 步驟的憤怒之路第 2 部分
- 為社交產品設計后端
- 阿爾及利亞通往全球 API 第 3 部分的憤怒之路
- Google 如何創造只有他們才能創造的驚人的數據中心網絡
- Autodesk 如何在 Mesos 上實施可擴展事件
- 構建全球分布式,關鍵任務應用程序:Trenches 部分的經驗教訓 1
- 構建全球分布式,關鍵任務應用程序:Trenches 第 2 部分的經驗教訓
- 需要物聯網嗎? 這是美國一家主要公用事業公司從 550 萬米以上收集電力數據的方式
- Uber 如何擴展其實時市場平臺
- 優步變得非常規:使用司機電話作為備份數據中心
- 在不到五分鐘的時間里,Facebook 如何告訴您的朋友您在災難中很安全
- Zappos 的網站與 Amazon 集成后凍結了兩年
- 為在現代時代構建可擴展的有狀態服務提供依據
- 細分:使用 Docker,ECS 和 Terraform 重建基礎架構
- 十年 IT 失敗的五個教訓
- Shopify 如何擴展以處理來自 Kanye West 和 Superbowl 的 Flash 銷售
- 整個 Netflix 堆棧的 360 度視圖
- Wistia 如何每小時處理數百萬個請求并處理豐富的視頻分析
- Google 和 eBay 關于構建微服務生態系統的深刻教訓
- 無服務器啟動-服務器崩潰!
- 在 Amazon AWS 上擴展至 1100 萬以上用戶的入門指南
- 為 David Guetta 建立無限可擴展的在線錄制活動
- Tinder:最大的推薦引擎之一如何決定您接下來會看到誰?
- 如何使用微服務建立財產管理系統集成
- Egnyte 體系結構:構建和擴展多 PB 分布式系統的經驗教訓
- Zapier 如何自動化數十億個工作流自動化任務的旅程
- Jeff Dean 在 Google 進行大規模深度學習
- 如今 Etsy 的架構是什么樣的?
- 我們如何在 Mail.Ru Cloud 中實現視頻播放器
- Twitter 如何每秒處理 3,000 張圖像
- 每天可處理數百萬個請求的圖像優化技術
- Facebook 如何向 80 萬同時觀看者直播
- Google 如何針對行星級基礎設施進行行星級工程設計?
- 為 Mail.Ru Group 的電子郵件服務實施反垃圾郵件的貓捉老鼠的故事,以及 Tarantool 與此相關的內容
- The Dollar Shave Club Architecture Unilever 以 10 億美元的價格被收購
- Uber 如何使用 Mesos 和 Cassandra 跨多個數據中心每秒管理一百萬個寫入
- 從將 Uber 擴展到 2000 名工程師,1000 個服務和 8000 個 Git 存儲庫獲得的經驗教訓
- QuickBooks 平臺
- 美國大選期間城市飛艇如何擴展到 25 億個通知
- Probot 的體系結構-我的 Slack 和 Messenger Bot 用于回答問題
- AdStage 從 Heroku 遷移到 AWS
- 為何將 Morningstar 遷移到云端:降低 97%的成本
- ButterCMS 體系結構:關鍵任務 API 每月可處理數百萬個請求
- Netflix:按下 Play 會發生什么?
- ipdata 如何以每月 150 美元的價格為來自 10 個無限擴展的全球端點的 2500 萬個 API 調用提供服務
- 每天為 1000 億個事件賦予意義-Teads 的 Analytics(分析)管道
- Auth0 體系結構:在多個云提供商和地區中運行
- 從裸機到 Kubernetes
- Egnyte Architecture:構建和擴展多 PB 內容平臺的經驗教訓
- 縮放原理
- TripleLift 如何建立 Adtech 數據管道每天處理數十億個事件
- Tinder:最大的推薦引擎之一如何決定您接下來會看到誰?
- 如何使用微服務建立財產管理系統集成
- Egnyte 體系結構:構建和擴展多 PB 分布式系統的經驗教訓
- Zapier 如何自動化數十億個工作流自動化任務的旅程
- Jeff Dean 在 Google 進行大規模深度學習
- 如今 Etsy 的架構是什么樣的?
- 我們如何在 Mail.Ru Cloud 中實現視頻播放器
- Twitter 如何每秒處理 3,000 張圖像
- 每天可處理數百萬個請求的圖像優化技術
- Facebook 如何向 80 萬同時觀看者直播
- Google 如何針對行星級基礎設施進行行星級工程設計?
- 為 Mail.Ru Group 的電子郵件服務實施反垃圾郵件的貓捉老鼠的故事,以及 Tarantool 與此相關的內容
- The Dollar Shave Club Architecture Unilever 以 10 億美元的價格被收購
- Uber 如何使用 Mesos 和 Cassandra 跨多個數據中心每秒管理一百萬個寫入
- 從將 Uber 擴展到 2000 名工程師,1000 個服務和 8000 個 Git 存儲庫獲得的經驗教訓
- QuickBooks 平臺
- 美國大選期間城市飛艇如何擴展到 25 億條通知
- Probot 的體系結構-我的 Slack 和 Messenger Bot 用于回答問題
- AdStage 從 Heroku 遷移到 AWS
- 為何將 Morningstar 遷移到云端:降低 97%的成本
- ButterCMS 體系結構:關鍵任務 API 每月可處理數百萬個請求
- Netflix:按下 Play 會發生什么?
- ipdata 如何以每月 150 美元的價格為來自 10 個無限擴展的全球端點的 2500 萬個 API 調用提供服務
- 每天為 1000 億個事件賦予意義-Teads 的 Analytics(分析)管道
- Auth0 體系結構:在多個云提供商和地區中運行
- 從裸機到 Kubernetes
- Egnyte Architecture:構建和擴展多 PB 內容平臺的經驗教訓