挽救電動車產業 印度政府再次開啟投資

    印度政府日前通過一項 23 億美元的電動車產業振興計劃──2020 國家電動車行動計劃(NEMMP 2020 plan),打算重新帶起終止補貼後明顯下滑的電動車銷量。   印度政府過去對電動車的銷售補貼相當成功,全盛時期銷售量甚至超過 10 萬輛,但當新暨再生能源部 MNRE 在 2012 年 3 月停止補貼後,銷售量開始下滑,到了 2013 年,只剩 2.1 萬輛。幾年前,印度有 65 家電動車製造商,現在只剩 10家還在營運。   NEMMP 計劃目標是在 2020 年有 6 到 7 百萬輛電動車上路,而其中 4 到 5 百萬輛為二輪車,若達到該銷量數字,還能節省超過 200 萬噸燃料的使用。   雖然大多數電動車公司在過去兩年來已停止營運,但假如 NEMMP 2020 可在接下來的 3 或 4 個月間實施,預期印度電動車產業仍可復甦。     (圖片來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

美電動車銷量 7 月破萬持續看漲

美國汽車媒體 GreenCarReports 報導,由於日產和通用兩家公司的聆風和雪佛蘭沃藍達在美國市場銷量表現不俗,美國 7 月插電式電動汽車銷量繼續看漲。聆風和雪佛蘭沃藍達的月度銷售量相加第二次超過 5000 台,上次月度銷量超過 5000 台是去年 8 月。    數據顯示,2014 年 7 月美國插電式電動車整體銷量為 1 萬 533 輛。其中日產聆風當月在美國本土市場的銷量為 3,019 輛,位居第一;其次是雪佛蘭沃藍達,銷量為 2,020 輛,取代了此前豐田普銳斯季軍的位置;豐田普銳斯當季銷量為 1,371 輛。   不難發現,美國新能源汽車市場的主要車型相對集中。日產的聆風、雪佛蘭沃藍達和豐田的普銳斯一直占據主導地位,也是美國傳統汽車品牌中新能源汽車領域的三大陣地。事實上,日產聆風電動車 7 月在美國市場的銷量並不是歷史最高銷量。其聆風電動車銷量的高峰是今年 5 月,共計銷售 3,117 輛,同比上漲 46%。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

Tesla 展霸氣!推「8 年不限里程保固」

電動車大廠特斯拉(Tesla)近日再推霸氣新政策,根據馬斯克(Elon Musk)在官方部落格發表的文章,現在他們最受歡迎的車款 Model S 將享有 8 年不限里程的保固,雖然這項新措施對客戶非常大方,但馬斯克也表示這將對短期內的獲利有負面影響。   「如果我們真的相信電動機比傳統的汽油引擎可靠,而且有著更少的油質殘渣與廢氣,那我們的保固政策就該反映出這點。」馬斯克信心十足的說。另外,他在文章內也對投資者表示,雖然因為保修儲備必須提升到更高的檔次,這項政策短期內對公司的盈利會有負面影響,但長期來說,他相信只要及早做出正確的決定肯定會對公司有所幫助。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

LG Chem 再下一城 與奧迪簽電池供應協議

    近來積極拓展車用電池事業的南韓化學巨擘 LG Chem Ltd. 宣佈,該公司已敲定價值數億美元的電動車電池供應合約,對象是德國汽車製造商福斯 (Volkswagen AG) 旗下的豪華車廠奧迪 (Audi AG)。   LG Chem 目前為通用汽車 (General Motors Co.)、雷諾 (Renault SA)、福特汽車 (Ford Motor Co.)、現代汽車 (Hyundai Motor Co.) 以及起亞汽車 (Kia Motors Corp.) 等 20 家業者的車用電池供應商。日前 LG Chem 才宣布將與通用汽車等汽車廠商攜手研發一款車用電池,其單次充電的里程數多達 200 英里,為市面上大多數電動車的兩倍以上。   20 日 LG Chem 又傳出好消息,該公司透過聲明表示,會為奧迪的次世代插電式混合動力電動車提供車用電池,總值多達數百億韓圜,而由於奧迪與母公司福斯一起共用了許多汽車平台,因此 LG Chem 認為未來應該能與福斯敲定更多類似的協議。     (圖片來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

Tesla Model S 變身電動跑車 性能更強

  Saleen Automotive 在改車界享負盛名,無論任何車款經其改裝後,都會變得更快更有勁。最近他們看上了 Tesla 的 Model S 電動車,將其改裝為 Saleen FourSixteen,比起原版本擁有更高性能。   Saleen FourSixteen 採用與 Model S 相同的 416 匹引擎,不過其齒輪比率卻提高至 11.39:1,能大幅提高跑車的加速性能,因此由 0 加速至 100 公里只需 4 秒,比起 Model S 足足快了 1 秒。此外,Saleen FourSixteen 同時亦改善了冷卻系統及防傾桿,與及採用賽車用的車底盤及碳纖維剎車盤。   車廂內部也經過重新設計,將 Model S 原有的五座位改成全真皮的四座位,變成了一部真正的四座位超級電動跑車。該跑車目前已開放預訂,但售價並不便宜,約 15 萬 2 千美元。     (圖片來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

跟着whatwg看一遍事件循環

前言

對於單線程來說,事件循環可以說是重中之重了,它為任務分配不同的優先級,井然有序的調度。讓js解析,用戶交互,頁面渲染等互不衝突,各司其職。

我們書寫的代碼無時無刻都在和事件循環打交道,要想寫出更流暢,我們就必須深入了解事件循環,下面我們將從規範中翻譯和解讀整個流程。

以下內容來自whatwg文檔,均為個人理解,若有不對,煩請指出,我會第一時間修改,避免誤導他人!

正文

為了協調用戶操作,js執行,頁面渲染,網絡請求等事件,每個宿主中,存在事件循環這樣的角色,並且該角色在當前宿主中是唯一的。

簡單解釋一下宿主:宿主是一個ECMAScript執行上下文,一般包含執行上下文棧,運行時執行環境,宿主記錄和一個執行線程,除了這個執行線程外,其他的專屬於當前宿主。例如,某些瀏覽器在不同的tabs使用同一個執行線程。

不僅如此,事件循環又存於在各個不同場景,有瀏覽器環境下的,worker環境下的和Worklet環境下的。

Worklet是一個輕量級的web worker,可以讓開發者訪問更底層的渲染工作線,也就是說你可以通過Worklet去干預瀏覽器的渲染環境。

提到了worklet,那就順便看一個例子(需開啟服務,不要以file協議運行),通過這個例子,可以看到事件循環不同階段觸發了什麼鈎子函數:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            .fancy {
                background-image: paint(headerHighlight);
                display: layout(sample-layout);
                background-color: green;
            }
        </style>
    </head>
    <body>
        <h1 class="fancy">My Cool Header</h1>
        <script>
            console.log('開始');
            CSS.paintWorklet.addModule('./paint.js');
            CSS.layoutWorklet.addModule('./layout.js');

            requestAnimationFrame(() => {
                console.log('requestAnimationFrame');
            });
            Promise.resolve().then(() => {
                console.log('微任務');
            });
            setTimeout(function () {
                document.querySelector('.fancy').style.height = '150px';
                ('translateZ(0)');

                Promise.resolve().then(() => {
                    console.log('新一輪的微任務');
                });
                requestAnimationFrame(() => {
                    console.log('新一輪的requestAnimationFrame');
                });
            }, 2000);
            console.log(2);
        </script>
    </body>
</html>

// paint.js
registerPaint(
    'headerHighlight',
    class {
        static get contextOptions() {
            console.log('contextOptions');
            return {alpha: true};
        }

        paint(ctx) {
            console.log('paint函數');
        }
    }
);

// ==========================分割線

// layout.js
registerLayout(
    'sample-layout',
    class {
        async intrinsicSizes(children, edges, styleMap) {}

        async layout(children, edges, constraints, styleMap, breakToken) {
            console.log('layout階段');
        }
    }
);

事件循環有一個或多個Task隊列,每個Task隊列都是Task的一個集合。其中Task不是指我們的某個函數,而是一個上下文環境,結構如下:

  • step:一系列任務將要執行的步驟
  • source:任務來源,常用來對相關任務進行分組和系列化
  • document:與當前任務相關的document對象,如果是非window環境則為null
  • 環境配置對象:在任務期間追蹤記錄任務狀態

這裏的Task隊列不是Task,是一個集合,因為取出一個Task隊列中的Task是選擇一個可執行的Task,而不是出隊操作。

微任務隊列是一個入對出對的隊列。

這裏說明一下,Task隊列為什麼有多個,因為不同的Task隊列有不同的優先級,進而進行次序排列和調用,有沒有感覺react的fiber和這個有點類似?

舉個例子,Task隊列可以是專門負責鼠標和鍵盤事件的,並且賦予鼠標鍵盤隊列較高的優先級,以便及時響應用戶操作。另一個Task隊列負責其他任務源。不過也不要餓死任何一個task,這個後續處理模型中會介紹。

Task封裝了負責以下任務的算法:

  • Events: 由專門的Task在特定的EventTarget(一個具有監聽訂閱模式列表的對象)上分發事件對象
  • Parsing: html解析器標記一個或多個字節,並處理所有生成的結果token
  • Callbacks: 由專門的Task觸發回調函數
  • Using a resource: 當該算法獲取資源的時候,如果該階段是以非阻塞方式發生,那麼一旦部分或者全部資源可用,則由Task進行後續處理
  • Reacting to DOM manipulation: 通過dom操作觸發的任務,例如插入一個節點到document

事件循環有一個當前運行中的Task,可以為null,如果是null的話,代表着可以接受一個新的Task(新一輪的步驟)。

事件循環有微任務隊列,默認為空,其中的任務由微任務排隊算法創建。

事件循環有一個執行微任務檢查點,默認為false,用來防止微任務死循環。

微任務排隊算法:

  1. 如果未提供event loop,設置一個隱式event loop。
  2. 如果未提供document,設置一個隱式document.
  3. 創建一個Task作為新的微任務
  4. 設置setp、source、document到新的Task上
  5. 設置Task的環境配置對象為空集
  6. 添加到event loop的微任務隊列中

微任務檢查算法:

  1. 如果微任務檢查標誌為true,直接return
  2. 設置微任務檢查標誌為true
  3. 如果微任務隊里不為空(也就是說微任務添加的微任務也會在這個循環中出現,直到微任務隊列為空):
    1. 從微任務隊列中找出最老的任務(防餓死)
    2. 設置當前執行任務為這個最老的任務
    3. 執行
    4. 重置當前執行任務為null
  4. 通知環境配置對象的promise進行reject操作
  5. 清理indexdb事務(不太明白這一步,如果有讀者了解,煩請點撥一下)
  6. 設置微任務檢查標誌為false

處理模型

event loop會按照下面這些步驟進行調度:

  1. 找到一個可執行的Task隊列,如果沒有則跳轉到下面的微任務步驟
  2. 讓最老的Task作為Task隊列中第一個可執行的Task,並將其移除
  3. 將最老的Task作為event loop的可執行Task
  4. 記錄任務開始時間點
  5. 執行Task中的setp對應的步驟(上文中Task結構中的step)
  6. 設置event loop的可執行任務為null
  7. 執行微任務檢查算法
  8. 設置hasARenderingOpportunity(是否可以渲染的flag)為false
  9. 記住當前時間點
  10. 通過下面步驟記錄任務持續時間
    1. 設置頂層瀏覽器環境為空
    2. 對於每個最老Task的腳本執行環境配置對象,設置當前的頂級瀏覽器上下文到其上
    3. 報告消耗過長的任務,並附帶開始時間,結束時間,頂級瀏覽器上下文和當前Task
  11. 如果在window環境下,會根據硬件條件決定是否渲染,比如刷新率,頁面性能,頁面是否在後台,不過渲染會定期出現,避免頁面卡頓。值得注意的是,正常的刷新率為60hz,大概是每秒60幀,大約16.7ms每幀,如果當前瀏覽器環境不支持這個刷新率的話,會自動降為30hz,而不是丟幀。而李蘭其在後台的時候,聰明的瀏覽器會將這個渲染時機降為每秒4幀甚至更低,事件循環也會減少(這就是為什麼我們可以用setInterval來判斷時候能打開其他app的判斷依據的原因)。如果能渲染的話會設置hasARenderingOpportunity為true。

除此之外,還會在觸發resize、scroll、建立媒體查詢、運行css動畫等,也就是說瀏覽器幾乎大部分用戶操作都發生在事件循環中,更具體點是事件循環中的ui render部分。之後會進行requestAnimationFrame和IntersectionObserver的觸發,再之後是ui渲染

  1. 如果下麵條件都成立,那麼執行空閑階段算法,對於開發者來說就是調用window.requestIdleCallback方法
    1. 在window環境下
    2. event loop中沒有活躍的Task
    3. 微任務隊列為空
    4. hasARenderingOpportunity為false

借鑒網上的一張圖來粗略表示下整個流程

小結

上面就是整個事件循環的流程,瀏覽器就是按照這個規則一遍遍的執行,而我們要做的就是了解並適應這個規則,讓瀏覽器渲染出性能更高的頁面。

比如:

  1. 非首屏相關性能打點可以放到idle callback中執行,減少對頁面性能的損耗
  2. 微任務中遞歸添加微任務會導致頁面卡死,而不是隨着事件循環一輪輪的執行
  3. 更新元素布局的最好時機是在requestAnimateFrame中
  4. 盡量避免頻繁獲取元素布局信息,因為這會觸發強制layout(哪些屬性會導致強制layout?),影響頁面性能
  5. 事件循環有多個任務隊列,他們互不衝突,但是用戶交互相關的優先級更高
  6. resize、scroll等會伴隨事件循環中ui渲染觸發,而不是根據我們的滾動觸發,換句話說,這些操作自帶節流
  7. 等等,歡迎補充

最後感謝大家閱讀,歡迎一起探討!

提前祝大家端午節nb

參考

composite

深入探究 eventloop 與瀏覽器渲染的時序問題

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

只看到了別人28歲從字節跳動退休,背後的期權知識你知道嗎?

前一陣字節跳動程序員,年僅 28 歲的郭宇財務自由,宣布退休的消息在網上火了一把,這個事情大家應該都知道了,細節就不多說了。

我剛看了這個新聞之後,起初內心出現的幾個關鍵詞是:卧槽、牛、羡慕……在意識到瞎感慨、羡慕沒啥用之後,我心裏不禁有個疑問:他的錢是怎麼來的?

我找在字節上班的朋友打聽了一下,據說郭同學近幾年投資賺了錢。當然還有網上大部分傳的,郭同學的發家致富是因為有字節跳動的期權,期權的價值隨着字節的估值翻上了天。

說到期權,估計很多人對期權不太清楚,除了關注熱點,我們還得學點知識對不對。今天我就和大家聊聊期權,省的將來大家遇到類似機會了,你一臉懵逼,甚至掉坑裡。

同時,因為我不是專業的,只是接觸過,所以講的不對、不嚴謹的,大家多擔待。

講期權之前,我們先接着上面說完郭同學的期權。

郭同學 2014 年加入字節,當時字節估值 5 億美元,現在字節估值 1000 億美元以上,估值妥妥的漲了 200 倍啊。如果當時有 10 萬期權,現在值 2000 萬;如果有 100 萬期權,現在值 2 億。就算考慮上後幾輪字節融資帶來的稀釋,打個折扣,那也是一筆不小的財富啊。

那麼郭同學有多少期權呢?說實話我也不知道,引用幾年前他和同學的對話,大家自己猜測吧。

郭同學的事說完了,我們繼續說期權。

1. 什麼是期權?

先舉個例子:

比如公司承諾你說,4 年之後,可以按每股 10 塊錢的價格,購買公司 1 萬份股票。期權的“期”就是指 4 年時間;期權的“權”就是 10 塊錢購買 1 萬份股票的權利。

等 4 年之後,如果公司的股票價格漲到了 100 塊,你依然可以用 10 塊錢的價格購買 1 萬份股票。花 10 萬買的股票就值 100 萬了,轉手賣出去之後,你能賺 90 萬。恭喜你!

另外一種可能是,如果 4 年後公司股票價格掉到 8 塊錢,這時候你肯定就不會按 10 塊錢價格購買股票了,不行使這個權利你也不會虧錢。

期權在國內互聯網公司不算少見,這當初是從硅谷那些互聯網公司學來的。

公司為了留住你,同時也為了長期激勵你,期權通常不會一下都給你,按上面的例子來說,4 年時間,可能每滿一年給你 1/4 數量的期權,或者是按月給。這也是為什麼有人把期權稱為“金手銬”。

2. 離職了期權怎麼辦?

上面的例子繼續展開說,如果乾滿了兩年,還沒幹滿四年,離職了期權怎麼辦?

這種情況,需要看之前你和公司怎麼約定的。通常有 3 種方式:

  1. 干滿 2 年,給了 50%,那麼就可以對這 50% 的期權行權,然後帶走,等着公司上市后變成股票。
  2. 公司回購你這 50% 的期權。
  3. 被公司收回,什麼都沒有。

說一個我自己的例子,我在 2008 年打工的時候,公司給過我期權,數量不多,具體的價格、時間已經完全記不住了,後來離職的時候,期權都被公司收回了。當時對期權完全不懂,想着收回就收回唄。後來那家公司發展的不是很好,即使我堅守到現在,那些期權啥也兌現不了。否則,我現在腸子都要悔青了。

3. 有期權是不是肯定拿低工資?

這個不一定。比如小米早期,就有高工資低期權、低工資高期權兩種方案供員工選擇。

如果你覺得老闆靠譜、公司有希望,同時少拿點工資也不影響自己的生活,當然可以選擇低工資高期權。博一把,一旦成了,那麼期權帶來的財富肯定遠超過工資。

當然選擇高工資低期權,也能理解,畢竟生活不易,很多人都要養家糊口。而且創業公司的成功率非常低,期權最後能兌現都是小概率事件。萬一期權不能兌現,除了損失了工資,時間成本和機會成本也不小。

但是大家要小心,有的公司會用期權給你畫個大大的餅,刻意把你的工資壓到非常低。如果老闆真有誠意,起碼會給你開一個可接受的工資。

期權是為了留住和激勵優秀員工的,工資太低,優秀員工的忠誠度、穩定性怎麼保證?

4. 白紙黑字

如果你遇到的老闆是天天把分期權掛在嘴上,但是遲遲不和你簽協議,那你要小心了。無論怎樣,任何口頭承諾都沒有任何意義。

一定要白紙黑字落在協議上,特別是行權時間、價格、數量、期限、公司回購價格等等要寫到合同協議里,省的將來產生糾紛。

當然,最省心的還是找一個靠譜的公司,比如:

  1. 公司的創始人信用好,如果他之前兌現過期權,那就更好了。
  2. 是著名投資機構投資的公司。
  3. 過往的融資都很順利,而且每一輪融資公司估值都漲的很快。
  4. 能吸引很多優秀的人才加入,也能側面說明這家公司比較健康。大家都眼瞎的概率還是很小的。

寫完以上幾點,我不禁想到了曾經的樂視,好像能滿足以上好幾點……

5. 期權的其他知識

進入公司差一年,為什麼期權相差很多?
拿字節跳動來說,入職時間差一年,可能期權差一個數量級。發展越迅猛的公司,這個差距越大,早期公司估值低,越早加入越有優勢。

期權怎麼變現?
通常除了公司回購,只能等上市了。

員工是否可以賣掉期權?
一般來說,員工是不能出售期權的。如果員工可以出售期權,只能賣給你的公司。

6. 乾股

再說一下乾股。

有些技術大牛在加入創業公司的時候,創始人可能會對技術大牛說:你出技術,不用出錢了,我白給你 20% 的乾股(或叫技術股)。

乾股聽起來好像挺好,大家一起干,不用出錢,還可以分紅。

但是通常乾股是虛股,只有分紅的權利,沒有參与經營、決策的權利,往往也不能轉讓。

乾股是不規範的叫法,由於技術合伙人沒有實際出資,也沒經過工商登記,有可能忙活半天,最後你的名字都不會出現在股東名單里。如果之前也沒簽過協議,這麼不清不楚的,將來會不會被踢出局,都不好說。

最穩妥的辦法還是去工商局登記變更,把乾股變成法律上認可的股權。

最後

以上就是這篇文章的主要內容,估計很多讀者會覺得,期權、股票這些離自己太遠,和自己關係不大。

千萬別這麼想!

第一、現在互聯網行業給股票、期權的公司不算少見,提前儲備點知識,萬一以後談 offer 的時候出現這些字眼,你也不至於啥也不懂。

第二、覺得自己現在還很菜,公司的股票、期權都是給核心員工的,輪不到自己。現在菜又怎樣,誰不是由菜變強的,現在沒有股票、期權,不代表以後也拿不到。

第三、在工資不降低或者可接受的範圍內,我建議大家拿股票、期權,萬一哪天自己就莫名其妙的發財了呢。

第三點大家一定要謹慎,再次提醒一下你們,別為了股票、期權就接受一個特別低的工資,這塊我教訓深刻。

就寫這麼多吧,希望這篇掃盲文章能讓你們有收穫。起碼我旁邊的碼農二毛又有收穫了:

二毛說:四哥你這麼一說,我明白了,我現在就算能跳槽進字節,就算給我期權,現在太晚了,字節估值都這麼高了,別說暴富,估計連湯都喝不上了。我應該怎麼辦呢?

我說:打開你的炒股軟件……

二毛說:我明白了,四哥你是讓我買字節的股票,拿着股票也可以跟着字節市值上漲賺錢。

我說:呸,字節還沒上市,你買毛線。我的意思是,如果幾年前你能拿出來選股票的勁頭來分析、選擇出一家潛力公司,早跳槽過去堅持到現在,估計你也發財了。

感謝閱讀,如果覺得有用,希望你可以分享給你的朋友、同事,或者點個在看支持一下。

—END—

我準備了一些純手打的高質量PDF,有好友贊助的也有我自己的,大家可以免費領取:

深入淺出Java多線程、HTTP超全匯總、Java基礎核心總結、程序員必知的硬核知識大全、簡歷面試談薪的超全乾貨。

別看數量不多,但篇篇都是乾貨,看完的都說很肝。

領取方式:掃碼關注后,在公眾號後台回復:666

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

微服務中如何設計一個權限授權服務

基於角色的訪問控制  (RBAC) 

  是將系統訪問限製為授權用戶的一種方法,是圍繞角色和特權定義的與策略無關的訪問控制機制,RBAC的組件使執行用戶分配變得很簡單。

  在組織內部,將為各種職務創建角色執行某些操作的權限已分配給特定角色。成員或職員(或其他系統用戶)被分配了特定角色,並且通過這些角色分配獲得執行特定系統功能所需的權限。由於未直接為用戶分配權限,而是僅通過其角色(一個或多個角色)獲取權限,因此,對單個用戶權限的管理就變成了簡單地為用戶帳戶分配適當角色的問題。這簡化了常見操作,例如添加用戶或更改用戶部門。

RBAC定義了三個主要規則

  1、角色分配:僅當對象已選擇或分配了角色時,對象才能行使權限。

  2、角色授權:必須為主體授權主體的活動角色。使用上面的規則1,此規則可確保用戶只能承擔獲得其授權的角色。

  3、權限授權:僅當對象的活動角色被授權時,對象才能行使權限。使用規則1和2,此規則可確保用戶只能行使其被授權的權限。

創建RBAC的模型

菜單 

  public class SysMenu
    {
        /// <summary>
        ///     父級
        /// </summary>
        public int ParentId { get; set; } = 0;

        /// <summary>
        ///     菜單名稱
        /// </summary>
        [StringLength(20)]
        public string Name { get; set; }

        /// <summary>
        ///     菜單地址
        /// </summary>
        [StringLength(20)]
        [Required]
        public string Url { get; set; }

        /// <summary>
        ///     層級
        /// </summary>
        [Column(TypeName = "tinyint(4)")]
        public int Level { get; set; } = 1;

        /// <summary>
        ///     菜單權限(list<int /> json)
        /// </summary>
        [StringLength(100)]
        public string Operates { get; set; }

        /// <summary>
        ///     排序
        /// </summary>
        public int Sort { get; set; }

        /// <summary>
        /// 菜單圖標
        /// </summary>
        public string Icon { get; set; }        
    }

 功能

  public class SysOperate
    {
        /// <summary>
        ///     按鈕名稱
        /// </summary>
        [StringLength(20)]
        [Required]
        public string Name { get; set; }

        /// <summary>
        ///     備註
        /// </summary>
        [StringLength(int.MaxValue)]
        public string Remark { get; set; }

        /// <summary>
        /// 唯一標識
        /// </summary>
        [Required]
        public int Unique { get; set; }
    }

角色

  public class SysRole 
    {
        /// <summary>
        ///     角色名稱
        /// </summary>
        [StringLength(20)]
        [Required]
        public string Name { get; set; }

        /// <summary>
        ///     備註
        /// </summary>
        [StringLength(int.MaxValue)]
        public string Remark { get; set; }
    }

用戶

    public class SysUser
    {
        /// <summary>
        ///     角色id
        /// </summary>
        public int RoleId { get; set; }

        /// <summary>
        ///     用戶名
        /// </summary>
        [StringLength(32)]
        [Required]
        public string UserName { get; set; }

        /// <summary>
        ///     密碼
        /// </summary>
        [StringLength(500)]
        [Required]
        public string Password { get; set; }
    }

 微服務中讓它成為一個授權權限服務

  在日常工作中,總會有很多系統要做,每個系統都要一套完整的權限功能,有現成的直接拿來粘貼複製,沒有現成的又要浪費很多時間去設計實現它。 如果有這樣一個服務,我們可以節省很多不必要的粘貼複製操作,節省很多時間。

  於是 ketchup.zero 這樣一個服務就誕生了。它是基於ketchu微服務框架來實現的一個權限授權服務,基本可以滿足我們日常工作的的權限需求。

  服務的前端是基於vue的模板d2admin 開發的。

ketchup.zero的功能

登陸

面板

 

 用戶配置角色

 

 菜單設置擁有那些權限

 

 權限/功能/按鈕 管理

 

 角色設置權限

 

最後安利

如果它對你有幫助,請給一波start

服務 ketchup.zero 源碼地址:https://github.com/simple-gr/ketchup.zero

微服務框架 ketchup 源碼地址:https://github.com/simple-gr/ketchup 

ketchup 交流群:592407137

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

前端業務代碼中的配置化

業務代碼中的配置化

工作中有許多邏輯冗雜、迭代頻繁的業務代碼,隨着迭代將越來越難以維護,一些場景適合通過配置化的方式來處理便於維護。

一、什麼是業務代碼配置化?

根據業務場景使用配置化的 Object|Array|Map 處理條件判斷邏輯,通常需要配置文件 CONFIG.js,若邏輯複雜需添加 getConfig 的處理函數 – tool.js

  • 本質上 if/else 邏輯是一種狀態匹配

  • 表驅動法,使用表數據,存儲對應的狀態處理

  • 可讀性好,減少了繁雜嵌套的 if-else,讀取配置,邏輯更清晰

  • 可維護性高,邏輯分支的增刪只是 CONFIG 的增刪

二、如何在業務場景中進行代碼配置化?

1. 簡單的狀態映射

  • 按需使用 Object|Map 配置
單一條件
  • Object 形式:
// CONFIG.JS
  export const STATUS = {
    STUDENT: 0,
    TEACHER: 1,
    MA_NONG: 2,
  };
  export const WORK_MAP = {
    STATUS.STUDENT: '學生',
    STATUS.TEACHER: '老師',
    STATUS.MA_NONG: '碼農',
  };

// index.js
  this.setData({
    work: WORK_MAP[status],
  });

  axios.post(url, { status: STATUS.MA_NONG });
  • Map 形式:
// CONFIG.JS
export const WORK_MAP = new Map([
  [0, "學生"],
  [1, "老師"],
  [2, "碼農"],
]);
// index.js
this.setData({
  work: WORK_MAP.get(status),
});
多重條件
const config = new Map([
  [
    (condition0, condition1, condition2) =>
      condition0 && condition1 && condition2,
    () => {
      console.log("map0");
    },
  ],
  [
    (condition0, condition1, condition2) =>
      condition0 || condition1 || condition2,
    () => {
      console.log("map1");
    },
  ],
]);
config.forEach((action, _if) => _if(0, 1, 0) && action());

2. 每個狀態有多種屬性

  • 多個屬性
  • 使用 Array 配置
// CONFIG.JS
  export const CONFIG = [
    {
      status: STATUS.STUDENT,
      name: '學生',
      action: '談戀愛',
    },
    {
      status: STATUS.TEACHER,
      name: '老師',
      action: '教書',
    },
    {
      status: STATUS.MA_NONG,
      name: '碼農',
      action: '寫bug',
    },
  ];

// index.js
  <!-- 根據狀態不同的行為 -->
  function action(status) {
    const { name, work } = CONFIG.find(i => i.status === status);
    console.log(`${name}在${action}`);
  }

3. 每個狀態有多種屬性且參數定製化

  • 參數高度定製化,不同狀態需要適配接口不同的字段
  • 使用 Array 配置
  • 通過配置函數並傳參注入接口數據可滿足定製化需求
// CONFIG.JS
  export const CONFIG = [
    {
      status: STATUS.STUDENT,
      name: '學生',
      action: () => {
        console.log('學生的工作是談戀愛');
      },
    },
    {
      status: STATUS.TEACHER,
      name: '老師',
      action: (info) => {
        alert(`老師${info.age}歲,每天${info.action}`);
      },
    },
    {
      status: STATUS.MA_NONG,
      name: '碼農',
      action: (info) => {
        toast(`碼農工作${info.workTime}年了,頭髮僅剩${info.hair}根了`);
      },
    },
  ];

// index.js
  <!-- 根據接口狀態action -->
  function action(res) {
    const { action, info } = CONFIG.find(i => i.status === res.status);
    action && action(info); // 傳參定製化
  }

三、實例

大首頁瀑布流 item 樣式

  • 根據 list 接口下發的 item 的類型(type)&樣式(layout)字段取 item 中的封面、標題、標籤、頭像…,字段各不相同
  • 十幾種 item 類型,有的還有不同的 layout,item 數據下發方式不同
  • 公共組件,需要適配其他模塊的接口數據作展示

index.xml

  • 數據驅動,減少模板中的判斷邏輯
<view class="panel" bind:tap="goDetail">
  <!-- 封面 -->
  <image  wx:if="{{panel.cover}}" class="panel__cover" src="{{panel.cover.image}}">
      <view class="panel__tag {{panel.tagClass}}" wx:if="{{panel.tagClass}}">{{panel.tag}}</view>
  </image>
  <!-- 標題 -->
  <view class="panel__titl" wx:if="{{panel.title}}">{{panel.title}}</view>
  <!-- footer -->
  <view class="panel__footer" wx:if="{{panel.showFooter}}">
    <image class="panel__footer-icon" wx:if="{{panel.user.icon}}" src="{{panel.user.icon}}"></image>
    <text class="panel__footer-name" wx:if="{{panel.user.nickname}}">{{panel.user.nickname}}</text>
    <text class="panel__footer-comment" wx:if="{{panel.commentCount}}">{{panel.commentCount}}評論</text>
  </view>
</view>

CONFIG.js

import { Layout, NewsType, Redirect } from 'src/constant';
import { formatImage, formatUser } from './tool';

/**
 * 配置項
 * @param {String} title 標題
 * @param {String} cover 封面
 * @param {String} tag 標籤
 * @param {Object} user 用戶信息
 * @param {Boolean} showFooter 是否显示footer
 * @param {Boolean} isAd 是否廣告
 * @param {Function} itemWrap 兼容接口數據函數,數據可能以ref_xxx下發,比如帖子:ref_post
 * ......
 */

<!-- 默認配置項 -->
export const DEFAULT = {
  title: ({ title = '' }) => title,
  cover: ({ image_list = [], article_images = [] }) =>
    formatImage(image_list[0]) || formatImage(article_images[0]),
  showFooter: true,
  user: ({ user, user_account, article_source_tx = '' }) =>
    user
      ? formatUser(user)
      : user_account
      ? formatUser(user_account)
      : {
          icon: '',
          nickname: article_source_tx,
        },
};

export const CONFIG = [
  {
    type: NewsType.NEWS,
    ...DEFAULT,
    tag: '資訊',
    tagClass: 'news',
  },
  {
    type: NewsType.VIDEO,
    ...DEFAULT,
    tag: '',
    tagClass: 'video',
    cover: ({ image_gif_list = [], image_list = [] }) => formatImage(image_gif_list[0] || image_list[0]),
    video: ({ video_url = '', tencent_vid = '', image_gif_list = [] }) => ({
      hasVideo: true,
      src: tencent_vid || video_url,
      video_url,
      tencent_vid,
      gifCover: formatImage(image_gif_list[0]),
    }),
  },
  {
    type: Redirect.EVAL_DETAIL,
    layouts: [
      {
        layout: Layout.EVALUATION,
        ...DEFAULT,
        tag: '口碑',
        tagClass: 'praise',
      },
      {
        layout: Layout.PRAISE_COMPONENT,
        ...DEFAULT,
        tag: '口碑',
        tagClass: 'praise',
        itemWrap: ({ ref_car_score = {} }) => ref_car_score,
        title: ({ chosen_topic = '' }) => chosen_topic,
        commentCount: ({ comment_count = null }) => comment_count,
        cover: ({ images = [], recommend_images = [] }) =>
          formatImage(images[0]) ||
          formatImage(getCoverFromRecommendImages(recommend_images)),
      },
      {
        layout: Layout.NORMAL,
        ...DEFAULT,
      },
    ],
  },
  ......
];

tool.js

import { CONFIG, DEFAULT, AD_CONFIG } from "./CONFIG";
// 獲取瀑布流item數據
export const getPanelData = (item) => {
  const getConfigByTypeAndLayout = () => {
    let config = CONFIG.find((i) => i.type == item.type);
    if (item.isAd) {
      config = AD_CONFIG;
    }
    if (config && config.layouts) {
      config = config.layouts.find(
        (i) => i.layout === item.layout_type || i.layout === item.display_style
      );
    }
    if (!config) {
      config = DEFAULT;
      console.log("no-config", item.type, item.layout_type, item);
    }
    return config;
  };
  const getPanelDataByConfig = (c) => {
    const panel = {};
    let _item = item;
    if (c.itemWrap) {
      _item = c.itemWrap(item);
    }
    Object.keys(c).forEach((key) => {
      if (typeof c[key] === "function") {
        panel[key] = c[key](_item);
      } else {
        panel[key] = c[key];
      }
    });
    return panel;
  };
  // 根據item的類型、樣式獲取配置
  const config = getConfigByTypeAndLayout(item);
  // 根據配置獲取瀑布流item信息
  return getPanelDataByConfig(config);
};

四、結語

所以,業務代碼配置化很簡單,大家也都一直在用,只是如果在一些業務場景中都形成配置化的習慣或者共識,可能更好維護吧。

鄙人拙見,大佬賜教~

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

在採用K8S之前您必須了解的5件事情

作者簡介

Christopher Tozzi,自2008年來以自由職業者的身份對Linux、虛擬化、容器、數據存儲及其相關主題進行報道。

時至今日,Kubernetes已然成為風靡一時的容器編排調度工具,許多IT分析師均提出了企業應當在何時採用Kubernetes的深刻建議。然而,和所有其他的軟件平台一樣,Kubernetes並非是一個適用於所有人的靈丹妙藥。我更傾向於認為人們在有些時候過分誇大了Kubernetes的作用,以至於他們產生了一種錯覺:他們無法離開Kubernetes,而實際上,Kubernetes比他們真正的需求要複雜得多。

為了分析人們真正的需求與Kubernetes的匹配程度,我分析了企業在採用Kubernetes編排之前必須考慮的5個事情。

Kubernetes是什麼?

如果您關注容器,您可能會知道Kubernetes是一個用於容器編排的開源工具,它可以自動執行諸如啟動容器、停止容器以及在同一個容器的不同實例之間的負載均衡等重要任務。

簡而言之,Kubernetes的主要目的是最大限度地減少工程師必須手動執行的管理工作量,並通過簡化容器操作,幫助企業大規模運行複雜的容器化應用程序。

決定是否採用Kubernetes的關鍵要素

基於Kubernetes的設立初衷,如果您喜歡自動化,討厭手動執行重複性的任務,那麼Kubernetes無疑是您的極佳選擇。

這是您決定是否採用Kubernetes的重要前提,但是,您不能僅根據這一“前提”就決定是否採用Kubernetes。在採用Kubernetes之前,您還需要考慮並權衡其他重要的因素。

1、Kubernetes的基礎設施規模

您的基礎設施規模是其中一個決定Kubernetes是否能夠很好地為您所用的關鍵要素。

Kubernetes的設計初衷是協調分佈在真正龐大的環境中的容器,這往往意味着企業應當擁有數十台主機服務器。根據過往的實施經驗,如果基礎架構中的服務器少於50個,那麼您可能沒有足夠的資源來利用Kubernetes的全部優勢。

這並不是指Kubernetes無法在較小規模的基礎設施上運行。實際上,如果您願意,您可以在單個主機上運行Kubernetes。然而,由於Kubernetes其中的一個研發目的是:通過在數量龐大的集群中分佈容器化應用程序提供高可用性,因此,如果您只有少量服務器,則無法享受到Kubernetes的某些價值。

除此之外,考慮到設置和維護Kubernetes的複雜性,如果您的基礎設施規模較小,無法完全實現Kubernetes的高可用性承諾,那麼或許您不應投入過多時間和精力在Kubernetes上。

對於較小的基礎架構,您可以使用較為簡單的容器編排工具,或者使用如AWS ECS等具有內置編排的基於雲的容器服務。

2、Kubernetes操作系統環境

Kubernetes主要是一種Linux技術。儘管Kubernetes可以用於管理託管Windows服務器上的容器化應用程序,這些應用程序作為Kubernetes服務器集群內的所謂工作節點運行。但託管Kubernetes核心服務的主要服務器或者說主節點必須是Linux。

因此,如果您的商店以Windows為中心,那麼Kubernetes並非您的最佳選擇。但是您可以選擇Rancher輕鬆將Kubernetes的優勢引入Windows,並且極大程度降低使用的複雜性。

3、安裝和設置Kubernetes

在決定採用Kubernetes之前,您還需要評估您可以在此項目上投入的工作時間。

普通的開放源代碼版本的Kubernetes缺少內置的應用程序,也並未提供一種可以適用於所有默認配置的安裝方式。在集群正常運行之前,您需要投入大量的時間從頭開始編寫及調整配置文件。因此,安裝和配置Kubernetes的過程或許是一個令人生畏的過程,您需要投入大量的時間和精力。

部分Kubernetes發行版提供了交互式安裝程序腳本,可以幫助您自動執行大部分設置過程。如果您選擇Rancher等Kubernetes發行版,則有望在一两天內輕鬆完成配置及安裝。

第三種選擇是使用諸如Google Kubernetes Engine等雲供應商解決方案,將Kubernetes作為託管服務在雲上運行。在這種情況下,您可以自行選擇安裝及設置。但值得注意的一點是,在確定如何配置Kubernetes環境時,您的選擇可能會受到限制。

您必須意識到最為關鍵的一點:不要低估配置Kubernetes的難度。在您真的要全身心投入Kubernetes之前,請確保您所付出的努力是值得的。另一方面,如果您無法確定為企業在生產集群上安裝和部署Kubernetes的難度,您可以嘗試使用K3s等輕量級Kubernetes發行版來進行測試,預估後續需要付出多少努力來進行Kubernetes的配置和設置。

4、Kubernetes和聲明式配置管理

Kubernetes採用了所謂的聲明式配置管理方法,這就意味着,您需要自行編寫配置文件來設置Kubernetes應用程序應當如何運行,而Kubernetes將自動指出如何使應用程序符合規範。

聲明式配置管理與命令式配置管理相反,在命令式配置管理中,您可以自行配置應用程序的每個組件,並讓其按照您所想要的方式運行。

聲明式配置是Kubernetes在許多用戶實例中如此強大和可伸縮的其中一個原因。您可以設置一次配置,並且根據需要多次應用它。

但是,如果您的配置需求不斷變化,或者在工作負載或環境中的不同部分之間變化,那麼您應當如何處理呢?在這種情況下,聲明式配置管理將成為一個障礙,您將發現自己需要不斷地調整先前認為是“一勞永逸”的配置文件。

因此,在您選擇採用Kubernetes之前,您需要考慮應用程序的配置需求。只有當您所需要的配置相對通用且靜態時,Kubernetes才是一個不錯的選項。

5、Kubernetes和多雲

Rancher等部分Kubernetes發行版的主要功能之一,是單個Kubernetes部署可以編排多個集群,無論集群位於在不同的公有雲還是私有雲上。這一功能使Kubernetes成為協助控制多雲架構複雜性的優秀工具。

在跨多雲部署容器化應用程序,並且Kubernetes的設置和配置工作很合理時,多雲上的Kubernetes是十分有意義的。

在這一因素中,您需要留意的是,在考慮是否以及何時採用Kubernetes時,應考慮您當前的多雲戰略以及多雲擴展計劃。

結 語

Kubernetes是一個非常棒的工具,在正確設置的情況下,它可以產生巨大的價值。但是,它並沒有達到殺手級應用程序的狀態,因為它無法在所有用戶實例中交付價值。在您被巨大的宣傳攻勢攻陷,並確定您無法離開Kubernetes之前,請清醒地對自己的需求進行評估,明確Kubernetes是否能在真正意義上幫助您更加有效、更加可靠地運行應用程序。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案