Design

Design
asp.net mvc

2019年4月1日 星期一

Nginx websocket平衡負載設置

主要重點為http頭部請求代上這兩個請求升為websokect
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

events {
    worker_connections  1024;
}


http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
 
    upstream websocket {
     #例如有這兩台我需要負載平衡
     server localhost:3100;  
     server localhost:3101;    
    }
 
    server {
       #代理監聽3102 ws://localhost:3012 可以發現我們在3100 3101之間做平衡
        listen 3102;
        location / {
            proxy_pass http://websocket;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
   
        }
    }
}




底下為一些參數的說明做個筆記
#运行用户
user nobody;
#启动进程,通常设置成和cpu的数量相等
worker_processes  1;
 
#全局错误日志及PID文件
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
 
#pid        logs/nginx.pid;
 
#工作模式及连接数上限
events {
    #epoll是多路复用IO(I/O Multiplexing)中的一种方式,
    #仅用于linux2.6以上内核,可以大大提高nginx的性能
    use   epoll; 
 
    #单个后台worker process进程的最大并发链接数    
    worker_connections  1024;
 
    # 并发总数是 worker_processes 和 worker_connections 的乘积
    # 即 max_clients = worker_processes * worker_connections
    # 在设置了反向代理的情况下,max_clients = worker_processes * worker_connections / 4  为什么
    # 为什么上面反向代理要除以4,应该说是一个经验值
    # 根据以上条件,正常情况下的Nginx Server可以应付的最大连接数为:4 * 8000 = 32000
    # worker_connections 值的设置跟物理内存大小有关
    # 因为并发受IO约束,max_clients的值须小于系统可以打开的最大文件数
    # 而系统可以打开的最大文件数和内存大小成正比,一般1GB内存的机器上可以打开的文件数大约是10万左右
    # 我们来看看360M内存的VPS可以打开的文件句柄数是多少:
    # $ cat /proc/sys/fs/file-max
    # 输出 34336
    # 32000 < 34336,即并发连接总数小于系统可以打开的文件句柄总数,这样就在操作系统可以承受的范围之内
    # 所以,worker_connections 的值需根据 worker_processes 进程数目和系统可以打开的最大文件总数进行适当地进行设置
    # 使得并发总数小于操作系统可以打开的最大文件数目
    # 其实质也就是根据主机的物理CPU和内存进行配置
    # 当然,理论上的并发总数可能会和实际有所偏差,因为主机还有其他的工作进程需要消耗系统资源。
    # ulimit -SHn 65535
 
}
 
 
http {
    #设定mime类型,类型由mime.type文件定义
    include    mime.types;
    default_type  application/octet-stream;
    #设定日志格式
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
 
    access_log  logs/access.log  main;
 
    #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,
    #对于普通应用,必须设为 on,
    #如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,
    #以平衡磁盘与网络I/O处理速度,降低系统的uptime.
    sendfile     on;
    #tcp_nopush     on;
 
    #连接超时时间
    #keepalive_timeout  0;
    keepalive_timeout  65;
    tcp_nodelay     on;
 
    #开启gzip压缩
    gzip  on;
    gzip_disable "MSIE [1-6].";
 
    #设定请求缓冲
    client_header_buffer_size    128k;
    large_client_header_buffers  4 128k;
 
 
    #设定虚拟主机配置
    server {
        #侦听80端口
        listen    80;
        #定义使用 www.nginx.cn访问
        server_name  www.nginx.cn;
 
        #定义服务器的默认网站根目录位置
        root html;
 
        #设定本虚拟主机的访问日志
        access_log  logs/nginx.access.log  main;
 
        #默认请求
        location / {
            
            #定义首页索引文件的名称
            index index.php index.html index.htm;   
 
        }
 
        # 定义错误提示页面
        error_page   500 502 503 504 /50x.html;
        location = /50x.html {
        }
 
        #静态文件,nginx自己处理
        location ~ ^/(images|javascript|js|css|flash|media|static)/ {
            
            #过期30天,静态文件不怎么更新,过期可以设大一点,
            #如果频繁更新,则可以设置得小一点。
            expires 30d;
        }
 
        #PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
        location ~ .php$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
 
        #禁止访问 .htxxx 文件
            location ~ /.ht {
            deny all;
        }
 
    }
}

2019年3月20日 星期三

正向代理與反向代理差異

因為偶爾會有機會接觸到nginx一直不清楚當中反向代理跟正向代理的真正意思,也只知道nginx可以當作大多的伺服器與負載平衡用,也很多作為反向代理的作用,至於是什麼我們來說說吧

首先我們看張圖


正向代理
正向代理比較像是一個中間服務器就像是一個中繼站,例如client端像目標server端發出請求,中間透過了正向代理跟server端取得資料返回給client端,client端這邊就需要做些設置才能使用.

反向代理
反向代理就是相反的意思,主要是把反向代理當作伺服器,由client端直接跟反向代理要求資料,由反向代理決定資料該走向何處,就像是個接口一個伺服器.

區別
正向代理需要手動設置代理伺服器IP指定代理去跟目標server端要取資料,反向代理則就跟一般一樣去跟目標server要資料只是中間透過反代理伺服器所以真實伺服器是不可見.

使用情境
正向代理可以隱藏我們client端自身因為我們是透過正向代理去跟目標server端要取資料,今天我們client端可能被封鎖限制某些網站不能進去,但是我們正向代理卻可以,就可以透我們正向代理去跟目標server要資料就是我們俗稱的翻牆.

反向代理就可以做到很多事情我們最熟知的就是平衡負載,其他就例如隱藏目標server壓縮緩存內容當中繼站,可以達到存取資料加速.



2019年3月10日 星期日

Youtube Download Antd-Vue + Nodejs 簡單練習

看到Facebook就有人在問ui套件該怎選擇,我留了









其實每個專案最後都會自己受用的技術跟ui框架,用別人的ui框架小功能開發當然快,但是一複雜就是會受限於功能上,最後這些問題下導致拖累開發速度,另一方面自己如果能學習開發框架的能力及技術當然總有一天自己也可以成為別人的巨人.

回到標題
這麼愛寫功能練習的我假日用了大概2小時簡單寫了個  Antd-Vue + Nodejs 為server的Youtube下載的功能,主要antd我沒這麼熟悉也常常看到有人在推崇就試著寫看看,果然用別人寫好的東西就是快,但是我覺得相對會有很多限制css跟一些版型上的問題,也會造成很多人再用但是卻實際根本不知道怎寫的情況.
Node這邊用了youtube-dl去解析youtube的資料做顯示分析各種資料格式可以供使用者直接下載,當然還有轉檔功能youtube-dl也都可以做到.

我有部屬到Heroku 有興趣可以看一下
https://youtubego.herokuapp.com/

2019年3月6日 星期三

Vue-virtual-scroll 虛擬滾動實作


前言
我們常常在開發畫面往往遇到最頭痛的問題就是效能問題,一個好的功能如果沒有流暢的操作畫面,我想寫得再多功能也是於事無補,特別是在使用v-for時 如果我們要渲染幾萬筆資料往往是畫面還沒出來就先卡住了,更何況是Mobile版本,所以就有了我們的virtual-scroll,這邊我就寫個簡單的範例,一方面也當作練習,廢話不多 我們先看實現效果



可以發現我們可視的畫面是固定的我們卻可以實現大量list效果的顯示

思路
例如我們有一萬筆資料 我只想每次渲染五筆 這時候第一步我們需要個虛擬的主要是要顯示我們的卷軸用這個 例如一萬筆高度乘以每筆30px ,再來高度有了 每五筆的渲染呢 就是要透過我們每次捲動時計算scrollTop在這個位置時我們的資料畫面的第一筆至第五筆的是在第幾筆資料的可見區域進行渲染,簡單講就是我們卷軸再捲時我們再透過translate調整Y軸固定我們顯示的位置,我知道這樣講解可能不太清楚我們就直接看程式碼吧 我也有放在我的github(https://github.com/MarsCaiWORD/Vue-virtual-scroll)






2019年3月5日 星期二

Vue雙向綁定的原理&實現

前言

Vue也寫了這麼久了對雙向綁定原理也是有點一知半解,就來實際操作JavaScript寫個簡單版Vue雙向綁定功能,了解語言的底層運作的話以後各種開發情境甚至自己開發前端framework都是有利的.

雙向綁定原理

我們可以先可以先建立個我們一般new vue的方法然後這邊我們console出我們的資料觀察



可以發現我們a屬性下還有我們相對應的get() set()的方法熟悉我們javascirpt原生的朋友一定可以猜出vue是透過Object.defineProperty()為底層監控我們的資料的異動然後實現我們雙向綁定的原理,我知道可能很多人還不知道Object.defineProperty()這邊就寫個簡單的範例
btw. ES6新出的Proxy也可以可以達到同樣的效果




























Vue架構

首先我們都知道Vue是基於MVVM的架構如下圖,分別為View,ViewModel,Model,這麼做有什麼好處呢,我們知道以前也有個MVC的架構,在MVC架構下我們元件都是共用在複雜邏輯的畫面時就會造成以下圖的問題,有時候光要找問題就很頭痛了,所以才衍生出現在有MVVM或是Flux架構,這邊我們我們講Vue就來說說MVVM架構,多個ViewModel就有點像個中繼站負責我們View跟Model之間的橋樑

MVC:
「flux mvc」的圖片搜尋結果














MVVM:
「MVVM vue」的圖片搜尋結果














簡單解釋如下:
View:
為我們UI的部分負責呈現我們DOM
ViewModel:
為負責同步View及Model之間的橋樑,讓畫面的更新可以即時同步到資料上
Model:
就是我們的資料

vue實際做法
至於綁定的實際做法細節還分為以下做解釋如下圖






















Observer相當於Model層觀察vue實例中的data數據,當數據發生變化時,通知Watcher訂閱者。

Compile指令解析器位於View層,初始化View的視圖,將數據變化與更新函數綁定,傳給Watcher訂閱者。

Watcher是整個模型的核心,對應ViewModel層,連接Observer和Compile。所有的Watchers存於Dep訂閱器中,Watcher將Observer監聽到的數據變化對應相應的回調函數,處理數據,反饋給View層更新界面視圖。


實現的簡單代碼如下有興趣的可以去此UP主(http://www.cnblogs.com/canfoo/p/6891868.html)底下會有詳細的解釋跟代碼,實際跑過一輪可以發現很多細節,也對架構整個流程更加了解




參考資料:
http://www.cnblogs.com/canfoo/p/6891868.html
https://segmentfault.com/a/1190000009397476
https://www.jianshu.com/p/d20aa65d89ba

2019年3月1日 星期五

取得Eelement的Css Selectors

有時候我們架構繁雜我們的css可能不像現在有前端這些framework整理好我的css
透過簡單的code去查詢我們element身上的css selectors,邏輯大致上是透過我們的document.styleSheets再去跟物件本身做逐一比對,最後可以列印出我們這個element身上有綁哪些css selectors

HTML:

  <ul>
     <li class="myclass" id="myli">Hello</li>
  </ul>
CSS:
.myclass{
   color:red;       
}
li.myclass{
   background-color:black;
}
ul li{
   float:left;
}

a{
   float:left;
}


Script:
function css(a) {
    var sheets = document.styleSheets, o = [];
    a.matches = a.matches || a.webkitMatchesSelector || a.mozMatchesSelector || a.msMatchesSelector || a.oMatchesSelector;
    for (var i in sheets) {
        var rules = sheets[i].rules || sheets[i].cssRules;
        for (var r in rules) {
            if (a.matches(rules[r].selectorText)) {
              console.log(rules[r])
                o.push(rules[r].selectorText);
            }
        }
    }
    return o;
}

document.addEventListener('click',function(e) {
console.log(css(e.target));

})

console.log(css(document.getElementById('myli')));

2019年2月21日 星期四

JavaScript 理解原型鍊(prototype chain)及繼承(inheritance)

前言

現在前端爆炸的年代,我們開發都依賴在巨人的肩膀上很多前端FrameWork我們甚至可以不用知道背後的原理,JavaScript最簡單一句話就是所有東西都是Object因為其實也不需要複雜的底層架構,但是作者Brendan Eich還是覺得需要有一種機制讓對象串聯起來,所以就有原型鍊的出現,跟new class的出現,ES6的class其實是語法糖,不像Java C++  這類泛用程式有完整的繼承方式,java c++ new class後面都是調用我們"類"的建構函數(constructor),但JavaScript的new class其實調用的是我們的建構函數(constructor) function,就像我剛說的JavaScript的class其實就是語法糖,這就是當初作者為了完善語言所做的,好的 我們就來理解一下JavaScript的底層吧.

原型鍊(prototype chain)

在我們寫JavaScript時一定都會發現我們都有個__proto__這就是我們的原型鍊






接下來我們就可以簡單說明一下

function DOG(name){
    this.name = name;
  }  

//__proto__
DOG.prototype = { species  : '犬科' , jump:function JUMP(){
  }};

//constructor
var dogA = new DOG('大毛'); 
var dogB = new DOG('小黑'); 
console.log(dogA); 
console.log(dogA.name) // 大毛 原本的物件指定屬性
console.log(dogA.species) //犬科 原本的物件指定屬性 沒有就往__proto__找
console.log(dogB) // 犬科 可以發現我們prototype的species跟jump變成共用的方法

可以把__proto__想成有建構DOG這個函數都會有的內共用的屬性或方法  印出dogB.species 雖然我們沒有原本物件屬性沒有但我們一樣可以從__proto__裡面找到我們的species跟jump  大致上會長跟下面一樣

所以簡單一句話說就是 建構的dogA跟dogB都可以共用到我們proto的內容 , 然後找屬性的順序就是從我們原本的物件有的屬性 例如舉例的name開始找 沒有再從__proto__下面找這樣一層一層的下去




繼承(inheritance)

上面是樣的建構函數我們的__proto__可以共用屬性或方法,今天要是不同建構函數我們又想要共用這時就需要我們的繼承了 我們可以先看看ES5跟ES6的差異,ES6更加直覺 也跟C#越來越像,最後可以發現我們也讓不同建構函數達到了跟java c++一樣的繼承效果
//ES5

//父類別 狗的種類
function DogBase(){
    this.name = "狗名字";
    this.color = "black"
    this.age = "1"
}
//共用跑的方法 
DogBase.prototype.Run = function(){
    return "跑"
}

//子類別 黃金獵犬
function GoldenRetriever(name){
  //我們可以去繼承父類的基本屬性 
   DogBase.call(this);  
    this.name = name;
}

//今天我也想要讓 黃金獵犬有Run的方法 
//GoldenRetriever去繼承Chihuahua
GoldenRetriever.prototype = new DogBase;

//构造实例
var es5 = new GoldenRetriever("黃金獵犬"); 
console.log(es5);
console.log(es5.Run());
//ES6

//父類別 狗的種類
class DogBase{
   constructor(name, color, age,run) {
    this.name = "狗名字";
    this.color = "black"
    this.age = "1"
    this.Run = function(){
    return "跑"
    }
  }
}

//子類別 黃金獵犬
class GoldenRetriever extends DogBase{
   constructor(name) {
    super('color', 'age','run')
    this.name = name;
   }
  //我們可以去繼承父類的基本屬性 
}


//构造实例
var es6 = new GoldenRetriever("黃金獵犬"); 
console.log(es6);
console.log(es6.Run());






參考資料來源
https://ssarcandy.tw/2017/12/06/javascript-prototype-chain/
https://pjchender.blogspot.com/2016/06/javascriptprototypeprototype.html
http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html
https://segmentfault.com/a/1190000015766680
http://es6.ruanyifeng.com/#docs/class-extends

2019年2月19日 星期二

Chromium 72+ 多個iframe載入下使用confirm alert原生對話盒造成網頁崩潰








































問題範例(目前尚未解決) 會造成chrome崩潰
主要在社群看到相關問題,我自己也很常遇到chrome的bug
所以我這邊先在 https://bugs.chromium.org 查詢
果然被我找到
更新當天就有人在提問了
https://bugs.chromium.org/p/chromium/issues/detail?id=931521&fbclid=IwAR0aolbI_kam8uQBw6LGbJnGKe5Ynbca_xcyz0m0DTxPyAx2PPajQn1fVpo










































我這邊簡單用codepen寫了範例測試 也提供了解決辦法
iframe這邊使用js動態塞入src去載入或者是等到iframe載完再去使用對話盒
就可以暫時解決這問題,這問題滿嚴重的希望感覺解決

2019年1月30日 星期三

C#基礎 關於float、double、decimal 浮點計算精度問題

C#中關於浮點計算 float、double、decimal  有這三中 實數型可以使用
但是我們都知道使用float、double會有小數點計算不準確的情況
特別是跟錢有關係的最好都使用高精準度decimal,知所以會叫高精準度就代表也有精度損失的時候,不過跟比float、double算是商業上夠用了等等下面會舉個例子

我們先來看小數點計算精度損失的例子
可以發現我們float、double計算都出現精度損失的問題這種問題如果不理會
後續會造成很大的嚴重後果 所以最好都使用decimal



當然我剛有提到decimal雖然擁有高精度但是就代表也會有精度損失的問題下面就舉個例子
可以看到我們的結果不是我們要的10000000000000000000000000000.1
不過這是比較極端的例子 正常也不會到這麼大的位數



再來我們再進行比對時資料結構一些問題 往往會需要先toString()在進行比對
可以發現我們float、double都是 true 原因是轉為字串float、double會自動把小數點後的零去除
但是卻發現decimal是false  原因是轉為字串 小數點後的零被保存下來
這時我們需要去除小數點後的零  stackoverflow 上的大神 有一招很酷的方法
就是我們的decimal 除掉 1.000000000000000000000000000000000
就會神奇發現我們小數點後的零都不見了 這時我們就可以擴充成方法作為使用  在進行比對我們就可以解決上述的問題



以上是C# 浮點精度 需要注意的事項  還是乖乖用decimal吧  雖然這是small tips不過還是開發時不可不注意的東西,以下是程式碼



namespace 練習
{
    class Program
    {
        static void Main(string[] args)
        {

            //float
            float f = 1.1f;
            f += 1.1f;

            //double
            double d = 1.1d;
            d += 1.1d;

            //decimal
            decimal de = 1.1m;
            de += 1.1m;

            Console.WriteLine("{0:G50}", f);
            Console.WriteLine("{0:G50}", d);
            Console.WriteLine("{0:G50}", de);


            //decimal 精度損失的例子
            decimal dd = 10000000000000000000000000000m;
            dd += 0.1m;
            Console.WriteLine("{0:G50}", dd);

            //float 比對
            float f1 = 1.1f;
            float f2 = 1.100f;
            Console.WriteLine(f1.ToString() == f2.ToString());

            //decimal 比對
            double d1 = 1.1d;
            double d2 = 1.100d;
            Console.WriteLine(d1.ToString() == d2.ToString());

            //decimal 比對
            decimal de1 = 1.1m;
            decimal de2 = 1.100m;
            Console.WriteLine(de1.ToString() == de2.ToString());

            decimal Money1 = 1.1m;
            decimal Money2 = 1.100m;

            //去除小數點後的零 方便作比對用
            Console.WriteLine(Money1.Streamline().ToString() == Money2.Streamline().ToString());


            Console.Read();
        }

    }


    
}

namespace CustomExtensions
{
    public static class Extension
    {
        public static decimal Streamline(this decimal d)
        {
            return d / 1.000000000000000000000000000000000m;
        }
    }
}

2018年11月21日 星期三

NativeScript 心得

最近想寫練習android & ios手機原生 NativeScript 現在剛好有支援angular 跟 vue 我是選擇vue來做開發 angular 我也有看一下 也是大同小異  ,  我自己在環境上花了不少時間 遇到不少坑  整體開發還可以看的出來Nativescirpt 還有需要改進很多地方 , 因為手邊沒有mac所以先選擇android先做練習 ,
主要是要熟練native的布局例如gridlayout .stacklayout .等等  還有native的structure整體什麼東西做什麼事情,部分的地方還是要靠native去撰寫 ,最好的話看一下原生java是怎寫的,  其他就如寫vue javascirpt typescript css部分支援 比較不一樣的就是router 改用 manual routing 不過這也沒什麼問題  ,官方的document都寫得滿清楚的 也有Demo參考 ,我覺得如果原本就熟練vue的話 邊學邊開發是完全沒問題 ,我覺得最大的好處是  我寫一版就能支援android跟ios系統 ,   不過還是要注意部分語法還是要寫android跟ios差異判斷,還支援Hot Reload 整理開發速度會快非常多 目前已經快寫完 簡單的youtube播放器 支援編輯自己的音樂清單 跟背景播放功能
到時候可能會上google play. 也不一定會上, 算是在學得新技能方面 解鎖成就(1/1)