發表文章

目前顯示的是 2021的文章

[Nodejs] npm install 時跑出錯誤

在 Ubuntu 20.04, Node version: 16.13.0 在安裝 opecc 出噴出一堆錯誤,原本以為是 npm WARN deprecated node-pre-gyp@0.14.0: Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future 這個警告造成無法安裝,但更新之後一樣無法安裝 最好詳細追查錯誤 log 看到底下: 1555 error /bin/sh: 1: python: not found 大致猜測是 20.04 預設沒有 python, 而是 python3 所以用 ln -s /usr/bin/python3 /usr/bin/python 之後 重新執行 npm i 就可以安裝囉!

非同步模型筆記

Concurrency: 兩件以上的事情,同時被一個處理單位處理,以分時的方式。 ex: 處理A事情處理到一半,把 call stack 丟出去,載入 B stack 到暫存器中,以分時的方式處理。 Parallelism: 多個事件,被多個處理單位同時處理。 這兩種程式在開發的時候都非常困難,因為有 shared memory 的問題! Shares memory 會造成 1. Race condition 2. Dead lock 解決方式 1. functional programing - 每件事都是 immutable 2. Actor model - 把 mutable 的狀態封裝在物件內,只透過非同步的通訊方式交換訊息 Actor 1. 輕量化的物件,有自己內部可改變的 state,別人不可改,也不共享 2. 跑在自己的執行緒上面 3. 沒有 shared memory state 4. 別的 actor 來的訊息,會按照順序存在 mailbox 中,依序處理 5. 只能透過訊息改變其他 actor 6. 程式變得更可擴展,因為更輕量且每個 call stack 都很小 CSP Model Actor vs CSP 相同: 1. 不同的執行單元是透過傳 message 的方式溝通 2. 他們自己內部都有 private state,所以不需要 lock 3. 他們不是用共享記憶體的方式通訊,而是通訊來達到共享記憶體 不同: 1. CSP 不關注 Process 本身,所以 CPS 的 processes are anonymous,然而每個 Actor 都會有自己的身份 2. Actor 都是用非同步的方式傳送訊息,但是 CSP 則是同步,也就是 CSP 會 blocking Asynchronous model callbacks: 當相依的事件做完之後,會呼叫下一件要做的事情 會有 callback hell 的問題 promise => async/await: promise 底層其實也是透過 callback, 只是將 callback 封裝在內部, 搭配內部 state (fulfilled, pending, reject) 的管理,將 callback hell 的問題解決。 更詳細的解說請參考:  https://zhuanla

[ReactNative] react-native run ios 出錯

由於最近想學 React Native,所以便從官方文件去建置環境,但發現會出現一堆問題類似下面的 ** BUILD FAILED ** The following build commands failed: Ld /Users/xxx/Library/Developer/Xcode/DerivedData/AwesomeProject-ardlldkqvtvwnthjzmutsniznwjh/Build/Products/Debug-iphonesimulator/AwesomeProject.app/AwesomeProject normal x86_64 (1 failure) 目前對我有效的使用方式是 Podfile 也要先修正一個地方 use_flipper! 改為 use_flipper!({ 'Flipper-Folly' => '2.3.0' }) 再來是底下步驟: 1. Node.js 環境升到最新版 (目前是v15.10.0) 2. 開啟 Xcode 清除專案 # Xcode 的 Product 選項 # Clean Build Folder # 註:有人有提供需要在 File > Workspace Settings > Build System ## 從 New Build System 改為 Legacy Build System ## 但對我無效,所以我最後改回 New Build System 3. 移除一些檔案並重裝 rm -rf ~/Library/Caches/CocoaPods cd 專案路徑/ios rm -rf Pods rm -rf ~/Library/Developer/Xcode/DerivedData/* pod deintegrate pod setup pod install cd 專案路徑 rm -rf node_modules npm install # 有 Podfile.lock 也記得一起移除 4. 重新啟動 Metro server (佔用一個 terminal) npm start "--reset-cache" 5. 重新執行 npx react-native run-ios 資料來源: https

[Jenkins] 安裝 Jenkins 與Laravel在jenkins上執行測試

圖片
安裝 我這邊使用 docker 作為快速建置的方式 可以使用  https://hub.docker.com/repository/docker/neilwangtw/jenkins-php72 此為環境 PHP7.2 且 最新的 jenkins 詳細的 Dockerfile 與 docker-compose.yml 在這 https://github.com/qazwsxedccsqzse/jenkins-php72 使用方式就是先建立個目錄 /data/jenkins 接著進去裡面將 docker-compose.yml 啟起來 docker-compose up -d jenkins 預設是使用 8080 port 接下來就是去 web 介面設定 一開始在 /data/jenkins/secrets/initialAdminPassword 會有一組 hash 是拿來解鎖 Jenkins 的 輸入完之後 一開始可以先安裝 jenkins 推薦的 plugin 有額外需要的之後可以再裝! 到這邊就設定完了 從 bitbucket 上取得 repo 1. 先透過 docker 產生一組 ssh 的金鑰 # docker exec -it {jenkins docker id} bash # su jenkins $ cd ~ $ ssh-keygen 這時候就金鑰就會在實體主機的 /data/jenkins/.ssh 公鑰: /data/jenkins/.ssh/id_rsa.pub 私鑰: /data/jenkins/.ssh/id_rsa 註: 如果遇到權限問題,可以先把 /data/jenkins 的權限設定到 777 或是先在 docker 內部產生一個檔案,看一下對應實體主機, 所產生的 user 與 group 為何,我自己這邊產生的是 tss:kvm 2. 先設定用來可以存取 bitbucket 的密鑰  在 Repository Settings 內有 Access keys 或是直接到 https://bitbucket.org/組織/專案名稱/admin/access-keys/ 去新增 jenkins 的 ssh 公鑰 這個設定完就代表 jenkins 這個用戶可以去 bitbucket 上

[演算法] KMP

KMP演算法是在一段文字中,找出指定的子字串出現位置(substring search)的演算法 比較詳細的說明我就不闡述,把資料留在文末。 名詞定義一下: 在一段文字中的文字,假設叫做 text 要搜尋的子字串,假設叫做 pattern 在 text 中比對到的位置使用 i, 在 pattern 中比對的位置使用 j Prerequisites 製作出 prefix table 什麼是 Prefix table Prefix table 是這個 pattern 字串所有的子字串的最長前後綴的表 舉例: pattern = ABCDABD 各個子字串的最長前後綴 子字串 前綴 (prefix) 後綴 (prefix) 最大公前後綴字串長度 A 空 空 0 AB A B 0 ABC A,AB C,BC 0 ABCD A,AB,ABC D,CD,BCD 0 ABCDA A ,AB,ABC,ABCD A ,DA,CDA,BCDA 1 ABCDAB A, AB ,ABC,ABCD,ABCDA B, AB ,DAB,CDAB,BCDAB 2 這時候就可以把最大公前後綴字串長度變成程式在用的模式 pattern A B C D A B D 0 0 0 0 1 2 0 -1 0 0

[Linux] SSH Tunnel

前情提要 由於中華電信最近除了海底纜線斷掉之外,連內部路由都有問題,造成部分用戶的 socket 會連不到我們架設的伺服器,於是想到把自建的 socket server 從機房中複製一份到 GCP 上面。 但由於安全性的問題,資料庫是在機房內網,且沒有對外 IP,還有 redis 也是在機房內網,同樣沒有對外 IP,這時候該怎麼辦? 厲害同事介紹了一招,SSH Tunnel。 SSH Tunnel 單純就是幫忙做 Port Forwarding。 假設我現在我有台主機 A,需要連線到內網的資料庫,但只有主機 B 才可以直接透過內網連線到資料庫,則我們可以透過 SSH Tunnel 將內網資料庫的 3306 port,對應到主機 A 的自定義 port,流量則是透過主機 B 轉給內網的資料庫。 定義一下名詞: 主機 A => socket server 主機 B => ap 資料庫 => db 1. 先在 db 內開一個專門用來 ssh 的帳號,假設叫 tunneluser 2. 在 db 開的 tunneruser 的 ~/.ssh/authorized_keys 內新增 socket server 的 public key 3. 在 ap 內開一個專門用來 ssh 的帳號,假設叫 tunneluser 4. 在 ap 開的 tunneruser 的 ~/.ssh/authorized_keys 內新增 socket server 的 public key 5. 接下來在 socket server 上的 ~/.ssh/config內新增 Host ap HostName 1.2.3.4 User tunneluser Port 22 IdentityFile ~/.ssh/id_rsa Host db HostName 2.2.3.4 Port 22 User tunneluser ProxyCommand ssh -q -W %h:%p ap IdentityFile ~/.ssh/id_rsa 6. 接著在 socket server 中輸入 nohup ssh -N -L 3306:localhost:3306 db & nohup 跟後面的 & 是為了把 ssh tunnel 放在背景持續執行 第一個 3306 是 so

[MySQL] 8.0 replica

最近剛好需要幫公司的資料庫做 replica, 但由於之前的資料庫沒有開啟 binlog, 所以研究了一下該怎麼操作。 如果是剛開始建立服務,建議 binlog 的設定要記得打開,如果沒有打開的話,變成要實作 replica 就需要先將資料備份出來,然後在備份出來的 master 資料還原給 slave,之後再去開啟 master 的 binlog,與建立要給 slave 同步用的帳號。 稍微解釋一下主從式架構,主要是由 master 來執行讀與寫,然後每個操作會記錄在 binlog 中,master 會透過 REPLICATION 這個權限讓 slave 可以去取回 binlog 的操作,藉由非同步的方式同步資料。 預先提醒,如果 slave 是由 master 透過複製虛擬機出來的,如果遇到 Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs;  these UUIDs must be different for replication to work 這個錯誤,就是代表 MySQL Server 的 UUID 重複,這時候只需要把 slave 的 /var/lib/mysql/auto.cnf 這個檔案刪除,之後執行 service mysql restart 就可以解決問題囉! Master 1. 以 Ubuntu 20.10 為例,MySQL 設定 replica 的設定檔在 /etc/mysql/mysql.conf.d/mysqld.cnf 在該檔案中加入 binlog_do_db = 指定的資料庫 bind-address = 0.0.0.0 server_id = 1 log_bin = /var/lib/mysql/mysql-bin.log log-slave-updates = 0 expire_logs_days = 10 # 如果開始 sync_binlog = 1 與innodb_flush_log_at_trx_commit # 一致性會是最好,但會影響效能。 sync_binlog = 0 innodb_flush_log_at_trx_commit = 0 # in

[MySQL] schema 與資料類型優化

圖片
選擇優化的資料類型 原則: 越小越好 因為會佔用最小的磁碟、記憶體與CPU快取。 越簡單越好 操作整數比操作字串代價低,因為字串排序規則 ex: 儲存ip應該用 unsigned int - 4 bytes, 用 varchar 會用到 15 bytes 儲存時間應該用 mysql 內建的時間類型 DATETIME, TIMESTAMP可以儲存相同資料:時間日期,精確到秒 TIMESTAMP 只用 DATETIME 一半的儲存空間,根據時區自動變化 TIMESTAMP 允許的時間範圍比 DATETIME 小很多 避免 NULL 在 innodb 上有單獨的 bit 儲存 null 值,但在 myisam,但還是盡量避免 整數類型 tinyint - 8 bits smallint - 16 bits mediumint - 24 bits int - 32 bits bigint - 64 bits 如果是有正負數的,會因為 1 bits 會用來記錄正負,故範圍為 -2^(n-1) ~ 2^(n-1) unsigned 的範圍則是 -2^n ~ 2^n MySQL 可以為整數指定寬度,例如 INT(11),其實沒什麼意義,11只是表示與 MySQL 相關工具(client 端的 cli) 用來顯示的長度,對於儲存與計算來說,INT(1)與INT(20)是一樣的。 實數類型 decimal(M,N) - M: 最大位數, N: 小數點後有幾位 ex: decimal(18, 9) => 9位數字.9位數字,總共使用 9 個 bytes float => 4 bytes double => 8 bytes decimal的計算雖然比較精確,但需要額外,但需要額外的空間與計算開銷,資料量較大時,可以用 bigint 代替 decimal,假設需要精準到萬分之一,則可以將數字*1百萬,將結果存在 bigint 內,可以同時避免福點數計算不精準與 decimal 計算代價太高。 字串類型 VARCHAR row_format=fix,這樣就都會固定長度,沒意義 varchar會需要額外1~2 bytes記錄長度, 假設用 latin1 charset, varchar(10) => 11 bytes, varchar(1000) => 1002