魚皮項目簡易版 RPC 框架開發(四)

本文為筆者閱讀魚皮的項目 《簡易版 RPC 框架開發》的筆記,如果有時間可以直接去看原文,

1. 簡易版 RPC 框架開發

前面的內容可以筆者的前面幾篇筆記

魚皮項目簡易版 RPC 框架開發(一)

魚皮項目簡易版 RPC 框架開發(二)

魚皮項目簡易版 RPC 框架開發(三)

引用:

1. 簡易版 RPC 框架開發

魚皮項目簡易版 RPC 框架開發(一)

魚皮項目簡易版 RPC 框架開發(二)

魚皮項目簡易版 RPC 框架開發(三)

RPC框架的簡單理解

HTTP 請求處理源代碼?

package com.yupi.yurpc.server;import com.yupi.yurpc.model.RpcRequest;
import com.yupi.yurpc.model.RpcResponse;
import com.yupi.yurpc.registry.LocalRegistry;
import com.yupi.yurpc.serializer.JdkSerializer;
import com.yupi.yurpc.serializer.Serializer;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;import java.io.IOException;
import java.lang.reflect.Method;/*** HTTP 請求處理*/
public class HttpServerHandler implements Handler<HttpServerRequest> {@Overridepublic void handle(HttpServerRequest request) {// 指定序列化器final Serializer serializer = new JdkSerializer();// 記錄日志System.out.println("Received request: " + request.method() + " " + request.uri());// 異步處理 HTTP 請求request.bodyHandler(body -> {byte[] bytes = body.getBytes();RpcRequest rpcRequest = null;try {rpcRequest = serializer.deserialize(bytes, RpcRequest.class);} catch (Exception e) {e.printStackTrace();}// 構造響應結果對象RpcResponse rpcResponse = new RpcResponse();// 如果請求為 null,直接返回if (rpcRequest == null) {rpcResponse.setMessage("rpcRequest is null");doResponse(request, rpcResponse, serializer);return;}try {// 獲取要調用的服務實現類,通過反射調用Class<?> implClass = LocalRegistry.get(rpcRequest.getServiceName());if (implClass == null) {rpcResponse.setMessage("Service not found: " + rpcRequest.getServiceName());doResponse(request, rpcResponse, serializer);return;}Method method = implClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());Object result = method.invoke(implClass.newInstance(), rpcRequest.getArgs());// 封裝返回結果rpcResponse.setData(result);rpcResponse.setDataType(method.getReturnType());rpcResponse.setMessage("ok");} catch (Exception e) {e.printStackTrace();rpcResponse.setMessage(e.getMessage());rpcResponse.setException(e);}// 響應doResponse(request, rpcResponse, serializer);});}/*** 響應* @param request* @param rpcResponse* @param serializer*/void doResponse(HttpServerRequest request, RpcResponse rpcResponse, Serializer serializer) {HttpServerResponse httpServerResponse = request.response().putHeader("content-type", "application/json");try {// 序列化byte[] serialized = serializer.serialize(rpcResponse);httpServerResponse.end(Buffer.buffer(serialized));} catch (IOException e) {e.printStackTrace();httpServerResponse.end(Buffer.buffer());}}
}

代碼功能概述

這段代碼實現了一個基于 HTTP 協議的 RPC 服務器請求處理器,負責接收客戶端請求、反射調用本地服務方法并返回響應結果。核心功能包括請求反序列化、服務方法調用、結果封裝和序列化響應。

核心組件分析

序列化器

  • 使用 JdkSerializer 進行請求和響應的序列化與反序列化。
  • doResponse 方法中將響應對象序列化為字節流。

請求處理流程

  • 通過 request.bodyHandler 異步處理請求體。
  • 將請求體字節流反序列化為 RpcRequest 對象。
  • 若反序列化失敗,返回包含錯誤信息的響應。

服務調用機制

  • 通過 LocalRegistry.get() 根據服務名獲取實現類。
  • 使用反射機制調用目標方法:implClass.getMethod() 獲取方法,method.invoke() 執行調用。
  • 捕獲調用過程中的異常并封裝到響應中。

響應構建

  • 成功調用時設置方法返回值到 rpcResponse.data
  • 異常時設置異常信息到 rpcResponse.messagerpcResponse.exception

關鍵方法說明

handle()

  • 主處理方法,接收 HttpServerRequest 對象。
  • 采用異步非阻塞方式處理請求體。
  • 協調反序列化、服務調用和響應流程。

doResponse()

  • 設置 HTTP 響應頭 content-type: application/json
  • RpcResponse 序列化為字節流寫入響應體。
  • 異常時返回空緩沖區。

補充

JdkSerializer

JDK序列化是Java平臺提供的一種對象序列化機制,通過java.io.Serializable接口實現。它允許將對象轉換為字節流,便于存儲或傳輸,并能在需要時重新構造為原始對象。

詳細分析見:

魚皮項目簡易版 RPC 框架開發(三)

doResponse

序列化響應對象為字節流的方法

doResponse 方法中,將響應對象序列化為字節流通常涉及以下幾個關鍵步驟:

使用 JSON 序列化庫
常見的 JSON 序列化庫如 JacksonGsonFastjson 可以將 Java 對象轉換為 JSON 字符串,再進一步轉為字節流。例如,使用 JacksonObjectMapper

ObjectMapper objectMapper = new ObjectMapper();
byte[] responseBytes = objectMapper.writeValueAsBytes(responseObject);

手動構建字節流
如果需要自定義格式,可以直接拼接字符串并調用 getBytes() 方法轉換為字節流。例如:

String responseString = "{\"status\":\"success\",\"data\":" + customData + "}";
byte[] responseBytes = responseString.getBytes(StandardCharsets.UTF_8);

使用協議緩沖區(Protocol Buffers)
對于高性能場景,可以通過 Protocol Buffers 定義消息格式并生成字節流:

ResponseProto.Response response = ResponseProto.Response.newBuilder().setStatus("OK").setData(data).build();
byte[] responseBytes = response.toByteArray();

設置正確的 Content-Type 和編碼
確保響應頭中包含正確的 Content-Type 和字符編碼(如 application/json; charset=UTF-8),以便客戶端正確解析字節流。

處理異常情況
捕獲序列化過程中可能拋出的異常(如 JsonProcessingException),并返回錯誤信息或默認響應。例如:

try {byte[] responseBytes = objectMapper.writeValueAsBytes(responseObject);// 發送字節流到輸出流
} catch (JsonProcessingException e) {byte[] errorBytes = "{\"error\":\"Serialization failed\"}".getBytes();
}

優化性能
對于高頻調用場景,可以復用序列化工具實例(如 ObjectMapper),避免重復創建對象帶來的開銷。

?printStackTrace

理解 printStackTrace 的作用

printStackTrace() 是 Java 中 Throwable 類的方法,用于將異常的堆棧跟蹤信息輸出到標準錯誤流(System.err)。它顯示了異常的類型、消息以及從方法調用棧頂到底的完整路徑,幫助開發者快速定位問題根源。

使用場景

  • 調試階段:在開發或測試階段,通過打印堆棧跟蹤快速定位異常發生的代碼位置。
  • 日志記錄:結合日志框架(如 Log4j、SLF4J),將堆棧信息寫入日志文件而非直接打印到控制臺。

代碼示例

try {// 可能拋出異常的代碼int result = 10 / 0;
} catch (ArithmeticException e) {e.printStackTrace(); // 打印堆棧跟蹤到 System.err
}

輸出格式說明

堆棧跟蹤通常包含以下內容:

  1. 異常類型:如 ArithmeticException
  2. 異常消息:如 / by zero
  3. 調用棧:從觸發異常的方法到最外層的調用方法,每行顯示類名、方法名、文件名和行號。

示例輸出:

java.lang.ArithmeticException: / by zeroat com.example.Test.main(Test.java:10)

替代方案(生產環境推薦)

直接使用 printStackTrace() 在生產環境中可能不夠靈活,建議:

  • 日志框架:通過 logger.error("Error occurred", e) 記錄異常,支持分級存儲和格式化。
  • 自定義輸出:重定向堆棧跟蹤到字符串或文件,例如:
    StringWriter sw = new StringWriter();
    e.printStackTrace(new PrintWriter(sw));
    String stackTrace = sw.toString();
    

注意事項

  • 性能影響:頻繁調用 printStackTrace() 可能影響性能,尤其在循環或高頻操作中。
  • 信息暴露:堆棧跟蹤可能暴露敏感信息(如內部類名),需謹慎處理。

通過合理使用 printStackTrace() 或其替代方案,可以高效排查異常問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93482.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93482.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93482.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

力扣-79.單詞搜索

題目鏈接 79.單詞搜索 class Solution {int m, n;public boolean exist(char[][] board, String word) {m board.length;n board[0].length;boolean[][] visited new boolean[m][n];// 遍歷網格中的每個單元格作為搜索起點for (int i 0; i < m; i) {for (int j 0; j …

LabVIEW的To More Specific Class功能說明

?To More Specific Class 是 LabVIEW 中用于控件引用類型轉換的關鍵函數。可將通用 GObject 引用&#xff0c;精準轉為 Listbox、TreeControl 等特定控件類引用&#xff0c;讓開發者能調用專屬屬性&#xff08;如獲取列表行數&#xff09;&#xff0c;實現對不同控件類的差異化…

Ubuntu20.04安裝和配置Samba實現Win11下共享文件夾

Samba是在Linux和UNIX系統上實現 SMB / CIFS 協議的開源軟件&#xff0c;主要用于局域網內的文件共享和打印服務。Samba通過SMB/CIFS協議實現跨平臺資源共享&#xff0c;支持匿名用戶和本地用戶訪問共享目錄&#xff0c;客戶端主要為Windows系統。其核心進程包括&#xff1a; ?…

設計模式(八)結構型:橋接模式詳解

設計模式&#xff08;八&#xff09;結構型&#xff1a;橋接模式詳解橋接模式&#xff08;Bridge Pattern&#xff09;是 GoF 23 種設計模式中的結構型模式之一&#xff0c;其核心價值在于將抽象部分與實現部分分離&#xff0c;使它們可以獨立變化。它通過“組合”而非“繼承”…

【邊緣填充】——圖像預處理(OpenCV)

目錄 1 邊界復制&#xff08;BORDER_REPLICATE&#xff09; 2 邊界反射&#xff08;BOEDER_REFLECT&#xff09; 3 邊界反射101&#xff08;BORDER_REFLECT101&#xff09; 4 邊界常數&#xff08;BORDER_CONSTANT&#xff09; 5 邊界包裹&#xff08;BORDER_WRAP&#xf…

git同步到github出錯-幾個問題-一天晚上(2025.7.29)

訪問不了github 代理和加速器都正常&#xff0c;但是就是訪問不了這個網站嘗試過幾種方法都不行&#xff0c;后面突然可以了。 之后發現一種情況會不行&#xff1a;同時開啟 同步不了 http連接 https://blog.csdn.net/m0_73972962/article/details/146198392 一堆問題 ssh連接才…

Redis未授權訪問的利用的幾種方法原理以及條件

一、redis通過定時任務反彈shell1.利用條件&#xff1a;需要能夠登錄redis數據庫&#xff0c;并且redis以root用戶運行。同時/var/spool/cron目錄要具有寫和執行權限。二、Redis主從getshell1.原理&#xff1a;在Redis 4.x之后&#xff0c;Redis新增了模塊功能&#xff0c;通過…

DNF 與 YUM 的區別詳解:從 CentOS 7 到 CentOS 9 的演進

&#x1f365; DNF 與 YUM 的區別詳解&#xff1a;從 CentOS 7 到 CentOS 9 的演進標簽&#xff1a;CentOS、YUM、DNF、Linux 包管理、系統升級、兼容性 適用版本&#xff1a;CentOS 7、CentOS 8、CentOS 9&#x1f9e9; 一、背景介紹 CentOS 中使用的包管理工具是 RedHat 系列…

mp核心功能

條件構造器mybatisPlus支持各種復雜的where條件, 滿足日常的開發wrapper類就是條件構造器提供了很多子類條件構造器的用法&#xff1a;QueryWrapper和LambdaQueryWrapper通常用來構建select、delete、update的where條件部分UpdateWrapper和LambdaUpdateWrapper通常只有在set語句…

pcm,msd調制解調仿真

PCM&#xff08;脈沖編碼調制&#xff09;和MSD&#xff08;多符號差分&#xff09;調制解調系統的MATLAB仿真代碼。 PCM (脈沖編碼調制) 仿真 %% PCM調制解調仿真 clear; clc; close all;% 參數設置 Fs 8000; % 采樣頻率 (Hz) t_duration 0.02; % 信號持續時間 (秒…

【網絡安全】信息網絡安全建設方案(WORD)

1.1 安全整體架構 1.2 安全建設拓撲 1.3 安全建設內容與目標 2.1 用戶側安全建設思路 2.2 用戶側安全建設拓撲 2.3 用戶側安全建設內容 2.3.1 PKI 升級改造 2.3.2 安全防護 2.3.3 安全檢測 2.3.4 安全管理 3.1 跨網安全訪問與交換平臺安全建設思…

微服務 01

微服務是一種軟件架構風格&#xff0c;它是以專注于單一職責的很多小型項目為基礎&#xff0c;組合出復雜的大型應用。 &#xff08;對應的是單體架構風格&#xff09; 一、認識微服務 1、單體架構 單體架構&#xff1a;將業務的所有功能集中在一個項目中開發&#xff0c;打…

20250726讓榮品的PRO-RK3566開發板使用TF卡啟動

20250726讓榮品的PRO-RK3566開發板使用TF卡啟動 2025/7/26 8:58緣起&#xff1a;需要升級 榮品的PRO-RK3566核心板的 底板上的FPGA程序。 由于沒有使用RK809的電量計功能&#xff0c;板子一上電就會被關機&#xff01;^_于是給生產線制作了一張TF卡/啟動卡&#xff0c;插到底板…

Selenium使用指南

&#x1f345; 點擊文末小卡片&#xff0c;免費獲取軟件測試全套資料&#xff0c;資料在手&#xff0c;漲薪更快 概述selenium是網頁應用中最流行的自動化測試工具&#xff0c;可以用來做自動化測試或者瀏覽器爬蟲等。官網地址為&#xff1a;相對于另外一款web自動化測試工具QT…

[機緣參悟-235]:通過AI人工升級網絡的工作方式和特征理解人的思維方式

AI人工神經網絡通過模擬生物神經元連接機制、構建層級化特征提取結構&#xff0c;并結合數據驅動的學習方式&#xff0c;為理解人類思維方式提供了技術參照框架&#xff0c;但其本質仍是基于統計的模式匹配&#xff0c;與人類意識層面的思維存在根本差異。以下從其工作方式、基…

【C#補全計劃:類和對象(七)—— 重寫虛方法】

一、virtual和override1. 問題引入&#xff1a;使用里氏替換原則時&#xff0c;使用父類容器裝載子類對象&#xff0c;若不使用virtual和override而是使用new&#xff0c;當子類調用兩個類共有的方法時&#xff0c;調用的是父類的方法而不是子類的方法&#xff1a;using System…

TCPIP之常用協議

一、TCPIP之網絡支撐協議 1.ARP ARP是網絡層協議&#xff0c;在同一廣播域內&#xff0c;將IP地址解析成MAC地址. 1.1 無故ARP 請求型無故ARP 設備在網絡中不管是自動獲取ip地址還是手動配置ip地址&#xff0c;設備都會發送請求型無故ARP檢查這個ip地址是否有重復的。 應…

網絡之路24:VLAN基礎實驗

正文共&#xff1a;2345 字 18 圖&#xff0c;預估閱讀時間&#xff1a;3 分鐘目錄網絡之路第一章&#xff1a;Windows系統中的網絡0、序言1、Windows系統中的網絡 1.1、桌面中的網卡 1.2、命令行中的網卡 1.3、路由表 1.4、家用路由器網絡之路第二章&#xff1a;認識企業設備2…

基于Verilog的神經網絡加速器設計

本設計實現了一個高效的神經網絡加速器,專注于卷積神經網絡(CNN)的核心計算功能。該設計具有以下創新點: 并行處理架構:同時處理多個卷積窗口,提高計算吞吐量 動態權重加載:支持運行時更新卷積核權重 流水線優化:卷積、激活、池化三級流水線設計 可配置參數:支持不同尺寸…

基于springboot的零食商城的設計與實現/零食銷售系統的設計與實現

用戶&#xff1a;注冊&#xff0c;登錄&#xff0c;商品信息&#xff0c;團購商品&#xff0c;公告資訊&#xff0c;后臺管理&#xff0c;在線客服&#xff0c;購物車&#xff0c;個人中心管理員&#xff1a;登錄&#xff0c;個人中心&#xff0c;用戶管理&#xff0c;商品類型…