跳到主要內容
Yihua Tsai的大頭照

~難得有閒人~

碌碌無為無不為,汲汲營生不營生。

我是Yihua Tsai,寫程式的工程師。從 1996 年開始經營這個小站,記錄 系統管理、PHP、Laravel、gRPC 等技術筆記,也寫點生活與隨想。

最新文章

技術 最新

網站全部叫AI機器人改版

AI出現後,程式開發速度愈來愈快,所以我的網站也拿來做實驗更新的時間間隔也愈來愈短。 這次直接用 Grok Bot,創了一個專精於UI/UX機器人,一個網站設計師兼切版,一個主要寫程式的工程師,然後就叫他們看我的網站然後去改版。 總共花了 1 小時左用,用了大約 20% 的用量(我也不知多少token),然後新網站就完成了。 主要大改變是多了夜間模式,其他就視覺上的改善,變化不大。沒有讓我耳目一新的感覺,不過也算不錯了,至少以後網站維護就交給機器人了,大大減少因為忘記更新系統而被攻擊的機率

· 約 1 分鐘閱讀
技術

好久沒更新的新版上線囉

網站放著不管也不更新好久了,上個月發現整個 Server 被駭入當成了挖礦工具,在搶救一番後重新開機,就再也起不來了。Server正式趴下。QQ 好在資料還是在安全模式下都抓回來了,於是就開始著手將系統及framework 都升級到最新版本,再觀察看看,什麼時候又要變挖擴工具了。。。 這次重新上線也順便將網站外觀都改了一遍,主要是用 Tailwind css 來設計,不過說到設計前端頁面,其他去年自己就有在做,但總覺得就是不斷用不同的 Tailwind css 定義好的格式去建立一個網站,整體缺乏設計感,自己一直看得很不爽,所以就不想更新了。 今年再來做一次,這次就全部交給 Gemini AI 了,Tailwind css 要記的 class 實在是太多了,我完全不想記,所以就全交給 AI 來處理了,成品比自己做的好多了。 在 laravel framework 升級方面,AI也幫了不少忙,只是時常會一下就用光當日限額的 token,但的確幫我省了不少一開始的時間。 這次頁面的大改版距離上次的設計的風格也有10幾年了,其實滿喜歡之前的風格的,只是螢幕硬體上的升級,舊的網站也愈來愈不適合現在的大小,所以還是改一改符合現代化風格囉。

· 約 2 分鐘閱讀
技術

ProtoBuf on Laravel

ProtoBuf on Laravel 實作 proto 建置, gRPC Server 及 gRPC Client。 以下內容是假定在 Laravel 已運行良好情況下開始設置。 實作環境 OS: Ubunto 20.04 PHP: 8.04 Laravel: 8 運行環境需要的指令及延伸套件 Install PHP extension for protobuf $ sudo pecl install protobuf Install protoc command $ sudo apt install protobuf-compiler Instal protobuf complier grpc $ sudo apt install protobuf-compiler-grpc Laravel 可以新建一個 Laravel 專案來測試,或是在原本已有的 Larvel 專案。 Install google/protobuf to Laravel $ cd {laravel-project-folder} $ composer require google/protobuf create protobuf folder structure to base path $ cd {laravel-project} $ mkdir protobuf $ mkdir protobuf/build $ mkdir protobuf/src make *.proto file to protobuf/src read docs https://developers.google.com/protocol-buffers/docs/proto3 example: user.proto syntax = "proto3"; package mypackage; message UserRequest { uint32 id=1; } message User { uint32 id = 1; string name = 2; string email = 3; string created_at = 4; string updated_at = 5; } generate protobuf program for php $ protoc --proto_path=protobuf --php_out=protobuf/build protobuf/src/user.proto 這個指令會自動幫你生成 protobuf 需要的 php 檔在protobuf/build 裡,這些檔,我們都不用去動它。 set psr-4 autoload for php in composer.json "autoload": { "psr-4": { "App\": "app/", "Database\Factories\": "database/factories/", "Database\Seeders\": "database/seeders/", "Mypackage\": "protobuf/build/Mypackage/", "": "protobuf/build/" } }, 到這裡,你可以試著用 protoc 產生的物件來試著轉換自己的 Model 資料。 gRPC on Laravel Install grpc related packages $ composer require grpc/grpc $ composer require spiral/roadrunner-grpc Download rr-grpc and protoc-gen-php-grpc command Go to https://github.com/spiral/php-grpc/releases to downd latest version save rr-grpc to laravel base folder $ cd {laravel-project-folder} $ cp {download-folder}/{extrac-folder}/rr-grpc ./ save protoc-gen-php-grpc to /usr/bin $ sudo cp {download-folder}/{extrac-folder}/protoc-gen-php-grpc /usr/bin Generator protobuf files 參考上面Laravel的步驟,但這裡要加入 Server 的設定 Example user.proto syntax = "proto3"; package mypackage; service UserService { rpc getUser(UserRequest) returns(User) {} } message UserRequest { uint32 id=1; } enum Gender { male = 0; female = 1; other = 2; } message User { uint32 id = 1; string name = 2; string email = 3; string created_at = 4; string updated_at = 5; message UserProfile { string nickname = 1; string intro = 3; Gender gender = 4; string birthday = 5; } } 這個範例中加入了 rpc server 相關的設置 service UserService { rpc getUser(UserRequest) returns(User) {} } 這個在我們產生相關檔案時,會自動幫我們建立 UserService 的 Interfeace, 裡面則有一個 getUser 的 Method 會傳回 User 這個 message 物件。 Generate protoBuf php files $ protoc --proto_path=protobuf --php_out=protobuf/build --grpc_out=protobuf/build --plugin=protoc-gen-grpc=/usr/bin/protoc-gen-php-grpc protobuf/src/user.proto Usage: protoc [OPTION] PROTO_FILES OPTIONS --proto_path: proto 檔案的所在資料夾 --php_out: php 檔產生處 --grpc_out: 用 protoc-gen-php-grpc 產生的檔案存放位置 --plugin: 使用 plugin, 這裡指定用 protoc-gen-grpc 這個 plugin, 後面再指定指令所在位置 實作 UserService 這裡就依自己在 Laravel 中習慣去建立你自己的物作。 建立 App/Serivces/UserService (app/Services/UserService.php) 小於?php namespace AppServices; use AppModelsUser as DBUser; use MypackageUser; use MypackageUserRequest; use MypackageUserServiceInterface; use SpiralGRPC; class UserService implements UserServiceInterface { public function getUser(GRPCContextInterface $ctx, UserRequest $in): User { $userId = $in->getId(); $user = DBUser::find($userId); $userProto = new User(); $userProto->setId($user->id); $userProto->setName($user->name); $userProto->setEmail($user->email); $userProto->setCreatedAt((string) $user->created_at); $userProto->setUpdatedAt((string) $user->updated_at); return $userProto; } } 建立 gRPC 執行的 worker Create worker.php in base path on laravel 小於?php use IlluminateContractsConsoleKernel; require_once __DIR__ . '/vendor/autoload.php'; /** 載入 Laravel 核心 */ $app = require_once __DIR__.'/bootstrap/app.php'; $app->make(Kernel::class)->bootstrap(); /** 加入 gRPC Server 物件 */ $server = $app->make(SpiralGRPCServer::class); /** 註冊想要的服務 */ $server->registerService(MypackageUserServiceInterface::class, new AppServicesUserService()); /** 啟始 worker */ $worker = new SpiralRoadRunnerWorker(new SpiralGoridgeStreamRelay(STDIN, STDOUT)); $server->serve($worker); 設定 gRPC gRPC 是由 rr-grpc 來啟動,它是由 rr 來改寫的,所以一樣吃 .rr.ymal 的設定檔 rr 是 roadrunner 的縮寫,指令即其縮寫。 .rr.yaml grpc: listen: "tcp://0.0.0.0:50051" proto: "protobuf/src/user.proto" workers: command: "php worker.php" pool: numWorkers: 4 啟動 gRPC Server $ ./rr-grpc serve -v -d gRPC Server 就起來了,接下來設置 gRPC Client 來測試連線。 建立 gRPC Client for PHP 一樣由 protoc 來自動產生 php code $ protoc --php_out=protobuf/build --grpc_out=protobuf/build --plugin=protoc-gen-grpc=/usr/bin/grpc_php_plugin protobuf/src/user.proto --plugin: 使用 plugin, 這裡指定用 protoc-gen-grpc 這個 plugin, 改用 grpc_php_plugin 指令。 跟前面產生 UserServiceInterface.php 類似,但這裡產生 UserServiceClient.php 開始取得資料 建以一個 user.php 的指令 $ cd {laravel-project-folder} $ touch user.php $ chmod 755 user.php user.php 內容 #!/usr/bin/php 小於?php require_once __DIR__ . '/vendor/autoload.php'; use MypackageUserServiceClient; use MypackageUserRequest; use GrpcChannelCredentials; $client = new UserServiceClient('0.0.0.0:50051', [ 'credentials' => ChannelCredentials::createInsecure(), ]); if (!isset($argv[1])) { die("Please specify the user id "); } $userId = $argv[1]; $request = new UserRequest(); $request->setId($userId); /** @var User $response */ list($response, $status) = $client->getUser($request)->wait(); if ($status->code !== GrpcSTATUS_OK) { echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL; exit(1); } print $response->serializeToJsonString()." "; 用指令去取得資料 $ ./user.php {userId} exampe: command $ ./user.php 22 result {"id":22,"name":"酈樺美","email":"dexter87@example.org","createdAt":"2021-10-26 15:03:51","updatedAt":"2021-10-26 15:03:51"} 文件中 "小於?php " 請自行轉換。

· 約 14 分鐘閱讀
技術

HTTPS裡的Ajax , 總是用 HTTP 去取得資料

最近在用 vue 的 vue-router 玩 單一頁面應用(SPA), 在開發環境裡都還算順利, 就順順的把弄好的東西丟上網站去, 結果一直遇到 跨來源資源共用 (CORS) 問題而無法取得資料, 因為線上的是 https 連線的, 但網頁裡的非同步應用卻都是用 http 來連線. 在網路上找相關問題的解答大部分是強制使用 https 去連線, 但這問題在 PHP 還好做, 在 Vue 或是 axios 裡我就是新手了, 也依建議去做強制設定, 但還是一直在 https 的環境裡去連 http 的連線. 程式解決不了, 我就改由系統去看, 結果發現我設了 HTTPS 的獨立 Log 居然都沒有任何連線記錄, 然後再查看 PHP 的 $_SEVER 變數, SERVER_PORT 居然是 80, 那為什麼我的 HTTPS 可以連線呢? 唯一可以在 PHP 找到 HTTPS 相關的只有 HTTP_X_FORWARDED_PROTO 是 HTTPS, 所以看起來是有別的技術問題, 但最近DNS跟網站空間都搬家, 到底是哪裡有問題也不清楚, 只能一個個找起. 中間過程實在有點累也有點笨就不提了... 直到今天我查了一下 HTTPS 的 SSL 資訊, 怎麼不是我去註冊的免費SSL, 而是 Cloudflare 申請的, 所以就去 Cloudflare 網站查我的網域狀態, 看到了一個設定. 在網域名稱下有個 SSL 的項目, 我設了 Flexible, 就是這個設定 Cloudflare 會幫你把網站加上 https 時也能順利連線, 只是他的低層自動用 http 去抓資料, 這真的是一個很佛心的設計, 讓你不用多花錢也可以有 https 的連線, 但對 Ajax 的應用來說就苦囉. SSL 的設定有四個選項 Off Flexible Full Full (Strict) 如果你有有效的第三方的 SSL 憑證的話, 那就要選 Full (Strict), 這樣才會有真的 https 連線到網站去. 如果是自己建立的SSL 憑證, 那就選 Full. 如果都沒有但也想用 https , 那就選 Flexible , 但網站上要避免使用 ajax

· 約 3 分鐘閱讀
隨筆

絕學無憂

絕學無憂。 過去在讀到老子這段話時,以為是去除知識、腦袋空空就不會有區別心,就不會有煩惱,總覺得好像是有哪裡不對,如果真是這樣,那我直接把道德經丟掉不就好了。 但最近片斷看到了蘇格拉底的無知說法,還有金剛經的無所住而生其心,再回頭看到這段,發覺原來他們講得應該是一件事吧。 也就是我們要摒棄成見,重新用最根本的心其看待每一件事情。 老子告訴我們,這樣做的話那就沒有煩惱憂慮了。 蘇格拉底告訴我們,這樣做的話才是求真的方法。 金剛經告訴我們,這樣做的話你的心才不會有分別心。 成見是什麼,就是我們平日裡的所學及經驗。 但知識是累積的,沒有累積的知識怎麼會有現在舒適方便的生活,所以我們也不能否定知識累積的重要性,但更重要的是對每一個知識的驗證,也就是科學最注重的懷疑的精神。 東方哲學告訴我們結果是無憂無慮,於是導出了閒雲野鶴的神仙觀念。 西方哲學告訴我們那是一個求真的方法,於是導出了現代科學。 佛家哲學告訴我們如何做到沒有分別心,於是導出了眾生生而平等及博愛的概念。 這些結果其實也無所謂好壞,單看人的志向為何,學無止盡,只是該學的是愈接近真實的事,而不是立基在無數的假說之後的假說。

· 約 2 分鐘閱讀