整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          海報圖片生成服務在狐友的落地實踐

          海報圖片生成服務在狐友的落地實踐

          目背景

          狐友作為搜狐的一款社交產品,在流量傳播上有著旺盛的需求點。而在流量傳播所需的眾多載體之中,海報圖片以其簡單的分享形式、可定制的視覺體驗、自帶二維碼識別導流等特點,成為了社交產品高頻必備的流量載體。

          作為狐友的前端開發,生成海報圖片就成為了我們工作中持續不斷的一個重要需求點。以下是狐友目前的產品前端服務矩陣和海報圖片的產品形式。

          圖 1 狐友產品前端服務矩陣和海報圖片的產品形式

          海報圖片實現現狀

          從上圖1可以看到,生成海報圖片對于狐友產品矩陣來說是一個高頻強需求。海報圖片作為分享載體,對于各平臺的分享流程對接也非常暢通和直觀,例如不同于小程序卡片分享只能拘泥于微信平臺,網頁分享的鏈接形式不夠直觀。

          而在海報圖片這個重要環節,長期的主要技術手段一直是通過各客戶端開發在本地設備上進行繪制,但這種方案存在如下的劣勢困擾著我們:

          • 各端無法復用:如圖2, 如果要全平臺都要做圖片分享,那么需要各端分別開發,即使生成的圖片一模一樣,也要開發iOSAndroidH5、小程序一共4遍,整體開發各端無法互相復用。
          • 長圖大圖崩潰:客戶端限于設備平臺或系統限制,對于長圖的生成并不友好,會出現長圖因為內存或算力限制無法生成的情況,其中小程序尤為明顯,在微信的框架下很容易長圖生成造成程序直接崩潰。
          • 開發效率較低:客戶端本地繪制海報圖片,一般需要手寫原生代碼效率不高。小程序端雖然使用wxml-to-canvas(H5端使用html-to-canvas)來繪制減輕了一些手寫命令式繪制代碼的負但,但這種標記語言轉canvas在實現上也存在缺陷,相比HTML+CSS的表達力還是非常受限。所以,海報圖片在代碼層面開發效率比較低。

          為了解決以上問題,我們開始著手調研并實踐落地了一套全新的海報圖片統一服務,命名為hy-ssr-img

          圖 2 狐友大前端海報生成各端開發狀態

          海報圖片統一服務


          海報圖片統一服務是一套基于PuppeteerNode.js后端服務端(SSR)渲染頁面并截圖生成海報圖片的服務,這一服務解決了原有海報圖片生成的三大問題:

          • 各端無法復用 -> 4端同時復用:iOSAndroidH5、小程序4端只需要開發一遍即可,效率提升400%,如圖3
          • 長圖大圖崩潰 -> 無懼長圖渲染:不需要再擔心長圖渲染問題,服務端渲染圖片能力理論上可以達到上萬長度的渲染,針對不超過5屏的圖片需求來說綽綽有余
          • 開發效率較低 -> 開發效率最優:使用效率超高、表達力超強的標記語言HTML + CSS渲染,開發效率和表達力都達到最優狀態

          圖 3 海報圖片統一服務各端復用

          那么,海報圖片統一服務是如何建立起來的呢?下面是從項目立項開始的具體設計方案。

          項目選型


          首先,我們調研了業界現有的圖片渲染方案,如下表。通過下表的調研總結可以看出各個方案各有優劣勢。由于復用提效是重要需求點,我們把方案鎖定了服務端渲染方向上,即入選方案為:

          • Node.js截圖方案
          • 服務端圖層繪畫方案

          在對比兩種方案,以及參考相關業務實踐后,我們最終選用了最常見的【Node.js截圖方案】。因為服務端圖層渲染選用的圖形庫在排版表達力上遠不及HTML+CSS在瀏覽器上的表達力,而且系統預期的使用對象是前端開發人員,并不是產品和運營,所以服務端圖層渲染方案的拖拽方式并不是必選項,反而由于拖拽渲染表達力的限制,對于實現一些排版復雜的圖片非常吃力。而Node.js截圖方案則沒有這方面的問題,前端開發只需要常規開發頁面即可,然后交給Puppeteer渲染后進行截圖形成最終用戶看到的海報圖片。

          表 1 項目選型方案對比

          項目架構流程方案

          在確定了【Node.js截圖方案】之后,我們對項目整體架構流程進行了設計,首先由于我們的應用的后端Java接口服務已經非常成熟,針對參數的合法性校驗及加簽解簽等防護措施都已建立,所以我們在開發Node.js服務時就沒有必要再造輪子,那么怎么把這些基礎接口功能和Node.js服務聯系起來呢?我們決定把Node.js服務放到內網,通過只允許后端服務直接訪問的方式來達到這一目的,這樣后端接口層就像一個盾牌,擋在用戶和Node.js服務之間,而我們就可以專注實現Node.js的截圖功能了。整體方案流程如下圖4:

          圖 4 Node.js截圖方案整體流程方案

          僅首屏SSR渲染方案

          整體架構流程方案確定后,我們就需要細化截圖相關的詳細流程方案。在經過調研之后,我們發現常見的截圖開源方案在我們的使用場景中還有很多需要優化的點和不滿足需求的部分,因此我們決定自研開發【僅首屏SSR渲染】方案。針對項目特點,每個海報圖片只有一張,所以不存在首屏渲染過后還要渲染第二頁的場景,因此該方案只包含首屏字符串渲染即可,不需要帶有常見 SSR 的客戶端激活渲染的打包構建及執行流程。 去掉常見SSR方案中的非首屏渲染邏輯后,頁面就只包含了首屏必要的渲染代碼(HTML + CSS),去除一切不需要的環節(JS執行激活),保證頁面給到 Puppeteer渲染時是最簡化的狀態,盡可能減少網絡I/O和本地磁盤I/O,只包含單純的渲染過程,以加速渲染速度。以下是常見方案和自研方案的對比。

          最常見的截圖方案是通過請求網頁地址,渲染后截圖,如圖5。

          圖 5 Node.js截圖詳細流程常見方案

          這種方案不管是CSR(客戶端渲染)方式,還是SSR(服務端渲染)方式,都還是有優化空間。我們可以發現,Puppeteer請求網頁的網絡消耗是可以被節省下來的,如果我們直接使用在本地生成好的HTMLCSS,則請求網頁并下載所用的時間就可以節省下來,獲得更快的截圖速度。

          另外頁面的動態渲染通過SSR來進行,這樣完全不需要客戶端JS的存在,直接還可以省去加載客戶端JS的時間,獲得更優的渲染速度,這種優化后的Node.js截圖詳細流程方案如圖6所示。

          圖 6 優化后的Node.js截圖詳細流程方案

          該方案還有技術細節需要設計,即如何完成SSR渲染首屏的工作,由于我們的技術棧是Vue,所以選用vue-server-renderer為基礎庫來完成這一過程,如圖7。

          圖 7 僅首屏SSR渲染方案技術流程

          項目業務技術流程設計

          項目業務技術流程設計


          整體架構流程方案確定之后,我們就要進行更細化的業務技術流程設計,這里有很多細節需要考慮:

          • 后端接口層如何和Node.js截圖服務進行通信?
          • 截圖服務是一個高耗時服務,如何防止長鏈接堆積?
          • 如何設計海報圖片緩存層?如何設計提供海報預渲染?
          • 其他流程細節...

          為了解決這些問題,我們設計了如下的流程,如圖8。

          圖 8 Node.js截圖服務業務技術流程

          可以看到整個流程設計由接口同步請求和截圖異步任務兩大塊組成。我們把Node.js截圖服務當做一個純渲染圖片的服務,用戶發起請求給后端服務時會攜帶渲染頁面所需要的動態參數,后端服務則負責參數校驗等工作,并且下發給用戶一個異步任務ID。然后后端服務會請求截圖服務,截圖服務收到請求后并不會立刻截圖,而是直接返回后端服務,并開啟異步任務去進行耗時的截圖服務,這樣就可以防止長鏈接堆積造成服務不可用的情況發生。之前下發給用戶側的異步任務ID就是異步截圖任務完成后通知后端服務的憑證,這樣當截圖服務完成后就可以通知后端服務截圖完成狀態(截圖成功或者失敗),而用戶側則可通過輪詢后端服務接口得知截圖是否完成并使用海報圖片了,當然可以設置一個超時時間來完成整個截圖服務的交互閉環。

          對于海報圖片的緩存層也是要考慮的,因為很多場景下用戶請求的海報圖片是一模一樣的,比如我們的熱榜海報會在固定時間生成一次,那么緩存層可以有效緩解截圖耗時操作,并且為預生成海報圖片提供了基礎。比如我們會在特定時間通過代碼自動預渲染一批海報,當第一個用戶來訪問時就不需要等待耗時的截圖服務,直接返回渲染好的海報圖片即可。那么命中緩存的條件是什么呢?對于長的一模一樣的海報圖片當然希望只生成一次后都走緩存層。我們的設計中決定“圖片長相”的因素有兩個:

          1.海報地址:對應不同的海報樣式

          2.海報參數:對應同一個海報樣式中的不同數據

          所以,我們通過hash(“海報地址”+“海報參數”)的方式得到緩存命中的key,以此來控制命中緩存。另外截圖服務生成海報圖片后會直接上傳到CDN進行存儲,用戶側加載海報圖片的速度和穩定性也得到了相應的保障。

          項目技術選型及工程化方案

          項目技術選型及工程化方案


          在業務技術流程方案確定后,就需要為此搭建一套工程化開發環境,來支持項目業務的具體開發。我們基于公司現有基礎設施以及技術棧,確定了以下主要技術選型:

          • 接口服務框架:Express
          • 頁面渲染框架:Vue
          • 支持SSR渲染:vue-server-renderer
          • 支持瀏覽器截圖:Puppeteer
          • 支持頁面開發環境 :webpack
          • 圖片存儲:OSS (公司內部對象存儲服務)
          • 服務端日志:Logstash + Kafka+ Elasticsearch + Kibana(公司內部基礎日志服務鏈)
          • 部署:DomeOS (公司內部云服務平臺)

          如圖9,展示了通過以上技術棧及基礎設施組建的整個工程化方案。

          圖 9 Node.js截圖服務工程化方案

          這里需要說明是,一個海報圖片對應一個頁面,一個頁面會有兩個入口文件:一個CSR(客戶端渲染)用于開發頁面時使用,一個SSR(服務端渲染)用于截圖時Puppeteer渲染頁面使用。這么設計的原因是,CSR渲染使用webpack-dev-server是現成的開源方案,對于開發時熱更新等支持不需要自定義開發,開箱即用,如果開發時也使用SSR進行就需要進行針對性的改造,由于開發體驗上并沒有區別,我們就選用了更高效地搭建方式。而截圖時頁面渲染方式就是上文提到的【僅首屏 SSR 渲染】。

          項目關鍵優化實踐


          從用戶發起請求到海報圖片返回,這整個過程的耗時需要進行“壓榨”,以獲得更好的用戶體驗。以下是我們在開發過程中實踐和驗證的相關重點優化和部分效果收益。從第一版基礎開發到最后優化完成的版本,截圖服務總用時從1300ms+降低到了600ms+(注:測試數據均取相同開發機10次執行結果的平均值,渲染相同的海報圖片,圖片為超長圖且內容豐富,長寬為:4967×750)。表2為各關鍵優化點明細。

          表 2 項目關鍵優化實踐

          項目在線文檔預覽系統


          為了方便使用海報圖片的開發人員,我們還配套開發了海報生成系統在線文檔。開發人員可以通過該系統查看現有的海報圖片以及相關參數字段,并可以通過右方的編輯器更改字段的值并實時得到新的渲染圖進行預覽和下載。如圖10,開發人員可以在這個playground里進行所見即所得的預覽及操作。

          圖 10 海報在線文檔預覽系統

          項目日志實踐

          海報圖片服務作為一個后端服務,日志采集分析和監控是必不可少的,我們可以通過日志得到以下信息:

          • 海報圖片生成的訪問情況
          • 海報圖片生成的性能優劣
          • 海報圖片生成失敗的原因
          • 海報圖片生成異常的報警

          所以,我們封裝了3種log日志用于海報圖片服務:

          • access:記錄每次請求的請求日志
          • debug:記錄生成圖片的關鍵節點信息的日志
          • error:記錄生成圖片失敗及原因的錯誤日志

          日志處理完成后,我們接入了公司現有日志基建服務來完成后續的日志采集、存儲和分析等功能,如圖11所示,通過這一套日志流程,我們就可以更加放心地上線并時刻關注我們服務的運行情況,輕松做到快速排查和分析問題。

          圖 11 海報系統日志服務

          項目部署方案


          海報生成是一個耗時任務,其繪制速度依賴于服務器的CPU和內存。經過線上數據評估,截圖服務qps最大支持60即可,經使用JMeter并發測試:

          • 當使用單實例(CPU1核 + 內存 2G)單進程部署項目時,并發為1時生成5000像素的圖片需要耗時約2s,并發數超過1時,后面的請求得等待前面請求生成完圖片,才會生成,生成圖片時間會隨并發數成倍增加。
          • 當使用單實例(CPU1核 + 內存 2G)多進程部署項目時,并發為1時生成5000像素的圖片需要耗時約2s,并發數超過1時,當并發數少于進程數時,會同時生成圖片,并發為5時,圖片返回時間約為9s,此時CPU占用會超過40%,內存占用20%,雖然CPU和內存在并發數量為5的時候占用率不高,但是生成圖片的速度會大幅下降,所以需要增大單實例CPU和內存的大小。
          • 當使用單實例(CPU4核 + 內存 6G)多進程部署時,并發為1時生成5000像素的圖片耗時約1s,并發數為5的時候,圖片返回時間約為3s,當并發為10的時候,圖片返回時間約為8s。此時CPU占用會超過20%,內存占用10%。

          所以為了保證圖片的生成速度和穩定性,使并發量少的時候圖片生成速度盡可能快,并發量大的時候圖片生成速度在可接受時間內,采用了多實例加多進程的部署方式,如圖12,項目部署于DomeOS平臺,部署了5臺 (CPU4核 + 內存 6G) 實例,每個實例通過pm2啟動4個進程。通過負載均衡可以使請求平均打到每個實例的每個進程上,讓并發少的時候最快的生成圖片,并發大的時候充分利用所有實例,加快整體生成圖片時間。生成5000像素的圖片,當并發數小于5時,圖片可以在1s左右返回,當并發數為20,圖片可以在3s左右返回,當并發數為60時,圖片可以在8s之內返回。

          圖 12 海報系統部署方案

          項目成果

          截止到2023年初,海報圖片服務已上線海報10+個。每個海報只需開發1遍就可供給H5、小程序、AndroidiOS共4端進行使用。每天平均生成海報圖片6000+,每張海報圖片平均生成時間400ms左右,支持超長圖可達10000+像素。

          未來展望

          隨著項目迭代,海報服務未來可能有更大的需求訴求,下面列出海報服務未來進化的一些展望:

          1、賦能外部開發人員

          目前項目是以普通項目的開發模式進行研發,如果提供給非內部研發人員使用則有很多流程和規范上的問題難以解決。未來可以支持渲染遠程組件,通過遠程組件的方式下發給外部研發進行開發,以此隔絕海報服務核心邏輯和業務方邏輯,使得業務方只需關心業務,也防止業務方無意間可能影響到海報核心邏輯。此外,在整個過程中還可以增加審核遠程組件等項目管理能力。

          2、賦能非研發人員

          為了海報圖片渲染極具靈活性,我們把開發人員作為首要滿足對象。未來除了開發人員可以開發海報頁面,同時可以支持非研發人員通過拖拽編輯等低代碼方式完成海報圖片的生產,這樣針對簡單海報圖片的場景,運營、產品等非研發人員也可以進行海報圖片的制作,進一步提高生產效能。

          作者:狐友FE

          來源:微信公眾號:搜狐技術產品

          出處:https://mp.weixin.qq.com/s/D1N9qxHYGRBUlCGePvqj3w

          之前做的 WordPress 插件,更多涉及的是管理功能,比如用戶管理,分類管理這些插件等等,這些主要這些功能比較純粹,然后 WPJAM Basic 已經實現了 WordPress 后臺的各種底層類庫和交互組件,只要功能需求就能快速做好。

          但是最近在更新 Autumn Pro 5.0 的功能的時候,也開始有所涉獵 WordPress 的前端開發。 我就把一些常用的前端功能整理成統一的插件,一是方便日后更新,也是方便其他主題的集成。

          全能彈窗 WordPress 插件

          今天就來介紹這批插件中的第一個,一個全能的 WordPress 彈窗插件,也可以叫模態框插件,目前已經實現了海報 / 打賞 / 分享 / 搜索彈窗,接下來還會實現登錄 / 公告等彈窗,也提供彈窗接口,只要簡單幾行代碼也可以實現你自己的彈窗。

          插件激活之后,在后臺「WPJAM」菜單下就又會有「頁面彈窗」的子菜單,當然如果已經使用 Autumn Pro 主題,這個在菜單在「Autumn」菜單下,總之不在「WPJAM」菜單,就是在主題設置菜單下,點擊進去就進入彈窗的設置頁面了:

          文章海報彈窗

          如上圖所示,文章海報彈窗,需要你設置 logo 和標語,然后選擇自動插入(Autumn Pro 主題已經通過代碼插入,上面的自動插入選項也會沒有),就可以在頁面上顯示「生成海報」按鈕:

          當然其他主題你也可以自己通過 wpjam_get_poster_button($args=[]) 來手工插入,這里 $args 的默認值是:['title'=>'生成海報', 'class'=>'poster-button', 'icon'=>'ri-image-line'],你也可以自定義修改它:

          總之最后在頁面上出現「生成海報」按鈕,點擊它之后就會生成海報彈窗:

          樣式還是可以的,當然你也自己改一下 CSS,去調整海報的樣式,這里再多說兩句,海報是通過 HTML2Canvas 生成圖片的,這樣做好處,就是無需在服務端去生成海報圖片了,能夠顯著降低服務端的消耗,同時海報上的二維碼也是使用 jQuery.qrcode 前端 jQuery 插件實現,也不是服務端生成的圖片,更進一步降低服務器的消耗,本來這些功能就應該在前端實現的嘛,現在的瀏覽器能力也是越來越強了。

          文章打賞彈窗

          我們繼續看會最上面的設置圖,文章打賞彈窗需要設置「打賞標題 / 標語和收款碼」這三個選項,之后就會出現「打賞作者」的按鈕:

          同樣它的自定義調用函數是wpjam_get_donate_button($args=[]),$args的默認值是:['title'=>'打賞作者', 'class'=>'donate-button', 'icon'=>'ri-money-cny-circle-line']。

          點擊之后的彈窗如下:

          文章分享彈窗

          文章分享彈窗沒有設置選項,它的自定義調用函數是 wpjam_get_share_button($args=[]),$args 的默認值是:['title'=>'分享', 'class'=>'share-button', 'icon'=>'ri-share-forward-2-fill']。

          點擊生成的分享按鈕之后彈窗如下:

          文章搜索彈窗

          最后一個是文章搜索彈窗,通過它可以在后臺設置常用搜索詞:

          搜索按鈕不能自動插入,它只能通過 wpjam_get_search_button($args=[]) 函數手動插入,$args 的默認值是:['title'=>'', 'class'=>'search-button', 'icon'=>'ri-search-line']。

          比如 Autumn 的搜索按鈕就如下:

          點擊它之后就可以進行文章搜索:

          除了顯示搜索框和后臺設置的熱門搜索之外,還顯示當前用戶的搜索歷史,是不是有種大站才有搜索的感覺,哈哈。

          日常的工作中(比如微信小程序),我們經常有這樣的需求,就是需要使用程序生成推廣海報,然后海報里要包含指定的二維碼,這樣用戶分享出去別人掃碼之后就可以確定用戶推薦關系。

          單獨生成海報背景或者單獨生成二維碼通常還算比較簡單,但如果要將兩者結合到一起那還是需要花一點心思的。

          那現在怎么解決呢?如何使用PHP在服務器生成推廣海報呢?對的,使用PHP中的GD庫。具體過程請往下看。

          前期準備

          1、海報背景圖。背景圖一般存服務器,程序本地讀取;

          2、推廣二維碼。可以是二維碼圖片鏈接,也可以是字符串圖像流。如果自己生成二維碼,詳見phpqrcode官網,地址:https://sourceforge.net/projects/phpqrcode。

          3、開啟PHP的GD擴展

          操作步驟

          首先熟悉一下幾個關鍵的PHP函數:

          1、getimagesize:取得圖像大小。getimagesize() 函數將測定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM或 WBMP 圖像文件的大小并返回圖像的尺寸以及文件類型和一個可以用于普通 HTML 文件中 IMG 標記中的 height/width 文本字符串。如果不能訪問 filename 指定的圖像或者其不是有效的圖像,getimagesize() 將返回 FALSE 并產生一條 E_WARNING級的錯誤。

          2、image_type_to_extension:取得圖像類型的文件后綴。

          3、imagesx:取得圖像寬度。

          4、imagesy:取得圖像高度。

          5、imagecreatetruecolor:新建一個真彩色圖像。imagecreatetruecolor() 返回一個圖像標識符,代表了一幅大小為 x_size 和 y_size 的黑色圖像。是否定義了本函數取決于 PHP 和 GD 的版本。從 PHP 4.0.6 到 4.1.x 只要加載了 GD 模塊本函數一直存在,但是在沒有安裝 GD2 的時候調用,PHP 將發出致命錯誤并退出。在 PHP 4.2.x 中此行為改為發出警告而不是錯誤。其它版本只在安裝了正確的 GD 版本時定義了本函數。

          6、imagecolordeallocate:取消圖像顏色的分配。

          7、imagefill:區域填充。imagefill() 在 image 圖像的坐標 x,y(圖像左上角為 0, 0)處用 color 顏色執行區域填充(即與 x, y 點顏色相同且相鄰的點都會被填充)。

          8、imagecopyresampled:重采樣拷貝部分圖像并調整大小。imagecopyresampled() 將一幅圖像中的一塊正方形區域拷貝到另一個圖像中,平滑地插入像素值,因此,尤其是,減小了圖像的大小而仍然保持了極大的清晰度。

          9、getimagesizefromstring:從字符串中獲取圖像尺寸信息。同 getimagesize() 函數。 區別是 getimagesizefromstring() 第一個參數是圖像數據的字符串表達,而不是文件名。

          10、imagecopymerge:拷貝并合并圖像的一部分。

          11、imagejpeg:輸出圖象到瀏覽器或文件。

          12、imagedestroy:銷毀一圖像。

          熟悉完了這十幾個核心方法后,我們就可以編碼了。核心代碼如下:

          以上代碼是利用PHP生成推廣海報的主要部分,有了它我們就可以很容易的生成推廣海報了。

          參考案例:

          1、生成帶有二維碼的海報。

          2、生成帶有圖像,昵稱和二維碼的海報。

          從以上示例可以看出,只要我們定義好核心代碼之后,后面生成不同的推廣海報,只需要調整config配置參數即可。


          主站蜘蛛池模板: 色妞色视频一区二区三区四区 | 精品无码一区在线观看| 中文字幕在线观看一区二区 | 成人国产精品一区二区网站| 中日av乱码一区二区三区乱码| 在线观看国产一区二三区| 精品人妻一区二区三区毛片| 日韩aⅴ人妻无码一区二区| 麻豆一区二区在我观看| 亚洲av无码一区二区三区网站| 日亚毛片免费乱码不卡一区| 精品人妻少妇一区二区三区不卡 | 国产福利酱国产一区二区| 一区二区日韩国产精品| 少妇激情AV一区二区三区| 国产精品毛片VA一区二区三区 | 亚洲av鲁丝一区二区三区| 伊人久久大香线蕉av一区| 国产一区二区精品久久岳| chinese国产一区二区| 无码毛片一区二区三区视频免费播放 | 色综合视频一区二区三区 | 激情久久av一区av二区av三区| 国产福利一区二区三区| 亚洲AV成人一区二区三区在线看 | 亚洲不卡av不卡一区二区| av无码人妻一区二区三区牛牛| 国产成人无码精品一区在线观看 | 国产在线一区二区综合免费视频| 久久久久女教师免费一区| 大屁股熟女一区二区三区| 日韩精品无码一区二区三区四区| 国产亚洲自拍一区| 久久99国产精品一区二区| 色欲综合一区二区三区| 无码国产伦一区二区三区视频| 中文字幕精品一区影音先锋| 日韩人妻一区二区三区免费| 亚洲国产精品一区| 久久青青草原一区二区| 精品久久综合一区二区|