EzyPlatform xử lý lỗi tập trung thế nào?

Exception là một trong những tính năng cực kỳ mạnh của java, nó cho phép các nhà phát triển xử lý lỗi khi cần thiết thay vì lúc nào cũng phải xử lý lỗi, ví dụ thay vì code thế này: public void step1() { if (correct) { return result; } return error; } public void step2() { var result, error = step1(); if (error != null) { return error; } return process2(result); } public void step3() { var result, error = step2(); if (error != null) { return error; } return process3(result); } Thì bạn chỉ cần viết thế này: public void step1() { if (correct) { return result; } throw new Exception("somthing"); } public void step2() { return process2(step1()); } public void step3() { try { return process3(result); } catch(Exception e) { // process error } } Mã nguồn sẽ ngắn gọn hơn rất nhiều. Với EzyPlatform thậm chí mọi việc còn đơn giản hơn thế khi các Exception được xử lý tập trung ở các lớp global, sẽ tiết kiệm công sức rất nhiều cho các nhà phát triển. Đường đi của một exception Tương ứng với đường đi của một yêu cầu đến và được xử lý bởi EzyPlatform thì exception cũng sẽ được sinh ra trong quá trình này: Tại servlet cũng có thể ném ra các exception hoặc các lỗi như không tìm thấy URI nào khớp với yêu cầu từ client gửi đến. Tại các interceptor cũng có thể ném ra các exception để không cho phép yêu cầu được đến controller. Tại các controller các nhà phát triển có thể ném ra các exception tương ứng với nghiệp vụ mà mình xử lý. Khi một exception được ném ra thì nó sẽ không rơi vào hố đen hay gây crash chương trình bởi vì EzyPlatform được thừa hưởng từ EzyHTTP và EzyFox Server sẽ điều hướng toàn bộ các exception này đến các lớp xử lý tập trung. Nếu exception không được xử lý thì nó sẽ được coi là lỗi và được xử lý bởi các lớp cài đặt giao diện UnhandledErrorHandler, nếu không tồn tại lớp xử lý lỗi thì mặc định EzyPlatform sẽ trả về trạng thái INTERNAL_SERVER_ERROR. Một số lớp xử lý exception do EzyPlatform cung cấp Ở admin đã có sẵn lớp xử lý exception chung có tên AdminGlobalExceptionHandler với mã nguồn như sau: @ExceptionHandler @AllArgsConstructor public class AdminGlobalExceptionHandler extends EzyLoggable { private final RequestURIManager requestUriManager; @TryCatch(ProjectMissingDependenciesException.class) public Object handle(ProjectMissingDependenciesException e) { logger.info("{}({})", e.getClass().getSimpleName(), e.getMessage()); return ResponseEntity.builder() .status(StatusCodes.FORBIDDEN) .body( singletonMap( "projectMissingDependencies", e.getMissingDependencies() ) ) .build(); } // các hàm xử lý khác. @TryCatch(DeserializeValueException.class) public Object handle( HttpServletRequest request, RequestArguments arguments, DeserializeValueException e ) { logger.info("{}({})", e.getClass().getSimpleName(), e.getMessage(), e); HttpMethod method = arguments.getMethod(); String uriTemplate = arguments.getUriTemplate(); if (requestUriManager.isApiURI(method, uriTemplate)) { return ResponseEntity.badRequest( singletonMap( e.getValueName(), "invalid" ) ); } return Redirect.to(addLanguageToUri(request, "/bad-request")); } } Lớp này xử lý gần toàn bộ các exception thông thường mà bạn hay dùng ví dụ như PermissionDeniedException, ForbiddenActionException vậy nên khi phát triển các plugin phần admin bạn cũng sẽ gần như không bao giờ phải xử lý exception nữa. Đối với các exception hoặc các lỗi không được xử lý thì lớp AdminGlobalErrorHandler sẽ tiếp nhận và làm công việc của mình với mã nguồn như sau: @EzySingleton @AllArgsConstructor public class AdminGlobalErrorHandler extends EzyLoggable implements UnhandledErrorHandler { private final AdminViewFactory viewFactory; private final AdminMenuManager menuManager; private final RequestURIManager requestUriManager; private final AdminEnvironmentManager environmentManager; @Override public Object processError( HttpMethod method, HttpServletRequest request, HttpServletResponse response, int errorStatusCode, Exception exception ) { if (environmentManager.isDebugMode()) { logger.info( "process error for request uri: {}, params: {}", request.getRequestURI(), request.getQueryString(), exception ); } String matchedUri = (String) request.getAttribute(ATTRIBUTE_MATCHED_URI); if (matchedUri == null) { matchedUri = request.getRequestURI(); } boolean isApiUri = method != HttpMethod.GET || requestUriManager.isApiURI(method, matchedUri); if (isApiUri) { return toResponseEntity(errorStatusCode, exception); } Menu menu = menuManager.getMenuByUri(matchedUri); if (menu == null) { MenuItem menuItem = menuManager.getMenuItemByUri(matchedUri); if (menuItem != null) { menu = menuManager.getMenuByFullName(menuItem.getMenuFullName()); } } if (menu == null) { return processError(request, errorStatusCode, exception); } return viewFactory.newViewBuilder() .template("default-menus") .addVariable("menu", menu) .build(); } private Object processError( HttpServletRequest request, int errorStatusCode, Exception exception ) { if (environmentManager.isDebugMode()) { return toResponseEntity(errorStatusCode, exception); } if (errorStatusCode == StatusCodes.NOT_ACCEPTABLE) { return ResponseEntity .status(StatusCodes.NOT_ACCEPTABLE) .build(); } else if (errorStatusCode == StatusCodes.INTERNAL_SERVER_ERROR) { return Redirect.builder() .uri(addLanguageToUri(request, "/server-error")) .addAttribute( "exceptionMessage", exceptionToSimpleString(exception) ) .build(); } else if (errorStatusCode == StatusCodes.BAD_REQUEST) { return Redirect.to(addLanguageToUri(request, "/bad-request")); } return Redirect.to(addLanguageToUri(request, "/not-found")); } private ResponseEntity toResponseEntity( int errorStatusCode, Exception exception ) { return ResponseEntity.status(errorStatusCode) .body( Collections.singletonMap( "error", exception != null ? exception.getClass().getName() : String.valueOf(errorStatusCode) ) ) .build(); } } Ở đây nó cũng không làm gì nhiều, chỉ đơn giản là kiểm tra xem loại lỗi là gì để trả về một trang mặc định hay trả về dữ liệu dạng json. Đối với web thì EzyPlatform cũng cung cấp sẵn hai lớp WebGlobalExceptionHandler, WebGlobalErrorHandler các nhà phát triển có thể thừa kế hai lớp này hoặc khai báo các lớp mới để xử lý các exception do mình tạo ra, ví dụ: @ExceptionHandler public class ElearningGlobalExceptionHandler extends WebGlobalExceptionHandler {} @EzySingleton public class ElearningGlobalErrorHandler extends WebGlobalErrorHandler {} Tổng kết lại Xử lý exception là một trong những công việc tương đối dễ bỏ sót hoặc xử lý chồng chéo. Việc EzyPlatform gom lại toàn bộ các exception vào một nơi để xử lý sẽ giúp phần mềm của chúng ta an toàn hơn, hoạt động ổn định hơn, đồng thời cũng giúp cho việc phát triển nhanh chóng hơn.

Phân tích SWOT: Hoạt động không thể bỏ qua khi lập kế hoạch Marketing

Chắc hẳn ai trong số những người làm marketing, kể cả là những người mới bắt đầu cũng đã từng nghe đến cụm từ SWOT. Mô hình này đã trở nên quá phổ biến hiện nay bởi lẽ dù cho doanh nghiệp của bạn có quy mô là 1 thành viên hay 500 thành viên, phân tích SWOT vẫn luôn là một cách hiệu quả để đánh giá công ty, dự án của bạn.Tổng quan về mô hình SWOT Khái niệm SWOT được phát triển bởi các giáo sư Kenneth Andrews và Roland Christensen vào những năm 1960. Mục đích ban đầu là cung cấp một công cụ giúp các công ty cải thiện quy trình lập kế hoạch chiến lược, nhấn mạnh tầm quan trọng của việc phân tích và đánh giá các yếu tố ảnh hưởng đến hoạt động kinh doanh. SWOT là từ viết tắt cho bốn yếu tố cơ bản:Điểm mạnh (Strengths): Những đặc điểm tích cực và lợi thế cạnh tranh mà tổ chức sở hữu. Đây có thể là có độ nhận diện thương hiệu tốt, đội ngũ nhân viên chất lượng, sản phẩm xuất sắc, hoặc vị trí địa lý thuận lợi,...Điểm yếu (Weaknesses): Những hạn chế hoặc khuyết điểm cần khắc phục trong tổ chức. Chúng có thể bao gồm dịch vụ khách hàng kém, thiếu hụt nguồn lực, hoặc quy trình làm việc không hiệu quả, thiếu một USP được xác định rõ ràng,...Cơ hội (Opportunities): Những yếu tố tích cực trong môi trường bên ngoài có thể mang lại lợi ích cho tổ chức. Các cơ hội có thể được tạo ra từ xu hướng thị trường, những công nghệ mới, hoặc các thay đổi trong quy định pháp luật.Thách thức (Threats): Những yếu tố bên ngoài có thể gây ra rủi ro hoặc khó khăn cho tổ chức. Những thách thức - Mối đe dọa này có thể là sự cạnh tranh gia tăng, biến động kinh tế, hoặc thay đổi trong nhu cầu của khách hàng,...Kết luận: Sau khi phân tích đầy đủ 4 nội dung, bạn cần đưa ra 1 số kết luận cụ thể. Bạn có thể dựa vào mối liên hệ giữa các yếu tố trên:SO: lấy điểm mạnh để tận dụng cơ hộiST: lấy điểm mạnh để hạn chế rủi ro, vượt qua thách thứcWO: lấy hạn chế, yếu điểm để làm được cơ hộiWT: hạn chế điểm yếu để tránh thách thứcNhững lưu ý về cách trình bày SWOTĐể phân tích được 4 yếu tố trong mô hình SWOT trên, bạn cần nghiên cứu rất kỹ về 2 phương diện:Nội bộ: bao gồm Điểm yếu và Điểm mạnh của công tyNgoại bộ: bao gồm Cơ hội, Thách thức nào từ bên ngoài có ảnh hưởng đến công ty doanh nghiệp của bạnĐể trình bày một cách dễ hiểu và hiệu quả, mỗi yếu tố trong mô hình SWOT thường được trình bày thành một nội dung riêng (thường được chia thành mỗi cột trong 1 bảng).Ví dụ cụ thể về SWOTPhân tích SWOT ví điện tử Momo  Kết luậnPhân tích mô hình SWOT là một công cụ phổ biến và hiệu quả để bạn nắm được tình hình nội bộ của doanh nghiệp, giúp doanh nghiệp có cái nhìn toàn diện về vị trí của mình trong thị trường.

Tìm kiếm Assets, Khởi tạo Scene và quản lý mã nguồn

Như bài trước, chúng mình đã giới thiệu các bạn tổng quan về Unity về cách tải và giao diện Unity Editor. Với tiếp nối, thì bọn mình sẽ đem đến các bạn, cách để tìm kiếm Assets, khởi tạo scene và quản lý mã nguồn. 1. Chuẩn bị Assets: a) Tải Assets:Các bạn có thể tìm kiếm hình ảnh các quân cờ và bàn cờ trên các nền tảng cung cấp Assets nổi tiếng như Unity Assets Store hoặc Itch.io để tải và sử dụng. Lưu ý là các bạn nên tìm kiếm các assets cung cấp bản quyền (Licence) sử dụng và sửa chửa nhé.b) Đưa Assets vào Project:Sau khi các bạn đã chuẩn bị xong các hình ảnh quân cờ và bàn cờ, các bạn có thể import vào Unity bằng cách như sau: Cách 1: Import thông qua Package Manager của Unity (Window -> Package Manager). Cách 2: Kéo folder chứa Assets bạn cần vào thẳng Project. Lưu ý là các bạn nên bỏ trong thư mục Assets và tạo sắp xếp thư mục như bài trước. 2. Tạo Scene và Khởi tạo Script: a) Tạo Scene:Định nghĩa Scene:Đầu tiên là tạo scene, vậy thì phải hiểu scene là gì, scene ở đây là một thành phần cơ bản trong hệ thống của Unity. Scene đại diện cho một không gian làm việc hoặc môi trường trong game. Nó là nơi bạn tổ chức các đối tượng (objects), ánh sáng, camera, âm thanh, và các yếu tố khác tạo nên trò chơi hoặc ứng dụng.Nói về scene thì mình cũng sẽ nói sơ qua 1 chút về các hệ trục tọa độ trong Unity, thì Unity về cơ bản sẽ có 4 hệ trục tọa độ: Trục thế giới (World Coordinate System): là hệ trục 3D của thế giới trong Unity 3d, đây cũng là trục cố định và áp dụng cho tất cả các gameobject có trong 1 scene. Trục tọa độ màn hình (Screen Coordinate System): là hệ trục 2D được tính bằng pixel, được tính từ (0, 0) góc dưới bên trái màn hình và tính tới (Screen.width, Sceen.height), hệ trục này sẽ thay đổi tùy vào tỷ lệ / độ phân giải của màn hình của thiết bị. Trục GUI (GUI Coordinate System): hệ trục này khá tương tự hệ trục tọa độ màn hình chỉ khác là điểm bắt đầu (0, 0) được tính từ góc trên bên trái màn hình. Trục GUI (GUI Coordinate System): Trục viewport (Viewport Coordinate System): hệ trục này cũng khá giống 2 trục màn hình và GUI, tuy nhiên nó không bị phụ thuộc vào tỷ lệ / độ phân giải của màn hình thiết bị, mà nó sẽ là cố định, hệ này sẽ tính từ điểm dưới bên trái màn hình (0, 0) tới điểm trên bên phải màn hình (1, 1), vd điểm (0.5, 0.5) luôn luôn ở giữa màn hình cho dù là thiết bị có độ phân giải là bao nhiêu. Hướng dẫn tạo Scene: Các bạn từ thư mục scene đã tạo trước đó, chuột phải vào sau đó chọn Create, chọn Scene, 1 scene mới sẽ được tạo. Mặc định Unity khi khởi tạo sẽ có 1 scene trống, tuy nhiên vì mình tính sẽ làm 2 scene, 1 để làm main menu, 1 cho game nên mình sẽ tạo thêm 1 scene đặt tên là Start và Game. b) Khởi tạo script: Tạm bỏ qua scene Start, mình sẽ tập trung vào scene Game trước, trước tiên mình sẽ hướng dẫn tạo gameobject (Gameobject là một đối tượng cơ bản trong mọi Scene - có thể hiển thị hoặc không hiển thị nhưng ở trong scene thì đều là gameobject, và là thành phần trung tâm của hệ thống Unity. GameObject có thể xem là 1 hộp chứa dùng để tổ chức và quản lý các thành phần (components), giúp tạo ra các đối tượng trong game hoặc ứng dụng. Tạo gameobject: Các bạn cũng bấm chuột phải vào cửa sổ Hierachy, chọn xuống create empty vậy là xong, 1 object empty đã được tạo, thì với gameobject này sẽ không có bất kỳ thành phần (component) nào khác ngoài Transform. Transform là gì: Thì về cơ bản nó là một component bắt buộc gắn với mọi GameObject. Transform xác định vị trí (position), góc xoay (rotation), và kích thước (scale) của GameObject trong không gian 3D hoặc 2D. Tiếp đến mình vào folder Scripts, chuột phải chọn Create/Folder, đặt tên folder là Managers để chứa tất cả script quản lý của game ở đây. Tiếp theo trong folder Managers mình tiếp tục chuột phải chọn Create/Scripts đặt tên script mới tạo là GameManager. Mở script lên, mặc định thì class của chúng ta sẽ được kế thừa lớp Monobehavior của Unity, và sẽ có 2 hàm mặc định là Start() và Update() như sau. using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameManager : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } } Mình sẽ nói sơ qua về những thứ mới ở đây, đầu tiên là MonoBehavior nó là 1 lớp cơ bản trong Unity, nếu muốn gắn script vào gameobject chúng ta bắt buộc phải kế thừa MonoBehavior. Monobehavior sẽ cung cấp cho chúng ta các phương thức và tính năng cần thiết để tương tác với gameobject, cũng như là vòng đời, quản lý sự kiện và điều khiển hành vi của gameobject trong Unity. Về vòng đời của script các bạn có thể tham khảo: Unity - Manual: Order of execution for event functions Còn về 2 phương thức mặc định là Start và Update thì về cơ bản, khi 1 gameobject được khởi chạy, thì script có hàm Start được gắn vào gameobject sẽ khởi chạy 1 lần, còn update sẽ được gọi xuyên suốt chương trình cho đến khi gameobject bị phá hủy, hàm update sẽ được gọi mỗi 1 lần mỗi frame (vì vậy nên hàm này cũng nên sử dụng 1 cách có tính toán vì nếu lạm dụng có thể gây nặng chương trình ảnh hưởng tới game) Tác giả: Nguyễn Minh Thuận

Bí quyết công nghệ của EzyPlatform - Cách chống DDoS socket

DDoS là một kiểu tấn công vô cùng nhức nhối khi sản phẩm của chúng ta có số lượng người dùng tăng cao và bị để mắt bởi các hacker, không có một phương pháp nào hiệu quả một 100% đối với các cuộc tấn công DDoS vậy nên sẽ cần phải kết hợp cả các giải pháp từ phần cứng cho đến phần mềm. May mắn là EzyPlatform đã được thừa hưởng giải pháp từ EzyFox Server.Tấn công DDoS là gì? Là một cách thức của kẻ tấn công làm cho máy chủ của chúng ta không thể nhận thêm bất kì yêu cầu nào nữa, dẫn đến việc không thể phục vụ bất kỳ người dùng nào. Người dùng có thể chờ mãi không đăng nhập được hay không sử dụng được bất kỳ dịch vụ nào. Về cơ bản có 2 kiểu tấn công chính: Kẻ tấn công khai thác lỗ hổng từ một API xử lý rất nặng nào đó, và gửi request liên tục vào đây làm cho server dùng toàn bộ tài nguyên chỉ để phục vụ cho kẻ tấn công này. Kẻ tấn công sử dụng nhiều nguồn tài nguyên gấp rất nhiều lần khả năng chịu đựng của server, khiến cho nó không còn khả năng chấp nhận những request khác nữa. Đối với trường hợp thứ 2, nếu kẻ tấn công có thể huy động được hàng nghìn thiết bị để giả lập giống như user thật điều đó sẽ rất khó để chống đỡ, vì trong 1 luồng dữ liệu socket, việc xử lý 1 request là tương đối nặng nề. Về phía phần mềm thì EzyPlatform và EzyFox Server cung cấp một loạt các giải pháp để chống DDoS như sau: Sử dụng hữu hạn số thread. Hạn chế số lượng session. Hạn chế số lượng request. Phân phối đều tài nguyên. Sử dụng hữu hạn số lượng thread Nếu bạn tưởng tượng cứ mỗi một yêu cầu gửi đến thì EzyFox Server sẽ lại tạo ra một luồng để xử lý kiểu này: Thread newThread(() => process(request)); newThread.start(); Thì không phải phải như vậy. Bởi vì máy tính cũng có số lượng hữu hạn số luồng, mỗi luồng lại tiêu tốn một tài nguyên nhất định, ví dụ mỗi luồng tiêu tốn 2MB và có 1,000 yêu cầu đồng thời như vậy sẽ tiêu tốn hết 2GB bộ nhớ và điều này không ổn. Chính vì vậy mà EzyPlatform và EzyFox Server sử dụng hữu hạn số lượng thread thông qua cơ chế thread pool, nghĩa là một yêu cầu khi gửi đến sẽ không được xử lý ngay lập tức bởi một thread mà được đưa vào trong một hàng đợi và được xử lý khi có một thread nhàn rỗi. Tuy nhiên không chỉ có một mà có rất nhiều thread pool tồn tại trong EzyPlatform và EzyFox Server cho các mục đích khác nhau, bạn có thể tuỳ chỉnh thông qua cấu hình: <thread-pool-size> <statistics>1</statistics> <stream-handler>8</stream-handler> <socket-data-receiver>8</socket-data-receiver> <system-request-handler>8</system-request-handler> <extension-request-handler>8</extension-request-handler> <socket-disconnection-handler>2</socket-disconnection-handler> <socket-user-removal-handler>3</socket-user-removal-handler> </thread-pool-size> Hạn chế số lượng session Mỗi client sẽ được đại diện bởi 1 session, và mỗi một session lại chiếm một số lượng tài nguyên nhất định, nên cần giữ số lượng session ở mức thấp nhất có thể. Như đã đề cập trong bài trước EzyFox Server sử dụng 1 thread để thanh tra và loại bỏ các loại session: Đã quá thời gian đăng nhập cho phép. Đã quá lâu không có request nào gửi đến server. Một session nếu muốn giữ kết nối với server phải gửi command ping định kì, có thể 3 hoặc 5 giây tuỳ theo bạn cấu hình. Nếu quá 15 giây mà không có bất kì lệnh ping nào chẳng gửi đến server chẳng hạn, server sẽ chủ động ngắt kết nối với session này. Hạn chế số lượng request Sẽ có rất nhiều request được gửi đến EzyPlatform và EzyFox Server, tuy nhiên nó cần giới hạn số lượng request tối đa cho một client, ví dụ như trong hình, server sẽ chỉ chấp nhận các request màu xanh tại 1 thời điểm, còn những request màu đỏ, do vượt quá số lượng mà server có thể chịu tải sẽ bị drop và không được xử lý. Các request cũng sẽ không được xử lý ngay, mà còn phải trải qua 1 quá trình điều phối xoay vòng để có thể đảm bảo tài nguyên được phân phối một cách hợp lý. Điều này sẽ bắt buộc kẻ tấn công phải huy động rất nhiều máy hoặc nhiều IP khác nhau để tấn công EzyPlatform, mặc dù nó không thể đảm bảo 100% chống toàn bộ cuộc tấn công nhưng cũng sẽ gây cản trở và làm nản lòng kẻ tấn công. Phân phối đều tài nguyên Để server không chỉ phục vụ duy nhất 1 client nào đó, chúng ta cần phải xử dụng cơ chế "băng đạn tròn" để xoay tua liên tục. Mỗi client sẽ có 1 request queue, mỗi lần xử lý sẽ lấy 1 request từ một queue và rồi lại cho queue này về cuối. Ví dụ: Queue1: A1, A2, A3 Queue2: B1, B2, B3 Queue3: C1, C2, C3 Lượt xử lý đầu tiên sẽ lấy A3 ra để xử lý và trạng thái sẽ là: Queue2: B1, B2, B3 Queue3: C1, C2, C3 Queue1: A1, A2 Lượt xử lý tiếp theo sẽ lấy B3 ra để xử lý và trạng thái sẽ là: Queue3: C1, C2, C3 Queue1: A1, A2 Queue2: B1, B2 Cứ như vậy cho đến khi nào các queue rỗng hết thì thôi. Điều này sẽ đảm bảo server sẽ phục vụ đều cho tất cả client và buộc kẻ tấn công phải liên tục nhồi request vào EzyPlatform, chỉ cần dừng tấn công server lại hoạt động bình thường. Cấu hình Bạn có thể tìm thấy cấu hình cho phần chống DDoS của EzyPlatform trong tập tin socket/settings/ezy-settings.xml đoạn mã: <session-management> <session-max-idle-time>15</session-max-idle-time> <session-max-waiting-time>30</session-max-waiting-time> <session-max-request-per-second> <value>20</value> <action>DISCONNECT_SESSION</action> </session-max-request-per-second> </session-management> Tổng kết Tấn công DDoS không phải là hiếm gặp và khó chống đỡ 100%, sẽ yêu cầu cả giải pháp phần cứng và phần mềm. Về phần mềm thì EzyPlatform đã đưa ra các giải pháp tương đối trọn vẹn để đảo bảo server sẽ hoạt động ổn định và sống sót qua cuộc tấn công DDoS thông qua các cơ chế phân phối tài nguyên đều và hợp lý, sử dụng hữu hạn số thread thông qua hàng đợi và thread pool.

Bí quyết công nghệ của EzyPlatform - Định dạnh gói tin socket

Trong EzyPlatform và EzyFox Server tồn tại 3 giao thức là: TCP, UDP và Websocket. Websocket sẽ sử dụng định dạng gói tin kiểu JSON, nguyên do của việc này là Websocket được sử dụng chủ yếu cho web nên JSON sẽ dễ gỡ lỗi hơn và cũng dễ lập trình hơn cho các nhà phát triển front-end. Tuy nhiên TCP, UDP thường được sử dụng cho phần mềm chạy trên các thiết bị di động, IoT hay desktop, sẽ là cơ hội tuyệt vời để EzyPlatform và EzyFox Server đưa các kỹ thuật vào để tối ưu dung lượng gói tin.Định dạng gói tin là gì? Là một cách thức mô tả thành phần của một gói tin, ví dụ: [header][body] Đây là định dạng của một gói tin có phần đầu (header) và phần thân (body), với dữ liệu cụ thể ta có thể có: [chiều dài = 11, kiểu = chuỗi][Hello World] Thì phần đầu sẽ có các dữ liệu mô tả chiều dài và kiểu của phần thân, còn phần thân sẽ chứa dữ liệu thực tế. Một ví dụ khác về định dạng gói tin dạng json: { "message": "Hello World" } Định dạng này không có header nhưng lại yêu cầu phải có các ký tự { và } để thể hiện việc bắt đầu và kết thúc gói tin. Tại sao một gói tin lại cần định dạng? Một thông điệp trong thực tế sẽ dễ bị chia nhỏ thành các phần khác khi gửi nhận qua mạng, ví dụ thông điệp: Hello World Có thể bị chia thành 2 lần gửi là Hello và World. Cùng với đó server sẽ phải đợi cho một gói tin có đầy đủ thì mới được xử lý chứ không được xử lý một phần, chính vì vậy mà chúng ta sẽ cần định dạng để biết đâu là một gói tin đầy đủ, đâu là chưa. Định dạng gói tin của EzyPlatform socket Một gói tin của EzyPlatform và EzyFox Server socket sẽ có 2 thành phần chính: Header: dùng để mô tả thông tin của gói tin. Payload: là nơi chứa thông tin thực tế của một gói tin. Hai thành phần tuỳ chọn bao gồm: Header dự trữ: trong trường hợp 1 byte là không đủ, chúng ta có thể sử dụng thêm các byte khác để làm header. Payload Length: dùng để lưu kích thước của Payload. Định dạng phần header Theo tư duy thông thường chúng ta sẽ tổ chức header thế này cho tường minh: { "isBigSize": true, "isEncrypted": true, "isCompressed": true, "isText": true, "isRawBytes": true, "isUdpHandshake": true } Tuy nhiên nếu mỗi ký tự là một byte thì cách này lại quá tốn, chính vì vậy mà EzyFox Server có cách tổ thức như sau: Bit đầu tiên: định nghĩa rằng gói tin này là là lớn hay nhỏ, nếu lớn thì PayLoad Length sẽ có kích thước tối đa là 4 bytes tương đương với 2^31 - 1 bytes, và nếu gói tin này là nhỏ thì PayLoad Length sẽ có kích thước tối đa là 2 bytes tương đương với 2^16-1 bytes. Bit thứ 2: định nghĩa rằng gói tin này bị mã hoá hay không Bit thứ 3: định nghĩa gói tin này có bị nén 2 không Bit thứ 4: định nghĩa gói tin này là text hay là byte array Bit thứ 5: định nghĩa gói tin này có cấu trúc không hay chỉ là mảng byte đơn thuần Bit thứ 6: định nghĩa gói tin này có phải là bản tin bắt tay của UDP hay không Bit thứ 7: dùng để dự trữ Bit thứ 8: dùng để định nghĩa rằng có 1 byte làm header nữa hay không. Theo cách này chúng ta sẽ chỉ cần sử dụng 1 byte thay vì hàng trăm byte, ngoài ra vẫn có thể mở rộng được phần header khi chỉ cần chỉ định bit thứ 8 là 1. Định dạng phần body Trên thực tế EzyPlatform và EzyFox Server không bắt buộc phải sử dụng một định dạng cố định, bạn có thể tuỳ ý cài đặt định dang mà mình muốn, nhưng mặc định thì sẽ là MsgPack. Đây là một định dạng gói tin gần giống json tuy nhiên nó lại sử dụng các bit đầu của một byte để làm đặc tả thay vì chuỗi. Ví dụ thay vì dùng 4 byte để mô tả cho giá trị integer 1 thì MsgPack dùng 1 byte duy nhất với các bit là 00000001. Đối với chuỗi Hello World thì MsgPack sẽ chỉ cần mất thêm 1 byte để mô tả về độ dài của chuỗi thay vì phải mất 2 byte cho 2 ký tự ", và chuỗi Hello World sẽ được chuyển thành byte array như sau: [171, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100] Bạn có thể tìm thấy cài đặt tại module ezyfox-msgpack. Tổng kết Định dạng gói tin cho EzyPlatform và EzyFox Server socket được thiết kế sao cho nó tốn ít dung lượng nhất có thể để tối ưu tốc độ gửi nhận giữa client và server. Một gói tin sẽ chỉ mất một byte cho header và phần body mặc định sẽ được sử dụng MsgPack để hỗ trợ tự động cho các nhà phát triển tối thiểu hoá dữ liệu gửi nhận qua mạng.

Nghiên cứu thị trường là gì? Các bước để nghiên cứu thị trường chi tiết nhất hiện nay

“Biết mình biết ta, trăm trận trăm thắng” – câu nói nổi tiếng này không chỉ đúng trong chiến trận mà còn áp dụng hoàn hảo trong marketing. Đó chính là lý do tại sao nghiên cứu thị trường trở thành bước đi đầu tiên và không thể thiếu trong mọi chiến lược marketing.Vậy nghiên cứu thị trường là gì?Nghiên cứu thị trường (Market Research) là quá trình thu thập, phân tích dữ liệu về thị trường, khách hàng, và các yếu tố liên quan như market size (quy mô thị trường), market growth (tiềm năng phát triển của thị trường), market trend (xu hướng thị trường), phân khúc thị trường,... nhằm hỗ trợ doanh nghiệp đưa ra quyết định đúng đắn.Ứng dụng của nghiên cứu thị trườngĐánh giá tính khả thi của sản phẩm hoặc dịch vụ mới: Trước khi ra mắt, nghiên cứu thị trường giúp doanh nghiệp phân tích nhu cầu, đánh giá phản ứng của khách hàng và giảm thiểu rủi ro thất bại.Xác định phân khúc hoặc thị trường chưa được khai thác: Nghiên cứu thị trường giúp nhận diện những cơ hội mới, đặc biệt là các thị trường ngách chưa được đối thủ khai thác.Dự đoán xu hướng thị trường: Bằng cách phân tích dữ liệu thị trường, doanh nghiệp có thể dự đoán các xu hướng kinh doanh trong tương lai và chuẩn bị các chiến lược đón đầu.Điều chỉnh chiến lược tiếp thị và định giá: Thông tin về sở thích, thói quen và khả năng chi tiêu của khách hàng giúp doanh nghiệp đưa ra các chiến lược định vị sản phẩm và định giá phù hợp hơn.Giảm thiểu rủi ro: Bằng việc hiểu kỹ về thị trường, doanh nghiệp sẽ hạn chế những quyết định sai lầm gây tổn thất cho doanh nghiệp.Gợi ý chi tiết các bước để nghiên cứu thị trường hiệu quảCó rất nhiều cách để nghiên cứu thị trường và không có một khuân mẫu nào dành cho công việc này. Trong bài viết này, mình sẽ gợi ý các bước để nghiên cứu thị trường hiệu quả thông qua những mô hình nghiên cứu nổi tiếng. Bạn có thể tham khảo và thử áp dụng, sau đó tự điều chỉnh theo nhu cầu:Bước 1: Nghiên cứu và phân tích theo mô hình 3C hoặc mô hình 5CCả 2 mô hình đều rất phổ biến và được ưa chuộng khi nghiên cứu thị trường. Tuy nhiên, mô hình 5C sẽ đem đến cái nhìn toàn diện hơn. Cụ thể mô hình 5C bao gồm:Công ty (Company)Xác định cá tính thương hiệu và văn hóa doanh nghiệp.Đánh giá điểm mạnh và điểm yếu so với đối thủ.Đặt mục tiêu cụ thể cho thị trường.Khách hàng (Customers)Hiểu rõ đặc điểm và nhu cầu của khách hàng mục tiêu.Xác định quy mô và hành vi tiêu dùng của tệp khách hàng.Dự đoán những thay đổi trong hành vi tiêu dùng.Đối thủ cạnh tranh (Competitors)Nhận diện đối thủ trực tiếp và gián tiếp.Phân tích điểm mạnh/yếu về sản phẩm, marketing, truyền thông.Đánh giá thị phần của đối thủ.Đối tác (Collaborators)Xây dựng mối quan hệ chiến lược với đối tác.Tìm cách gia tăng sự ưu tiên trong hợp tác.Môi trường kinh doanh (Climate)Phân tích tác động của môi trường vi mô và vĩ mô đến doanh nghiệp.Dự đoán các yếu tố trong tương lai và đưa ra phương án ứng phó.Bước 2: Phân tích SWOTSWOT là mô hình giúp doanh nghiệp hiểu rõ nội tại của mình. Trong SWOT bao gồm:Strengths - Điểm mạnhWeaknesses - Điểm yếuOpportunities - Cơ hộiThreats - Thách thứcBước 3: Phân Tích STPSegmentation (Phân khúc): Chia thị trường thành từng nhóm khách hàng với đặc điểm riêng biệt.Targeting (Chọn mục tiêu): Tập trung vào phân khúc phù hợp nhất với chiến lược của doanh nghiệp.Positioning (Định vị): Định vị thương hiệu trong tâm trí khách hàng, tạo sự khác biệt.Bước 4: Lựa chọn chiến lược marketingTừ bức tranh tổng quan ở trên, bạn có thể lựa chọn chiến lược marketing phù hợp nhất với doanh nghiệp của bạn trong giai đoạn này. Thông thường, những chiến dịch marketing - mix sẽ được ưu tiên lựa chọn bởi tính linh hoạt và toàn diện. Một số mô hình bạn có thể lựa chọn là 4P, 4C, 7P...Nếu bạn vẫn chưa hiểu các yếu tố trong mô hình marketing – mix, mình sẽ giúp bạn phân tích và hiểu rõ hơn ở bài viết sau.Kết luậnThị trường luôn biến đổi không ngừng, và trong một thế giới đầy cạnh tranh, chỉ có những doanh nghiệp hiểu rõ thị trường, khách hàng và chính mình mới có thể tồn tại và phát triển bền vững. Nghiên cứu thị trường không chỉ là công cụ để giảm thiểu rủi ro mà sẽ là chìa khoá giúp bạn có những chiến lược hoàn hảo nhất!

Bí quyết công nghệ của EzyPlatform - Quản lý socket

Trong socket không tồn tại khái niệm về người dùng (user) đây là một khái niệm mà EzyFox Server sinh ra, trong bài này chúng ta sẽ cùng tìm hiểu về socket user cụ thể hơn là lớp EzyUser.Tại sao đã có phiên (session) rồi lại phải sinh ra người dùng (user)? Một phiên sẽ được định danh bởi một id, tuy nhiên trong phần mềm thực tế thì chúng ta lại thường xác định một người dùng thông qua email, số điện thoại hay tên đăng nhập. Mỗi người dùng lại đăng nhập bằng nhiều thiết bị khác nhau, mỗi session chỉ đáp ứng được một thiết bị vậy nên chúng ta cần đến user để quản lý các session tương ứng với các thiết bị. Chính vì có chứa các thông tin đăng nhập nên socket user cũng sinh ra để quản lý các thông tin ánh xạ với thông tin người dùng trong cơ sở dữ liệu ví dụ như adminId hay userId. Một socket user được đại diện bởi một đối tượng EzyUser. Tìm hiểu về lớp EzyUser Đúng hơn là chúng ta sẽ tìm hiểu về việc cài đặt giao diện EzyUser với thiết kế lớp như sau: Giao diện EzyUser cung cấp các hàm cơ sở của một socket user. Lớp EzySimpleUser cung cấp các hàm cài đặt. Một số dữ liệu mà một socket user quản lý bao gồm: sessionMap: Một map quản lý các session ánh xạ theo id. maxSessions: Số lượng session tối đa tương đương với số thiết bị tối đa mà một người dùng có thể đăng nhập. startIdleTime: Thời gian ghi nhận không còn session nào, nghĩa là các thiết bị đã ngắt kết nối hết. maxIdleTime: Thời gian tối đa tính theo milli giây để một socket user có thể tồn tại sau khi không còn session nào, nghĩa là không có thiết bị nào được kết nối đến. locks: Quản lý các đối tượng lock để bạn có thể sử dụng cho các nghiệp vụ cần đồng bộ hoá dữ liệu tương ứng với từng người dùng. ... Socket user được quản lý thế nào Các socket user được quản lý bởi các lớp manager theo sơ đồ lớp như sau: EzyUserManager: Giao diện chứa các hàm cơ sở cho việc quản lý socket user. EzyAbstractUserManager: Cài đặt một số hàm cơ bản của EzyUserManager. EzyZoneUserManagerImpl: Lớp này quản lý các socket user của cả một zone, nếu bạn muốn gửi thông báo đến toàn bộ người dùng cho cả 1 zone, bạn có thể sử dụng lớp này. EzyAppUserManagerImpl: Lớp này quản lý các socket user của một app, nó không tạo mới mà chỉ giữ tham chiếu đến người dùng của zone. Bạn cần lưu ý rằng mỗi zone sẽ quản lý người dùng độc lập, nghĩa là dù cho có cùng một tên đăng nhập nhưng trên 2 zone sẽ có hai đối tượng EzyUser với cùng username được tạo ra. Giải quyết vấn đề reconnect Như đã đề cập ở bài trước chúng ta có vấn đề reconnect. Khi có socket user nó cũng góp phần giải quyết một ít. Khi không còn bất kỳ session nào nữa thì vẫn có một khoảng thời gian EzyFox Server sẽ cho phép đối tượng user tồn tại và bạn cũng có thể cấu hình khoảng thời gian này, ví dụ: <user-management> <user-max-idle-time>15</user-max-idle-time> </user-management> Nếu trong khoảng thời gian này người dùng đăng nhập trở lại bạn có thể trả về cho client trạng thái hiện tại, ví dụ một người chơi đang ở trong bàn chơi bạn sẽ gửi thông tin trạng thái của bàn chơi hiện tại cho client và trận đấu vẫn sẽ tiếp tục, ngược lại, quá thời gian thì trận đấu sẽ kết thúc. Giải quyết vấn đề chỉ cho phép một thiết bị đăng nhập tại một thời điểm Cũng đã đề cập trong bài trước, giả sử chúng ta có một trò chơi hành động, ở một thời điểm chỉ có một thiết bị được đăng nhập để điều khiển nhân vật, chúng ta có thể giới hạn số lượng session trên một user là 1 và cho phép thay đổi thiết bị, ví dụ chúng ta có thể cấu hình như sau: <user-management> <user-max-idle-time>15</user-max-idle-time> <allow-change-session>true</allow-change-session> <max-session-per-user>1</max-session-per-user> </user-management> Cấu hình này đảm bảo chỉ 1 thiết bị được đăng nhập tại một thời điểm, nếu thiết bị mới được đăng nhập, thiết bị cụ sẽ bị ngắt kết nối. Tổng kết Socket user là một khái niệm tương đối quan trọng của EzyFox Server và EzyPlatform và nó được đại diện bởi lớp EzyUser. Các socket user được quản lý bởi các lớp manager. Thông qua socket user chúng ta có thêm công cụ để giải quyết các vấn đề reconnect và giới hạn số lượng thiết bị đăng nhập.

Tổng quan về Unity và thiết lập dự án

Trước khi chúng ta đến với phần thiết lập dự án trong Unity, hãy cùng tìm hiểu qua về Unity Engine nhé.Tổng quan về Unity: Unity là một game engine phổ biến được phát triển bởi Unity Technologies, cho phép tạo trò chơi 2D, 3D và các ứng dụng tương tác trên nhiều nền tảng như PC, di động, máy chơi game, VR/AR và web. Với ngôn ngữ lập trình C Sharp, Unity dễ học và sử dụng, hỗ trợ lập trình viên qua giao diện trực quan và tài nguyên phong phú. Cộng đồng đông đảo và tài nguyên như Unity Asset Store giúp tiết kiệm thời gian phát triển. Unity miễn phí cho các nhà phát triển nhỏ và cá nhân, và đã được sử dụng để phát triển nhiều game nổi tiếng như Among Us và Monument Valley.1. Cài đặt Unity Hub: Truy cập vào website: https://unity.com/download để tải Unity Hub. 2. Cài đặt Unity Editor: Sau khi cài đặt Unity Hub đăng nhập vào Unity Hub bằng tài khoản Unity, chưa có thì có thể tạo. Tìm và cài đặt phiên bản Unity 2022.3.10f1 LTS trong link: https://unity.com/releases/editor/whats-new/2022.3.10#installs và nhấn vào Install, trình duyệt sẽ hỏi cài đặt qua unity hub chọn ok và phiên bản unity 2022 sẽ tự động được chuyển qua unity hub để cài đặt. Lưu ý có thể chọn các phiên bản Unity mới hơn hoặc cũ hơn cũng được, tùy vào các bạn, nhưng nên sử dụng các phiên bản được đánh dấu là LTS (Long Term Support) là các phiên bản được hỗ trợ lâu dài, các phiên bản này thường được đánh giá là ổn định và ít lỗi hơn so với các phiên bản không được đánh dấu là LTS. Sau khi chuyển hướng qua Unity Hub để cài đặt bản unity, chọn vào option Visual Studio Community để cài đặt Visual Studio, hoặc nếu trên máy đã có sẵn các IDE hỗ trợ code C Sharp .Net sẵn rồi thì có thể bỏ qua. Đối với các option platfoms có thể bỏ qua nếu chỉ build windows, còn nếu mục tiêu của bạn là phát triển trên các nền tảng khác thì có thể chọn nền tảng tương ứng. Dự án chess 2d mình sẽ làm trên windows và sẽ build windows nên mình sẽ không chọn gì ở phần này và chọn Continue. Sau khi cài đặt xong phiên bản Unity, các bạn chọn vào add new để tạo dự án mới, nhập tên dự án: Chess, có các lựa chọn là 2D để làm game 2d, 3D để làm game 3D, VR để làm game vr, ngoài ra còn các sample project mà Unity cho sẵn, các bạn có thể tạo để vọc vạch sau, còn trong phạm vi dự án là chess 2d nên mình sẽ chọn project 2D. Chọn đường dẫn lưu dự án, tiếp tới chọn organization chọn tới organization của bạn chọn xong thì bấm add, project sẽ được tạo và mở lên tự động. Tổng quan về giao diện Unity Engine Giao diện Unity Engine về cơ bản có các khu vực như trên: (1) Đây là khu vực thanh công cụ, ở đây các bạn có thể thấy các menu về file, edit, asset, vv của Unity. (2) Đây là Hierachy là khu vực chứa scene (1 cảnh / 1 màn chơi) đang load, các gameobjects (các đối tượng làm nên 1 game hoàn chỉnh) trong scene. (3) Đây là khu vực scene cũng là khu vực mà các bạn sẽ tương tác, kéo thả các gameobjects. (4)Đây là cửa sổ game, tại đây tất cả những gì camera render sẽ được hiển thị tại đây. (5) Inspector sẽ hiển thị mọi thông tin về gameobjects đang làm việc một cách chi tiết, kể cả những Components được đính kèm và những thuộc tính của nó. (6) Cửa sổ project, tại đây chúng ta có thể xem được tất cả các assets có trong dự án (assets là các tài nguyên trong dự án gồm hình ảnh, âm thanh, file script, animation, vv) (7) Cửa sổ console đây là cửa sổ sẽ hiển thị các thông tin được log ra trong quá trình phát triển game. Cấu trúc thư mục và dự án Về cơ bản chúng ta có thể bỏ tất cả mọi thứ vào cửa sổ project mà không cần tới việc cấu trúc thư mục, tuy nhiên khi chúng ta mở rộng dự án hoặc cần phải sửa đổi nâng cấp về sau, việc có quá nhiều tài nguyên bỏ vào dự án mà không có bất kỳ cấu trúc nào sẽ gây ra 1 sự lộn xộn và chúng ta sẽ rất khó để có thể tìm tới tài nguyên mà chúng ta cần, và rất khó để quản lý tài nguyên. Vì vậy chúng ta cần phải cấu trúc thư mục của dự án ngay từ đầu, vd trong dự án này mình sẽ chia thư mục như sau: Về cơ bản mình sẽ chia các folder để chứa theo loại tài nguyên, vd: Hình ảnh sẽ có folder riêng và trong folder hình ảnh sẽ có folder nhỏ hơn chứa hình ảnh cho UI, hình ảnh cho game play, vv. Script code sẽ có folder riêng là scripts và sẽ có các folder nhỏ hơn như folder cho managers chứa các script manager, folder cho quân cờ chứa các script xử lý logic cho các quân cờ, vv. Với các tài nguyên khác cũng dùng chung nguyên tắc để tạo thư mục. Link tham khảo: https://unity.com/how-to/organizing-your-project Bài tiếp theo chúng ta sẽ bắt đầu vào phát triển dự án và lập trình cho bàn cờ. Tác giả: Nguyễn Minh Thuận

Tổng quan dự án Chess Offline 2D trên Unity

Tổng quan dự án Chess Offline Unity 2D Mục tiêu của dự án Dự án game Chess Offline Unity 2D không chỉ là cơ hội để bạn tạo ra một trò chơi cờ vua đơn giản mà còn giúp bạn: Làm quen với Unity Engine Hiểu cách hoạt động của game engine, cách sử dụng Game Objects, Components, và các công cụ trong Unity. Nâng cao kỹ năng lập trình Áp dụng các khái niệm OOP (Lập trình Hướng Đối Tượng), cấu trúc dữ liệu, và thuật toán để giải quyết các bài toán logic trong game. Tìm hiểu quy trình phát triển game Từ việc thiết lập dự án, thiết kế đồ họa, đến lập trình logic và tối ưu hóa sản phẩm. Dự án dành cho ai? Người mới bắt đầu với Unity muốn tìm hiểu cách tạo một game 2D đơn giản.! Lập trình viên muốn cải thiện kỹ năng lập trình và tư duy giải thuật thông qua việc triển khai luật chơi cờ vua. Danh sách bài viết về chủ đề dự án Chess Offline Unity 2D: Tổng án dự án game Chess Offline Unity 2D Tổng quan về Unity và thiết lập dự án. Tìm kiếm Assets, Khởi tạo Scene và quản lý mã nguồn Tạo và lập trình các quân cờ. Viết mã logic di chuyển của các quân cờ. Xây dựng logic bắt quân và các luật cơ bản của cờ vua. Kiểm tra nước chiếu và chiếu bí. Xử lý lượt chơi và logic kết thúc trận đấu. Tạo giao diện người dùng (UI) cho game. Tối ưu hóa và hoàn thiện game. Tác giả: Nguyễn Minh Thuận

Bí quyết công nghệ của EzyPlatform - Quản lý phiên kết nối socket

Giữ kết nối để gửi nhận chủ động thì hay nhưng quản lý kết nối thì lại tương đối mệt mỏi, đó là lý do tại sao làm ví dụ về socket có vẻ đơn giản nhưng khi xây dựng một socket server lại là cả một núi việc, hiểu rõ vấn đề này EzyPlatform, hay nói chính xác hơn là EzyFox Server đã đóng gói lại việc quản session (phiên) và các nhà phát triển không cần bận tâm, thậm chí là không cần biết đến sự tồn tại của phiên mà chỉ quan tâm đến người dùng.Những vấn đề của quản lý phiên Phiên (kết nối) là một khái niệm trừu tượng được dùng để nói về thực thể chứa các thông tin kết nối giữa server và client. Với EzyPlatform và EzyFox Server nó được hiện thực hoá bằng giao diện EzySession, và nó có những vấn đề nhất định: Kết nối cũng là một khái niệm trừu tượng, giữa client và server không thực sự biết rằng chúng có đang giữ kết nối với nhau không. Trong môi trường thực tế, hiếm khi client sẽ gửi thông báo ngắt kết nối đến server. Một phiên cũng chiếm một lượng tài nguyên nhất định và cần được giải phóng khi không được dùng nữa. Reconnect (kết nối lại) rất khó xử lý chung chung được mà phụ thuộc vào từng phần mềm cụ thể. Một người dùng có nhiều thiết bị, tuy nhiên có những phần mềm ví dụ như trò chơi chỉ cho phép người dùng một thiết bị tại một thời điểm. Để giải quyết được những vấn đề này EzyPlatform và EzyFox Server có những thiết kế tương đối phức tạp. Thiết kế các lớp đại diện cho phiên Các lớp đại diện cho phiên kết nối sẽ được thiết kế như sau: Ở đây chúng ta có 3 lớp: Đầu tiên là giao diện EzySesson. Nó cung cấp các hàm cơ sở để quản lý thông tin phiên kết nối. Tiếp theo là lớp trừu tượng EzyAbstractSession. Lớp này chứa các trường và các hàm cài đặt cụ thể. Cuối cùng là lớp EzySimpleSession. Lớp này cũng không làm gì nhiều, nó chỉ bổ sung thêm hàm để lấy ra thông tin của non-blocking I/O channel. Một số thông tin có trong lớp EzyAbstractSession bao gồm: id: Là mã của client, được tăng dần đều để đảo bảo không bao giờ bị trùng. name: Để nhận diện phiên lúc debug, thông tin này cũng là duy nhất. clientId: Id từ phía client gửi lên, thông tin này cũng không đáng tin cậy nhưng cũng hỗ trợ việc debug. sessionKey: Là thông tin khoá mã hoá dữ liệu giữa client và server. channel: Là thông tin kênh kết nối socket. extensionRequestQueue: Là hàng đợi chứa các yêu cầu chung nhận từ client. packetQueue: Là thông tin hàng đợi các gói tin cần phản hồi cho client. .. Từng thông tin trong một phiên đều rất quan trọng, và mình sẽ viết các bài chi tiết về chúng nhé. Thiết kế các lớp quản lý phiên Các phiên được quản lý bởi EzySessionManager với thiết kế như sau: Giao diện EzySessionManager chứa các hàm cơ sở cho việc quản lý phiên. Lớp EzySimpleSessionManager cài đặt việc quản lý phiên, nó có các công việc tương đối nặng nề, đặc biệt là việc phải chạy định kỳ để kiểm tra toàn bộ các phiên xem có phiên nào đã không còn hợp lệ để loại bỏ. Lớp EzyNioSessionManagerImpl cũng không làm gì nhiều, nó chỉ định rõ kiểu lớp đại diện cho phiên. Giao diện EzySessionFactory lớp này chứa các hàm cơ sở cho việc khởi tạo ra một đối tượng đại diện cho phiên và cũng chính là ứng dụng của factory design pattern. Lớp EzyAbstractSessionFactory cài đặt hàm khởi tạo các thông tin cho phiên nhưng vẫn đề chờ hàm tạo phiên vì nó chưa biết chính xác kiểu lớp của phiên, đây cũng chính là ứng dụng của factory method design pattern. Lớp EzyNioSessionFactory cài đặt hàm để tạo ra đối tượng phiên. Khi đã có những thành phần cần thiết bây giờ chúng ta có thể đi giải quyết các vấn đề đã được liệt kê ở trên. Giải quyết các vấn đề Chúng ta sẽ lần lượt giải quyết các vấn đề. Giải quyết vấn đề thông tin kết nối. Để client và server luôn biết về sự tồn tại của nhau thì EzyPlatform và EzyFox Server duy trì yêu cầu ping/pong giữa client và server, client sẽ là người chủ động gọi ping và server phản hồi về pong. Nếu một phiên quá lâu không nhận được ping từ client thì khi định kỳ thanh tra EzySimpleSessionManager sẽ loại bỏ phiên idle quá lâu. Giải quyết vấn đề client không gửi ngắt kết nối đến server. Vẫn là dùng ping/pong sẽ giải quyết được vấn đề này. Server sẽ tự chủ động loại bỏ phiên, giải phóng các tài nguyên của phiên sau một khoảng thời gian. Đối với các phiên không gửi yêu cầu đăng nhập trong một khoảng thời gian cũng sẽ bị EzySimpleSessionManager coi là không hợp lệ và bị loại bỏ. Giải quyết vấn đề giải phóng tài nguyên EzyPlatform và EzyFox sẽ xoá bỏ hoàn toàn các thông tin của một phiên chứ không giữ lại, vậy cho nên đối với các dữ liệu quan trọng, nhà phát triển sẽ cần lưu vào cơ sở dữ liệu để tránh mất mát. Như bạn có thể thấy ở trên mỗi phiên lại quản lý dữ liệu ở trong các hàng đợi của riêng mình, nên việc giải phóng tài nguyên cũng rất đơn giản là chỉ cần giải phóng phiên là xong. Giải quyết vấn đề reconnect Hồi đầu mới viết EzyFox Server mình cũng đã cố gắng giải quyết triệt để vấn đề kết nối lại theo một cách chung nhất nhưng không thành công do có những vấn đề về bảo mật và nghiệp vụ của mỗi phần mềm lại khác nhau. Vậy nên EzyFox Server giải quyết một phần bằng cách sinh ra khái niệm EzyUser mà mình sẽ giải thích ở bài sau để cho phép thay thế phiên, còn về mặt dữ liệu reconnect thì sẽ có nhiều cách để cách nhà phát triển gửi về cho client được. Một người dùng có nhiều thiết bị Mỗi một thiết bị sẽ được đại diện bởi một phiên, vì mỗi phiên có id riêng nên không trùng nhau, vì vậy việc quản lý nhiều phiên cũng tương đối dễ dàng, tuy nhiên cũng thông qua khái niệm EzyUser mà mình sẽ viết trong bài sau, mình sẽ giải thích chi tiết hơn về việc cách giải quyết với nhiều thiết bị kết nối đồng thời và việc chỉ cho phép một thiết bị được kết nối tại một thời điểm nhé. Tổng kết Quản lý phiên là một bài toán khó, nó đòi hỏi EzyPlatform phải đưa ra một thiết kế tỉ mỉ vì nếu không có một thiết kế tốt sẽ dẫn đến xử lý không tốt đồng nghĩa với việc sẽ có memory leak và bộ nhớ sẽ bị đầy nhanh chóng. Cũng thông qua việc quản lý phiên này EzyPlatform sẽ giải quyết được những vấn đề học búa trong lập trình socket, đóng gói chúng lại để các nhà phát triển sẽ không cần phải bận tâm về các vấn đề này nữa.

Bí quyết công nghệ của EzyPlatform - Socket realtime

Lập trình các phần mềm thời gian thực luôn là một chủ đề thú vị nhưng cũng là một trong những thách thức không nhỏ dành cho các nhà phát triển. Việc có thêm socket sẽ là công cụ để các nhà phát triển làm cho các phần mềm trở nên sinh động hơn thông qua các tính năng thời gian thực như trò chơi, chat hay là thông báo.Socket là một thành phần của EzyPlatform Như đã nói trong bài mô hình triển khai EzyPlatform trên một máy chủ, Socket là một trong 3 thành phần chính của EzyPlatform. Tuy nhiên không phải dự án nào cũng cần thiết phải có socket, chính vì vậy bạn có thể không bật socket lên và bạn có thể disable nó đi để tránh in spam log ở console của admin. Khi bạn bật socket thì giao diện admin sẽ tự động kết nối. Khi bạn truy cập vào dashboard, một kết nối tự động được mở và lấy các thông số của socket server thông qua giao thức websocket. Kiến trúc phần mềm của socket trong EzyPlatform Kiến trúc này vẫn tuân theo những gì mà EzyFox Server đã thiết kế. Tuy nhiên EzyPlatform đã khởi tạo sẵn một số zone bao gồm: admin: Zone này chỉ phục vụ cho admin. chat: Zone này phục vụ cho các các plugin, theme chat. game: Zone này phục vụ cho các plugin, theme trò chơi. user: Zone này phục vụ cho người dùng nói chung. Ngoài ra bạn cũng có thể tự tạo zone cho mình nếu muốn, tuy nhiên chúng tôi khuyến khích bạn tái sử dụng các zone đã được tạo sẵn để tránh sinh ra quá nhiều zone không cần thiết. Người dùng được xác thực thế nào? Người dùng bao gồm cả admin và user sẽ được xác thực thông qua các lớp UserLoginController của các plugin trước và sau đó bị chốt chặn bởi một lớp mặc định có tên SocketLoginController. Thông qua các bước login người dùng sẽ được nhận dạng là admin hay là user hay là không biết danh tính, khi bạn xử lý yêu cầu của người dùng ở app hoặc plugin bạn có thể truy cập thông tin dữ liệu người dùng thông qua hàm user.getProperty(SocketUserData.class). Dữ liệu được xử lý thế nào Một trong những điểm cực kỳ mạnh của EzyPlatform cũng chính là của EzyFox Server đó là việc nó hỗ trợ nhiều giao thức, tuy nhiên tất cả các dữ liệu từ các giao thực này sẽ được đưa về các lớp xử lý chung. Dữ liệu đến từ các nguồn sẽ được chuyển đổi thành EzyData (EzyObject, EzyArray) bản chất là dạng dữ liệu kiểu đối tượng hay mảng. Sau đó sẽ được đưa vào hàng đợi để xử lý. Ở phía các handler cũng có thêm tầng abstract để chuyển đổi dữ liệu từ EzyData sang dạng đối tượng Java thông thường. Tổng kết Socket realtime sẽ mang lại sức sống mới cho các phần mềm, tuy nhiên về mặt kỹ thuật thì nó tương đối phức tạp. May mắn là EzyPlatform đã cố gắng đóng gói sự phức tạp đó để lộ ra những thứ dễ dàng cho các nhà phát triển. Trong bài viết này chỉ là một phần siêu nhỏ của socket trong EzyPlatform, mình sẽ giới thiệu với các bạn nhiều hơn ở các bài tiếp theo nhé.

Sự khác biệt giữa Chiến lược và Chiến dịch

Trong thế giới marketing, hai từ “chiến lược” và “chiến dịch” được nhắc đến rất nhiều, nhưng có khi nào bạn tự hỏi “Hai khái niệm này khác nhau thế nào nhỉ?”. Bài viết này sẽ giúp các bạn chưa phân biệt được rõ 2 khái niệm này để tránh việc dùng nhầm lẫn.Định nghĩa đơn giản về 2 khái niệmChiến lược (Strategy) – Lộ trình tổng thểĐược ví như bức tranh lớn. Chiến lược là định hướng dài hạn giúp doanh nghiệp theo đuổi và đạt được những mục tiêu tổng thể của mình. Chiến lược là cái "khung", giúp xác định lộ trình dài hạn. Đây là câu trả lời cho câu hỏi: “Doanh nghiệp muốn đạt được gì trong tương lai?”. Hiểu đơn giản, chiến lược là một loạt những hành động để đối phó và đáp ứng với những tình hình thực tế của thị trường.Để xác định được chiến lược, bạn cần nắm rõ về những mục tiêu doanh nghiệp muốn đạt được đồng thời cũng nên lưu ý đến xem những mục tiêu đó có phù hợp với văn hoá, tầm nhìn - sứ mệnh của doanh nghiệp hay không.Ví dụ trong giai đoạn mới bắt đầu của tổ chức mã nguồn mở Young Monkeys, với mục tiêu marketing là tăng sự nhận diện và nhận thức về thương hiệu, yêu cầu truyền thông phải educate khách hàng, Young Monkeys đã lựa chọn Chiến lược marketing - mix 4C (Customer, Cost, Convenience, Communication). Tại sao lại chọn 4C trong nhiều mô hình chiến lược marketing - mix, mình sẽ giải thích ở bài sau.Chiến dịch (Campaign) – Hành động cụ thể để thực hiện chiến lượcTrong khi chiến lược là định hướng tổng thể, thì chiến dịch là những hành động cụ thể, có thời hạn nhất định, để triển khai và thực hiện chiến lược. Chiến dịch sẽ giúp chiến lược được triển khai qua từng giai đoạn và tạo ra những kết quả đo lường được trong ngắn hạn.Ví dụ ở trường hợp trên, sau khi xác định được chiến lược 4C, cần cụ thể hoá từng mục bằng các chiến dịch như chiến dịch livestream, tổ chức các buổi workshop,... Vì vậy các hành động cụ thể bao gồm: Xác định nền tảng livestream, xây dựng tuyến nội dung, chuẩn bị phương tiện,... Bảng phân biệtSự liên quan chặt chẽ đến nhauChiến lược giống như bản đồ toàn diện của doanh nghiệp, bao quát tầm nhìn dài hạn và các mục tiêu mà doanh nghiệp muốn đạt được. Để thực hiện chiến lược đó, doanh nghiệp thường triển khai nhiều chiến dịch khác nhau. Như vậy, mỗi chiến dịch là một mảnh ghép của chiến lược, có nhiệm vụ giúp đẩy từng bước nhỏ tiến tới mục tiêu lớn hơn.Vậy làm thế nào để xây dựng được một chiến lược hiệu quả cho doanh nghiệp của bạn? Hãy theo dõi các blog sau của EzyPlatform nha!