Design

Design
asp.net mvc

2019年12月3日 星期二

Sumitomo Mitsui Trust Bank Programming Contest 2019


I found a website that help promotes logical thinking , there will be a period of competition , you can register get start for the competition and get points , Let's take a look at recent matches .


















A - November 30

Solution

2019-M2-D2 follows 2019-M1-D1 so we just check M1 & M2 are they equal

m1, d1 = map(int, input().split())
m2, d2 = map(int, input().split())
 
if m1 == m2:
 print(0)
else:
 print(1)



B - Tax Rate

Solution

this question the point is rounded down to the nearest integer , math.ceil(N / 1.08) is before tax  ,  round down math.ceil(N / 1.08) times 1.08 to an integer if result equal N Takahashi's memory is true  print(result) else false print(":(")
import math
N = int(input())
 
B = math.ceil(N / 1.08)
if math.floor(B * 1.08) == N:
  print(B)
else:
  print(':(')

C - 100 to 105

Solution

if one items cost range is 100~105 , two items is 200 ~210 , three items is 300~315 , and so on ,
each item plus 5 tens digit , so we can get the rules
x = int(input())
count = x//100
res = x%100
if count*5 >= res:
    print(1)
else:
    print(0)

D - Lucky PIN

Solution

Use three loops to get three unique values. Loops meet the condition index value +1 to find the value of the next position
N = int(input())
S = input()
cnt = 0

 
for i in range(10):
    for j in range(10):
        for k in range(10):
            idx = S.find(str(k))
            if idx != -1:
                idx = S.find(str(j),idx+1)
                if idx != -1:
                    idx = S.find(str(i),idx+1)
                    if idx != -1:
                        cnt += 1
                        print(k,j,i)
 
print(cnt)
to be continued....

2019年11月7日 星期四

[紀錄]nodejs Mongodb分頁模糊查詢

 
app.post('/api/video', function (req, res) {
  try {
    var PageSize = req.body.PageSize;
    var PageIndex = req.body.PageIndex;
    if (!PageSize || !PageIndex) {
      return;
    }

    var Search = {};
    if (req.body.Search) {
      Search = {
        'name': {
          $regex: `^.*${req.body.Search}.*`,
          $options: 'i'
        }
      }
    }
    var dbo = client.db("db");

    dbo.collection('video').find(Search).sort({
      upload_at: -1
    }).skip(PageSize * PageIndex - PageSize).limit(PageSize).toArray((err, items) => {
      if (err) {
        console.log(err)
        throw err;
      }
      dbo.collection('video').countDocuments(Search, function (err, count) {
        res.end(JSON.stringify({
          "result": items,
          "pageCount": Math.ceil(count / PageSize),
          "videoCount": count,
        }));
      client.close();
      })
    });
  } catch (e) {
    console.error(e);
  }
});

MessagePack vs json.Net 效能PK

Perf comparison graph

一張圖吸引了我去測試MessagePack的效能
至於是不是真的這麼神  我們時間跑看看測試程式碼跟執行結果如下

Main:
    public  static void Main(string[] args)
        {
            MessagePackSerializer.SetDefaultResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance);

            var summary = BenchmarkRunner.Run();
            Console.Read();
        }


Measure:

 
using BenchmarkDotNet.Attributes;
using MessagePack;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace SerializationPerformance
{
    [MemoryDiagnoser]
    public class Measure
    {

        public readonly MyClass data;
        public byte[] bytes;
        public string Json_string;
        public Measure()
        {
            MessagePackSerializer.SetDefaultResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance);
            data = new MyClass
            {
                Age = 99,
                FirstName = "hoge",
                LastName = "huga",
            };
            bytes = LZ4MessagePackSerializer.Serialize(data);
            Json_string = LZ4MessagePackSerializer.ToJson(bytes);
        }



        [Benchmark]
        public byte[] MessagePack_Serialize_Bytes()
        {
           byte[] result = MessagePackSerializer.Serialize(data);
            return result;
        }


        [Benchmark]
        public string MessagePack_Serialize_String()
        {
            byte[] result = MessagePackSerializer.Serialize(data);
            
            return MessagePackSerializer.ToJson(result);
        }


        [Benchmark]
        public MyClass MessagePack_Deserialize()
        {
            MyClass result = MessagePackSerializer.Deserialize(LZ4MessagePackSerializer.FromJson(Json_string));
            return result;
        }


        [Benchmark]
        public byte[] LZ4MessagePack_Serialize_Bytes()
        {
            var result = LZ4MessagePackSerializer.Serialize(data);
            return result;
        }


        [Benchmark]
        public string LZ4MessagePack_Serialize_String()
        {
            var result = LZ4MessagePackSerializer.Serialize(data);
            return MessagePackSerializer.ToJson(result);
        }

    
        [Benchmark]
        public MyClass LZ4MessagePack_Deserialize()
        {
           
            MyClass result = LZ4MessagePackSerializer.Deserialize(LZ4MessagePackSerializer.FromJson(Json_string));
            return result;
        }

        [Benchmark]
        public string jsonNet_Serialize()
        {

            string result = JsonConvert.SerializeObject(data);
            return result;
        }



        [Benchmark]
        public MyClass jsonNet_Deserialize()
        {
            var result = JsonConvert.DeserializeObject(Json_string);
            return result;
        }
    }

    public class MyClass
    {

        public int Age { get; set; }


        public string FirstName { get; set; }


        public string LastName { get; set; }

        public string FullName { get { return FirstName + LastName; } }
    }

}
可以看到我們較常用的object跟string之間的轉換速度上其實沒太大差異,如果單純只是二進制的轉換會快非常多 至於內存消耗可以看到MessagePack是優於json.Net不過型別的支援程度json.Net還是比較好用的 如果對於效能有要求這邊是滿推薦使用MessagePack只是在一些型別例如datetime jobject jarray等等格式就需要做另外formatter處理,就看個人的喜好決定了 轉為json字串也需要多打一串他的方法

2019年7月20日 星期六

心情上轉換

題外話..最近2T硬碟壞掉,多半一些隨興測試跟一些架構上原本要打在BLOGGER上的CODE,重要的還好有備份雲端,不過寫很多東西也算是滿珍貴的內容,會去修吧看能不能多少救回來一些.

拉回來 
我每天都會關注一些國內外投資跟軟體業相關資訊跟和一些電子報,綁定我的mail或通訊軟體,國外我推薦fastcompany,國內其中科技橘報算是內容滿符合我胃口的,可能因為我是軟體開發工程師? 

前幾天剛好聽到個橘報電台內容覺得滿值得思考的,也是我平常一直在調適自己的心態上跟作息上的方法,有興趣可以點下面.



一開始算是閒聊內容,介紹投資書的內容跟一些心得.
中半段開始談到如何優先投資自己的時間在重要的事情上面,我覺得比較有趣的接下來說的一些內容,查理.蒙格書有提到貪婪、恐懼、盲目樂觀、從眾、嫉妒,這些都是人類的在投資上的弱點,反過來說在工作上也都會這些情形,每個人往往都會有情緒,內容有提到我們今天覺得工作做的很得心應手很有成就感,我們就可以多做一點,今天我們心情差就少做一點,但不至於完全不做,今天你覺得你在工作是最重要的那就在工作多花點時間,今天你覺得你額外時間做其他事情比較重要,就把重要的時間在額外的事物上面,你最終一定要會有取捨,我還記得有次我在跟矽谷的前輩聊天,也是討論到取捨的問題,他說了why not both...,當時覺得果然是高手,其實現在想想有時候不是你能力範圍做不到,而是你心態上能否保持平衡,最重要還是你最終的選擇,你選擇了工作,還有啥好抱怨的,真的做不下去離開走人,也不要主觀做任何批判,有時候你想要的也不一定你承擔的住,凡事盡力而為,你最後雖然可能不能贏,但是你心態心境上至少都可以隨時保持進步的狀態,今天你對的起自己也能跟別人交代,機會還是會有的,跟自己是這樣說,我真的能做到嗎?
如何看待 Facebook 总部一中国男性职工因面临被辞退于 2019 年 9 月 19 日跳楼自杀?

2019年7月11日 星期四

FTP主動模式 & 被動模式

主動模式 ACTIVE


FTP客戶端隨機開啟一個大於1024的端口N向服務器的21號端口發起連接,發送FTP用戶名和密碼,然後開放N+1號端口進行監聽,並向服務器發出PORT N+1命令,告訴服務端客戶端採用主動模式並開放了端口。 FTP服務器接收到PORT命令後,會用其本地的FTP數據端口(通常是20)來連接客戶端指定的端口N+1,進行數據傳輸。
命令連線: 用戶端 port N –> 伺服器 port 21
資料連線: 伺服器 port 20 –> 用戶端 N+1
常見問題:
伺服器防火牆需開20、21,因為用戶端因為是隨機PORT作為連接,通常被擋都是用戶端防火牆,而且這風險也滿大的用戶端隨機開個PORT給外部連接.


被動模式 PASSIVE
FTP客戶端隨機開啟一個大於1024的端口N向服務器的21號端口發起連接,發送用戶名和密碼進行登陸,同時會開啟N+1端口。然後向服務器發送PASV命令,通知服務器自己處於被動模式。服務器收到命令後,會開放一個大於1024的端口P(端口P的範圍是可以設置的)進行監聽,然後用PORT P命令通知客戶端,自己的數據端口是P。客戶端收到命令後,會通過N+1號端口連接服務器的端口P,然後在兩個端口之間進行數據傳輸。
命令連線: 用戶端 port N –> 伺服器 port 21
資料連線: 用戶端 port N+1 –> 伺服器 port P
其中 NP 都必須大於 1023
常見問題:
被動模式就是變伺服器開隨機PORT給客戶端作為連接使用,現在的FTP SERVER軟體都有支援開範圍的PORT,還有一點是要注意如果是外部連內網,有可能回的IP會是內部網路IP造成用戶端無法連接,這個在軟體上也可以設定

2019年6月6日 星期四

拓元驗證碼辨識為例 python + tensorflow(卷積神經網路CNN) +Flask(API)

我們直接看結果吧  以下是我針對拓元驗證碼 一萬次的訓練結果 成功率99%
最後把方法透過Flask把python封裝成API可以調用.
這東西很好玩,因為可以應用的場景非常廣,想的到的複雜辨識都可以一套解決,最重要的是可以一直訓練,所以就算很複雜的驗證碼邏輯,只要餵好資料其他基本上就都可以解決
而且速度非常快,不過CNN缺點就是需要大量訓練素材,而且我這邊是訓練四碼如果是不同碼又需要重新訓練,當然可以做文字切割後再去各別辨識這樣效率成功率也會更高,下次再來玩玩GAN或許可以解決需要大量素材的問題,可能牽涉違法 程式碼就不貼了,單純練習應用.



tensorflow,python,神經網絡的相關知識我滿推薦 騰訊工程師周莫煩的youtube頻道講解得很簡單明瞭,特別這類的中文教學本來就不多,有興趣可以點下面網址看看
https://www.youtube.com/channel/UCdyjiB5H8Pu7aDTNVXTTpcg



以下也都是寫得不錯的文章
http://puremonkey2010.blogspot.com/2017/07/toolkit-keras-mnist-cnn.html
https://www.zhihu.com/question/22298352
https://medium.com/@syshen/%E5%85%A5%E9%96%80%E6%B7%B1%E5%BA%A6%E5%AD%B8%E7%BF%92-2-d694cad7d1e5

2019年5月6日 星期一

ASP.NET MVC 三層架構Three tier 實作

滿久之前有跟大家提三到層架構,回顧可以先點這裡,卻一直少了實作的部分,這範例專案其實三年前就做好了只是一直放著沒時間補上,這架構其實也算很古老了,今天就把這部分補上.

這邊的範例就是簡單的identity登入功能 透過三層架構的方式
順序從前端輸入登入  打Controller層自己建的登入WabApi方法 再到Service層驗證登入的邏輯  最後在Repository層跟DB溝通 完整降低耦合 邏輯切割 邏輯也只須關注Service層 不管在系統開發業務切割都有很大的好處.首先我們先看下面這張專案圖
當然以上不是一定的,純粹給大家一個基本三層的建構概念體驗當中的魅力
首先我們要進行分層我們需要熟悉一種技術Dependency injection(DI 依賴注入) 
Interface(https://aspnetmars.blogspot.com/2017/05/interface-c.html)透過介面的方式實作,這也都算滿老的基礎技術網路上也滿多文章的,這有時間再整理一篇,我們繼續.


首先我們需要使用先nuget我們的di套件這邊使用Unity(https://aspnetmars.blogspot.com/2017/05/unity-di.html),也不一定要用unity也有其他種大同小異
有兩種MVC跟WebAPI的版本 我這邊是兩個都載 差別就是一個是Controller用跟WebAPI用.其實也只要用WebApi,MVC版是看你們有沒要在Controller的地方注入


然後官方也有提醒記得在Global.asax加入以下這段
然後可以發現我們App_Start多了兩個檔案UnityConfig.cs跟UnityMvcActivator.cs 
我們重點放在UnityConfig.cs注入的相關參數都會在這執行,UnityMvcActivator基本上不太會動到主要功用就是程序剛執行要跑的部分


相關可以發現我依照名稱尾端名稱分別注入了Service跟Repository其實簡略點可以只注入Service
然後FormAllInterfaces自動就去找Interface完成我們的注入
然後可以發現我們多了個getInjectionMembers底下實作了LoggingInterceptionBehavior
主要功用為去攔截我們每個注入的方法,這好處是什麼.你應該也猜到了.就是可以記錄我們的log這邊我是使用了Nlog(https://aspnetmars.blogspot.com/2017/05/nlog-bug.html+ Slack再來就跟各位演示整個流程

還沒忘記我們一開始的功能吧 開始登入網站 看看這架構的魅力吧

1.首先登入這沒問題



















2.再來就是打API來到我們Controller層 可以發現我們這邊又去呼叫Service層
































3.來到Service層,這邊又去呼叫我們Repository層要資料 這邊就是可以寫我們商業邏輯的地方,可以發現我們吧一些驗證邏輯寫在這如果我們邏輯需要異動只要改這個部分也不會影響到Controller 做到業務分層,在共同開發下也更為清楚,好處可以說是非常多,特別是在東西越來越多的狀況下越能體會到這架構的好處






























4.來到Repository層 這邊就是可以去我們資料庫要資料了 像我們每一層都需要定義Model分層的話又可以讓每個階層的東西放在各自位置這也是好處之一.























5.最後在Repository > Service > Controller  當然就是登入成功啦


然後剛剛有跟各位提到LoggingInterceptionBehavior
我這邊自己寫的 基本上是長這樣  紀錄 呼叫 , 回傳 或 Exception 這邊紀錄是使用Nlog我也有寫過一篇大家可以去看看,然後我範例記錄位置我是記錄在Slack 因為那時候Slack很潮XD 

Slack就會長這樣 完整記錄有注入過的方法的資訊 紀錄格式就不一定看各位想紀錄什麼

錯誤的話就會像這樣 我在哪一層哪個方法錯誤


以上就大概是簡單的範例  
架構上要說簡單也簡單 要說繁雜就是繁雜  後續還要考慮單元測試 自動部屬 等等等  還有很多可以在說明跟優化,有任何問題可以在底下留言.

2019年4月12日 星期五

關於投資風險(虛擬幣,股票,房地產,其他?)



聊聊寫程式以外的東西吧 投資
近幾年一直看到網路上打著幾%獲利,說著看似很高端的名詞( 虛擬貨幣 人造衛星 人工智能AI  獲利軟體 看盤工具 ).
我自己本身一直都在研究投資相關的資訊,我也是比較嚴謹的人,身為一個工程師實事求是,就來說說近幾年我看到的情況吧.








虛擬貨幣 ( 比特幣,乙太幣,ICO,OTC等等)
最早虛擬貨幣還沒很紅的時候,透過挖礦&投資&搬磚,的確是有批人因為幣值的攀升價格賺到一筆可觀的錢,但隨著挖礦的人越來越多,幣越來越少的情況,交易所一家一家卻越來越多資訊告訴你虛擬貨幣多好賺多好賺?真有這麼好的事嗎?

挖礦
就如我剛說的幣越來越少的情況,設備費用我們姑且不談,你吃最大的成本就是電費,電費所付出的成本早就沒辦法跟你挖礦情形攤平甚至到獲利,但是你會說還有以太幣阿 這麼多幣種可以挖,沒錯 你知道 我知道 大家都知道 ,交易所換幣別的交易費就夠你受了,還有就如我剛說的電費已經不合成本了,還能賺?.

礦池
大家一起挖按比例分攤幣,聽起來好像風險很低,這中間還有沒算到礦池抽的fee,交易所抽成,還有電費,還能賺?

搬磚
搬磚簡單說就是賺匯率差,透過A交易所跟B交易所之間的匯率差賺錢,聽起來好像風險更低了,但是中間的風險就是你無法保證交易時間中的匯率差跟交易所的安全性 交易所安全性問題上網看一堆在倒閉就不多說了,通常交易在你生成交易這段時間匯率是你無法掌控的你真的有辦法賭定你交易期間不會因為匯率波動造成虧損嗎,交易所也不是白痴,長期來你的風險一定是虧損大於獲利甚至全無,還能賺?

軟體
他會告訴你一項工具可以觀察某些甚至很多數據(任何交易商品都有類似東西),讓你透過每個月或是買斷的方式購買這軟體工具,拉幾個數據跟K線對照圖就告訴你看軟體獲利多簡單,他賺的就是你的軟體錢(軟體能賺我還賣你幹嘛),當然我不反對這類工具,因為也真的有人利用工具賺錢,但是我只能說市場是多種因素跟人為造成的,不是用工具幾個指標就能說得清.

股票投顧
市面上有很多所謂帶進帶出的老師,也是跟軟體類似每個月付多少錢,付得多會員等級就越高,就如我上面所說市場因素這麼多你一個老師說賺就賺那誰賠錢,老師也是賺學費為主
也很多事讓你繳學費他教你怎投資的類型,還是那句話這麼好賺當老師幹嘛,最常利用的手法為對沖[透過多空頭時做的方式(虧損少量手續費 多空卻一定會有一邊大量獲利]為了是什麼?就是為了營造賺錢的跡象,當然股票還是可以賺錢但是一定要有自己的一套方法不是一昧相信別人,台灣就是填鴨式教育只想追尋答案過程省略,還是一句話貪阿


龐式詐騙
這也是目前最常見而且最多的東西,這應該說是老早在各領域都會有的手法,而且相當成熟市場上甚至有人專門在賣這類的白皮書教人怎做詐騙,手法不外乎是跟你說投資多少錢多久可以獲利多少,每天po錢 跑車 吃喝玩樂的畫面,講一些高深一些似懂非懂的東西(在我看來是有點可笑),甚至利用釣魚的方式讓你吃點甜頭在利用A被害者錢去補B受害者的獲利,再透過拉下線的方式造成龐大的系統,或許你真有一段時間有錢多收,但我能告訴你最後泡沫搓破是遲早的事情,利用的就是人性的貪念,我就簡單說一句賺錢這麼簡單 我還告訴你幹嘛 我自己賺就好啦


房地產
近期新聞都有報導會有一種專挑網路上自售房屋的屋主,會假裝跟你說要買房子,會告訴只能付給你例如10%的訂金 其餘尾款要等到另一家房子賣掉還才能給你,詐騙也會找來合夥的代書要你權狀,證件,印鑑證明要你交給代書跟你說確保你房子不會賣給其他人,後續再拿你的房子去跟銀行貸款等到貸款錢到手後再找理由跟你說房子不買了,過戶給原本的屋主,屋主就這樣背上大筆貸款金額.還有一種是一屋多賣的情況你買房卻他有賣給其他人 這種情況最好是找有信用的建商公司 並有採用履約保證.


結語
投資前最好多看多聽,甚至安全點定存都是很好的方式,切勿借錢讓眼前的假象沖昏腦袋,投資當然有風險但不是被當韭菜宰,最好的投資就是自己,讓自己多長點知識,努力在工作有所成就,不管身心上都會得到最大的成就.

2019年4月10日 星期三

Windows Mongodb Replica set + Sharding Cluster

Replica set 
Mongodb的高可靠性的架構,主要原理為Primary資料庫之外會同時在Secondary資料庫生成一樣的資料防只在在主資料庫有問題的狀況下我們還有Secondary的資料就有點像HA的機制,詳細如下分為三種角色


1.Primary
唯一具有寫跟讀的角色,主要的存取節點


2.Secondary
只能讀取的角色,可以有一個以上的Secondary,Primary資料會複製一份到Secondary












3.Arbiter
Arbiter不會存取任何資料,主要功能為在Primary無法跟其他Secondary溝通時
會跳出來推舉為新的Secondary擔任Primary



















Sharding Cluster 
分片如字面上的意思就是把資料做切分放置在不同位置,這樣做的主要用意為我們單機如果有大量的資料硬碟快撐不住了 負載爆炸,我們把資料做切分減少每個單機上的資料量提升空間的使用率 減少負載 有種load balance的感覺 一般我們常使用架構為sharding cluster其他種就 不做說明


至於詳細的架構如下 我們一般都是直接連接資料庫拿資料也就是我們如圖上的Shard的位置,當我們做了Sharding的機制後我們就需要個Router層因為我們已經做分層處理了直接存取Shard我們只能看到資料的片段而已這時候Router就起來作用 至於Router怎知道資料該怎取怎處理呢,Config Server就是在做這類資訊的處理存放些Metadata及計算的索引紀錄每個資料Shard的位置.




















實作

介紹這麼多是不是了解不少,那麼我們為什麼需要Replica set + Sharding Cluster呢 Sharding Cluster的壞處就是當一台資料庫掛了我們就無法處理了 這時候Replica set是不是就剛好把這個洞補起來了 我們就有個高可靠性 又有效率的Mongodb架構
Sharding是建立在Replica set架構之上我們首先間建立Replica set

首先我們建立三個檔案primary.conf  secondary.conf   arbiter.conf 的config如下


primary.conf
systemLog:
    destination: file
    path: "C:\\mongodb\\logs\\primary\\log.log"
    logAppend: true
storage:
    dbPath: "C:\\mongodb\\data\\primary"
    directoryPerDB: true
net:
    port: 27017 
    bindIp: 127.0.0.1
processManagement:
    windowsService:
        serviceName: primary
        displayName: primary
replication:
    replSetName: rs
secondary.conf
systemLog:
    destination: file
    path: "C:\\mongodb\\logs\\secondary\\log.log"
    logAppend: true
storage:
    dbPath: "C:\\mongodb\\data\\secondary"
    directoryPerDB: true
net:
    port: 27018
    bindIp: 127.0.0.1
processManagement:
    windowsService:
        serviceName: secondary
        displayName: secondary
replication:
    replSetName: rs
arbiter.conf
systemLog:
    destination: file
    path: "C:\\mongodb\\logs\\arbiter\\log.log"
    logAppend: true
storage:
    dbPath: "C:\\mongodb\\data\\arbiter"
    directoryPerDB: true
net:
    port: 27019
    bindIp: 127.0.0.1
processManagement:
    windowsService:
        serviceName: arbiter
        displayName: arbiter
replication:
    replSetName: rs

這時候可以把我們的服務開起來
#安裝服務
mongod --config "C:\mongodb\config\primary.conf" --install
mongod --config "C:\mongodb\config\secondary.conf" --install
mongod --config "C:\mongodb\config\arbiter.conf" --install

#啟動服務
net start primary
net start secondary
net start arbiter

#進入(這時角色都一樣需要設定)
mongo 127.0.0.1:27017

#加入Primary rs為replSetName設定的
rs.initiate( {   _id : "rs",members: [ { _id : 0, host : "127.0.0.1:27017" } ]})

#加入Secondary
rs.add("127.0.0.1:27018")

#加入Arbiter
rs.addArb("127.0.0.1:27019")

#查看狀態
rs.status()


最後我們查看狀態已經把各個角色都指定好






































再來我們可以試著Primary寫入資料看看是不是已經達到同步的效果
var data = [];
for (var i = 0; i < 50; i++){
    data.push({
        "index":"資料"+NumberInt(i),
        });
}
db.demo.insertMany(data);


然後可以看到我們的Primary跟Secondary都有我們剛新增的資料

未完待續 還有我們的 Sharding Cluster 

2019年4月7日 星期日

TF30063: 您未取得存取 xxxxx 的授權。

很久之前在2015升2017的時候 或是更改AD密碼的時候會出現此問題,突然想到這邊紀錄一下,給遇到相同問題的人

TF30063: 您未取得存取 xxxxx 的授權。





















解決辦法:
刪除本地端緩存 路徑如下
C:\Users\userName\AppData\Local\Microsoft\Team Foundation\x.0\Cache

原因:
可能為更改AD帳號密碼後本地緩存的密碼還是舊的,導致他登入時都依照就的緩存舊的權限下去登入.

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;
        }
    }
}