<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # iDoneThis-從頭開始擴展基于電子郵件的應用程序 > 原文: [http://highscalability.com/blog/2012/6/20/idonethis-scaling-an-email-based-app-from-scratch.html](http://highscalability.com/blog/2012/6/20/idonethis-scaling-an-email-based-app-from-scratch.html) ![](https://img.kancloud.cn/bb/2b/bb2b26a2c82829d7d51f9ffc08322e27_238x64.png) *這是 [iDoneThis](http://idonethis.com) 的首席技術官 Rodrigo Guzman 的來賓帖子,它使您的公司狀態報告可以最輕松地進行。* **iDoneThis** 是一個簡單的管理應用程序,每天結束時都會通過電子郵件向您的團隊發送電子郵件,詢問您:“今天您做了什么?” 只需回答幾行即可完成。 第二天早上,您團隊中的每個人都了解了團隊在前一天的成就,以使每個人都參與其中,并開始新的一天。 在我們推出之前,我們在一個周末以最基本的方式構建了 iDoneThis。 不好意思,我們使用 Gmail 收件箱的“密件抄送”字段發送了前幾批每日電子郵件。 結果是,從網站存在的第 3 天開始,我們就已經在該網站上吸引了用戶。 從 2011 年 1 月推出以來,我們每天手動發送數百封電子郵件,到每月發送超過 100 萬封電子郵件和處理超過 20 萬封傳入電子郵件。 總共,客戶記錄了 170 萬次完成。 ## 統計資料 * 每天 1 萬封入站電子郵件 * 每天發送 40k 電子郵件,其中大部分發生在美國高峰時段,時間是美國的 6 便士,預計會如期到達。 * 每秒幾個 Web 請求,突發。 Web 服務器大部分閑置。 * 1GB 的用戶內容,5GB 的數據庫 * 為文檔建立索引以進行實時搜索 * 所有這些都使用單個 xlarge EC2 實例處理。 ## 疊放 * python 幾乎所有內容 * django 用于網絡界面 * apache + mod_wsgi * PostgreSQL * 傳入的電子郵件由 sendgrid 解析 API 和內部用 python 編寫的自定義電子郵件處理器處理 * coffeescript,骨干,jquery 和 sass * lucene + solr 用于在碼頭實例后面搜索運行 ## 電子郵件-從 Gmail 到 SendGrid 我們從 Gmail 中的密件抄送開始,因為如果我們從應用程序服務器發送電子郵件,則它們都將被標記為垃圾郵件。 Mailchimp 不允許我們在電子郵件中進行大量更改,因為它是為傳統電子郵件營銷而構建的。 當令人驚訝的是,成百上千的人注冊了該服務時,我們使用 [SendGrid](http://sendgrid.com) 在 cronjob 上切換到了自定義腳本(“ sendmail”)。 Sendmail 是我們今天仍然使用的,通過迭代改進來處理出現的錯誤情況。 它曾經每周崩潰一次,現在幾乎從未發生過。 為了實現這一目標,sendmail 從簡單的 for 循環變為使用數據庫來跟蹤每封電子郵件的狀態,并具有可以優雅地處理不同狀態轉換的邏輯。 不過,起初讓它成為一個簡單的 for 循環對我們很有幫助-在觀察了所有常見的失敗方式之后,設計機械使其可靠的要容易得多。 為了處理傳入的電子郵件,我們從 200 行腳本(稱為“ getmail”)開始,以通過 IMAP 訪問 Gmail 收件箱。 該過程不可靠,在引發異常后會使數據庫處于不良狀態,因此必須由保姆親自操作。 不僅如此,還要有人從條目中刪除不需要的行(簽名,回復文本等)。 我們使用標準庫構建了一個傳入解析器,這使我們的 getmail 過程更加可靠。 800 行 Python 代碼非常混亂,這些 Python 代碼專用于正確處理編碼,部分和啟發式方法,從而使不需要的行成為可能。 我們從 getmail 遷移到 SendGrid 的傳入解析 API,該 API 基本上將傳入電子郵件轉換為 HTTP POST 請求,因此我們只需要擔心編寫 Web 應用程序。 我們之所以進行切換是因為由于 Google 的速率限制,getmail 無法足夠快地處理傳入的電子郵件。 更糟糕的是,getmail 的設計目的不是讓它同時運行多個副本,當傳入電子郵件的速率太大時,getmail 會開始引發很多問題。 ## 擴展流程 可伸縮性是一件有趣的事。 早期,我們面臨的主要瓶頸本身不是技術性的,而是開發人員的時間-面對大量電子郵件,這僅僅是我的問題! 今天基本上也是這樣。 這意味著性能和可伸縮性基于代碼設計中的簡單性,周到的抽象性和敏捷性的原則。 首先要毫不留情地將功能范圍限制到最低限度或將其全部外包。 只有在該功能發布并且我們看到它被使用后,我們才對其進行優化以確保其性能(例如,我們添加了 [Celery](http://celeryproject.org/) 以異步發送通知電子郵件,之后該通知已成為 UX 的重要組成部分) 。 其次,使代碼盡可能簡單(寫和讀)。 這通常涉及犧牲性能。 例如,對于復雜的查詢,ORM 并不總是產生最高效的 SQL,但是我們將其擱置一旁,直到該功能投入生產為止。 誠然,這導致了一些尷尬的時刻,但是更多的時候它使我們遠離過早的優化,并且我們的代碼庫相對干凈并且易于使用。 隨著傳入和傳出電子郵件的數量增加,我們考慮切換到多服務器體系結構。 但是,這開始給我們的連續部署庫增加了很多復雜性。 因此,我們沒有進行優化,而是購買了一臺更大的計算機,并構建了一個負載和性能監視系統。 當前,iDoneThis 在單個 xlarge EC2 實例上運行。 我們可以通過做一些工作來擺脫一些小實例,但我們更愿意為簡單起見和開發人員時間進行優化。 但是,我們流程中最重要的部分可能是我們擁有非常好的連續部署。 每個開發人員都可以使用一個簡短的命令將 git repo 的任何分支部署到生產中,該過程需要幾秒鐘。 這意味著生產中和我們開發中的產品永遠不會有太大差異。 這也意味著我們可以在實時觀察發生的情況后快速進行迭代。 ## 重新構建現代網絡 iDoneThis 的 Web 界面最初是一個非常簡單的 Django 項目。 只是一些模型,視圖和模板。 隨著產品的發展,我們繼續采用 Web 應用程序開發的舊范式:所有事情都與頁面加載和表單提交有關。 這在一段時間內為我們提供了很好的服務,但是當我們的用戶將數據放入我們的系統時,他們需要更好的界面來訪問它。 我們慢慢開始堆積 jQuery 意大利面條以及支持它的后端功能。 結果是一團糟。 一種有效,但是很難調試和迭代。 同樣,選擇只引入絕對必要的復雜性,我們使用 CoffeeScript 和 Backbone.js 重新編寫了前端,從而產生了更易管理的組織代碼。 當我們采取這一步驟時,我們很大程度上將后端留給了自己,僅根據需要添加了對前端新功能的支持。 事實證明這是有問題的。 由于 iDoneThis 主要基于電子郵件,后來又推出了 iPhone 應用程序,因此我們最終獲得了三個用于用戶數據 I / O 的渠道:電子郵件,Web 和 iPhone 應用程序-每個渠道都有其自己的細微差別。 對我們來說,這使得我們的一些用戶交互和流程不能像您在普通網絡應用程序上所期望的那樣完全正常工作,而 Django 抽象使這種工作變得容易。 例如,當一個用戶被邀請加入一個團隊時,他開始接收來自我們的電子郵件,并且可以像其他任何人一樣回復它們,但是他從未訪問過該站點來設置帳戶。 隨著我們構建后端以支持所有這些功能,代碼變得越來越不規則。 我們盡可能地接受 TDD 來幫助解決這一問題,但更重要的是,我們決定切換到基于 API 的體系結構-我們仍在進行此切換。 看起來,方式是 Django 后端主要由兩個組件組成:一個負責提供可由 Backbone.js 和 iPhone 應用程序使用的 json API,以及一組負責提供給前端的簡單視圖和模板。 代碼和 html 占位符。 到目前為止,用這種風格編寫的代碼比老式的代碼要簡單得多,并且更易于測試。 但是,弄清進行切換的來龍去脈是一筆相當大的時間投資,因為 django 并不是針對這種范例而設計的。 新代碼更簡潔的事實使我認為,最終它們在迭代速度方面都將獲得回報。 ## 得到教訓 * **外包辛勤工作,盡可能外包**。 即使對于基于電子郵件的產品,也要對發送和接收的電子郵件都使用 sendgrid,這就是我們要做的。 當然,在某些時候,內部做這些事情是有意義的,但是對于一家初創公司而言,那一點可能就是 t =無窮大。 * **性能上的簡化**:我們可能會放棄使用較小的 EC2 實例并使用 nginx,但是使用 mod_wsgi 的默認 apache 配置工作得很好,并且更易于自動化。 我們經常做這樣的事情:讓最簡單最容易的事情出現,擔心它的性能,然后再進行拋光。 * 短時間內,我們朝著將組件拆分為在其自己的服務器中運行的方向發展。 這開始造成的麻煩超出其應有的價值,因此,我們最終獲得了**單個 EC2 實例**。 單個 EC2 實例使我感到恐懼。 當您丟失該實例時會發生什么? @布蘭登:我認為他們應該有某種備份,并有恢復計劃。 即使您有多個實例,也存在“丟失實例”問題。 歸結為擁有可恢復的備份。 很抱歉...一個 5GB 的數據庫和每秒幾個 Web 請求*這些天*是“高可擴展性”? 新聞日慢多少? 那么,告訴我,如何運行單個 EC2 實例“可伸縮”? @Hrish:備份將使您得以恢復,但它們并不會采取任何措施來防止服務中斷。 AWS 有時會發生中斷,但是它們幾乎總是被隔離到一個實例區域中-也就是說,區域故障彼此獨立。 如果任何區域發生故障的概率為 p,則由于區域發生故障而導致單個實例設置脫機的概率也為 p。 但是,如果應用程序是從兩個區域提供服務的,并且可以在那些區域之一的消失中幸存下來,則應用程序因區域故障而脫機的可能性為 p ^ 2。 通過擴展到第二個可用性區域,可以將故障風險降低一個數量級。 使用 Django 應用程序,這應該相當容易。 Web 服務器不應存儲狀態,因此丟失服務器不會使應用程序脫機。 可以使用 Elastic Load Balancer 來放置 Web 服務器的前端,而 ELB 可以在區域中斷中幸存下來。 可以跨區域以鏡像配置設置 PostgreSQL,或者可以將 PostgreSQL 換成 MySQL,并為數據庫使用多可用區 RDS 實例。 對于像我們在 6 月 14 日看到的那樣的故障可以恢復的應用程序,差異可能是每月數百美元。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看