Home Blog Page 75

Lấy access token sử dụng refresh token với Keycloak

access token
Lấy access token sử dụng refresh token với Keycloak

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Mình đã giới thiệu về Refresh Token grant type trong OAuth 2.0 trong bài viết về Các loại grant types trong OAuth 2.0. Trong bài viết này, mình sẽ hướng dẫn các bạn cách chúng ta lấy mới access token sử dụng refresh token với Keycloak là như thế nào các bạn nhé!

  Authorization Code grant type với Proof Key for Code Exchange (PKCE) trong OAuth 2.1
  Thêm mới client hỗ trợ OAuth Authorization Code grant type trong Keycloak

Đầu tiên, mình sẽ tạo mới trong Keycloak một client với Authorization Code grant type để làm ví dụ:

Thực hiện lấy access token cho client này, các bạn sẽ thấy kết quả như sau:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJZR29TSXBPblRKeTJmbjhzLWk4WlBKMC1xWkxybEEtNVI4ZjhXbTFjYjVVIn0.eyJleHAiOjE2MzU2NDMxMDYsImlhdCI6MTYzNTY0MjgwNiwiYXV0aF90aW1lIjoxNjM1NjQyNzk0LCJqdGkiOiJjZTY4ZDIxYS04YzdkLTQ1YWItOWMxNC1jYzdkMTM5NWNmOGMiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvaHVvbmdkYW5qYXZhIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjhhNTA5MmZhLWQ4MTUtNDYyMC05MmFiLTRhYzg3NTQyNjg1YyIsInR5cCI6IkJlYXJlciIsImF6cCI6Imh1b25nZGFuamF2YV9hdXRob3JpemF0aW9uX2NvZGUiLCJub25jZSI6IjllZW1meGhiazYiLCJzZXNzaW9uX3N0YXRlIjoiN2E4ZGMxODktMTVlZS00ZWZhLWEwZGEtNmY5ZjdlY2Y2MjczIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiZGVmYXVsdC1yb2xlcy1odW9uZ2RhbmphdmEiXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiS2hhbmggTmd1eWVuIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiaHVvbmdkYW5qYXZhIiwibG9jYWxlIjoiZW4iLCJnaXZlbl9uYW1lIjoiS2hhbmgiLCJmYW1pbHlfbmFtZSI6Ik5ndXllbiIsImVtYWlsIjoiaHVvbmdkYW5qYXZhLmNvbUBnbWFpbC5jb20ifQ.JgklBAraEs__i2CHI0z7KQZBy5JeIVfBPzP4cORxNEcI53zbGEmsCqHZoNt0qwcURGc9EV77jzOnqlq6j7wWPhtwhpzOHT3JupqGD86CyaUJ9rh-GrhnKDy7YMTp9337X7J2qzp5YIIK0tmroGjNR7dIpHn1ThatNLM-8w2KnydT7DhYjHx1gaX7HKXAuaiBhNbR7PYrS1-FsbxT--QjNNs-mgTXl7OVnqpCPcRCt8pBPu15kPbP00i7zJ7AaSmZfPNBt7rFPGkaYAX5kIi8FY0wf2RZuFMcgDpg-01rzfTkoWIXCdDSQPBagAveQUE6viaC-nsV7_-5zTCvGch_0A",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI5ZjYzNWQ5Mi1hOTdjLTQwMjktODE2YS05ZWU3YjAxMmE3NDUifQ.eyJleHAiOjE2MzU2NDQ2MDYsImlhdCI6MTYzNTY0MjgwNiwianRpIjoiYTZmYmQwMDUtNGZlOC00NTdjLWEwZmEtMDA5ODBiZjY4NmE0IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL2h1b25nZGFuamF2YSIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9hdXRoL3JlYWxtcy9odW9uZ2RhbmphdmEiLCJzdWIiOiI4YTUwOTJmYS1kODE1LTQ2MjAtOTJhYi00YWM4NzU0MjY4NWMiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoiaHVvbmdkYW5qYXZhX2F1dGhvcml6YXRpb25fY29kZSIsIm5vbmNlIjoiOWVlbWZ4aGJrNiIsInNlc3Npb25fc3RhdGUiOiI3YThkYzE4OS0xNWVlLTRlZmEtYTBkYS02ZjlmN2VjZjYyNzMiLCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIn0.zMYO5ZRupTskEs9QxJdnP3d24qcHavrLKG4pkQ-OLN8",
"token_type": "Bearer",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJZR29TSXBPblRKeTJmbjhzLWk4WlBKMC1xWkxybEEtNVI4ZjhXbTFjYjVVIn0.eyJleHAiOjE2MzU2NDMxMDYsImlhdCI6MTYzNTY0MjgwNiwiYXV0aF90aW1lIjoxNjM1NjQyNzk0LCJqdGkiOiI3NGFkNGMyNC1mYTliLTQ4MWMtYTgwZS1jMTVhNDk1NmU0ZDciLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvaHVvbmdkYW5qYXZhIiwiYXVkIjoiaHVvbmdkYW5qYXZhX2F1dGhvcml6YXRpb25fY29kZSIsInN1YiI6IjhhNTA5MmZhLWQ4MTUtNDYyMC05MmFiLTRhYzg3NTQyNjg1YyIsInR5cCI6IklEIiwiYXpwIjoiaHVvbmdkYW5qYXZhX2F1dGhvcml6YXRpb25fY29kZSIsIm5vbmNlIjoiOWVlbWZ4aGJrNiIsInNlc3Npb25fc3RhdGUiOiI3YThkYzE4OS0xNWVlLTRlZmEtYTBkYS02ZjlmN2VjZjYyNzMiLCJhdF9oYXNoIjoiRWpfZGlIMURTa0lINzlsMGpqMENsQSIsImFjciI6IjEiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJLaGFuaCBOZ3V5ZW4iLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJodW9uZ2RhbmphdmEiLCJsb2NhbGUiOiJlbiIsImdpdmVuX25hbWUiOiJLaGFuaCIsImZhbWlseV9uYW1lIjoiTmd1eWVuIiwiZW1haWwiOiJodW9uZ2RhbmphdmEuY29tQGdtYWlsLmNvbSJ9.Cm9kcio4DYM8f3WN_KQ5UJIe-RX8rRLKP0wlLJqwObE0tIxXAEqVOzr7gAv9WEpy_wDO3mC7NN4ZyfX8iQlm47UCdnFo-50vbeUDdfa1wtSM2FfnPOhV_76KwVDgD1KqImlHGdb0QbvzxAMS25RPrWeYWQsoJlVFqcOC52_sqQ217vJyuytComZ7BJ_otiKLSiUTmAAgmhc3UAiXjKseefzv858fn8b0Z-tVEJh-CfjwhnazRsxj5ukGYknX56wJHNGT35JU_Wph7rzv9EsRNm36_0Vt-7LyLBKrwWWV55MoPL_il7nzxUrehhfSzAzBzOSMhYqCuSfAAErKUKJGHw",
"not-before-policy": 0,
"session_state": "7a8dc189-15ee-4efa-a0da-6f9f7ecf6273",
"scope": "openid email profile"
}

Nội dung của refresh token nếu mình decode nó sử dụng https://jwt.io/ cơ bản như sau:

Các bạn để ý đến claim “typ” trong nội dung của refresh token trên nhé! Ở đây giá trị của claim này là Refresh, chúng ta còn có một số type khác của refresh token nữa, chẳng hạn như Offline,…

Refresh token sẽ luôn được trả về cùng với access token, giúp chúng ta có thể lấy access token mới mà không cần user phải đăng nhập trở lại.

Để lấy access token mới với refresh token thì trong request để lấy access token, các bạn chỉ cần truyền grant_type=refresh_token, giá trị của refresh token mà chúng ta có trong request lấy access token trước, client ID và client secret.

Với ví dụ này của mình, các bạn có thể lấy access token mới bằng cách request như sau:

Như các bạn thấy, với Refresh Token grant type, chúng ta không cần user phải đăng nhập nữa.

Một refresh token sẽ luôn có expiration time, mặc định của Keycloak là 30 phút các bạn nhé! Mỗi khi một access token mới được issue thì refresh token sẽ được issue lại, và các bạn có thể sử dụng cái mới nhất để expiration time được lâu hơn.

Chúng ta có thể sử dụng một refresh token để request access token nhiều lần. Tuy nhiên, các bạn có thể giới hạn số lần mà một refresh token có thể được sử dụng, bằng cách vào tab Tokens của Realm Settings, cấu hình field Revoke Refresh Token. Nếu các bạn turn on field này, thì có thể cấu hình số lần một refresh token được sử dụng lại:

Mặc định các bạn chỉ có thể sử dụng refresh token một lần thôi các bạn nhé!

Bài viết gốc được đăng tải tại huongdanjava.com

Có thể bạn quan tâm:

3D Artist Là Gì? Các Mức Lương Hấp Dẫn Trong Nghề 3D Artist

nghề 3d artist
3D Artist là gì? Các mức lương hấp dẫn trong nghề 3D Artist

Nghề 3D Artist cũng được xem là họ hàng chung của “Art” trong giới mỹ thuật nhưng khác với “Art”, người nghệ sĩ có thể diễn đạt, trình bày những tác phẩm của họ ở bất cứ đâu thì “3D Artist” chỉ có thể được những người nghệ sĩ thể hiện trên các hình ảnh máy tính, được tạo nên nhờ những công cụ phần mềm hỗ trợ. Có thể nói những tác phẩm của một dân trong “Nghề 3D Artist” được tạo nên từ những dòng thuật toán trên nền tảng dữ liệu.

nghề 3d artist

 Nghề 3D Artist là gì?

3D Artist là một nhà thiết kế đồ họa chuyên biệt, họ là những người thông thạo công nghệ máy tính và phần mềm thiết kế mới nhất. Với một 3D Artist, trách nhiệm và nghĩa vụ của bạn bao gồm thiết kế và tạo hoạt ảnh 3D cho các ngành khác nhau bao gồm ứng dụng di động, y học, khoa học, trò chơi điện tử và tiếp thị. 

Một 3D Artist sử dụng năng khiếu nghệ thuật và sự sáng tạo cùng với chuyên môn kỹ thuật của mình để đáp ứng nhu cầu của mọi khách hàng dù cho nó có thật sự oái oăm đến mức nào. Có cả một nền tảng nghệ thuật về nhiếp ảnh hoặc vẽ cũng như các kỹ năng máy tính đặc biệt có thể rất hữu ích trong sự nghiệp này.

Các công cụ hỗ trợ cho dân 3D Artist

 Để dân 3D Artist tạo ra được những tác phẩm thì họ cần có những công cụ hỗ trợ, nên ở đây chúng ta sẽ nói đến Blender Blugin. Blender là một trong các công cụ phổ biến trong Ngành 3D Artist.

Blender Plugin là gì?

Blender được biết là một công cụ phần mềm 3D được sử dụng rất phổ biến, rộng rãi vì rất nhiều tính năng hữu ích với tính chất hỗ trợ mã nguồn miễn phí. Có một điều đặc biệt là phần mềm Blender ngày càng có thêm nhiều Plugin được hỗ trợ có thể tích hợp với nó.

Trong bài viết này, sẽ được nói đến các Plugin Blender có tầm quan trọng và hữu ích có thể giúp một dân 3D Artist tạo ra được nhiều tác phẩm đắt giá hơn. Trong đó, ngoại trừ các Plugin buộc người dùng phải trả phí thì Blender cùng có hỗ trợ một số các Plugin miễn phí giúp dân 3D Artist mới vào nghề hay điều kiện kinh tế chưa ổn có thể trãi nghiệm và sử dụng. 

Các Blender Plugin dành cho dân 3D Artist

Dưới đây, sẽ là 10 loại Plugin hữu ích, phổ biến hàng đầu được sử dụng trong Blender:

  1. Amaranth
  2. RetopFlow
  3. TexTools
  4. Speed ​​Sculpt 
  5. Edge Flow
  6. BoxCutter
  7. HardOps
  8. Boolean
  9. MESHmachine
  10. Gaffer
  11. Blam

3d artist

Một số mức lương của dân trong nghề 3D Artist hiện nay

Trong giới 3D Artist mức lương sẽ tuỳ thuộc vào từng yếu tố như độ tuổi, vị trí như Animation Director, Producer, Graphic Designer,…  , và dưới đây sẽ là những mức lương trung bình hằng tháng được khảo sát chung trên thế giới để một dân 3D Artist mới dấn thân vào hoặc đã đi làm tham khảo. Dưới đây là một số ngành nghề tiêu biểu của nghề 3D Artist tại thị trường Việt Nam.

Thu nhập của một 3D Artist vị trí Animation Director (đạo diễn hình ảnh)

Đạo diễn hoạt hình làm việc trong nhiều lĩnh vực bao gồm: xưởng phim, xưởng sản xuất truyền hình, công ty game và công ty quảng cáo… Mức lương hàng năm của đạo diễn hình ảnh rơi vào khoảng 71,350 USD. Trong khi đó, 10% nhà quay phim kiếm được dưới 32.080 USD/năm và 10% khác kiếm được hơn 187.200 USD  vào năm. Các đạo diễn độc lập cũng có thu nhập cao nhất trong ngành giải trí, với New York là 112.060 USD/năm.

Xem thêm các công việc tuyển dụng 3D Artist lương cao trên TopDev

Thu nhập của một 3D Artist vị trí Producer (nhà sản xuất)

Hầu hết những người trong nghề, cụ thể là một dân 3D Artist đều cho rằng công việc của một giám đốc sản xuất là không thể thiếu trong bất kỳ nhà máy, công ty nào. Giám đốc sản xuất trực tiếp tham gia vào việc lập kế hoạch, kiểm soát và giám sát quá trình sản xuất để đảm bảo giao  sản phẩm kịp thời, đúng yêu cầu về số lượng theo tiêu chuẩn chất lượng đề ra trong kế hoạch. Mức lương quản lý sản xuất nhìn chung dao động từ 615.38 USD đến 879.11 USD/tháng, tùy thuộc vào kỹ năng, kinh nghiệm của ứng viên và quy mô công ty.

Thu nhập của một 3D Artist vị trí Graphic Designer (Thiết kế đồ hoạ)

Thiết kế đồ họa là một trong những ngành nghề không ngừng phát triển, đặc biệt là trong thời đại công nghệ 4.0 hiện nay. Điều này  kéo theo hu cầu nhân lực của nghề 3D Artist không ngừng tăng lên.Nhân viên thiết kế đồ họa là những chuyên gia dùng các phần mềm thiết kế đồ họa để trực quan hóa ý tưởng từ văn bản, nội dung thành hình ảnh, logo, catalogue tạp chí, quảng cáo, … Mức lương trung bình của một nhà thiết kế đồ họa tại Việt Nam dao động vào khoảng từ 351.64 USD đến 879.11 USD// tháng.  Ngoài ra, mức lương thiết kế đồ họa phụ thuộc vào số năm kinh nghiệm.

Ngoài câc vị trí công việc trên thì nghề 3D Artist vẫn còn những vị trí công việc khác như Series Director (đạo diễn series phim), Storyboarder (họa sĩ vẽ storyboard),  Art Director (giám đốc nghệ thuật),…

Những nội dung trên chỉ mới là một phần của cả một giới 3D Artist, là một dân 3D Artist sẽ cần phải biết và tìm tòi thêm rất nhiều thứ. Một 3D Artist cần phải trãi qua quá trình học tập từng bước, từng chi tiết để trãi nghiệm những gì đã học liên quan trong nghề 3D Artist. 

Intern: Trương Thị Hồng Anh

Có thể bạn quan tâm:

Xem thêm Việc làm CNTT hấp dẫn trên TopDev

Format (Làm đẹp) code php trong VS Code

format code php

Bài viết được sự cho phép của tác giả Phạm Bình

Chào các bạn,

Đây là bài viết tiếp theo của bài Code PHP chuẩn convention với PHP CodeSniffer. Trong bài này, mình sẽ hướng dẫn các bạn auto check lỗi và format code PHP trong Vs Code – một trong những code editor được yêu thích nhất hiện nay.

Lưu ý, để hiểu bài viết này hơn, thì bạn cần đảm bảo các yêu cầu sau:

  • Máy tính đã cài composer ở dạng global.
  • Máy tính đã cài PHP CodeSniffer ở dạng global.
  • Bạn hiểu ý nghĩa của 2 công cụ phpcs và phpcbf.
  • Bạn hiểu ý nghĩa của file cấu hình phpcs.xml trong dự án.

Nếu không, hãy đọc phần trước của bài viết này, tại đó mình có cung cấp các nội dung hữu ích về các yêu cầu trên.

  10 Frameworks tốt nhất hiện nay cho PHP
  4 lý do để VS Code là Text Editor ưa thích của mọi lập trình viên

I. GIỚI THIỆU VỀ TÍNH NĂNG FORMAT CODE TRONG VS CODE

Giống như nhiều editor khác, VS Code có tính năng tự động format code của bạn cho chuẩn hơn.

Hình ảnh mượn tạm từ một nguồn khác phambinh.net 

Phím tắt để format code trên VS Code tương ứng với từng hệ điều hành như sau:

  1. Trên Windows: Shift + Alt + F.
  2. Trên Mac: Shift + Option + F.
  3. Trên Linux: Ctrl + Shift + I.

Tuy nhiên, mặc định thì VS Code không tích hợp sẵn việc format code PHP, mà chúng ta phải cài thêm từ extension bên ngoài, và mình sẽ hướng dẫn các bạn cài ở ngay mục phía dưới đây.

II. FORMAT CODE PHP TRONG VS CODE VỚI PHP SNIFFER & BEAUTIFIER

Mình đã dùng thử khá nhiều extension format code PHP, thì thấy có thằng PHP Sniffer & Beautifier này là dễ dùng và dễ tùy biến nhất. Để cài đặt extension này, các bạn vào mục Extensions của VS Code, tìm kiếm với từ khóa là “Sniffer & Beautifier” sẽ ra.

Cách tìm và cài đặt extension trong VS Code

Chúng ta tiến hành cài đặt bình thường như các extension khác, và sau khi cài đặt xong, thì hãy đi đến phần cài đặt riêng của extension này như hình dưới.

Đi đến trang cài đặt riêng cho extension

Tại trang cài đặt riêng của extension Sniffer & Beautifier, có 3 thông tin setting quan trọng là Allowed Auto RulesetsExecutable Path CBF và Executable Path CS. Mình sẽ hướng dẫn các bạn các cấu hình các thông tin này sao cho phù hợp ngay sau đây.

Các setting quan trọng

2.1 Cấu hình thông tin Allowed Auto Rulesets

Tại mục (1) như trong hình, hãy bấm vào Edit in settings.json, và đảm bảo ở phpsab.allowedAutoRulesets được cấu hình như sau:

Để dễ copy, thì mình viết các value ra đây nhé:

1
2
3
4
5
6
7
8
9
10
11
12
{
    // ...
    "phpsab.allowedAutoRulesets": [
        ".phpcs.xml",
        ".phpcs.xml.dist",
        "phpcs.xml",
        "phpcs.xml.dist",   
        "phpcs.ruleset.xml",
        "ruleset.xml"
    ],
    // ...
}

2.2 Cấu hình 2 thông tin Executable Path CBF và Executable Path CS

Tại mục (2) như trong hình, chúng ta cần điền đường dẫn tới 2 công cụ là phpcbf và phpcs. Mình sẽ hướng dẫn các bạn cách lấy thông qua mấy bước đơn giản dưới đây.

Chạy lệnh sau để lấy ra đường dẫn tới thư mục home của composer:

composer config --list --global | grep "home"

Kết quả sẽ có dạng như sau, và phần bôi đậm chính là đường dẫn bạn cần quan tâm.

Lưu ý: mỗi máy sẽ cho ra một kết quả khác nhau, và bên dưới là kết quả trên máy của mình

[home] /Users/admin/.composer

Sau khi có đường dẫn home, thì đường dẫn tới phpcs và phpcbf sẽ có dạng như sau:

# Đường dẫn tới phpcbf
/Users/admin/.composer/vendor/bin/phpcbf

# Đường dẫn tới phpcs
/Users/admin/.composer/vendor/bin/phpcs

Vậy là chúng ta đã có đường dẫn tới phpcbf và phpcs, giờ chỉ cần điền chúng lần lượt mục Executable Path CBF và Executable Path CS trong trang cài đặt của extension Sniffer & Beautifier là xong.

Xem thêm các việc làm PHP lương cao trên TopDev

III. Dùng thử

Khởi tạo một dự án mới với 1 file phpcs.xml ở thư mục gốc, có rules theo PSR12 như sau:

1
2
3
4
<?xml version="1.0"?>
<ruleset name="PHP Standards">
    <rule ref="PSR12" />
</ruleset>

Tạo tiếp 1 file PHP có sẵn một vài lỗi convention:

1
2
3
4
5
6
7
8
9
<?php
// File này cố tình code sai convention
 
function sum ($a ,$b){
    return $a+$b;
}
 
echo sum(1,2);

Bật dự án lên bằng VS Code, và bạn sẽ thấy nó báo rất nhiều lỗi convention như sau:

Rất nhiều lõi convention được phát hiện

Và để fix hết các lỗi này, bạn chỉ cần Nhấn chuột phải chọn Format document, hoặc sử dụng tổ hợp phím format code như mình hướng dẫn ở đầu bài. Và dưới đây là kết quả sau khi format lại code, bạn sẽ thấy các lỗi convention trên đã được fix.

Các lỗi convention đã được fix.

Công việc tích hợp Sniffer & Beautifier vào VS Code để format code PHP đến đây là kết thúc, chúc các bạn thử nghiệm thành công.

Hẹn gặp lại bạn trong các bài viết tiếp theo.

Bài viết gốc được đăng tải tại phambinh.net

Có thể bạn quan tâm:

Truy cập ngay việc làm IT đãi ngộ tốt trên TopDev

Kinh Nghiệm Phỏng Vấn Dành Cho Các IT Support Tương Lai

kinh nghiệm phỏng vấn it support
Kinh Nghiệm Phỏng Vấn Dành Cho Các IT Support Tương Lai

IT Support là một công việc hấp dẫn trên thị trường việc làm công nghệ hiện nay. Nhiều bạn trẻ lựa chọn theo đuổi vị trí này với mong muốn được gắn bó và phát triển trong một môi trường làm việc tốt hơn, thu nhập và cơ hội nghề nghiệp cũng hấp dẫn hơn. Nếu đang cân nhắc đến công việc này, việc tìm hiểu qua những câu hỏi phỏng vấn thường xuất hiện hay một số kinh nghiệm phỏng vấn IT Support từ người đi trước là rất cần thiết. Trau dồi thêm kỹ năng với bài viết này nhé!

kinh nghiệm phỏng vấn it support
Colleagues on coffee break. Side view of cheerful young man and woman sitting at the table and chatting while man holding cup of hot drink

Một số câu hỏi thường xuyên xuất hiện khi phỏng vấn IT Support

1. Điểm mạnh, điểm yếu trong quá trình làm việc của bạn là gì?

Đây là câu hỏi gần như luôn xuất hiện ở bất cứ buổi phỏng vấn cho vị trí công việc nào. Đối với công việc IT Support đây càng là yếu tố quan trọng vì bạn phải thường xuyên tiếp xúc với khách hàng cũng như đàm phán công việc với các phòng ban liên quan.

Để trả lời tốt câu hỏi này với vai trò là một IT Support tương lai, điểm mạnh bạn nên nêu ra có thể là khả năng xử lý vấn đề, nhanh nhạy trong việc nắm bắt các sai sót và tìm cách khắc phục, linh hoạt cũng như có kỹ năng giao tiếp tốt.

Điểm yếu bạn có thể chia sẻ thành thật với nhà tuyển dụng và chắc chắn phải nói được cách mà bạn đang cố gắng để khắc phục điều này. Không có ai hoàn hảo, do đó yếu điểm chắc chắn sẽ xuất hiện, quan trọng là cách bạn khắc phục và cải thiện nó như thế nào. Nhà tuyển dụng sẽ đánh giá cao điều đó.

Xem thêm IT Support Là Làm Gì? Phát Triển Sự Nghiệp Với Vị Trí IT Support

2. Bạn đã có kinh nghiệm làm việc liên quan đến công việc IT Support chưa?

Với câu hỏi này, nhà tuyển dụng sẽ biết được bạn đã có kinh nghiệm làm việc trước đây chưa cũng như những kỹ năng mà bạn có có đáp ứng được yêu cầu của công ty với vị trí này không. Vẫn là điều quan trọng nhất trong mọi cuộc phỏng vấn, hãy thành thật. Kể cả bạn chưa có kinh nghiệm hay kinh nghiệm chưa đủ nhiều thì cũng hãy chia sẻ thành thật.

Điều quan trọng là tâm thế sẵn sàng học hỏi của bạn sẽ giúp nhà tuyển dụng đánh giá cao thái độ và có hướng đào tạo phù hợp thay vì nói quá đà về những gì mình có. Nhà tuyển dụng là những người đi trước và họ đủ năng lực để nhận biết những gì bạn nói có trung thực khi trả lời phỏng vấn hay không.

kinh nghiệm làm IT Support
Một số câu hỏi phỏng vấn vị trí IT Support

3. Theo bạn, đâu là yếu tố giúp bạn thành công với chuyên môn hiện tại của mình?

Đây là một câu hỏi rất hay để nhà tuyển dụng có thể xác định được mục tiêu và khoảng thời gian gắn bó của bạn với công việc của mình. Không có một khuôn mẫu chung hoàn hảo nào cho những câu hỏi như thế này, bạn hãy chia sẻ về hành trình theo đuổi đam mê của mình hay lí do tại sao bạn lại chọn gắn bó với công việc IT Support cho đến thời điểm hiện tại.

Song song với quá trình đó, bạn đừng quên chia sẻ những thành tựu mình đã đạt được trong suốt thời gian làm việc của mình. Và nhấn mạnh đâu là yếu tố giúp bạn có được những thành tựu đó, cũng như trong thời gian tới bạn sẽ làm những gì để đạt được những mục tiêu cao hơn. Điều đó không chỉ cho thấy ước mơ mà còn thể hiện cả sự nhiệt huyết của bạn với công việc của mình.

  IT Support Là Làm Gì? Phát Triển Sự Nghiệp Với Vị Trí IT Support
  Mẫu bảng mô tả công việc của IT Support

4. Bạn hiểu biết như thế nào về công việc IT Support và tại sao bạn lại chọn ngành nghề này?

Dường như khi đã ứng tuyển vào vị trí IT Support, ít nhiều ứng viên đều đã tìm hiểu trước và có sự hiểu biết nhất định với ngành mình mong muốn làm việc. Do đó đây có thể là câu hỏi khiến nhiều người cảm thấy đơn giản và không chuẩn bị nhiều, nhưng sự chuẩn bị chưa bao giờ là dư thừa. Hiểu biết càng nhiều càng cho nhà tuyển dụng thấy được sự nghiêm túc và tâm huyết của bạn trong công việc. Không chỉ là IT Support nói chung mà nếu có thể, hãy tìm hiểu thêm về vị trí này tại công ty đang ứng tuyển, nhà tuyển dụng sẽ đánh giá rất cao điều này.

Với câu hỏi về lý do tại sao bạn lại chọn ngành nghề này, bạn có thể dùng đam mê và những tính cách thích hợp của mình với công việc để chia sẻ với người phỏng vấn. IT Support đòi hỏi khả năng xử lý công việc và giải quyết các vấn đề một cách trôi chảy để đảm bảo sự vận hành trôi chảy của công ty. Bạn phải tham gia xử lý các vấn đề liên quan đến internet, mạng máy tính, phần mềm, phần cứng, các vấn đề về bảo mật thông tin,…

phỏng vấn IT Support

Các kinh nghiệm phỏng vấn IT Support nên cân nhắc

Để chuẩn bị cho một cuộc phỏng vấn thành công nhất, ngoài các vấn đề liên quan đến chuyên môn công việc của mình, bạn cũng đừng quên tìm hiểu thêm các thông tin về công ty như hoạt động, sản phẩm và phòng ban mình làm việc nếu có thể. Việc này sẽ rất hữu ích cho quá trình trả lời các câu hỏi của nhà tuyển dụng cũng như giải đáp được các thắc mắc của bạn khi cần.

Xem thêm các chương trình tuyển dụng IT Support lương cao trên TopDev

Ngoài ra cũng đừng quên chuẩn bị kỹ lưỡng cho vẻ ngoài của mình để tạo ấn tượng tốt trong mắt nhà tuyển dụng. Không cần quá cầu kỳ, chỉ cần đảm bảo một bộ trang phục sạch sẽ mà vẻ ngoài gọn gàng là đủ. Và đừng quên đến đúng giờ hẹn và chuẩn bị đủ các giấy tờ cần thiết theo yêu cầu công ty khi đi phỏng vấn.

Như bất cứ vị trí nào khác, để phỏng vấn thành công cho vị trí IT Support, hãy có sự đầu tư chất lượng và kỹ càng. Hi vọng một số thông tin được chia sẻ trong bài viết sẽ giúp bạn có thêm kinh nghiệm phỏng vấn IT Support. Đón đọc thêm nhiều chia sẻ với các chủ đề khác nhau cùng topdev.vn/blog nhé!

Có thể bạn quan tâm:

Xem thêm tuyển dụng việc làm IT hấp dẫn trên TopDev

PHP 8 có gì mới?

điểm mới của php 8
PHP 8 có gì mới?

Bài viết được sự cho phép của tác giả Phạm Bình

Chào anh em,

PHP đã chính thức phát hành phiên bản 8.0 (26/11/2020), với nhiều cải tiến mới cả về hiệu năng lẫn cũ pháp. Trong bài viết này, chúng ta cùng review các điểm thay đổi có trong PHP 8 nhé.

Trích lời dẫn trên trang chủ PHP.net

PHP 8.0 là một phiên bản cập nhật lớn của PHP. Phiên bản này bao gồm rất nhiều tính năng mới, đồng thời tối ưu cách truyền tham số (có thể đặt tên khi truyền tham số), union types (một biến có thể thuộc một vài kiểu dữ liệu), attributes, constructor, biểu thức match (cú pháp mới, gần giống switch case), toán tử nullsafe (cho phép truy xuất giá trị null một cách an toàn), JIT (trình biên dịch mới, giúp PHP 8 đạt hiệu năng cao), và cải tiến các về type system, xử lý lỗi, và tính nhất quán.

Chúng ta sẽ tìm hiểu lần lượt về các sự thay đổi của PHP 8 so với phiên bản trước lần lượt qua các mục dưới đây.

  Cách thiết lập JIT trong PHP 8
  Callback trong PHP là gì?

Xem thêm nhiều việc làm PHP hấp dẫn trên TopDev

I. TRUYỀN THAM SỐ THEO TÊN GỌI – PHP 8

Việc một function có nhiều tham số (với mình là từ 3 tham số trở nên), có thể khiến developer lúng túng khi sử dụng vì không nhớ rõ ý nghĩa của từng tham số, cũng như thứ tự truyền của chúng.

Ví dụ, function mkdir() (function giúp tạo thư mục) trong PHP có 4 tham số lần lượt là:

  • $directory: Bắt buộc, là đường dẫn để tạo thư mục
  • $permissions: Không bắt buộc, là khả năng truy cập vào thư mục (kiểu 0777, hay 0655), mặc định là 0777.
  • $recursive: Không bắt buộc, có cho phép tạo thư mục con ngay cả khi thư mục cha không tồn tại (cho phép tạo kiểu đệ quy), mặc định là false.
  • $context: Không bắt buộc, còn ý nghĩa là gì thì mình cũng chẳng hiểu lắm, chưa bao giờ dùng đến tham số này.

Các vấn đề mà một developer có thể gặp phải khi sử dụng mkdir() đó là:

  • Đôi khi không nhớ rõ thứ tự của 2 tham số $permissions và $recursive, không biết tham số nào được viết trước.
  • Nếu muốn đổi giá trị của tham số $recursive từ false thành true, developer buộc phải truyền cả tham số $permissions (vì $permissions đứng trước $recursive).

Cả hai vấn đề trên đều gây bất tiện khi sử dụng, để khắc phục nó, thì PHP cung cấp cú pháp mới cho phép truyền tham số theo tên gọi:

<?php // PHP 7.x mkdir('./hello/world', 0777, true); // PHP 8 mkdir(recursive: true, directory: './hello/world'); // Hoặc mkdir('./hello/world', recursive: true);

Lưu ý:
– Đây chỉ là cú pháp mới mà PHP 8 cung cấp để tiện sử dụng hơn khi cần, còn bạn vẫn có thể sử dụng cú pháp cũ bình thường trên phiên bản PHP 8 này.

– Tên tham số bạn không được phép “tự nghĩ ra” mà phải tuân theo tài liệu của PHP. Như trong ví dụ trên, recursive và directory là 2 tham số mà mình buộc phải tuân theo tài liệu mà PHP cung cấp.

Để xem “tên chuẩn” các tham số, có 2 cách:

Cách 1: Xem tài liệu chính thức trên trang chủ php.net (lưu ý phải xem trên trang chính thức, các trang khác có thể viết không đúng).

Cách 2: Sử dụng ReflectionFunction.

<?php // Muốn xem chi tiết các tham số của function mkdir $refFunc = new ReflectionFunction('mkdir'); foreach ($refFunc->getParameters() as $param) {     print $param . PHP_EOL; } /* Output Parameter #0 [ <required> string $directory ] Parameter #1 [ <optional> int $permissions = 0777 ] Parameter #2 [ <optional> bool $recursive = false ] Parameter #3 [ <optional> $context = null ] */

Lưu ý siêu quan trọng

Khuyên bạn nên sử dụng Cách 2 là chính xác nhất, Cách 1 không hẳn sẽ chính xác với mọi function. Như function mkdir trong ví dụ trên, thì tài liệu PHP viết sai 2 tên tham số là pathname và mode, đáng lẽ nó phải là directory và permissions mới đúng.

Tài liệu PHP ghi sai tên tham số, đáng lẽ phải là directory và permissions mới đúng.

II. TỐI GIẢN CÁCH SET THUỘC TÍNH TỪ CONTRUCTOR – PHP 8

Việc khởi tạo giá trị cho thuộc tính trong contructor của PHP 7 thường được viết như sau:

<?php // PHP 7 class Point {   public float $x;   public float $y;   public float $z;   public function __construct(     float $x = 0.0,     float $y = 0.0,     float $z = 0.0,   ) {     $this->x = $x;     $this->y = $y;     $this->z = $z;   } }

Nhưng với PHP 8, bạn có thể viết ngắn gọn thành

<?php // PHP 8 class Point {   public function __construct(     public float $x = 0.0,     public float $y = 0.0,     public float $z = 0.0,   ) {} }

III. UNION TYPES – PHP 8

PHP ngày càng hoàn thiện hơn về độ chặt chẽ của dữ liệu, trong phiên bản PHP 7.4, chúng ta có thể khai báo kiểu dữ liệu cho thuộc tính của lớp, tuy nhiên nó vẫn gặp một vài bất tiện. Nhưng bất tiện này đã khắc phục trong phiên bản 8 với khái niệm Union types – Cho phép một thuộc tính có thể thuộc nhiều kiểu dữ liệu.

<?php // PHP 7 class Number {     // Giả sử có một biến $numeber, và ta mong muốn nó ở dạng số     // Số thì có nhiều kiểu, số nguyên, số thập phân.     private $number;     // Nhưng hơi buồn     // Chúng ta không thể chỉ ra biến $number chỉ được phép thuộc dạng số với PHP 7     public function __construct($number)     {         $this->number = $number;     } } // Dẫn đến việc khởi tạo class, ta vẫn có thể truyền string như thường // Và không gặp một lỗi nào cả new Number('NaN'); // PHP 8 class Number {     // PHP 8 cho phép bạn khai báo biến $number chỉ được phép thuộc một trong 2 kiểu dữ liệu int hoặc float     // Khắc phục vấn đề của PHP 7 nêu trên     public function __construct(         private int|float $number     ) {} } // Nếu dùng thế này, bạn sẽ gặp lỗi new Number('NaN');

IV. NULLSAFE OPERATOR – PHP 8

Nullsafe operator – tạm dịch là Toán tử null an toàn. Cho phép bạn truy cập vào giá trị của một thuộc tính ở giá trị null mà không bị lỗi.

Ở các phiên bản PHP trước, để chắc chắn trước khi truy cập vào một giá trị, ta thường kiểm tra nó khác null để tránh lỗi, và nhìn nó có vẻ dài dòng như sau:

<?php $country =  null; if ($session !== null) {   $user = $session->user;   if ($user !== null) {     $address = $user->getAddress();     if ($address !== null) {       $country = $address->country;     }   } }

Nhưng với PHP 8, bạn có thể rút gọn thành:

<?php $country = $session?->user?->getAddress()?->country;

Khi bất kỳ thuộc tính nào trong “chuỗi” $session?->user?->getAddress()?->country là null, thì $country sẽ nhận giá trị là null và không có lỗi nào xảy ra.

V. BIỂU THỨC MATCH – PHP 8

Một biểu thức mới khá tương đồng với lệnh switch case được đưa vào trong phiên bản PHP 8 lần này là match, nhưng có một số điểm khác biệt sau:

  • match là một biểu thức, nghĩa là giá trị của nó có thể được trả về, bạn có thể dễ dàng lưu nó vào một biến để xử lý cho tiện.
  • Mỗi một nhánh của match chỉ được xử lý trên một dòng, nghĩa là bạn không cần break
  • match so sánh chặt chẽ về kiểu dữ liệu, giống như bạn so sánh sử dụng === vậy.

Bạn có thể xem ví dụ sau để hiểu rõ hơn:

<?php // PHP 7 switch (8.0) {   case '8.0':     $result = "Oh no!";     break;   case 8.0:     $result = "This is what I expected";     break; } echo $result; // Oh no! // PHP 8 $result = match (8.0) {   '8.0' => "Oh no!",   8.0 => "This is what I expected", }; echo $result; // This is what I expected

Lưu ýmatch khá tương đồng với switch case, nhưng không thể thay thế hẳn switch case.

VI. TRÌNH BIÊN DỊCH JIT – PHP 8

Hiểu nhanh thì JIT (Just In Time) là một kỹ thuật được PHP tích hợp vào việc biên dịch code PHP thành mã máy, giúp PHP 8 đạt được hiệu năng cao gấp 1,5 – 2 lần so với PHP 7. Nhưng đừng vội mừng, hãy xem biểu đồ dưới đây và mình sẽ giải thích cho bạn hiểu:

Biểu đồ so sánh tốc độ của PHP khi có JIT và không có JIT.

Trong biểu đồ trên:

  • bench.php, micro_bech.php, N-body, Mandelbrot đều là các bài test trên ứng dụng PHP đơn giản.
  • Các bài test còn lại, lần lượt test trên các ứng dụng PHP có độ phức tạp tăng dần.
  • Đường màu đen, kẻ dọc ở biểu đồ trên là ngưỡng tối đa khi PHP không sử dụng JIT.

Từ biểu đồ trên, rút ra nhận xét rằng:

Chỉ có ứng dụng PHP đơn giản khi áp dụng JIT mới có hiệu năng cao, còn các ứng dụng PHP phức tạp, sử dụng các framework, cms phổ biến như WordPress, Symfony (Chắc laravel cũng không ngoại lệ) thì sử dụng JIT lại không đem lại nhiều lợi ích. Thậm chí như trường hợp của Symfony khi áp dụng JIT còn làm ứng dụng chạy chậm hơn so với lúc không áp dụng.

Để nói hết về JIT thì bài viết này là chưa đủ, mình sẽ trình bày chi tiết ở một bài viết khác về cách cài đặt, ưu nhược điểm, cũng như phân tích nên dùng JIT trong dự án thực tế hay không.

VII. MỘT SỐ CẬP NHẬT KHÁC TRÊN PHP 8

Một số cập nhật điển hình khác trên PHP 8 như sau:

  • Thay vì sử dụng PHPDoc để chú thích, PHP 8 đã cung cấp thêm cấu trúc metadata.
<?php // PHP 7 class PostsController {     /**      * @Route("/api/posts/{id}", methods={"GET"})      */     public function get($id) { /* ... */ } } // PHP 8 class PostsController {     #[Route("/api/posts/{id}", methods: ["GET"])]     public function get($id) { /* ... */ } }
  • Toán tử @ vốn để “câm lặng lỗi” không còn được sử dụng ở PHP 8.
<?php // Khi thêm @ phía trước, nếu function có thực hiện lỗi cũng sẽ không báo lỗi // Nhưng đó đã là quá khứ rồi. // Ở PHP 8 vẫn báo lỗi bình thường @unlink('hello/world');
  • Cụm try {} catch () {} có thể không cần biến $exception trong catch.
<?php // PHP 7 try {     1/0; } catch (\Exception) { // Sẽ báo lỗi cú pháp ở dòng này     die('Something wrong'); } // PHP 8 try {     1/0; } catch (\Exception) { // Chạy bình thường     die('Something wrong'); }
  • Cho phép dấu phẩy ở cuối danh sách tham số.
<?php // PHP 7 class Uri {     private function __construct(         ?string $scheme,         ?string $user,         ?string $pass,         ?string $host,         ?int $port,         string $path,         ?string $query,         ?string $fragment // <-- Tham số cuối cùng không được phép có dấu phẩy     ) {         ...     } } // PHP 8 class Uri {     private function __construct(         ?string $scheme,         ?string $user,         ?string $pass,         ?string $host,         ?int $port,         string $path,         ?string $query,         ?string $fragment, // <-- Được phép viết dấu phẩy ở tham số cuối cùng     ) {         ...     } }

VIII. TỔNG KẾT

Trên là những cập nhật điển hình nhất của PHP 8, và bài viết của mình đã nêu được khoảng 80% những gì PHP cập nhật trong phiên bản lần này. Nếu muốn tìm hiểu chi tiết, bạn có thể đọc từ tài liệu chính thức của PHP.

Xin chào, hẹn gặp lại.

Bài viết gốc được đăng tải tại phambinh.net

Có thể bạn quan tâm:

Truy cập ngay việc làm IT đãi ngộ tốt trên TopDev

Các khái niệm cơ bản trong Apache Kafka

apache kafka
Các khái niệm cơ bản trong Apache Kafka

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Để làm việc với Apache Kafka, các bạn cần nắm một số khái niệm cơ bản về:

  • Producer
  • Consumer
  • Broker
  • Cluster
  • Topic
  • Topic Partitions
  • Partition Offset
  • Consumer Group
  Apache Kafka là gì?
  Cài đặt Apache Kafka sử dụng Docker Compose

Xem thêm tuyển dụng UI UX Designer hấp dẫn trên TopDev

Producer

Producer là những application produce data và gửi data tới Apache Kafka Server. Data này sẽ là những message có định dạng, được gửi dưới dạng mảng byte tới Apache Kafka server. Ví dụ như các bạn có một tập tin .txt chứa text bên trong, chúng ta có thể dùng Producer để đọc từng dòng trong tập tin này rồi gửi tới Apache Kafka server.

Consumer

Consumer là những application nhận message từ Apache Kafka server với message được gửi từ Publisher. Consumer cần phải subcribe vào một topic nào đó của Apache Kafka server để có thể nhận được tất cả các message được emit vào topic này.

Sau khi nhận được data, Consumer có thể thêm code để xử lý data theo nhu cầu của mình.

Broker

Broker là Apache Kafka server, là cầu nối giữa Message Publisher và Message Consumer, giúp chúng có thể trao đổi message với nhau.

Cluster

Cluster là một group các Brokers hay nói cách khác là group các Apache Kafka server.

Topic

Topic được định nghĩa trong Apache Kafka server, là nơi để Publisher send data và cũng là nơi để Consumer subscribe để nhận data từ Publisher. Sử dụng topic giúp Apache Kafka phân loại được message và Consumer cũng biết là mình lấy data từ đâu.

Topic Partitions

Apache Kafka là một distributed messaging system và chúng ta có thể setup Apache Kafka server với cluster. Trong trường hợp một topic nhận quá nhiều message tại cùng một thời điểm, chúng ta có thể chia topic này thành những partitions được share giữa các Apache Kafka server với nhau trong một cluster được handle các message này.

Một partition sẽ small và independent với các partitions khác. Số lượng partition cho mỗi topic thì tuỳ theo nhu cầu của ứng dụng mà chúng ta có thể quyết định.

Partition Offset

Trong một topic partition, các message sẽ được lưu trữ và đánh dấu theo từng offset. Mỗi khi một message mới vào topic, Apache Kafka server sẽ quyết định message này nằm trong partition nào, offset nào của partition đó. Giá trị của các offset sẽ tăng dần trong một partition và chỉ available cho một Apache Kafka server.

Để lấy được một message trong Apache Kafka server, chúng ta cần chỉ định rõ topic name, partition number và offset number.

Consumer Group

Consumer group là một group các Consumer consume message từ Apache Kafka server. Mỗi một Consumer Group sẽ share với nhau việc handle messsage.

Bài viết gốc được đăng tải tại huongdanjava.com

Có thể bạn quan tâm:

Xem thêm việc làm CNTT hấp dẫn trên TopDev

PHP Developer là gì? Lộ trình trở thành PHP Web

php developer
Lộ trình trở thành PHP web developer

Bài viết được sự cho phép của tác giả Phạm Bình

Hello các bạn,

Trong bài viết này mình sẽ chia sẻ với các bạn lộ trình để trở thành PHP web developer. Thực ra mình không rõ nên coi nội dung dưới đây là lộ trình, là kỹ năng, hay kiến thức nữa, nhưng đại loại nếu bạn muốn trở thành PHP web developer thì nội dung dưới đây sẽ có ích với bạn.

I. PHP WEB DEVELOPER LÀ GÌ

Tìm hiểu qua một chút về “cái đích” mà chúng ta sẽ hướng đến, thì PHP web developer là tên một nghề liên quan đến công việc lập trình web. Trong đó PHP là tên ngôn ngữ lập trình, web developer tạm dịch là “Người phát triển web”, vậy PHP web developer thì hiểu là “Người phát triển web sử dụng ngôn ngữ PHP” (Ngoài PHP thì còn nhiều ngôn ngữ khác cũng làm được web).

Ok, dễ hiểu đúng không. Nhưng thực ra, cái tên “PHP web developer” thì là cách gọi vắn tắt của “PHP/JavaSctipt/HTML/CSS/bla bla,… web developer“, nghĩa là để trở thành PHP web developer thì bạn cần phải học rất nhiều thứ, và PHP chỉ là một trong số chúng.

  10 PHP Instagram Scripts & Widgets tốt nhất
  Câu chuyện trước khi PHP có composer

Xem thêm tuyển dụng PHP lương cao trên TopDev

Giới thiệu thêm

Để tạo ra một trang web, bạn sẽ cần các kiến thức:
– Kiến thức về HTML/CSS/JavaScript: Dùng để tạo giao diện trang web.
– Kiến thức về ngôn ngữ lập trình: Dùng để xử lý các tính năng có trên trang web (hiểu nôm na là vậy), và PHP là một ngôn ngữ lập trình.
– Kiến thức về cơ sở dữ liệu: Là nơi lưu trữ dữ liệu cho trang web. PHP thường kết hợp MySQL – một loại cơ sở dữ liệu.
– Kiến thức về webserver: Là máy chủ để chạy web, Apache và Nginx là 2 loại web server phổ biến.

Bạn thấy không, có phải mỗi PHP đ*o đâu, cả mớ kiến thức đấy chứ. Mà đấy mới chỉ là “phần nổi của tảng băng” thôi đó, phần chìm mình sẽ liệt kê chi tiết trong bài viết, mà nói trước là mình cũng không thể liệt kê hết được vì nó quá nhiều.

II. QUY ƯỚC

Các kiến thức được chia thành 3 level: Hiểu, Biết sử dụng, Sử dụng thành thạo. Trong đó:

  • Hiểu: Đã từng tiếp xúc với kiến thức đó, hiểu ý nghĩa và vai trò, đã từng làm một số ví dụ đơn giản. Mức này rất dễ đạt được.

Tôi Hiểu PHP, vì tôi biết nó phù hợp với các dự án web, tôi cũng từng làm một dự án nhỏ về website tin tức sử dụng PHP để hiểu hơn về nó.

  • Biết sử dụng: Bao gồm Hiểu và đã từng áp dụng kiến thức đó trong một dự án cụ thể, dự án được áp dụng phải đủ lớn, đủ nghiêm túc, không phải là các pet project.
    Lưu ý: Một số từ khác trong bài viết như Biết thiết kếBiết tối ưuBiết vận dụngBiết làm cũng tương đồng với Biết sử dụng.

Tôi biết sử dụng PHP, vì tôi từng sử dụng nó trong một dự thực tế. Tuy đây chỉ là dự án cá nhân, nhưng tôi hoàn thiện nó với thái độ nghiêm túc, cố gắng hoàn thiện ở mức cao nhất có thể. Trong quá trình hoàn thành dự án, tôi vẫn học được thêm nhiều kiến thức mới.

  • Sử dụng thành thạo: Bao gồm Biết sử dụng và lặp đi lặp lại trong một vài dự án, trong quá trình lặp lại không (hoặc ít) học được thêm kinh nghiệm mới.

Tôi sử dụng thành thạo PHP, vì tôi từng tham gia vào nhiều dự án thực tế sử dụng PHP, trong quá trình đó, tôi không (hoặc ít) học được thêm kiến thức mới về PHP.

Nếu so với tháp Bloom trong bài viết Kinh nghiệm làm việc được tính như thế nào, thì:

  • Level Hiểu trong bài viết này tương ứng với level Hiểu của tháp Bloom.
  • Level Biết sử dụng tương ứng với level Vận dụng của tháp Bloom.
  • Level Sử dụng thành thạo tương ứng từ Level Phân tích trở lên của tháp Bloom.

III. LỘ TRÌNH

Lưu ý:
– Lộ trình dưới đây chưa được kiểm chứng, mà chỉ được đúc kết từ kinh nghiệm cá nhân của mình.
– Lộ trình dưới đây đã được mình tối ưu (không quá ngắn cũng không quá dài), đảm bảo phù hợp với nhu cầu tuyển dụng hiện tại.
– Lộ trình dưới đây sẽ được cập nhật thường xuyên.

Level 1: Nhập môn lập trình

Đây là kiến thức cơ bản nhất mà bất kỳ lập trình viên nào cũng phải biết, chứ không riêng web developer:

  • Biết sử dụng ít nhất một ngôn ngữ lập trình.
  • Biết sử dụng một số giải thuật cơ bản: sắp xếp nhanh (quick sort), sắp xếp nổi bọt, tìm kiếm nhị phân, tìm kiếm tuần tự.
  • Biết sử dụng một số cấu trúc dữ liệu cơ bản: stack, queue, linked list.
  • Biết sử dụng lập trình hướng đối tượng.
  • Hiểu một số quy trình phát triển phần mềm: quy trình thác nước, agile/scrum.

Level 2: Nhập môn lập trình web

Đây là các kiến thức mà bất kỳ web developer nào cũng phải biết:

  • Biết sử dụng HTML, CSS, JavaScript.
  • Biết sử dụng một số thư viện web cơ bản: jQuery, bootstrap.
  • Biết sử dụng PHP.
  • Biết sử dụng ít nhất một database quan hệ, gợi ý bạn nên học MySQL.
  • Biết thiết kế database quan hệ (chuẩn 3NF, phi chuẩn, index trong database).
  • Biết chuyển giao diện từ file thiết kế sang giao diện web (biết cắt html).
  • Biết sử dụng mô hình MVC trong lập trình web.
  • Biết sử dụng một số design pattern phổ biến: singleton, factory.
  • Hiểu về cách hoạt động của trang web: backend, frontend, client side, server side, request, response, header.
  • Sử dụng thành thạo coding convention trong PSR.
  • Biết sử dụng CLI.
  • Biết sử dụng một số tool trên CLI: npm, composer.
  • Biết sử dụng Restful API.
  • Hiểu về UI, UX.
  • Biết sử dụng GIT.
  • Biết sử dụng wordpress.
  • Biết sử dụng ít nhất một PHP framework, gợi ý bạn nên học Laravel.
  • Hiểu về một số lỗi bảo mật: xss, csrf, sql injection.
  • Hiểu về SEO.
  • Hiểu về SOLID.

Đang cập nhật thêm…

Level 3: Lập trình web chuyên sâu

Đạt tới “cảnh giới” này, bạn có thể lựa chọn 1 trong 3 hướng phát triển dưới đây:

2.1 Frontend developer

Frontend developer là những người làm về mặt giao diện, trải nghiệm, tương tác của trang web. Bất kể menu, màu chữ, font chữ, các modal bật lên, đóng lại,… tóm lại là những thứ mà người dùng có thể nhìn thấy đều được coi là frontend và đều là công việc của frontend developer.

  • Sử dụng thành thạo HTML, CSS và JS.
  • Sử dụng thành thạo ít nhất một frontend framework: reactjs, angular, vuejs.
  • Sử dụng thành thạo ít nhất một css preprocessor như scss, PostCSS.
  • Sử dụng thành thạo ít nhất một tool build frontend, gợi ý bạn nên chọn webpack.
  • Biết tối ưu SEO.
  • Biết thiết kế UI/UX.
  • Sử dụng thành thạo css BEM rules.

Đang cập nhật thêm…

Tìm việc làm Frontend ngay

2.2 Backend developer

Nếu frontend được thể hiện ngoài giao diện – cái mà người sử dụng có thể dễ dàng nhìn thấy và cảm nhận, thì backend lại là “trái tim” nằm phía sau, âm thầm xử lý các tác vụ mà người dùng thực hiện.

Frontend có thể dễ dàng vẽ lên một cái nút “Đăng nhập”, nhưng bấm vào cái nút đó là hàng loại các thao tác tìm kiếm, kiểm tra, xác minh được thực hiện phía backend.

  • Sử dụng thành thạo PHP
  • Sử dụng thành thạo ít nhất một database, gợi ý bạn nên học MySQL.
  • Sử dụng thành thạo ít nhất một framework, gợi ý bạn nên chọn Laravel.
  • Sử dụng thành thạo lập trình hướng đối tượng.
  • Biết sử dụng Linux.
  • Biết sử dụng ELK stack.
  • Biết sử dụng docker.

Đang cập nhật thêm…

Tìm việc làm Backend ngay

3.3 Full stack developer

Về cơ bản, Fullstack developer là người có thể làm được hết (hoặc phần lớn) các công việc của cả Frontend developer và Backend developer.

  • Experience with Back-end API development by using one of the following programming languages: JavaScript (NodeJS), Java, Ruby, PHP, Python, C#, Golang or Scala
  • Have strong knowledge in REST API
  • Experience with JavaScript or TypeScript with ReactJS, Angular, or Vue. Docker, NoSQL database, Relational database, Scrum/Agile development methodologies

Tìm việc làm Fullstack Developer lương cao

Bài viết gốc được đăng tải tại phambinh.net

Có thể bạn quan tâm:

Truy cập ngay việc làm IT đãi ngộ tốt trên TopDev

Code PHP chuẩn convention với PHP CodeSniffer

code php
Code PHP chuẩn convention với PHP CodeSniffer

Bài viết được sự cho phép của tác giả Phạm Bình

Chào các bạn,

Có lẽ không cần dài dòng, nếu chưa biết gì về coding convention thì mình đã có hẳn một bài viết xịn sò là Chuẩn coding convention trong PHP với PSR, bạn có thể tham khảo nếu thấy cần thiết. Còn trong bài viết này, mình sẽ hướng dẫn bạn cách sử dụng công cụ PHP CodeSniffer để kiểm tra convention tự động khi lập trình PHP.

  10 PHP Instagram Scripts & Widgets tốt nhất
  11 cách tăng tốc nhanh cho WordPress bằng file wp-conig.php

I. PHP CODESNIFFER LÀ GÌ?

Vài điểm Hightlight về PHP CodeSniffer như sau:

– PHP CodeSniffer gồm 2 công cụ chính là phpcs, và phpcbf. Trong đó phpcs là công cụ giúp bạn phát hiện lỗi coding convention, còn phpcbf là công cụ giúp bạn tự động tìm và sửa lỗi coding convention – đương nhiên là chỉ sửa được những gì mà nó có thể sửa.
– PHP CodeSniffer là một package PHP, có thể cài đặt bằng composer như nhiều package php bình thường khác, nó có thể cài đặt theo từng dự án, hoặc có thể cài global trên máy tính của developer.
– PHP CodeSniffer kiểm tra lỗi coding convention dựa trên các PSR, và nếu muốn bạn cũng có thể tự tắt/bật một số quy tắc của PSR để phù hợp với từng dự án, từng team phát triển.
– Bạn có thể dễ dàng tích hợp PHP CodeSniffer với các editor phổ biến như Sublime Text, VsCode,… trong bài viết này, mình cũng sẽ hướng dẫn các bạn các tích hợp với VsCode.

Tìm việc làm PHP đãi ngộ tốt trên TopDev

II. CÀI ĐẶT VÀ SỬ DỤNG PHP CODESNIFFER

2.1 Chuẩn bị

  • PHP 5.4 hoặc phiên bản cao hơn: PHP CodeSniffer được viết bằng PHP, nên máy của bạn chắc chắn cần được cài PHP. Kiểm tra phiên bản PHP bằng cách gõ php -v trên CLI của bạn.
  • Composer: Có nhiều cách để cài đặt PHP CodeSniffer, nhưng bạn nên cài thông qua Composer cho đơn giản, cũng như dễ dàng cập nhật PHP CodeSniffer khi có phiên bản mới. Mà mình nghĩ chẳng có php developer nào lại không có sẵn composer trên máy đâu. Kiểm tra composer đã có hay chưa bằng cách gõ composer trên CLI của bạn.

2.2 Cài đặt PHP CodeSniffer

Như mình đã trình bày, CodeSniffer có thể cài global hoặc cài theo từng dự án, trong bài viết này mình sẽ cài global luôn cho máu.

composer global require "squizlabs/php_codesniffer=*"

Sau khi cài xong, bạn cần tìm được thư mục home của composer, tùy vào từng hệ điều hành mà đường dẫn tới thư mục home sẽ khác nhau. Để tìm thư mục home, bạn chạy lệnh sau:

composer config --list --global | grep "home"

Kết quả sẽ dạng như sau:

[home] /Users/admin/.composer

Thì /Users/admin/.composer chính là thư mục home của composer.

Bước tiếp theo, cùng kiểm tra xem PHP CodeSniffer đã được cài đặt hay chưa, bằng cách chạy lệnh sau:

ls /Users/admin/.composer/vendor/bin

Nếu cài đặt thành công, thì sẽ có kết quả như sau:

phpcbf phpcs

2.3 Chạy thử PHP CodeSniffer

Đây là phần trọng tâm của bài viết, các bạn đọc cẩn thận và làm theo ví dụ nhé.

Tạo trước một file PHP và cố tình code sai convention, để thử xem thằng PHP CodeSniffer có nhận ra hay không.

cd ~ # di chuyển ra thư mục root
mkdir test_php_sniffer # tạo thư mục test_php_sniffer
cd test_php_sniffer # di chuyển vào thư mục vừa tạo
touch test.php # tạo file test.php

Copy nội dung sau bỏ vào file test.php

// File này cố tình code sai convention để thử độ tin cậy của PHP CodeSniffer

function sum ($a ,$b){
return $a+$b;
}

echo sum(1,2);

Chuẩn bị đã xong, giờ mình sẽ chạy lệnh sau để kiểm tra lỗi convention có trong file test.php trên.

cd test_php_sniffer # di chuyển vào thư mục chứa file test.php

/Users/admin/.composer/vendor/bin/phpcs test.php # chạy này

Chạy xong, trên terminal xuất hiện kết quả như sau:

FILE: /Users/admin/test_php_sniffer/test.php
--------------------------------------------------------------------------
FOUND 5 ERRORS AFFECTING 3 LINES
--------------------------------------------------------------------------
2 | ERROR | [ ] You must use "/**" style comments for a file comment
4 | ERROR | [ ] You must use "/**" style comments for a function comment
4 | ERROR | [x] Expected 0 spaces before opening parenthesis; 1 found
4 | ERROR | [x] Opening brace should be on a new line
8 | ERROR | [x] No space found after comma in argument list
--------------------------------------------------------------------------
PHPCBF CAN FIX THE 3 MARKED SNIFF VIOLATIONS AUTOMATICALLY
--------------------------------------------------------------------------

Time: 51ms; Memory: 4MB

Kết quả trên có 2 chỗ cần chú ý:

  • FOUND 5 ERRORS AFFECTING 3 LINES: Phát hiện được 5 lỗi trên 3 dòng.
  • PHPCBF CAN FIX THE 3 MARKED SNIFF VIOLATIONS AUTOMATICALLY: Nếu sử dụng phpcbf thì nó nó thể tự động fix được 3 lỗi.

Thử chạy nốt thằng phpcbf để xem nó tự động fix lỗi như thế nào nhé.

/Users/admin/.composer/vendor/bin/phpcbf test.php

Sau khi chạy xong lệnh trên, file test.php sẽ tự động được sửa lại, thành như sau:

Sau khi chạy phpcbf, nhưng vẫn còn tồn đọng một số lỗi convention

Đúng là code được sửa lại thật, nhưng có vẻ vẫn chưa đúng lắm, vẫn có 2 lỗi chưa fix được:

  • Dòng 4 vẫn bị sai convention ở dấu phẩy. Dấu phẩy phải nằm sát biến $a, và cách biến $b một dấu space mới đúng.
  • Dòng 6 vẫn bị sai convention ở dấu +. Phía trước và sau dấu + phải có một dấu space mới đúng.

– Ơ thế hóa ra thằng CodeSniffer này không được việc lắm nhỉ, có lỗi thì fix được có lỗi thì không?

– Không phải đâu nhé, là do mình chưa chỉ rõ chuẩn PSR cho nó thôi. Phần sau đây mình sẽ trình bày luôn.

Bạn tạo tiếp file tên là phpcs.xml ngang hàng với file test.php trên, có nội dung như sau:

<?xml version="1.0"?> <ruleset name="PHP Standards">
   <rule ref="PSR12" /> </ruleset>

Sau đó chạy lại lệnh phpcbf để fix lỗi:

/Users/admin/.composer/vendor/bin/phpcbf test.php

Sau đó cùng xem lại file test.php để xem nó được fix lỗi như thế nào.

Tất cả lỗi convention đã được fix

Bất ngờ chưa, các lỗi convention được fix hết luôn rồi kìa.

Fix được là do file phpcs.xml mình đã chỉ ra code được tuân theo chuẩn PSR12, nhờ đó mà thằng phpcbf sẽ biết đường mà fix theo chuẩn đó.

Qua ví dụ trên, mình đã chỉ các bạn đi qua một lượt các tính năng cơ bản của PHP CodeSniff, bạn có thể tìm hiểu chi tiết hơn ở wiki của PHP_CodeSniffer.

Bộ sưu tập áo thun cho dân IT, đủ các ngôn ngữ lập trình và hệ điều hành.
Click vào ảnh để xem.

III. LỜI KẾT

Bài viết này cũng khá dài rồi, nên mình tạm dừng ở đây, nhưng dự kiến sẽ còn 2 bài viết nữa xoay quanh thằng PHP CodeSniffer này. Một bài mình sẽ chia sẻ các rules trong file phpcs.xml, một bài mình sẽ chia sẻ cách tích hợp PHP_CodeSniffer với VsCode để vừa code vừa kiểm tra lỗi convention tiện lợi hơn. Hẹn gặp lại các bạn nhé.

Bài viết gốc được đăng tải tại phambinh.net

Có thể bạn quan tâm:

Truy cập ngay việc làm IT đãi ngộ tốt trên TopDev

Cài đặt FTP server sử dụng Docker

cài đặt fpt server
Cài đặt FTP server sử dụng Docker

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Mình đã hướng dẫn các bạn cách cài đặt FTP server trên Ubuntu. Trong bài viết này, mình sẽ hướng dẫn các bạn cài đặt FTP server sử dụng Docker các bạn nhé!

Chúng ta sẽ sử dụng vsftpd Docker Image ở địa chỉ Docker Hub https://hub.docker.com/r/fauria/vsftpd/.

  20 trường hợp sử dụng lệnh Docker cho developer
  Cách thiết lập một dự án Symfony để làm việc với Docker Subdomains

Xem thêm các chương trình tuyển dụng PHP lương cao trên TopDev

Docker Image này expose nhiều biến môi trường khác nhau giúp chúng ta có thể cấu hình FTP server theo cách mình muốn, bao gồm:

  • FTP_USER
  • FTP_PASS
  • PASV_ADDRESS
  • PASV_ADDR_RESOLVE
  • PASV_ENABLE
  • PASV_MIN_PORT
  • PASV_MAX_PORT
  • XFERLOG_STD_FORMAT
  • LOG_STDOUT
  • FILE_OPEN_MODE
  • LOCAL_UMASK
  • REVERSE_LOOKUP_ENABLE
  • PASV_PROMISCUOUS
  • PORT_PROMISCUOUS

Chi tiết ý nghĩa của mỗi biến môi trường, các bạn có thể đọc thêm tại đây.

Mình sẽ sử dụng default value cho các biến môi trường này nên mình chỉ cần chạy command sau là có thể start được 1 FTP server:

docker pull fauria/vsftpd

và:

docker run -d -p 21:21 -v /Users/khanh/Documents/vsftpd:/home/vsftpd --name vsftpd fauria/vsftpd

Mình mapping thư mục trên máy của mình với thư mục /home/vsftpd để chúng ta có thể dễ dàng làm việc với data trên FTP server này.

Kết quả:

Như các bạn thấy, sau khi chạy docker run command thì mình cũng chạy thêm một command nữa là docker logs để xem thông tin mặc định mà Docker Image này khởi tạo khi chạy Docker Container từ nó. Các bạn có thể sử dụng thông tin username và password được hiển thị ở đây để đăng nhập và làm việc với FTP server, các bạn nhé!

Bài viết gốc được đăng tải tại huongdanjava.com

Có thể bạn quan tâm:

Xem thêm việc làm CNTT hấp dẫn trên TopDev

Selenium IDE – Các câu lệnh kiểm tra

selenium ide
Selenium IDE – Các câu lệnh kiểm tra

Bài viết được sự cho phép của vntesters.com

Chào các bạn, như mình đã giới thiệu ở phần trước, Selenium IDE hầu như chỉ record lại những hành động của chúng ta trên trình duyệt. IDE không đủ thông minh để biết được chúng ta muốn kiểm tra những gì trên trang web đó. Bài này, mình sẽ giới thiệu với các bạn một số câu lệnh kiểm tra hay dùng trong Selenium IDE để kiểm tra các đối tượng UI trên trang web.

  Các kiểu “đợi chờ” trong Selenium Webdriver: Implicit wait, Explicit wait và Fluent wait
  Firefox profile preferences để download file với Selenium Webdriver

Xem thêm tuyển Data Science hấp dẫn trên TopDev

Selenium IDE – Tự động kiểm tra

Theo như mình biết thì hiện tại Selenium IDE chỉ hỗ trợ kiểm tra tiêu đề của trang web một cách tự động. Để làm được điều đó, chúng ta cần thiết lập cơ chế của IDE như sau:

B1: Mở Selenium IDE Options bằng menu item Options –> Options

B2: Kích hoạt chức năng “Record assertTitle automatically” trong thẻ General

tu dong kiem tra tieu de

Như vậy, khi chúng ta thực thi record với Selenium IDE, cứ mỗi trang mới được hiển thị, IDE sẽ tự động thêm dòng lệnh kiểm tra tiêu đề trang web cho chúng ta.

Selenium IDE – Các câu lệnh kiểm tra

Để thêm các câu lệnh vào Selenium IDE, các bạn có thể chọn menu item Edit –> Insert New Command, hoặc chọn Insert New Command ở Context Menu

thêm câu lệnh kiểm tra

Các câu lệnh về đối tượng UI

Đối với các đối tượng UI, thông thường chúng ta chỉ có hai loại kiểm tra: Tồn tại hay không tồn tại.

  • verifyElementPresent/assertElementPresent: Hai câu lệnh này dùng để kiểm tra một đối tượng UI tồn tại trên trang web.
  • verifyElementNotPresent/assertElementNotPresent: Hai câu lệnh này dùng để kiểm tra một đối tượng UI không tồn tại trên trang web.

Bên cạnh hai loại kiểm tra chính, Selenium IDE còn hỗ trợ chúng ta kiểm tra đối tượng UI ở mức độ chi tiết hơn như:

Cách hiển thị của đối tượng UI trên trang web:

  • Chiều cao: verifyElementHeight/assertElementHeight – verifyNotElementHeight/assertNotElementHeight
  • Chiều rộng: verifyElementWidth/assertElementWidth – verifyNotElementWidth/assertNotElementWidth
  • Toạ độ trái so với trang web: verifyElementPositionLeft/assertElementPositionLeft – verifyNotElementPositionLeft/assertNotElementPositionLeft
  • Toạ độ trên so với trang web: verifyElementPositionTop/assertElementPositionTop – verifyNotElementPositionTop/assertNotElementPositionTop

Các đối tượng UI được thiết kế với thuộc tính đặc biệt và chúng ta cần kiểm tra thuộc tính đó: verifyAttribute/assertAttribute – verifyNotAttribute/assertNotAttribute

Đối tượng UI đặc biệt như Checkbox hay RadioBox: verifyChecked/assertChecked – verifyNotChecked/assertNotChecked

Các câu lệnh về text

Đôi khi, chúng ta không cần kiểm tra một đối tượng UI, chúng ta chỉ muốn biết một dòng text có hay không có xuất hiện trên trang web. Lúc này, chúng ta có các câu lệnh kiểm tra vể text từ Selenium IDE.

  • verifyTextPresent/assertTextPresent: Hai câu lệnh này dùng để kiểm tra một dòng text tồn tại trên trang web.
  • verifyTextNotPresent/assertTextNotPresent: Hai câu lệnh này dùng để kiểm tra một dòng text không tồn tại trên trang web.

Vì bốn câu lệnh kiểm tra text này không tương tác với đối tượng UI nào, nên phần Target của câu lệnh chính là dòng text mà chúng ta muốn kiểm tra.

Trong trường hợp đặc biệt, chúng ta muốn kiểm tra text của một đối tượng UI xác định, chúng ta có hai câu lệnh verifyText/assertText. Lúc này, target chính là đối tượng UI của chúng ta, và Value chính là dòng text cần kiểm tra.

Các câu lệnh vể tổng thể trang web

Khi chúng ta quan trọng việc thiết kế trang web một cách tổng thể, Selenium IDE hỗ trợ chúng ta các câu lệnh có thể làm việc với toàn bộ trang web.

  • verifyBodyText/assertBodyText: Kiểm tra toàn bộ text trên trang web.
  • verifyCssCount/assertCssCount: Kiểm tra số lượng đối tượng UI sử dụng chung một thiết kế CSS
  • verifyXpathCount/assertXpathCount: Kiểm tra số lượng đối tượng UI có cùng XPath

Trên đây là một số câu lệnh dùng để kiểm tra trang web với Selenium IDE mà mình nghĩ là chúng ta thường xuyên sử dụng. Ngoài ra, Selenium IDE còn hỗ trợ chúng ta rất nhiều câu lệnh để chúng ta có thể sủ dụng trong các trường hợp đặc biệt mà các bạn có thể tìm thấy trong ô Command trên màn hình chính của Selenium IDE.

Bài viết gốc được đăng tải tại vntesters.com

Có thể bạn quan tâm:

Xem thêm việc làm CNTT hấp dẫn trên TopDev

Semaphore trong Java

Semaphore trong Java
Semaphore trong Java

Bài viết được sự cho phép của tác giả Giang Phan

Semaphore là gì?

Semaphore là một cơ chế giúp quản lý các nguồn chia sẻ và đảm bảo access không bị tắc nghẽn.

Có hai loại semaphore: binary semaphore và counting semaphore.

  • Binary semaphore (Mutex): được dùng làm lock vì nó chỉ có 2 giá trị là 0 và 1. Hai giá trị này đại diện cho trạng thái lock hay unlock.
  • Counting semaphore: thực hiện đếm resource để cho biết mức độ sẵn sàng của resource.

Xem thêm tuyển dụng Java lương hấp dẫn trên TopDev

Cơ chế hoạt động

Một Semaphore lưu trữ một danh sách các permit (hay ticket), mỗi khi gọi acquire() sẽ lấy 1 ticket từ Semaphore, mỗi khi gọi release() sẽ trả ticket về Semaphore. Nếu ticket không có sẵn, acquire() sẽ bị lock cho đến khi có ticket. Để kiểm tra số lượng ticket còn lại, sử dụng phương thức availablePermits().

Ví dụ chúng ta gọi các phương thức tuần tự như sau:

// Tạo một Semaphore có 5 ticket
Semaphore semaphore = new Semaphore(5);

// Yêu cầu lấy 1 ticket để sử dụng
semaphore.acquire(); // 5-1

// Đếm về số lượng ticket có sẵn
int numberOfAvailableTickets = semaphore.availablePermits(); // 4

// Trả 1 ticket về Semaphore
semaphore.release(); // 4+1

// Đếm về số lượng ticket có sẵn
semaphore.availablePermits(); // 5

Ví dụ sử dụng Semaphore

Giả sử một ngân hàng có 4 cây ATM, mỗi cây chỉ có thể phục vụ được một khách hàng tại một thời điểm. Chương trình bên dưới cho thấy Semaphore có thể đảm bảo chỉ tối đa 4 người có thể truy cập tại một thời điểm.

WorkerThread.java

package com.gpcoder.semaphore;

import java.util.concurrent.Semaphore;

public class WorkerThread extends Thread {

private final Semaphore semaphore;
private String name;

public WorkerThread(Semaphore semaphore, String name) {
this.semaphore = semaphore;
this.name = name;
}

public void run() {
try {
System.out.println(name + ": acquiring lock...");
System.out.println(name + ": available Semaphore permits now: " + semaphore.availablePermits());
semaphore.acquire();
System.out.println(name + ": got the permit!");

try {
System.out.println(name + ": is performing operation, available Semaphore permits : "
+ semaphore.availablePermits());
Thread.sleep(100); // simulate time to work
} finally {
// calling release() after a successful acquire()
System.out.println(name + ": releasing lock...");
semaphore.release();
System.out.println(name + ": available Semaphore permits now: " + semaphore.availablePermits());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

SemaphoreExample.java

package com.gpcoder.semaphore;

import java.util.concurrent.Semaphore;

public class SemaphoreExample {

private static Semaphore semaphore = new Semaphore(4);

public static void main(String[] args) {
System.out.println("Total available Semaphore permits: " + semaphore.availablePermits());
for (int i = 1; i <= 6; i++) {
WorkerThread atmWorker = new WorkerThread(semaphore, "AMT " + i);
atmWorker.start();
}
}
}

Chạy chương trình trên, ta có kết quả sau:

Total available Semaphore permits: 4
AMT 1: acquiring lock...
AMT 1: available Semaphore permits now: 4
AMT 1: got the permit!
AMT 1: is performing operation, available Semaphore permits : 3
AMT 2: acquiring lock...
AMT 2: available Semaphore permits now: 3
AMT 2: got the permit!
AMT 2: is performing operation, available Semaphore permits : 2
AMT 3: acquiring lock...
AMT 3: available Semaphore permits now: 2
AMT 3: got the permit!
AMT 3: is performing operation, available Semaphore permits : 1
AMT 6: acquiring lock...
AMT 4: acquiring lock...
AMT 4: available Semaphore permits now: 1
AMT 4: got the permit!
AMT 4: is performing operation, available Semaphore permits : 0
AMT 5: acquiring lock...
AMT 5: available Semaphore permits now: 0
AMT 6: available Semaphore permits now: 1
AMT 3: releasing lock...
AMT 4: releasing lock...
AMT 1: releasing lock...
AMT 4: available Semaphore permits now: 2
AMT 2: releasing lock...
AMT 2: available Semaphore permits now: 2
AMT 6: got the permit!
AMT 6: is performing operation, available Semaphore permits : 2
AMT 5: got the permit!
AMT 5: is performing operation, available Semaphore permits : 2
AMT 1: available Semaphore permits now: 3
AMT 3: available Semaphore permits now: 2
AMT 6: releasing lock...
AMT 6: available Semaphore permits now: 3
AMT 5: releasing lock...
AMT 5: available Semaphore permits now: 4

Ví dụ sử dụng Mutex

Mutex là một Semaphore với bộ đếm là 1. Tình huống có thể sử dụng là lock tài khoản khi rút tiền. Tại một thời điểm chỉ 1 thao tác rút tiền được chấp nhận.

Chúng ta sẽ sử dụng lại worker ở trên. Giả sử có 6 user cùng login vào một tài khoản ở các cây ATM khác nhau để thực hiện rút tiền, nếu chúng ta không sử dụng cơ chế synchronized thì cả 6 người đều có thể rút tiền cùng lúc và có thể rút nhiều hơn số tiền hiện có trong tài khoản.

Đoạn code bên dưới sử dụng Mutex giúp chúng ta kiểm soát được vấn đề này một cách dễ dàng.

package com.gpcoder.semaphore;

import java.util.concurrent.Semaphore;

public class MutexExample {

private static Semaphore semaphore = new Semaphore(1);

public static void main(String[] args) {
System.out.println("Total available Semaphore permits: " + semaphore.availablePermits());
for (int i = 1; i <= 6; i++) {
WorkerThread atmWorker = new WorkerThread(semaphore, "AMT " + i);
atmWorker.start();
}
}
}

Chạy chương trình trên, chúng ta có kết quả sau:

Total available Semaphore permits: 1
AMT 1: acquiring lock...
AMT 2: acquiring lock...
AMT 1: available Semaphore permits now: 1
AMT 2: available Semaphore permits now: 1
AMT 1: got the permit!
AMT 1: is performing operation, available Semaphore permits : 0
AMT 3: acquiring lock...
AMT 3: available Semaphore permits now: 0
AMT 4: acquiring lock...
AMT 4: available Semaphore permits now: 0
AMT 5: acquiring lock...
AMT 6: acquiring lock...
AMT 6: available Semaphore permits now: 0
AMT 5: available Semaphore permits now: 0
AMT 1: releasing lock...
AMT 1: available Semaphore permits now: 1
AMT 2: got the permit!
AMT 2: is performing operation, available Semaphore permits : 0
AMT 2: releasing lock...
AMT 2: available Semaphore permits now: 0
AMT 3: got the permit!
AMT 3: is performing operation, available Semaphore permits : 0
AMT 3: releasing lock...
AMT 3: available Semaphore permits now: 1
AMT 4: got the permit!
AMT 4: is performing operation, available Semaphore permits : 0
AMT 4: releasing lock...
AMT 6: got the permit!
AMT 6: is performing operation, available Semaphore permits : 0
AMT 4: available Semaphore permits now: 0
AMT 6: releasing lock...
AMT 5: got the permit!
AMT 5: is performing operation, available Semaphore permits : 0
AMT 6: available Semaphore permits now: 0
AMT 5: releasing lock...
AMT 5: available Semaphore permits now: 1

Bài viết đến đây là hết. Hy vọng sau bài viết này các bạn hiểu rõ hơn về Semaphore, cũng như biết cách sử dụng nó trong một số tình huống thích hợp.

Tài liệu tham khảo:

Cơ bản về Apache Kafka

apache kafka
Cơ bản về Apache Kafka

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Apache Kafka là một open-source distributed event streaming platform giúp chúng ta có thể tạo và process data stream real-time. Các bạn có thể hình dung đến những hệ thống mà mỗi giây, data đều được sinh ra và cần được xử lý ví dụ như hệ thống quản lý giao thông, quản lý thời tiết, data sẽ được tạo ra từ nhiều nơi khác nhau và cần được collect để xử lý. Sử dụng Apache Kafka với high scalable có thể giúp chúng ta giải quyết những bài toán như vậy.

  Cài đặt Apache Kafka trên macOS
  Sử dụng Apache POI để đọc, ghi dữ liệu từ file Excel trong Selenium

Xem thêm các việc làm Flutter lương cao trên TopDev

Apache Kafka là một hệ thống enterprise messaging, hoạt động với cơ chế Pub-Sub messaging architecture. Chúng ta có Message Publisher, Message Consumer và Message Broker. Message Publisher là nơi produce các message và emit các message vào Message Broker, Message Consumer là nơi nhận, nó sẽ subscribe Message Broker và nhận các message của Message Publisher thông qua Message Broker.

Apache Kafka Server sẽ đóng vai trò là một Message Broker.

Apache Kafka cung cấp cho chúng ta các library để làm việc với Publisher và Subscriber. Ngoài ra, Apache Kafka còn có thêm các component khác như Kafka Connect, Kafka Streams.

Apache Kafka được xây dựng từ đầu bởi LinkedIn, một mạng xã hội về việc làm, và được open-source từ năm 2011.

Bài viết gốc được đăng tải tại huongdanjava.com

Có thể bạn quan tâm:

Xem thêm thông tin việc làm CNTT hấp dẫn trên TopDev

Viết Thư Từ Chối Phỏng Vấn Bằng Tiếng Anh Như Thế Nào Cho Chuyên Nghiệp?

viết thư từ chối phỏng vấn bằng tiếng anh
Viết Thư Từ Chối Phỏng Vấn Bằng Tiếng Anh Như Thế Nào Cho Chuyên Nghiệp?

Sau khi đã nhận được kết quả ứng tuyển thành công vào một công ty, có thể bằng nhiều lý do khác nhau mà bạn cảm thấy mình không thể tiếp nhận phỏng vấn vị trí đó như dự định, làm sao để có thể từ chối một cách lịch sự nhất? Đặc biệt, trong một số trường hợp, bạn còn phải viết thư bằng tiếng anh, vậy đâu là cách viết thư từ chối phỏng vấn bằng tiếng Anh chuyên nghiệp và khéo léo? Bài viết dưới đây sẽ giúp bạn có thêm thông tin về vấn đề này.

viết thư từ chối phỏng vấn bằng tiếng Anh
Cách viết thư từ chối phỏng vấn bằng tiếng Anh

Cấu trúc cần có khi viết thư từ chối phỏng vấn bằng tiếng Anh

Cũng như cách bạn nộp đơn ứng tuyển vào công ty, khi viết đơn từ chối bất cứ vị trí nào cũng hãy thể hiện một nội dung chuyên nghiệp với bố cục rõ ràng. Nó sẽ giúp bạn xây dựng được ấn tượng tốt trong mắt nhà tuyển dụng và biết đâu bạn có thể quay lại công ty ở một vị trí khác trong tương lai. Trên hết, nó giúp tiết kiệm thời gian và công sức chờ đợi của cả hai phía. Theo đó, bố cục email sẽ gồm có:

Xem thêm các việc làm PHP lương cao trên TopDev

  • Tiêu đề email: Có 2 cách để bạn viết thư từ chối nhà tuyển dụng. Nếu bạn trả lời trực tiếp trên email mời phỏng vấn nhà tuyển dụng gửi đến thì không cần có tiêu đề. Trong trường hợp bạn viết một email mới, cần viết tiêu đề một cách ngắn gọn, rõ ràng, khái quát được mục đích bạn viết bức thư này. Chẳng hạn “Thank you for the interview letter”, “Reply for the interview invitation”,…
  • Lời chào và cảm ơn: Đây là yếu tố cực kỳ cần thiết và cũng là cách mở đầu bức thư của bạn. Gửi lời chào trực tiếp đến người gửi thư phỏng vấn cho bạn hoặc chức danh vị trí của họ – Dear HR Manager,… để thể hiện sự tôn trọng với người đọc.

Hãy gửi lời cảm ơn đến họ vì đã lựa chọn bạn cho vị trí này. Nhân sự và các phòng ban liên quan đã dành khá nhiều thời gian để chọn lọc hồ sơ và tin tưởng chọn bạn cho vị trí này, do đó trong trường hợp không thể tiếp nhận phỏng vấn, việc gửi lời cảm ơn đến họ sẽ khiến nhà tuyển dụng đỡ cảm thấy hụt hẫng và có ấn tượng tốt về bạn hơn.

  • Thank you very much for the interview invitation at A Company. I appreciate being considered as a candidate with the B position.
  • I’m grateful for the opportunity to interview at A Company with the B position.

Xem thêm Phỏng Vấn Data Analyst: TOP 5 Câu Hỏi Bạn Không Nên Bỏ Qua!

  • Trình bày lý do từ chối phỏng vấn: Đây là nội dung chính của bức thư. Có thể có nhiều lý do khác nhau khiến bạn quyết định từ chối lời mời, nhưng không ai biết được trong tương lai bạn có thể gặp lại công ty ở thời điểm nào đó, nên cách tốt nhất là hãy giữ lại ấn tượng tốt đẹp trong nhau. Hãy cố gắng lựa chọn một lý do từ chối nhẹ nhàng và đủ sức thuyết phục.
  • Gửi lời cảm ơn và lời chúc đến nhà tuyển dụng để kết thúc bức thư.
  • Thank you again and hope you will find a suitable candidate as soon as possible.
  • I wish you all the best in your search for a candidate.
thư từ chối
Một số điều cần có trong thư từ chối

Một số lưu ý khi viết thư từ chối phỏng vấn bằng tiếng Anh

Bạn nên cố gắng xem xét thật kỹ và sớm nhất lời mời phỏng vấn, và nếu không muốn tiếp nhận phỏng vấn hãy phản hồi bằng thư từ chối sớm nhất có thể, tốt nhất là trong khoảng 24 giờ. Việc này sẽ giúp nhà tuyển dụng tìm được ứng viên khác và tiến hành phỏng vấn, tránh lãng phí thời gian chờ đợi của cả 2 bên.

Về lý do từ chối, như đã nói ở trên, đừng đưa ra một lý do quá khách quan và không có gì đảm bảo tính xác thực của nó, như tin đồn về môi trường công ty không tốt hay phúc lợi công ty còn thấp,… Những lý do này sẽ rất dễ khiến bạn rơi vào “blacklist” của công ty và nó thật sự không tốt cho tương lai của bạn sau này.

  Văn hóa giao tiếp qua Email - Thế nào là chuyên nghiệp?
  Bí quyết phát triển hoạt động nhân sự qua email (Email Marketing) hiệu quả - Bạn đã biết?

Văn phong sử dụng trong bức thư cần lịch sự và chuyên nghiệp nhất có thể. Điều này không chỉ giúp bạn xây dựng ấn tượng tốt trong mắt nhà tuyển dụng mà biết đâu, trong tương lai khi bạn quay lại công ty ở một vai trò khác và điều này sẽ không gây cản trở đến công việc của bạn.

Ngoài ra, nếu được, bạn hoàn toàn có thể giới thiệu một ứng viên khác cho công ty. Hãy đưa ra vài thông tin cơ bản về ứng viên này cũng như để lại cách thức liên lạc trong bức thư. Nhà tuyển dụng sẽ quyết định việc lựa chọn và tiến hành các bước tiếp theo.

Một số mẫu email tham khảo

Một số mẫu viết thư từ chối phỏng vấn bằng tiếng Anh bạn có thể tham khảo:

email mẫu

Mẫu 1:

Dear Ms. Han – HR Manager of A Company,

I’m very appreciative of the interview opportunity for Content Marketing and learning more about your organization.

However, I regret that I have to deny this opportunity at this time. Because I was offered and accepted a job at another company, so I’m respectfully declining this offer.

Thank you again and hope you will find a suitable candidate as soon as possible.

Best regards,

Mẫu 2:

Dear Ms. Jennie,

Thank you so much for reaching out and send me the interview invitation,

However, I would like to withdraw my application for this position because of personal reasons.

I will keep this role in mind and refer anyone who may be a good match.

Thank you again for considering me for this position. Please do not hesitate to get in touch if you have any questions.

Thanks and Best regards,

Tùy theo mỗi lý do cá nhân khác nhau, mọi người sẽ có cách riêng để viết thư từ chối phỏng vấn. Tuy nhiên, về cơ bản cần đảm bảo đủ các yếu tố như trên để không làm khó chịu người nhận. Đón đọc thêm nhiều nội dung hấp dẫn khác cùng Topdev.vn/blog nhé!

Có thể bạn quan tâm:

Xem thêm tuyển dụng việc làm IT hấp dẫn trên TopDev

Thu thập và làm sạch dữ liệu khi sử dụng Linear Regression

linear regression
Thu thập và làm sạch dữ liệu khi sử dụng Linear Regression

Bài viết được sự cho phép của tác giả Kien Dang Chung

Video trong bài viết

Trước khi bắt đầu bài đầu tiên thu thập và làm sạch dữ liệu chuẩn bị cho thuật toán Linear Regression, chúng ta sẽ tìm hiểu qua quy trình làm việc khoa học dữ liệu.

  Ấn tượng trước những bước đột phá công nghệ mới của Line!
  Cơ hội nào cho "dân buôn" online?

Xem thêm tuyển 3D Artist hấp dẫn trên TopDev

Quy trình làm việc khoa học dữ liệu

Bất kể bạn áp dụng thuật toán Machine Learning nào cho vấn đề bạn gặp phải, chúng ta sẽ đều phải trải qua một quy trình làm việc (data science workflow).

Quy trình làm việc khoa học dữ liệu

Trong tất cả các dự án của Khóa học Machine Learning từ A đến Z, chúng ta sẽ áp dụng quy trình này, tuy rằng không phải lúc nào cũng đủ tất cả các bước trong đấy. Trong quy trình này có 3 giai đoạn và rất nhiều các bước.

  • Giai đoạn 1 – Chuẩn bị dữ liệu: Dữ liệu được thu thập và làm sạch. Phần lớn dữ liệu gốc đều ở dạng hỗn loạn, có thể thiếu thông tin hoặc thông tin sai lệch, do vậy cần được xử lý trước khi đưa vào các mô hình thuật toán.
  • Giai đoạn 2 – Thử nghiệm: tại giai đoạn này các giả định được đặt ra, dữ liệu được trực quan hóa thông qua các biểu đồ và lựa chọn các mô hình.
  • Giai đoạn 3 – Triển khai: Các báo cáo, đánh giá quá trình áp dụng và kết quả được triển khai thông qua các ứng dụng thực tế hoặc đơn thuần là các báo cáo.

Khi thực hiện các giai đoạn, có thể quay lại giai đoạn trước đó để chuẩn bị dữ liệu tốt hơn. Quy trình này được áp dụng cho các công việc thực tế, nhưng với các bài hướng dẫn trong Machine Learning AZ chúng ta sẽ rút gọn các bước lại để tập trung vào việc học tập hơn.

Các bước thực hiện trong Machine Learning A đến Z

Các bước được cô đọng lại như sau:

  • Bước 1: Hình thành câu hỏi
  • Bước 2: Thu thập dữ liệu
  • Bước 3: Làm sạch dữ liệu
  • Bước 4: Khám phá và trực quan hóa dữ liệu với biểu đồ
  • Bước 5: Áp dụng thuật toán hay mô hình huấn luyện
  • Bước 6: Đánh giá kết quả

Bài toán dự đoán doanh thu phim

Trước khi bắt đầu xử lý một vấn đề, chúng ta nên bỏ chút thời gian đặt ra những câu hỏi như Cái gì, Tại sao, Làm như thế nào, Ở đâu… những câu hỏi này giúp chúng ta trìu tượng hóa vấn đề. Cũng chính nhờ những câu hỏi này chúng ta sẽ xác định được loại dữ liệu nào là cần thiết bởi trong thực tế lượng dữ liệu là rất khổng lồ.

Trở lại với vấn đề mà chúng ta đang gặp phải trong bài toán dự đoán doanh thu phim. Những nhà đầu tư phim, họ rót vốn cho các bộ phim và quan tâm đến lợi nhuận các bộ phim. Áp dụng quy trình data science ở trên, bước đầu tiên chúng ta cần hình thành các câu hỏi. Câu hỏi đầu tiên:

“Chúng ta cần bao nhiêu tiền để sản xuất bộ phim này?”

Câu hỏi này thật sự chưa ổn, nó hơi mơ hồ. Với những người đầu tư phim, họ quan tâm đến lợi nhuận hơn là chi phí. Do đó, câu hỏi nên là:

“Chúng ta thu được bao nhiêu khi sản xuất bộ phim này?”

Câu hỏi này tốt hơn nhiều, nó đã nhắm đến lợi nhuận là tiêu chí các nhà đầu tư đo lường và kiểm tra cơ hội đầu tư. Chúng ta cần suy nghĩ thêm chút, vậy doanh thu sẽ phụ thuộc vào những yếu tố nào? Chúng ta có thể kể ra một loạt các yếu tố sau:

  • Diễn viên có phải các ngôi sao hạng A?
  • Kịch bản hay và nổi tiếng không?
  • Phim có sử dụng các công nghệ tạo hiệu ứng hiện đại nhất?
  • Chi phí quảng bá phim
  • Đạo diễn phim có số má trên thị trường không?

Nhưng chung quy, tất cả các yếu tố này đều quay về chi phí sản xuất hay ngân sách dành cho một bộ phim. Như vậy, chúng ta cần tìm hiểu chi phí sản xuất tất cả các bộ phim đã được phát hành. Các phim như Avatar, Titanic, The Advengers… đã tiêu tốn rất nhiều chi phí, nhưng họ cũng thu lại lợi nhuận khổng lồ. Những thông tin này thì có liên quan gì đến bộ phim mà chúng ta sắp đầu tư? Nếu chúng ta biết được các bộ phim đã tiêu tốn như thế nào để đạt được doanh thu này, chúng ta có thể dự đoán được doanh thu bộ phim của chúng ta thông qua thuật toán Linear Regression – Hồi quy tuyến tính.

Biểu đồ doanh thu ngân sách

Trong bài toán của chúng ta có hai yếu tố:

  • Doanh thu của bộ phim chính là mục tiêu cần tìm ra (target).
  • Ngân sách bộ phim là tham số độc lập (feature).

Như vậy chúng ta đã hoàn thành bước đầu tiên trong dự án, chúng ta đã xác định được các yếu tố (loại dữ liệu cần thiết). Chúng ta sẽ chuyển sang bước tiếp theo thu thập và làm sạch dữ liệu.

Thu thập dữ liệu phim

Trong phần trước, dựa vào các câu hỏi và phân tích chúng ta đã biết cần phải có những dữ liệu về doanh thu và ngân sách các bộ phim. Vậy cần tìm dữ liệu này ở đâu, rất may trong trang web www.the-numbers.com có tất cả dữ liệu này. Tất cả dữ liệu doanh thu và ngân sách trong website này ở dạng bảng và tôi đã đưa chúng vào file csv.

Bạn có thể tải về dữ liệu trong file cost_revenue_dirty.csv để tiếp tục bước tiếp theo làm sạch dữ liệu.

Tiền xử lý dữ liệu

Mở file cost_revenue_dirty.csv và xem nội dung file, có rất nhiều các thông tin bất thường, có những bộ phim có doanh thu bằng 0, ví dụ như phim Singularity chẳng hạn. Nguyên nhân là gì, nếu bạn xem cột Ngày phát hành (Cột B) thì hóa ra phim này chưa ra mắt, đến tận 31/12/2020 mới phát hành.

Dữ liệu doanh thu và ngân sách phim từ the-numbers.com

Thực hiện lọc các phim có doanh thu bằng 0, chúng ta thấy có rất nhiều các bộ phim như vậy. Nhưng không phải tất cả trong số chúng là chưa phát hành mà có những bộ phim đã hoàn thành nhưng không được công chiếu do đang trong quá trình kiện tụng và còn nhiều lý do khác nữa… Như vậy, chúng ta cần loại bỏ tất cả những bộ phim này vì nó là những trường hợp ngoại lệ, nó làm cho dữ liệu của chúng ta thiếu sót.

Chúng ta cũng chỉ cần hai loại thông tin là doanh thu và ngân sách phim do vậy chỉ giữ lại các cột Production Budget ()vàWorldwideGross()vàWorldwideGross(). Các cột thứ hạng phim, ngày phát hành, doanh thu trong nước sẽ được loại bỏ.

Sau khi loại bỏ các thông tin bị mất, sai sót, không đúng định dạng hoặc không cần thiết, chúng ta có được file dữ liệu sau khi làm sạch cost_revenue_clean.csv.

Như vậy, chúng ta đã hoàn thành 2 trong 6 bước đầu tiên là tìm ra các thông tin cần thiết và thu thập, làm sạch dữ liệu. Trong bài tiếp theo chúng ta sẽ tiếp tục bước tiếp theo là khai phá dữ liệu và trực quan hóa dữ liệu thông qua vẽ biểu đồ từ dữ liệu có được.

Tài nguyên liên quan bài viết

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm tuyển dụng việc làm CNTT hấp dẫn trên TopDev

Cài đặt Apache Kafka sử dụng Docker Compose

cài đặt apache kafka
Cài đặt Apache Kafka sử dụng Docker Compose

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Trong bài viết trước, mình đã hướng dẫn các bạn cách cài đặt Apache Kafka trên macOS, việc cài đặt sử dụng Docker Compose sẽ giúp chúng ta nhanh chóng start lên một Apache Kafka server mà không tốn nhiều effort, chỉ cần cài đặt Docker và tập tin docker-compose.yml. Cụ thể như thế nào? Trong bài viết này, mình sẽ hướng dẫn các bạn cách cài đặt Apache Kafka sử dụng Docker Compose các bạn nhé!

  Cách thiết lập một dự án Symfony để làm việc với Docker Subdomains

Xem thêm các việc làm OOP lương cao trên TopDev

Mình sẽ tạo mới một tập tin docker-compose.yml với Docker Compose version như sau:

version: '3.8'

Chúng ta sẽ khai báo 2 service, một cho Apache Zookeeper và một cho Apache Kafka:

services:
zookeeper:

kafka:

Vì Apache Kafka muốn chạy được phải có Apache Zookeeper nên mình sẽ khai báo service zookeeper trước.

Chúng ta sẽ sử dụng các Docker Image của Apache Kafka và Apache Zookeeper từ Confluent Platform https://www.confluent.io/ với địa chỉ Docker Hub là https://hub.docker.com/u/confluentinc. Nói nôm na thì Confluent Platform là một mở rộng của Apache Kafka, được xây dựng từ Apache Kafka cùng với các công cụ và service hữu ích khác giúp chúng ta có thể dễ dàng chạy và sử dụng Apache Kafka đó các bạn! Không có Docker Official Image từ Apache Kafka nên chúng ta có thể sử dụng các Docker Images từ Confluent Platform này.

Nội dung của zookeeper service như sau:

zookeeper:
image: confluentinc/cp-zookeeper:latest
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ports:
- 2181:2181

ZOOKEEPER_CLIENT_PORT là biến môi trường bắt buộc để định nghĩa port mà client có thể kết nối tới Apache Zookeeper. Trong trường hợp của chúng ta là Apache Kafka đó các bạn! Ở đây, mình cũng expose port 2181 là port mặc định của Apache Zookeeper ra ngoài.

Còn kafka service thì có nội dung như sau:

kafka:
image: confluentinc/cp-kafka:latest
depends_on: 
- zookeeper
environment:
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:29092
ports:
- 29092:29092

KAFKA_ZOOKEEPER_CONNECT được sử dụng để định nghĩa Apache ZooKeeper server mà Apache Kafka sẽ connect tới, còn KAFKA_ADVERTISED_LISTENERS dùng để expose Apache Kafka ra ngoài container để các client có thể connect tới. Đây là những biến môi trường bắt buộc các bạn phải khai báo khi start Docker Container từ cp-kafka Docker Image các bạn nhé!

Chúng ta cũng khai báo networks như sau:

networks:
huongdanjava:
driver: bridge

Toàn bộ nội dung của tập tin docker-compose.yml như sau:

version: '3.8'

services:
zookeeper:
image: confluentinc/cp-zookeeper:latest
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ports:
- 2181:2181

kafka:
image: confluentinc/cp-kafka:latest
depends_on: 
- zookeeper
environment:
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:29092
ports:
- 29092:29092

networks:
huongdanjava:
driver: bridge

Nếu bây giờ, các bạn chạy command docker compose up trong thư mục chứa tập tin docker-compose.yml này, các bạn sẽ thấy kết quả như sau:

Bây giờ thì các bạn có thể connect tới Apache Kafka server này để sử dụng rồi.

Bài viết gốc được đăng tải tại huongdanjava.com
Có thể bạn quan tâm:
Xem thêm tuyển dụng việc làm IT hấp dẫn trên TopDev

Producer – Consumer và đồng bộ hóa các luồng trong Java

đồng bộ hóa trong java
Vấn đề Nhà sản xuất (Producer) – Người tiêu dùng (Consumer) và đồng bộ hóa các luồng trong Java

Bài viết được sự cho phép của tác giả Giang Phan

Producer/ Consumer là một ví dụ kinh điển về vấn đề đồng hóa các luồng (multi-threading synchronization). Trong bài này tôi sẽ giới thiệu với các bạn vấn đề này và cách giải quyết để giúp các bạn hiểu rõ hơn về Java concurrency và mutli-threading.

Xem thêm các việc làm Java lương cao trên TopDev

Mô tả vấn đề Producer/ Consumer

Vấn đề mô tả hai đối tượng nhà sản xuất (Producer) và người tiêu dùng (Consumer), cả hai cùng chia sẻ một bộ đệm có kích thước cố định được sử dụng như một hàng đợi (queue).

Producer: công việc của nhà sản xuất là tạo dữ liệu, đưa nó vào bộ đệm và bắt đầu lại.

Consumer: công việc người tiêu dùng là tiêu thụ dữ liệu (nghĩa là loại bỏ nó khỏi bộ đệm), từng phần một và xử lý nó. Consumer và Producer hoạt động song song với nhau.

Vấn đề là đảm bảo rằng nhà sản xuất không thể thêm dữ liệu vào bộ đệm nếu nó đầy và người tiêu dùng không thể xóa dữ liệu khỏi bộ đệm trống, đồng thời đảm bảo an toàn cho luồng (thread-safe).

Giải pháp để giải quyết vấn đề Producer/ Consumer

Ý tưởng:

  • Giải pháp cho nhà sản xuất là đi ngủ (wait) nếu bộ đệm đầy. Lần tiếp theo người tiêu dùng xóa một mục khỏi bộ đệm, nó đánh thức (notify) nhà sản xuất, bắt đầu đưa dữ liệu vào bộ đệm.
  • Theo cách tương tự, người tiêu dùng có thể đi ngủ (wait) nếu thấy bộ đệm trống. Lần tiếp theo nhà sản xuất đưa dữ liệu vào bộ đệm, nó đánh thức (notify) người tiêu dùng đang ngủ (wait).
  • Trong khi làm tất cả điều này, phải đảm bảo an toàn cho luồng (thread safe).

Có nhiều giải pháp cho vấn đề Producer Consumer trong Java:

  • Sử dụng synchronized.
  • Sử dụng BlockingQueue.
  • Sử dụng Semaphore.
  • Sử dụng JMS (Java Messaging Service): JMS là một implementation của vấn đề Producer Consumer. Nhiều nhà sản xuất và nhiều người tiêu dùng có thể kết nối với JMS và phân phối công việc. Tôi sẽ giới thiệu với các bạn JMS ở một bài viết khác.

Trong bài này, tôi sẽ giới thiệu với các bạn cách sử dụng BlockingQueue và Semaphore.

Sử dụng BlockingQueue

Để giải quyết vấn đề, chúng ta sẽ cần 3 class:

  • Blocking Queue :
    • Sử dụng synchronized để đảm bảo thread-safe.
    • put() : sử dụng wait() để chờ khi queue đã đầy (full), và notifyAll() để thông báo khi thêm data mới vào queue.
    • take() : sử dụng wait() để chờ khi queue rỗng (empty), và notifyAll() để thông báo khi lấy data ra khỏi queue.
  • Producer Thread(s) : các thread mô phỏng các nhà sản xuất.
  • Consumer Thread(s) : các thread mô phỏng các người tiêu dùng.

Các bạn có thể sử dụng BlockingQueue có sẵn trong package java.util.concurrent . Trong bài này, tôi sẽ tự tạo một BlockingQueue để mô phỏng cơ chế hoạt động của Blocking Queue cho các bạn dễ hiểu.

BlockingQueue.java

package com.gpcoder.producerconsumer;

import java.util.LinkedList;

public class BlockingQueue {
private static final int compacity = 10;
private final LinkedList items = new LinkedList<>();

public synchronized void put(T value) throws InterruptedException {
while (items.size() == compacity) {
System.out.println("Queue is full");
wait();
}
items.addLast(value);
notifyAll();
}

public synchronized T take() throws InterruptedException {
while (items.size() == 0) {
System.out.println("Queue is empty");
wait();
}
notifyAll();
return items.removeFirst();
}

public synchronized int size() {
return items.size();
}
}

Producer.java

package com.gpcoder.producerconsumer;

import java.util.concurrent.ThreadLocalRandom;

public class Producer implements Runnable {

private final BlockingQueue queue;

Producer(BlockingQueue queue) {
this.queue = queue;
}

public void run() {
try {
while (true) {
queue.put(produce());
System.out.println("Produced resource - Queue size() = " + queue.size());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private Integer produce() throws InterruptedException {
Thread.sleep(50); // simulate time to produce the data
return ThreadLocalRandom.current().nextInt(1, 100);
}
}

Consumer.java

package com.gpcoder.producerconsumer;

import java.util.concurrent.ThreadLocalRandom;

public class Consumer implements Runnable {

private final BlockingQueue queue;

Consumer(BlockingQueue queue) {
this.queue = queue;
}

public void run() {
try {
while (true) {
queue.take();
System.out.println("Consumed resource - Queue size() = " + queue.size());
Thread.sleep(ThreadLocalRandom.current().nextInt(50, 300)); // simulate time passing
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

Main.java

package com.gpcoder.producerconsumer;

public class Main {

public static void main(String[] args) throws InterruptedException {
BlockingQueue boundedBuffer = new BlockingQueue<>();

Producer producer = new Producer(boundedBuffer);
Consumer consumer1 = new Consumer(boundedBuffer);
Consumer consumer2 = new Consumer(boundedBuffer);
Consumer consumer3 = new Consumer(boundedBuffer);

new Thread(producer).start();
new Thread(consumer1).start();
new Thread(consumer2).start();
new Thread(consumer3).start();

Thread.sleep(5000); // After 5s have another comsumer
Consumer consumer4 = new Consumer(boundedBuffer);
new Thread(consumer4).start();
}
}

Output chương trình:

Queue is empty
Queue is empty
Queue is empty
Queue is empty
Produced resource - Queue size() = 0
Consumed resource - Queue size() = 0
Queue is empty
Produced resource - Queue size() = 0
Consumed resource - Queue size() = 0
Produced resource - Queue size() = 1
Consumed resource - Queue size() = 0
Queue is empty
Produced resource - Queue size() = 1
Consumed resource - Queue size() = 0
....
Produced resource - Queue size() = 10
Queue is full
Consumed resource - Queue size() = 9
Produced resource - Queue size() = 10
Queue is full
Consumed resource - Queue size() = 9
Produced resource - Queue size() = 10
Consumed resource - Queue size() = 9
....
Produced resource - Queue size() = 10
Consumed resource - Queue size() = 9
Consumed resource - Queue size() = 8
Produced resource - Queue size() = 9
Consumed resource - Queue size() = 8
...
Consumed resource - Queue size() = 1
Produced resource - Queue size() = 2
Consumed resource - Queue size() = 1
Consumed resource - Queue size() = 0
Queue is empty
Produced resource - Queue size() = 1
Consumed resource - Queue size() = 0
...
  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java
  10 tips để trở thành Java Developer xịn hơn

Sử dụng Semaphore

Tương tự như BlockingQueue ở trên, với Semaphore chúng ta cũng cần 3 class:

  • Queue : sử dụng 2 Semaphore để đồng bộ hóa dữ liệu.
    • Semaphore Producer: được set giá trị là maximum của buffer size. Giá trị này tương ứng với số lượng item có thể được thêm vào buffer.
    • Semaphore Consumer: được set giá trị là 0. Giá trị này tương ứng với số lượng item có thể được lấy ra khỏi buffer.
  • Producer Thread(s) : các thread mô phỏng các nhà sản xuất.
  • Consumer Thread(s) : các thread mô phỏng các người tiêu dùng.

Ví dụ:

Để dễ theo dõi, tôi sẽ thêm một số dòng log để xem cách hoạt động của Semaphore.

package com.gpcoder.producerconsumer.semaphore;

import java.util.Stack;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadLocalRandom;

public class ProducerConsumerSemaphore {

private static final int BUFFER_SIZE = 4;
private final Semaphore writePermits = new Semaphore(BUFFER_SIZE);
private final Semaphore readPermits = new Semaphore(0);
private final Stack buffer = new Stack<>();

class Producer implements Runnable {
private String name;

public Producer(String name) {
this.name = name;
}

@Override
public void run() {
try {
while (true) {
System.out.println(name + ": acquiring lock...");
System.out.println(name + ": Producer available Semaphore permits now: " + writePermits.availablePermits());
writePermits.acquire();
System.out.println(name + ": got the permit!");

Thread.sleep(50); // simulate time to work
int data = ThreadLocalRandom.current().nextInt(100);
System.out.println(name + ": produced data " + buffer.push(data));

System.out.println(name + ": releasing lock...");
readPermits.release();
System.out.println(name + ": Consumer available Semaphore permits now: " + readPermits.availablePermits());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

class Consumer implements Runnable {
private String name;

public Consumer(String name) {
this.name = name;
}

@Override
public void run() {
try {
while (true) {
System.out.println(name + ": acquiring lock...");
System.out.println(name + ": Consumer available Semaphore permits now: " + readPermits.availablePermits());
readPermits.acquire();

Thread.sleep(ThreadLocalRandom.current().nextInt(50, 300)); // simulate time to work
System.out.println(name + ": consumed data " + buffer.pop());

System.out.println(name + ": releasing lock...");
writePermits.release();
System.out.println(name + ": Producer available Semaphore permits now: " + writePermits.availablePermits());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) throws InterruptedException {
ProducerConsumerSemaphore obj = new ProducerConsumerSemaphore();
Producer producer = obj.new Producer("Producer 1");
new Thread(producer).start();

for (int i = 1; i <= 3; i++) {
Consumer consumer = obj.new Consumer("Consumer " + i);
new Thread(consumer).start();
}

Thread.sleep(5000); // After 5s have another comsumer
Consumer consumer = obj.new Consumer("Consumer " + 4);
new Thread(consumer).start();
}
}

Chạy chương trình trên, ta có kết quả sau:

Producer 1: acquiring lock...
Producer 1: Producer available Semaphore permits now: 4
Producer 1: got the permit!
Consumer 1: acquiring lock...
Consumer 1: Consumer available Semaphore permits now: 0
Consumer 2: acquiring lock...
Consumer 2: Consumer available Semaphore permits now: 0
Consumer 3: acquiring lock...
Consumer 3: Consumer available Semaphore permits now: 0
Producer 1: produced data 94
Producer 1: releasing lock...
Producer 1: Consumer available Semaphore permits now: 0
Producer 1: acquiring lock...
Producer 1: Producer available Semaphore permits now: 3
Producer 1: got the permit!
Producer 1: produced data 85
Producer 1: releasing lock...
Producer 1: Consumer available Semaphore permits now: 1
Producer 1: acquiring lock...
Producer 1: Producer available Semaphore permits now: 2
...
Consumer 2: Producer available Semaphore permits now: 1
Consumer 2: acquiring lock...
Consumer 2: Consumer available Semaphore permits now: 0
Producer 1: produced data 9
Producer 1: releasing lock...
Producer 1: Consumer available Semaphore permits now: 1
Producer 1: acquiring lock...
Producer 1: Producer available Semaphore permits now: 1
Producer 1: got the permit!
...

Tại sao vấn đề Producer/ Consumer lại quan trọng?

Có thể được sử dụng để phân phối công việc giữa các worker khác nhau, dễ dàng tăng hoặc giảm theo yêu cầu. Như bạn thấy trong ví dụ trên, ban đầu một Producer có thể sản xuất đủ cho 3 Consumer. Nhưng sau đó, có thêm một Consumer thì hệ thống sản xuất không đáp ứng được, do đó chúng ta cần tăng hiệu suất của Producer lên hoặc tạo thêm một Producer khác để đủ phục vụ cho Consumer, tránh tình trạng thiếu sản phẩm.

Producer và Consumer được kết nối thông qua BlockingQueue, nó không biết sự hiện diện của nhau, tách rời các mối quan tâm (separation of concern), giúp hệ thống thống có thiết kế tốt hơn, nên dễ dàng nâng cấp và mở rộng.

Producer và Consumer không cần phải có sẵn cùng một lúc. Consumer có thể nhận các nhiệm vụ được sản xuất bởi Producer tại một thời điểm khác nhau.

Tài liệu tham khảo:

Bài viết gốc được đăng tải tại gpcoder.com

Có thể bạn quan tâm:

Xem thêm tuyển dụng IT hấp dẫn trên TopDev

Cài đặt Apache Kafka trên macOS

cài đặt apache kafka
Cài đặt Apache Kafka trên macOS

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Trong bài viết này, mình hướng dẫn các bạn cách cài đặt Apache Kafka trong macOS các bạn nhé!

Đầu tiên, các bạn cần đi đến trang Download của Apache Kafka https://kafka.apache.org/downloads để download latest version của nó! Các bạn hãy download phiên bản binary mới nhất.

  Apache Kafka là gì?
  Capacity Planning - Dự toán công suất cho ứng dụng (Tập 1 )

Xem thêm Tuyển dụng Machine Learning Fresher trên TopDev

Sau khi download xong, các bạn hãy giải nén tập tin download này ra.

Để có thể sử dụng Apache Kafka ở bất kỳ đâu trong máy của mình, mình sẽ chỉnh sửa tập tin .bash_profile để thêm đường dẫn tới thư mục bin của Kafka như sau:

export PATH=/Users/khanh/Downloads/kafka_2.13-3.0.0/bin:$PATH

Để những thay đổi của chúng ta có hiệu lực liền, các bạn hãy reload lại tập tin .bash_profile với câu lệnh như sau:

. ./.bash_profile

Để start Apache Kafka, điều đầu tiên, chúng ta cần làm là start Apache ZooKeeper trước.
Các bạn hãy đi đến thư mục của Apache Kafka. Trong thư mục này có thư mục config:

với những tập tin cấu hình mặc định của Apache Kafka và cả Apache ZooKeeper.

Các bạn có thể start Apache ZooKeeper sử dụng command như sau:

zookeeper-server-start.sh config/zookeeper.properties

Kết quả:
Sau khi đã start Apache ZooKeeper rồi thì lúc này, các bạn có thể start Apache Kafka.

Các bạn hãy chạy command sau:

kafka-server-start.sh config/server.properties

Kết quả:
Đến đây thì chúng ta đã hoàn thành việc cài đặt Apache Kafka trên macOS rồi đó các bạn!

Bài viết gốc được đăng tải tại huongdanjava.com
Có thể bạn quan tâm:
Xem thêm tuyển dụng việc làm IT hấp dẫn trên TopDev

Phỏng Vấn Data Analyst: TOP 5 Câu Hỏi Bạn Không Nên Bỏ Qua!

phỏng vấn data analyst
Phỏng Vấn Data Analyst: TOP 5 Câu Hỏi Bạn Không Nên Bỏ Qua!

Để hoàn thành tốt bất cứ quá trình ứng tuyển nào, việc chuẩn bị trước cho các buổi phỏng vấn luôn rất cần thiết nếu muốn có một kết quả thành công. Với vị trí hot như Data Analyst, đâu là những câu hỏi mà ứng viên nên tham khảo trước và có sự chuẩn bị kỹ lưỡng cho mình? Tìm hiểu thêm về top những câu hỏi phỏng vấn Data Analyst mà bạn không nên bỏ qua với bài viết dưới đây nhé!

phỏng vấn business analyst
Top câu hỏi phỏng vấn dành cho Business Analyst

1. Điều gì khiến bạn quyết định trở thành một Data Analyst?

Mục tiêu nghề nghiệp, lý do lựa chọn công việc là một câu hỏi quen thuộc trong hầu hết các buổi phỏng vấn ở mọi ngành nghề. Mục đích của nhà tuyển dụng khi đặt câu hỏi này là để xác định được quyết tâm cũng như mức độ gắn bó của bạn với công việc ra sao, bạn đã có những kinh nghiệm gì và có thể đóng góp được gì cho vị trí mà công ty đang đăng tuyển.

Với một nhà phân tích dữ liệu, câu trả lời của bạn có thể xoay quanh đam mê với việc nghiên cứu những con số, phân tích và đánh giá số liệu chẳng hạn. Đây là một câu hỏi rộng, và không có bất cứ khuôn khổ nào cho nó cả, việc yêu thích số liệu và hứng thú trong việc diễn giải nó hoàn toàn có thể là lý do để bạn lựa chọn gắn bó với công việc. Bạn càng trả lời sáng tạo và hấp dẫn sẽ càng để lại ấn tượng trong mắt người phỏng vấn, cũng như tạo thiện cảm trong suốt buổi phỏng vấn.

2. Trách nhiệm chính của một Data Analyst là gì?

Câu hỏi này sẽ cho nhà tuyển dụng thấy được những hiểu biết căn bản của ứng viên với vị trí Data Analyst. Để có thể kéo dài buổi phỏng vấn, nhà tuyển dụng có hứng thú đào sâu vào kiến thức và kỹ năng của bạn trong buổi phỏng vấn, việc cho thấy kiến thức nền tảng của bạn là rất cần thiết.

  "Làm PM, theo anh không cần biết về code, nhưng phải hiểu về SQL, database, những khái niệm cơ bản của code"
  Big Data có thật sự “toàn năng” và các cơ hội nghề nghiệp trong tương lai?

Với câu hỏi như thế này, bạn có thể tìm hiểu sơ qua về công việc chính mà một Data Analyst sẽ đảm nhận gồm những gì. Đó có thể là việc thu thập, tổng hợp và sắp xếp các dữ liệu. Đánh giá, đưa ra những nhận xét để thúc đẩy hiệu quả và khắc phục các sai sót. Bên cạnh đó thì khả năng phát hiện kịp thời các sai sót cũng là nhiệm vụ mà các Data Analyst cần phải đảm nhận.

câu hỏi phỏng vấn data analyst
Các câu hỏi thường gặp khi phỏng vấn Data Analyst

3. Thách thức lớn nhất bạn đã từng gặp phải trong quá trình làm một Data Analyst là gì?

Câu hỏi này sẽ vừa cho thấy kinh nghiệm làm việc vừa cho thấy khả năng giải quyết vấn đề của các Data Analyst tương lai. Do đó, hãy chắc chắn rằng khi bạn trình bày vấn đề mình đang gặp phải cũng cần đồng thời chia sẻ giải pháp mà bạn đã sử dụng để khắc phục khó khăn đó. Đây là cơ sở rất quan trọng để người phỏng vấn đánh giá năng lực của ứng viên, vậy nên hãy có sự chuẩn bị kỹ càng cho những câu hỏi như thế này.

Tùy theo kinh nghiệm làm việc của mỗi cá nhân mà bạn sẽ nhìn nhận được đâu là vấn đề khó khăn nhất mà mình đang gặp phải. Nên lựa chọn những vấn đề nào có thể đánh giá được khả năng thật sự của bạn cũng như có thể dễ dàng để nhà tuyển dụng hiểu được thay vì các vấn đề có tính chuyên biệt quá cao. Và đừng quên, trình bày cách giải quyết khó khăn thách thức sẽ càng thể hiện rõ năng lực của bạn.

Xem thêm tuyển dụng Data Analytics lương cao trên TopDev

4. Đã có kinh nghiệm làm việc trong lĩnh vực nào và sử dụng công cụ gì để phân tích dữ liệu?

Đây là câu hỏi giúp nhà tuyển dụng đánh giá về kinh nghiệm làm việc trước đây của bạn. Có khá nhiều lĩnh vực hiện nay cần đến sự giúp sức của các Data Analyst như phân tích hoạt động tiếp thị, phân tích tài chính, phân tích hoạt động,… Đừng quên chia sẻ với người phỏng vấn lĩnh vực mà bạn yêu thích và có mong muốn gắn bó để đánh giá sự thích hợp của bạn với công việc mình đang ứng tuyển.

business analyst làm gì

Thông tin về việc bạn đã từng sử dụng qua những công cụ phân tích dữ liệu nào sẽ cho thấy năng lực chuyên môn của bạn. Với câu hỏi này, hãy trình bày với nhà tuyển dụng những phần mềm bạn đã từng sử dụng, đâu là phần mềm bạn cảm thấy yêu thích nhất và thế mạnh của phần mềm đó là gì. Việc sử dụng phần mềm hiệu quả cũng là yếu tố quan trọng để nâng cao hiệu suất làm việc.

5. Khi được giao một dự án phân tích dữ liệu mới, bạn sẽ bắt đầu quy trình làm việc của mình như thế nào?

Câu hỏi này mục đích để đánh giá cách bạn xử lý vấn đề và quy trình làm việc có thật sự đáp ứng được mong đợi của nhà tuyển dụng hay không. Tùy theo cách làm việc của mình mà bạn có thể chia sẻ để nhà tuyển dụng đánh giá. Quan trọng nhất là đảm bảo được tính tối ưu về thời gian, chi phí và đạt được hiệu suất cao nhất cho dự án đó, còn lại sẽ không có bất cứ một quy chuẩn cụ thể nào yêu cầu bạn bắt buộc phải làm như thế cả.

Data Analyst là một công việc đòi hỏi tính kỹ lưỡng và cẩn thận cao. Do đó, trong suốt buổi phỏng vấn Data Analyst hãy cho nhà tuyển dụng thấy được rằng bạn là người đủ cẩn thận và đủ năng lực để đáp ứng những gì họ yêu cầu. Kinh nghiệm và bằng cấp dù quan trọng nhưng sẽ không là yếu tố quyết định tất cả. Đón đọc thêm nhiều bài viết khác về chủ đề Data Analyst tại Topdev.vn/blog nhé!

Có thể bạn quan tâm:

Xem thêm tuyển dụng IT hấp dẫn trên TopDev

Lưu RegisteredClient vào database trong Spring Authorization Server

registeredclient
Lưu RegisteredClient vào database trong Spring Authorization Server

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Trong bài viết trước, mình đã hướng dẫn các bạn cách hiện thực một Authorization Server sử dụng Spring Authorization Server, nhưng thông tin về RegisteredClient trong bài viết này được lưu trong memory. Để lưu thông tin RegisteredClient vào database thì chúng ta sẽ làm như thế nào? Trong bài viết này, mình sẽ hướng dẫn các bạn làm điều này các bạn nhé!

  Bean, ApplicationContext, Spring Bean Life Cycle và Component scan
  Authentication trong Spring Security

Xem thêm các chương trình tuyển dụng Spring lương cao trên TopDev

Đầu tiên, mình cũng tạo mới một Spring Boot project với Web Starter, Security Starter, Data JPA, PostgreSQL Driver:

và Spring Authorization Server:

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>0.2.0</version>
</dependency>

để làm ví dụ.

Kết quả:

Mình sẽ cấu hình Spring Security như trong bài viết Hiện thực OAuth Authorization Server sử dụng Spring Authorization Server như sau:

package com.huongdanjava.springauthorizationserver;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
public class SpringSecurityConfiguration {

@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests(authorizeRequests ->
authorizeRequests.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
// @formatter:on

return http.build();
}

@Bean
public UserDetailsService users() {
// @formatter:off
UserDetails user = User.withDefaultPasswordEncoder()
.username("admin")
.password("password")
.roles("ADMIN").build();
// @formatter:on

return new InMemoryUserDetailsManager(user);
}

}


Còn cấu hình cho Authorization Server, mình cũng làm tương tự như bài viết Hiện thực OAuth Authorization Server sử dụng Spring Authorization Server này nhưng phần khai báo thông tin RegisteredClient mình sẽ làm sau:

package com.huongdanjava.springauthorizationserver;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.time.Duration;
import java.util.UUID;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import org.springframework.security.oauth2.server.authorization.config.TokenSettings;
import org.springframework.security.web.SecurityFilterChain;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;

@Configuration
public class AuthorizationServerConfiguration {

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

return http.formLogin(Customizer.withDefaults()).build();
}

@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}

@Bean
public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException {
RSAKey rsaKey = generateRsa();
JWKSet jwkSet = new JWKSet(rsaKey);

return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
}

private static RSAKey generateRsa() throws NoSuchAlgorithmException {
KeyPair keyPair = generateRsaKey();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

// @formatter:off
return new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
// @formatter:on
}

private static KeyPair generateRsaKey() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);

return keyPairGenerator.generateKeyPair();
}

@Bean
public ProviderSettings providerSettings() {
// @formatter:off
return ProviderSettings.builder()
.issuer("http://localhost:8080")
.build();
// @formatter:on
}

@Bean
public TokenSettings tokenSettings() {
//@formatter:off
return TokenSettings.builder()
.accessTokenTimeToLive(Duration.ofMinutes(30L))
.build();
// @formatter:on
}
}

Để lưu thông tin RegisteredClient vào database, đầu tiên, chúng ta cần định nghĩa database structure để làm việc này.

Mặc định thì Spring Authorization Server cung cấp cho chúng ta script database để tạo database structure. Các bạn có thể copy chúng trong tập tin .jar của Spring Authorization Server:

Các bạn có thể vào Github của Spring Authorization Server ở đây để copy những tập tin này.

Mình sẽ sử dụng Flyway để quản lý database migration:

<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>

bằng cách copy những tập tin schema của Spring Authorization Server vào thư mục src/main/resources/db/migration như sau:

Trong script tạo table oauth2_authorization trong tập tin V1__oauth2-authorization-schema.sql có định nghĩa kiểu dữ liệu BLOB, có lẽ cho Oracle database:

CREATE TABLE oauth2_authorization (
id varchar(100) NOT NULL,
registered_client_id varchar(100) NOT NULL,
principal_name varchar(200) NOT NULL,
authorization_grant_type varchar(100) NOT NULL,
attributes varchar(4000) DEFAULT NULL,
state varchar(500) DEFAULT NULL,
authorization_code_value blob DEFAULT NULL,
authorization_code_issued_at timestamp DEFAULT NULL,
authorization_code_expires_at timestamp DEFAULT NULL,
authorization_code_metadata varchar(2000) DEFAULT NULL,
access_token_value blob DEFAULT NULL,
access_token_issued_at timestamp DEFAULT NULL,
access_token_expires_at timestamp DEFAULT NULL,
access_token_metadata varchar(2000) DEFAULT NULL,
access_token_type varchar(100) DEFAULT NULL,
access_token_scopes varchar(1000) DEFAULT NULL,
oidc_id_token_value blob DEFAULT NULL,
oidc_id_token_issued_at timestamp DEFAULT NULL,
oidc_id_token_expires_at timestamp DEFAULT NULL,
oidc_id_token_metadata varchar(2000) DEFAULT NULL,
refresh_token_value blob DEFAULT NULL,
refresh_token_issued_at timestamp DEFAULT NULL,
refresh_token_expires_at timestamp DEFAULT NULL,
refresh_token_metadata varchar(2000) DEFAULT NULL,
PRIMARY KEY (id)
);

Nếu các bạn đang sử dụng PostgreSQL database như mình thì cần phải đổi sang kiểu BYTEA các bạn nhé! Không thì chạy database migration sẽ bị lỗi.

Khai báo Datasource để chạy database migration như sau:

spring.datasource.url=jdbc:postgresql://localhost:5432/authorization_server
spring.datasource.username=khanh
spring.datasource.password=1

Giờ thì các bạn có thể định nghĩa RegisteredClient trong database, ví dụ như sau:

@Bean
public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {
// @formatter:off
RegisteredClient registeredClient = RegisteredClient.withId("e4a295f7-0a5f-4cbc-bcd3-d870243d1b05")
.clientId("huongdanjava1")
.clientSecret("123")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.tokenSettings(tokenSettings())
.build();
// @formatter:on

JdbcRegisteredClientRepository registeredClientRepository =
new JdbcRegisteredClientRepository(jdbcTemplate);
registeredClientRepository.save(registeredClient);

return registeredClientRepository;
}

Ở đây, mình định nghĩa một RegisteredClient với grant type là client_credentials với ID cố định để mỗi khi start app, không có duplicate record trong database. Tuỳ theo nhu cầu thì các bạn hãy viết code tương ứng nhé!

Chúng ta sẽ sử dụng đối tượng JdbcRegisteredClientRepository để lưu thông tin RegisteredClient này. Tham số khi khởi tạo đối tượng JdbcRegisteredClientRepository là JdbcTemplate.

Lúc này, nếu chạy ứng dụng lên các bạn sẽ thấy trong table oauth2_registered_client, một record mới của RegisteredClient mà mình đã khai báo ở trên được insert vào:

Các bạn cũng nên để ý là client secret được mã hoá sử dụng class DelegatingPasswordEncoder với thuật toán bcrypt. Hiện tại chúng ta chưa thể khai báo thuật toán mà mình muốn!

Xong rồi đó các bạn, nếu bây giờ các bạn chạy ứng dụng và lấy token của clientId ở trên, các bạn sẽ thấy kết quả như sau:

Tải Windows 10 Với Giá $8.19 & Miễn Phí Nâng Cấp Phiên Bản Windows 11

Hệ điều hành Windows 11 vượt trội chính thức ra mắt vào 05/10/2021 là phiên bản nâng cấp hoàn toàn miễn phí cho người dùng hiện tại đang sử dụng Windows 10.

Chỉ cần bạn là người mua Windows 10, bạn có cơ hội lựa chọn nâng cấp lên Windows 11 mà không phải trả thêm bất kỳ chi phí nào. Trong trường hợp máy của bạn chưa được cài đặt Windows 10, Keysoff.com cung cấp những ưu đãi tốt nhất về giải pháp an toàn, không rắc rối và tiết kiệm cho phần mềm Windows 10.

Nhận ưu đãi tốt nhất cho Windows 10 chỉ từ 8.19$

Keysoff.com mong muốn mang đến gói ưu đãi tiết kiệm nhất đối với các sản phẩm phần mềm với mức giá phù hợp để bạn có thể tận hưởng dịch vụ khách hàng đặc biệt cho trải nghiệm mua hàng.

Nâng cấp hệ điều hành Windows nhanh nhất với mức giảm giá ưu đãi 40%

Windows 10 là phiên bản hệ điều hành nhanh nhất và an toàn nhất cho đến thời điểm hiện tại. Bạn đang thiếu rất nhiều tính năng và ưu điểm xử lý giúp máy tính hoạt động hiểu quả hơn khi chưa cài Windows 10 cho máy tính của mình. Bạn có thể sở hữu key win bản quyền Windows 10 chính quyền trong chương trình ưu đãi của Keysoff.com và được giảm giá 40% khi áp dụng mã khuyến mãi “ESL40“.

Hoàn thành nhiều hơn với thời gian ngắn với MS Office cùng mức giảm giá 55%

Bộ phần mềm tối ưu MS Office giúp bạn hoàn thành nhiều công việc trong thời gian ngắn. Keysoff.com đưa ra ưu đãi lớn 55% trong chương trình khuyến mãi mùa thu cho 2 phiên bản MS Office 2016 và 2019 khi áp dụng mã giảm giá “ESL55” khi thanh toán.

Chúng tôi cung cấp nhiều công cụ phần mềm giúp bạn làm việc và học tập trên máy tính thoải mái hơn, an toàn hơn với mức giá ưu đãi cho toàn bộ sản phẩm và giảm giá tới 90% trong dịp khuyến mãi mùa hè với phiên bản tải về chính thức và dễ dàng cài đặt. Đừng bỏ lỡ dịp khuyến mãi lớn này.