Đăng bởi

[MinhQuanTech] S20 Ultra 12/128 zin, ko ám/lưu ảnh

Samsung S20 Ultra 12/128 màu đen, dòng FlagShip cấu hình cao cho anh em, camera sau 108MP zoom 100x, camera trước 40MP

—–

RAM: 12GB

ROM: 128GB

Wifi Bluetooth GPS NFC đầy đủ

Cảm biến ánh sáng/tiệm cận/xoay/đa điểm hoạt động tốt

Micro, Loa, Rung đầy đủ

—–

Màn hình không ám/không lưu ảnh

FaceID/TouchID chạy tốt

Còn nguyên áp suất

Máy zin 100%

—–

Ngoại hình máy đẹp

Phụ kiện: sạc nhanh + cáp C to C

—–

Giá 6TR

—–

Máy bán ra được test kĩ bằng phần mềm/thiết bị chuyên dụng

Đảm bảo tất cả linh kiện vẫn hoạt động tốt

Hỗ trợ sửa chữa giá vốn

Quý khách mua về hoàn toàn yên tâm sử dụng

—–

Công ty TNHH CNTT&VT MINH QUÂN

Địa chỉ: 48/2 Xuân Thủy P. Thảo Điền TP. Thủ Đức TPHCM

Call/Zalo/SMS: 0938-507-766

Đăng bởi

Chuyên lập trình web cho cửa hàng điện thoại/laptop

Chuyên lập trình web cho cửa hàng điện thoại/laptop

– Thanh toán trực tuyến

– Quản lý tồn kho nhiều chi nhánh

– Tìm kiếm theo chức năng (CPU gen 13, màn 2.8K, sạc ko dây, hỗ trợ 5G…)

– Giao hàng toàn quốc

– Chat hỗ trợ online

– Kho máy cũ

– Bán phụ kiện, linh kiện

– Bán các gói bảo hành VIP

– So sánh các máy

– Quản lý/theo dõi đơn hàng

– Tra cứu/lịch sử bảo hành

—–

Công ty TNHH CNTT&VT MINH QUÂN

Địa chỉ: 48/2 Xuân Thủy P. Thảo Điền TP. Thủ Đức TPHCM

Call/SMS/Zalo: 0938-507-766

Đăng bởi

Asus Vivobook 14 i5 Gen 13 13500H 2.8K BH 2/25 BOX

Laptop Asus Vivobook 14, cấu hình cao, CPU Gaming i5 Gen 13 13500H, màn hình 14″ nhỏ gọn, độ phân giải cực cao 2.8K, phù hợp cho doanh nhân/người di chuyển nhiều. Máy FULLBOX đầy đủ phụ kiện, còn bảo hành chính hãng lâu 02/2025

—–

CPU Gaming đời cao, Intel Core i5 Gen 13 13500H

RAM 8 GB, DDR4 3200Mhz

Ổ cứng SSD M2 512GB

Card đồ họa Intel UHD Graphics

Màn hình OLED 14″ độ phân giải cực cao 2.8K IPS 90Hz

Cổng giao tiếp HDMI, USB 3.0, LAN (RJ45), Type-C…

Camera, Micro, Loa đầy đủ

Pin ngon 2, 3 tiếng

Windows 11 Home bản quyền

Ngoại hình như mới ko trầy vết nào

Phụ kiện: FULLBOX

—–

Giá 13TR5

—–

Máy bán ra được test kĩ bằng phần mềm, thiết bị chuyên dụng

Đảm bảo tất cả linh kiện vẫn hoạt động tốt

Hỗ trợ sửa chữa/nâng cấp theo giá vốn

Quý khách mua về hoàn toàn yên tâm sử dụng

—–

Công ty TNHH CNTT&VT MINH QUÂN

Địa chỉ: 48/2 Xuân Thủy P. Thảo Điền TP. Thủ Đức TPHCM

Call/Zalo/SMS: 0938-507-766

Đăng bởi

MSI GF63 i5 Gen 10 10300H 8/512 GTX 1650 15″ 144Hz

Laptop Gaming MSI GF63 màn hình 144Hz, giá quá rẻ phù hợp túi tiền cho sinh viên học thiết kế đồ họa/nhà cửa, vừa có thể chơi game thoải mái

—–

CPU Intel Core i5 Gen 10 10300H

RAM 16 GB, DDR4 3200Mhz

Ổ cứng SSD M2 512GB

Card đồ họa NVIDIA GeForce GTX 1650

Màn hình 15.6″ FHD 144Hz

Cổng giao tiếp HDMI, USB 3.0, LAN (RJ45), Type-C…

Camera, Micro, Loa đầy đủ

Pin ngon 2, 3 tiếng

Windows 10 Home bản quyền

Ngoại hình máy đẹp keng

Phụ kiện: sạc zin theo máy

—–

Giá 9TR3

—–

Máy bán ra được test kĩ bằng phần mềm, thiết bị chuyên dụng

Đảm bảo tất cả linh kiện vẫn hoạt động tốt

Hỗ trợ sửa chữa/nâng cấp theo giá vốn

Quý khách mua về hoàn toàn yên tâm sử dụng

—–

Công ty TNHH CNTT&VT MINH QUÂN

Địa chỉ: 48/2 Xuân Thủy P. Thảo Điền TP. Thủ Đức TPHCM

Call/Zalo/SMS: 0938-507-766

Đăng bởi

Acer Aspire 5 i5 Gen 11 1135G7 8/512 14″ FHD

Laptop Acer Aspire 5, CPU i5 Gen 11 1135G7, màn hình 14″ FHD nhỏ gọn phù hợp cho người di chuyển nhiều, giá quá rẻ phù hợp cho sinh viên

—–

CPU Intel Core i5 Gen 11 1135G7

RAM 8 GB, DDR4 3200Mhz

Ổ cứng SSD M2 512GB

Card đồ họa Intel Iris XE

Màn hình 14″ FHD

Cổng giao tiếp HDMI, USB 3.0, Type-C, …

Camera, Micro, Loa đầy đủ

Windows 10 Home bản quyền

Ngoại hình máy đẹp keng

Phụ kiện: sạc zin theo máy

—–

Giá 5TR9

—–

Máy bán ra được test kĩ bằng phần mềm/thiết bị chuyên dụng

Đảm bảo tất cả linh kiện vẫn hoạt động tốt

Hỗ trợ sửa chữa/nâng cấp giá vốn

Quý khách mua về hoàn toàn yên tâm sử dụng

—–

Công ty TNHH CNTT&VT MINH QUÂN

Địa chỉ: 48/2 Xuân Thủy P. Thảo Điền TP. Thủ Đức TPHCM

Call/Zalo/SMS: 0938-507-766

Đăng bởi

HP 15s i7 Gen 11 1165G7 8/512 15″ FHD

Laptop HP 15s, ngoại hình đẹp hơn hẳn so với các hãng khác, cấu hình cao i7 Gen 11, giá rẻ phù hợp với sinh viên

—-

CPU Intel Core i7 Gen 11 1165G7

RAM 8 GB, DDR4 3200Mhz

Ổ cứng SSD M2 512GB

Card đồ họa Intel Iris XE

Màn hình 15″ FHD

Cổng giao tiếp HDMI, USB 3.0, Type-C, …

Camera, Micro, Loa đầy đủ

Windows 11 Home bản quyền

Ngoại hình máy đẹp keng

Phụ kiện: sạc zin theo máy

—–

Giá 8TR3

—–

Máy bán ra được test kĩ bằng phần mềm/thiết bị chuyên dụng

Đảm bảo tất cả linh kiện vẫn hoạt động tốt

Hỗ trợ sửa chữa/nâng cấp giá vốn

Quý khách mua về hoàn toàn yên tâm sử dụng

—–

Công ty TNHH CNTT&VT MINH QUÂN

Địa chỉ: 48/2 Xuân Thủy P. Thảo Điền TP. Thủ Đức TPHCM

Call/Zalo/SMS: 0938-507-766

Đăng bởi

Lenovo Ideapad Slim 3 i5 Gen 12 12450H 14″ BH 9/25

Laptop Lenovo Ideapad Slim 3, CPU i5 Gen 12 12450H mạnh hơn hẳn CPU laptop văn phòng, còn bảo hành chính hãng tới 09/2025

—–

CPU Intel Core i5 Gen 12 12450H

RAM 16 GB, DDR4 3200Mhz

Ổ cứng SSD M2 512GB

Card đồ họa Intel UHD

Màn hình 14″ FHD

Cổng giao tiếp HDMI, USB 3.0, Type-C, …

Camera, Micro, Loa đầy đủ

Windows 11 Home bản quyền

Ngoại hình máy đẹp keng

Còn bảo hành chính hãng tới 09/2025

Phụ kiện: sạc zin theo máy

—–

Giá 9TR5

—–

Máy bán ra được test kĩ bằng phần mềm/thiết bị chuyên dụng

Đảm bảo tất cả linh kiện vẫn hoạt động tốt

Hỗ trợ sửa chữa/nâng cấp giá vốn

Quý khách mua về hoàn toàn yên tâm sử dụng

—–

Công ty TNHH CNTT&VT MINH QUÂN

Địa chỉ: 48/2 Xuân Thủy P. Thảo Điền TP. Thủ Đức TPHCM

Call/Zalo/SMS: 0938-507-766

Đăng bởi

Card test main laptop là gì? Có chức năng gì với laptop?

Bạn đã nghe tới card test main laptop, nhưng không biết chúng là gì? Có chức năng gì trong laptop? Vậy thì bài viết này sẽ giúp bạn giải đáp bằng các thông tin dưới đây, các bạn hãy cùng mình tìm hiểu về linh kiện này nhé!

Card test main laptop là gì? 

 

Card test main laptop được biết đến là công cụ hỗ trợ sửa chữa mainboard laptop rất hiệu quả với những tính năng ưu việt. 

Bạn có thể hiểu rằng, card test main laptop là một thiết bị hỗ trợ kỹ thuật viên chuẩn đoán chính xác các lỗi liên quan đến phần cứng (cụ thể ở đây là mainboard) làm cho laptop bật không lên.

Thông thường, các loại card test main laptop sẽ được cắm trực tiếp trên khe PCI hoặc PCI express của mainboard bị lỗi để kiểm tra. Có hai cách để kiểm tra main bằng card test main, một là nhận biết các đèn LED trên card test main, hay là xem các chỉ số hiển thị trên card.

Cấu tạo card test main laptop 

 

Cấu tạo của card test main laptop sẽ có những bộ phận sau: 

– Khe cắm qua giao tiếp PCI và PCIE 1V.

– Đèn led báo nguồn (3v,5v,12v).

– Led RST: đèn này sẽ sáng tắt liên tục để báo hiệu có xung reset. Nếu đèn này không sáng hay sáng liên tục thì mainboard có thể đã bị mất điện áp mạch ram, cpu, chipset…

– Led báo CLK: báo hiệu xung clock đã hoạt động tốt.

– Các led 7 đoạn để báo POST: đây là led quan trọng nhất để xác định mainboard đang bị vấn đề gì?

– Một số loại card test main laptop đời cũ có thể có thêm một số loại đèn báo như IRDY, Frame…

Chức năng của card test main laptop

 

Card test main laptop sẽ báo code ở trên đèn LED và dựa trên mã code của từng hãng BIOS để kiểm tra mainboard. Điều này sẽ giúp cho quá trình kiểm tra hoạt động của mainboard trở nên dễ dàng hơn. Từ đó đảm bảo thời gian sửa chữa máy tính nhanh và đạt độ chính xác cao hơn so với các bước kiểm tra thông thường.

 

Nguyên tắc hoạt động của card test main laptop 

 

Khi các đèn LED đều sáng nghĩa là đã đủ nguồn. Một số trường hợp nguồn hoặc dây nối nguồn bị hở, bị đứt sẽ cấp nguồn không đủ cho main dẫn đến main không hoạt động.

Nếu main vẫn hoạt động bình thường thì LED reset chớp một lần còn nếu quá trình post diễn ra trôi chảy thì LED RUN sẽ nháy liên tục.

Nguyên tắc hoạt động của card test main laptop rất đơn giản, chủ yếu là dựa trên quá trình POST của BIOS.

Khi bật máy lên đối với loại nguồn AT hoặc nhấn nút Power thì trước tiên Main và CPU phải chạy được.

Tiếp theo là quá trình Post của BIOS hoạt động, nó kiểm tra tất cả main, cpu, ram…nói chung là thành phần kết nối với mainboard.

Quá trình này sẽ diễn ra trong yên lặng cho đến khi nghe được âm thanh thì màn hình mới hiện lên. Lúc này quá trình Post đã gần như thực hiện xong.

Nếu để tâm bạn sẽ thấy Post tiếp tục test ram, hdd, fdd… nhưng kỳ thực đây chỉ là quá trình báo kết quả hay là test lại lần nữa mà thôi. Khi màn hình hiện lên thì lúc này card test main đã hoàn thành nhiệm vụ và không cần đến nó nữa. Khi đó bạn có thể nhìn vào màn hình chẩn đoán các lỗi để khắc phục.

Vậy tóm tắt lại là card test main laptop chỉ được sử dụng từ khi nhấn nút Power cho đến khi màn hình hiện lên mà thôi.

Hướng dẫn sử dụng card test main laptop

Khi mainboard hoặc PC xảy ra lỗi thì bước đầu tiên sẽ dùng card test cắm vào cổng PCI/ISA còn trống bật máy lên và quan sát. Nếu không có biểu hiện nào về hình, tiếng và chữ… nghĩa là card test chưa được cắm cẩn thận vào mainboard.

Tắt máy cắm lại, khi card test hiện lên các thông số thì tra cứu ý nghĩa của các thông số đó để hiểu được mainboard hỏng chỗ nào và tiến hành xử lý.

Các lỗi thường gặp ở main máy tính khi cần dùng card test main laptop

Nếu card nhảy code C0, C1 hoặc D0, D1… Những lỗi này thường do mainboard và CPU chưa chạy, nhưng có thể  nguyên nhân nguồn Vcore cấp cho CPU không ổn định, mất nguồn BUS RAM hoặc main không hỗ trợ CPU.

Nếu card test nhảy code lung tung (tắt máy bật lên lại thì nhảy 1 mã code khác), gặp nhiều ở mainboard Gigabyte thì đa phần do lỗi BIOS, chỉ cần nạp lại BIOS là được. Cũng có trường hợp nhảy code loạn xạ nhưng không phải lỗi BIOS mà do bản chất card test dỏm nên báo không đúng.

Nếu card test dùng lại ở code 26 thì anh em nên kiếm tiền mua card test khác là được rồi. Lỗi này do bản chất card test bị lỗi. Thường gặp khi chúng ta kiểm tra trên mainboard Gigabyte và Intel.

Led 7 đoạn báo mã code C5, D6, 05 tùy theo loại mainboard sử dụng BIOS của hãng nào. Mã code này đa số do lỗi BIOS, anh em phải nạp lại BIOS.

Card test chạy tới code  7F thì mainboard đã khởi động lên hình. Những do thiết lập BIOS bị sai nên nó dừng lại yêu cầu bấm phím F1 để tiếp tục hoặc F2 để vào cài đặt BIOS. KHi ta nhấn F1 để tiếp tục thì card test sẽ nhảy tiếp tới FF và khi đó mainboard đã lên bình thường. Ngoài ra khi đã tới code này, đèn numlock đã sáng mà không lên hình thì anh em cần kiểm tra lại Card VGA rời, onboard, dây cáp nối màn hình, màn hình LCD.

Khi ta kích nguồn, nếu loa gắn trên maiboard phát ra tiếp ” bíp ” thì đa phần là mainboard và CPU đã hoạt động. Nếu kông lên hình thì anh em cần kiểm tra lại VGA, card màn hình.

Khi ta kích nguồn cho mainboard và thấy card test main lần lược nhảy các mã code từ Co, C1… D0, D1… EA… 7F rồi tới FF thì đã số là mainboard đã chạy hoàn toàn. Không lên hình thì cũng phải kiểm tra màn hình, card màn hình.

Card test mainboard nhảy code C0, C1.. rồi dừng C5, C6 hay D5, D6, EA thì đa số là lỗi Ram, cần phải vệ sinh sạch sẽ khe RAM, chân RAM (phải đảm bảo RAM còn xài tốt ). Nếu không lên thì cần kiểm tra lại nguồn BUS RAM, hấp hoặc thay chip cầu Bắc.

Mong rằng với những thông tin trên đây sẽ giúp bạn hiểu rõ hơn về card test main laptop.

Đăng bởi

Xây dựng API sử dụng Laravel và GraphQL

Chắc hẳn các bạn đã từng nghe về GraphQL GraphQL là một trong những đứa con của facebook được facebook tạo ra từ năm 2012 và được giới thiệu trước công chúng trong sự kiện React.js Conf 2015 nếu các bạn vẫn chưa biết hoặc muốn hiểu rõ hơn về GraphQL thì có thể tham khảo bài viết tổng quát GraphQL tại ĐÂY bây giờ chúng ta bắt đầu xây dựng một API sử dụng Laravel và GraphQL

Cài đặt và cấu hình GraphQL

Để cài đặt GraphQL chúng ta cần có sẳn một project Laravel sau đó mở file composer.json và thêm vào package sau :

    "require": {
        "folklore/graphql": "~1.0.0"
    },

Sau đó chạy lệnh :

$ composer install

Hoặc

$ composer update

Sau khi Composer update xong ta tiếp tục chạy lệnh :

$  php artisan

Đối với Laravel 5.X chúng ta thêm một service vào provider trong file *app/config/app.php *

Folklore\GraphQL\ServiceProvider::class

Và đăng ký một aliases :

'GraphQL' => Folklore\GraphQL\Support\Facades\GraphQL::class

Và chạy lệnh :

$ php artisan 

Nếu như các phương thức GraphQL xuất hiện như trong hình thì chúng ta đã cài đặt GraphQL thành công :Trong GraphQL gồm có 1 node root là viewer, gồm các lớp :

  • Connections: kết nối đến database
  • Felds: mô tả các fields trong node
  • Types: mô tả kiểu dữ liệu của field
  • Queries: mô tả cách truy vấn graph
  • Mutations: mô tả cách cập nhật graph

Bây giờ chúng ta bắt đầu vào việc tạo một UserType: để tạo UserType chúng ta chạy lệnh sau :

$ php artisan make:graphql:type UserType

Sau khi chạy lệnh thành sẽ xuất hiện một thư mục App một thư mục GraphQL/Type/UserType.php . Chúng ta bắt đầu mô tả các kiểu dữ liệu của User như sau:

class UserType extends BaseType
{
    protected $attributes = [
        'name' => 'User',
        'description' => 'A type'
    ];

    public function fields()
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::int())
            ],
            'name' => [
                'type' => Type::nonNull(Type::string())
            ],
            'email' => [
                'type' => Type::nonNull(Type::string())
            ],
            'created_at' => [
                'type' => Type::nonNull(Type::string())
            ],
            'updated_at' => [
                'type' => Type::nonNull(Type::string())
            ]
        ];
    }
}

Tiếp theo chúng ta tạo một UserQuery bằng cách chạy lệnh :

$ php artisan make:graphql:query UserQuery

Thư mục GraphQL/Query/UserQuery.php sẽ được tự động ra. tiếp tục chúng ta config như sau :

class UsersQuery extends Query {

    protected $attributes = [
        'name'  => 'User',
    ];

    public function type()
    {
        return Type::listOf(GraphQL::type('user'));
    }

    public function args()
    {
        return [
            'ids'   => [
                'name' => 'ids',
                'type' => Type::listOf(Type::int()),
            ],
        ];
    }

    public function resolve($root, $args, SelectFields $fields)
    {
        $select = $fields->getSelect();
        $with = $fields->getRelations();

        return User::where('id', '=', $args['id'])->with($with)->select($select)->get();
    }

}

Tiếp tục chúng ta tạo file Mutation bằng cách gõ lệnh :

$ php artisan make:graphql:mutation CreateUserMutation

Thư mục GraphQL/Mutation/CreateUserMutation.php sẽ được tự động ra. tiếp tục chúng ta config như sau :

class CreateUserMutation extends Mutation
{
    protected $attributes = [
        'name' => 'CreateUser',
        'description' => 'User mutation'
    ];

    public function type()
    {
        return GraphQL::type('User');
    }

    public function args()
    {
        return [
            'name' => [
                'type' => Type::nonNull(Type::string()),
                'rules' => ['required']
            ],
            'email' => [
                'type' => Type::nonNull(Type::string()),
                'rules' => ['required', 'email', 'unique:users']
            ],
            'password' => [
                'type' => Type::nonNull(Type::string()),
                'rules' => ['required', 'min:6']
            ]
        ];
    }

    public function resolve($root, $args, $context, ResolveInfo $info)
    {

        $user = new User();
        $user->fill($args);
        $user->password = bcrypt($args['password']);
        $user->save();
        return $user;
    }
}

Như vậy công việc tạo GraphQL đã hoàn tất bước cuối cùng là tiến thành config file config/graphql.php như sau :

 'schemas' => [
        'default' => [
            'query' => [
                'user' => App\GraphQL\Query\UserQuery::class,
            ],
            'mutation' => [
                'createUser' => App\GraphQL\Mutation\CreateUserMutation::class,
            ],
            // 'middleware' => []
        ],
    ],
    
    // The types available in the application. You can then access it from the
    // facade like this: GraphQL::type('user')
    //
    // Example:
    //
    'types' => [
        App\GraphQL\Type\UserType::class,
    ],

Như vầy chúng ta đã tiến hành xong các bước để thiết lập GraphQL bây giờ chúng ta truy cập Vào đường dẫn sau:

localhost/blog/public/graphiql

Giao diện xuất hiện:Đây chính là giao diện hiển thị của GraphQL . Bây giờ chúng ta sẽ bắt đầu viết một câu truy vấn đơn giản:

mutation {
    createUser (
        name: "test",
        email: "[email protected]",
        password: "test123"
    ){
        id,
        email
    }
}

Khi nhấn submit kết quả sẽ trả về như trong hình thì chúng ta đã thành công trong việc tạo truy vấn bằng GraphQL :Để truy ngược lại chúng ta làm như sau :

query {
    user(id: 1) {
        name,
        email
    }
}
Đăng bởi

Biến ứng dụng Laravel của bạn trở nên phức tạp hơn với gRPC

gRPC là gì ?

Chắc hẳn khi mới đọc tiêu đề, nhiều bạn thắc mắc tại sao lại biến ứng dụng đơn giản trở nên phức tạp để làm gì không biết, nhưng thực ra việc phức tạp này sẽ mang lại cho chúng ta rất nhiều lợi ích, với những ứng dụng nhỏ thì gRPC chưa thực sự cần thiết, tuy nhiên áp vào các ứng dụng lớn, cần được mở rộng trong tương lai, việc chuyển đổi từ REST sang gRPC đem lại hiệu quả rất lớn.

RPC

RPC, đó là chữ viết tắt của Remote Procedure Calls (tạm dịch là các cuộc gọi thủ tục từ xa), là một khái niệm nhằm cố gắng khái quát một lời gọi thủ tục thông thường trong trường hợp mà caller và receiver không cùng nằm trong một process – và được phân tán trên các máy riêng biệt. Việc này có ý nghĩa rất quan trọng vì trong các hệ thống phân tán (distributed system), application code ở nhiều server hơn là một server. Ví dụ thường thấy nhất chính là kiến trúc Microservice.

gRPC

Tối ưu cho việc “giao tiếp” giữa các server là lý do gRPC ra đời.

gRPC là một RPC framework gíup bạn kết nối giữa các service trong hệ thống, nó hỗ trợ load balancing, tracing, health checking và authentication, hỗ trợ từ ứng dụng mobile, trình duyệt cho tới back-end service, do Google phát triển.

Để giải bài toán trên, gRPC đã sử dụng binary để truyền đi thay vì phải encode chúng thành các ngôn ngữ trung gian JSON/XML. Việc này rõ ràng đã làm tăng tốc giao tiếp các servers lên rất nhiều, giảm overhead cho CPUs.

Thứ giúp gRPC giao tiếp binary ngon vậy chính là http/2, đây vốn là giao thức có rất nhiều cải tiến so với http/1.1

Sử dụng gRPC trong PHP

Không giống như Java, Go, hay Ruby,… PHP hiện tại chưa được chính Google hỗ trợ xây dựng SDK để dựng thành 1 gRPC server. Vì thế chúng ta muốn sử gRPC cho server thì cần thông qua 1 framework gọi là RoadRunner.

RoadRunner là 1 framework ở tầng infrastructure cho các ứng dụng PHP, nó được viết bằng Golang. Công việc của RoadRunner là chạy PHP dưới dạng các worker

Golang sẽ giúp RoadRunner chạy PHP app trên goroutine và hỗ trợ cân bằng tải trên các worker.

RoadRunner sẽ giữ các PHP worker luôn alive giữa các request, tránh việc tái khởi đọng lại app và tăng tốc cho các ứng dụng lớn. PHP worker được đặt trong resident memory, và luôn sẵn sàng cho request tiếp theo. RoadRunner còn sử dụng Goridge RPC sẽ giúp đẩy nhanh tốc độ load của ứng dụng lên server.

Cài đặt gRPC

Trước khi bắt đầu implement gRPC cho ứng dụng Laravel thì chúng ta setup môi trường development cho đủ các công cụ cần thiết

  • gRPC PHP extension
  • Google Protobuf
  • Google Protobuf compiler cho PHP server
  • Roadrunner

gRPC PHP extension

Việc cài thêm extension khá đơn giản, bạn chỉ cần sử dụng PECL và chạy lệnh

$ sudo pecl install grpc

Tuy nhiên nếu máy bạn có cài nhiều version PHP thì sẽ phức tạp hơn chút, mình đã gặp issue khi cài grpc là extension được build xong, khi sử dụng trong php.ini thì PHP không tìm thấy extension. Mình khắc phục bằng cách gỡ bỏ extension cũ và cài bằng lệnh này

$ sudo pecl php_suffix=7.4 install grpc 

thật (magic) PECL sẽ compile extension cho đúng phiên bản PHP mà bạn đang chọn là PHP 7.4

Cuối cùng bạn tìm file php.ini và thêm dòng này vào extension=grpc.so

Google Protobuf

Protocol buffer còn được biết như protobuf là language-neutral, platform-neutral của google phiên bản nội bộ được công bố vào năm 2001 và phiên bản công khai đầu tiên được giới thiệu vào năm 2008 ( Repository ), về cơ bản nó được sủ dụng để Serialized object, có vẻ nó khá giống XML hoặc JSON. Nó lưu trữ dữ liệu có cấu trúc có thể được Serialize hoặc De-Serialized tự động bưởi nhiều ngôn ngữ khác nhau. Nó được thiết kế để trở thành language/platform neutral và có thể mở rộng.

Việc cài protobuf cũng tương tự gRPC , bạn chạy command sau và rồi thêm dòng extension=protobuf.so vào php.ini

$ sudo pecl install protobuf

Google Protobuf compiler cho PHP server

Bởi vì gRPC chưa trực tiếp hỗ trợ các server viết bằng PHP nên với PHP chúng ta sử dụng 1 plugin để compile các file .proto cho PHP server

$ go get github.com/spiral/php-grpc/cmd/protoc-gen-php-grpc

để protoc có thể tìm thấy plugin mà bạn vừa kéo về thì bạn thêm vào file .zshrc (nếu đang dùng zsh) hoặc .bashrc 2 dòng này

export GO_PATH=~/go
export PATH=$PATH:/$GO_PATH/bin

đây là 1 pre-build binary để gen proto file, để sử dụng nó ta chỉ cần thêm plugin đó trong command compile ví dụ:

$ protoc --php_out=target-dir/ --php-grpc_out=target-dir/ sample.proto

Roadrunner

RoadRunner sẽ hỗ trợ bạn serve ứng dụng lên, tương tự nhưng artisan trong Laravel ý, bạn chỉ cần tải file rr-grpc về và để vào thư mục root của app

RoadRunner sẽ hỗ trợ bạn serve ứng dụng lên, tương tự nhưng artisan trong Laravel ý, bạn chỉ cần tải file rr-grpc về và để vào thư mục root của app

Implement gRPC server

Trong bài viết này mình sẽ implement gRPC cho phía server bằng PHP, và sử dụng luôn framework Laravel chọn xịn xò =))

Init project

Đầu tiền chúng ta cần init project

$ composer create-project laravel/laravel grpc-php-server

sau đó chúng ta cần cài thêm các package cần thiết như spiral/php-grpcgoogle/common-protos,… thành phẩm chúng ta sẽ có 1 file composer.json như này

{
    "name": "laravel/laravel",
    "type": "project",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"],
    "license": "MIT",
    "require": {
        "php": "^7.4|^8.0",
        "ext-grpc": "^1.37",
        "fideloper/proxy": "^4.4",
        "fruitcake/laravel-cors": "^2.0",
        "google/common-protos": "^1.3",
        "google/protobuf": "^3.16",
        "grpc/grpc": "^1.36",
        "guzzlehttp/guzzle": "^7.0.1",
        "laravel/framework": "^8.12",
        "laravel/tinker": "^2.5",
        "nyholm/psr7": "^1.4",
        "spiral/php-grpc": "^v1.5.0",
        "spiral/roadrunner": "^1.9",
        "spiral/roadrunner-laravel": "^3.7",
        "ext-json": "*"
    },
    "require-dev": {
        "facade/ignition": "^2.5",
        "fakerphp/faker": "^1.9.1",
        "laravel/sail": "^1.0.1",
        "mockery/mockery": "^1.4.2",
        "nunomaduro/collision": "^5.0",
        "phpunit/phpunit": "^9.3.3",
        "spiral/dumper": "^1.1.7"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/",
            "": "protos/generated/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ]
    },
    "extra": {
        "laravel": {
            "dont-discover": []
        }
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": "dist",
        "sort-packages": true,
        "platform": {
            "php": "7.4.18"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}

Trong file composer.json này mình có bổ sung thêm

"autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/",
            "": "protos/generated/"
        }
    },

mục đích là để load thêm các file được compile từ Protobuf vào project.

Tạo auth.proto

Mục đích của file này là giúp define ra các service và cấu trúc request/response. File này sẽ được viết bằng Protobuf hay Protocols Buffer, là một ngôn ngữ dùng để mô tả các cấu trúc dữ liệu, chúng ta dùng protoc để biên dịch chúng thành mã nguồn của các ngôn ngữ lập trình khác nhau có chức năng serialize và deserialize các cấu trúc dữ liệu này thành dạng binary stream.

syntax = "proto3";

package protobuf.identity;

option php_metadata_namespace = "Protobuf\\Identity\\Metadata";

service AuthService {
    rpc SignIn (SignInRequest) returns (Response) {}
    rpc SignUp (SignUpRequest) returns (Response) {}
}

message SignInRequest {
    string email = 1;
    string password = 2;
}

message SignUpRequest {
    string name = 1;
    string email = 2;
    string password = 3;
    string password_confirmation = 4;
}

message Response {
    int64 id = 1;
    string token = 2;
}

Trong file này đơn giản chỉ định nghĩa service AuthService sẽ có 2 method rpc là SignIn và SignUp, chúng nhận vào tham số message được define theo cấu trúc ở bên dưới.

Sau khi đã tạo file auth.proto chúng ta cần phải compile chúng ra thành các file để sử dụng trong project, bằng command:

$  protoc --php_out=./protos/generated/ --php-grpc_out=./protos/generated/ ./protos/auth.proto

như vậy là chúng ta sẽ có file source code nằm trong thư mục protos/generated như sau: 

đây cũng là thư mục mà mình bổ sung vào trong file composer.json ở trên đấy

Implement logic cho AuthServiceInterface

Sau khi sử dụng protoc để có được file AuthServiceInterface, chúng ta đơn giản chỉ cần tiến hành implement logic cho các func trong service thôi

<?php

namespace App\Grpc\Controllers;

use Protobuf\Identity\AuthServiceInterface;
use Protobuf\Identity\Response;
use Protobuf\Identity\SignInRequest;
use App\Grpc\Contracts\Validator;
use Illuminate\Contracts\Hashing\Hasher;
use Spiral\GRPC\Exception\InvokeException;
use Spiral\GRPC\StatusCode;
use Protobuf\Identity\SignUpRequest;
use Throwable;
use Spiral\GRPC\ContextInterface;

class AuthController implements AuthServiceInterface
{
    /**
     * Input validator
     *
     * @var Validator
     */
    protected Validator $validator;

    /**
     * Hasher
     *
     * @var Hasher
     */
    protected Hasher $hasher;

    /**
     * Create new instance.
     *
     * @param  Validator $validator
     * @param  Hasher $hasher
     */
    public function __construct(Validator $validator, Hasher $hasher)
    {
        $this->validator = $validator;
        $this->hasher = $hasher;
    }

    /**
     * @param ContextInterface $ctx
     *
     * @param  SignUpRequest $request
     * @return Response
     * @throws Throwable
     */
    public function SignUp(ContextInterface $ctx, SignUpRequest $request): Response
    {
        $data = json_decode($request->serializeToJsonString(), true);

        $this->validator->validate($data, [
            'email' => 'bail|required|email',
            'name' => 'required|max:255',
            'password' => 'required|confirmed',
        ]);

        $response = new Response();

        $response->setId(1);
        $response->setToken("token"); //TODO use jwt to handle token base auth

        return $response;
    }

    /**
     * @param ContextInterface $ctx
     * @param SignInRequest $in
     * @return Response
     * @throws Throwable
     */
    public function SignIn(ContextInterface $ctx, SignInRequest $in): Response
    {
        $data = json_decode($in->serializeToJsonString(), true);

        $this->validator->validate($data, [
            'email' => 'required|email',
            'password' => 'required|min:6',
        ]);

        $response = new Response();

        $response->setId("1");
        $response->setToken("token"); //TODO using jwt to handle token base auth

        return $response;
    }
}

đơn giản vậy thôi là chúng ta đã xong phần logic cho các method rpc của app rồi

Implement PHP worker

Phần quan trọng nhất đây rồi.

Chúng ta sử dụng RoadRunner để serve các PHP worker lên và lắng nghe các rpc nên PHP worker là 1 thành phần quan trọng trong ứng dụng của bạn

<?php

use Spiral\RoadRunner\Worker;
use Spiral\Goridge\StreamRelay;

ini_set('display_errors', 'stderr');

require __DIR__ . '/vendor/autoload.php';

$app = require_once __DIR__ . '/bootstrap/app.php';

$app->singleton(
    App\Grpc\Contracts\Kernel::class,
    App\Grpc\Kernel::class
);

$app->singleton(
    App\Grpc\Contracts\ServiceInvoker::class,
    App\Grpc\LaravelServiceInvoker::class
);

$kernel = $app->make(App\Grpc\Contracts\Kernel::class);

$kernel->registerService(Protobuf\Identity\AuthServiceInterface::class);

$w = new Worker(new StreamRelay(STDIN, STDOUT));

$kernel->serve($w);

Khi đã có PHP worker rồi, chúng ta sẽ sử dụng rr-grpc đã tải về ở trên để serve app lên thôi. rr-grpc có yêu cầu file config như sau:

grpc:
  listen: "tcp://127.0.0.1:9001"  # Define host cho service
  proto: "protos/auth.proto"      # Define rõ file proto ở đâu
  workers:
    command: "php worker.php"      # Start worker từ file worker vừa tạo ở trên
    pool:                          # Cấu hình số lượng worker và số lượng job tối đa
      maxJobs: 1
      numWorkers: 1

Bây giờ chúng ta chạy command: ./rr-grpc -c .rr.yaml serve -v -d là xong 

server đã sẵn sàng lắng nghe các yêu cầu từ client rồi

Cấu trúc thư mục hoàn chỉnh

Tạm kết

Như vậy là chúng ta đã implement được phía server, do bài viết đã dài nên mình tạm kết ở đây, trong bài viết tới mình sẽ tiếp tục implement phía client, làm cách nào để client có thể giao tiếp với server thông qua gRPC.

Demo