Abp + Grpc 如何實現用戶會話狀態傳遞

来源:https://www.cnblogs.com/myzony/archive/2018/08/10/9454612.html
-Advertisement-
Play Games

0.背景 在實際項目當中,我們採用的是 Abp 框架,但是 Abp 框架官方並沒有針對 Grpc 進行模塊封裝。基於此我結合 Abp 與 MagicOnion 封裝了一個 Abp.Grpc 模塊,它包括服務端和調用端兩部分的包。通過這兩個包,你可以很方便地在 Abp 框架當中集成 Grpc 實現服務 ...


0.背景

在實際項目當中,我們採用的是 Abp 框架,但是 Abp 框架官方並沒有針對 Grpc 進行模塊封裝。基於此我結合 Abp 與 MagicOnion 封裝了一個 Abp.Grpc 模塊,它包括服務端和調用端兩部分的包。通過這兩個包,你可以很方便地在 Abp 框架當中集成 Grpc 實現服務內部通訊。

但是在實際使用當中會出現一個問題,當 A 服務調用 B 服務的時候,A 服務當前登錄用戶為 admin,調用 B 服務的 IAbpSession 的值仍然為空,這個時候當 B 服務內部實現使用了 IAbpSession 時會出現問題。

這是因為通過 Grpc 介面調用時,並沒有傳遞諸如 Token 之類的東西,而在 B 服務內部的 IAbpSession 本身附加的數據是從 HttpContext 裡面獲取的,所以 B 服務當前是沒有用戶狀態的。

1.解決

所幸 IAbpSession 提供了一個 Use 方法,通過這個方法我們可以臨時地改變 IAbpSession 內部的值,當 。定義如下:

IDisposable Use(int? tenantId, long? userId);

使用方法如下:

public class TestAppService : ITransientDependency
{
    private readonly IAbpSession _abpSession;
    
    public TestAppService(IAbpSession abpSession)
    {
        _abpSession = abpSession;
    }
    
    public void TestMethod()
    {
        using(_abpSession.Use(10,20))
        {
            // 其他操作
        }
        
        // 出去 using 語句之後會自動釋放之前的值
    }
}

2.Grpc 介面改造

這裡 Abp.Grpc 庫使用的是 MagicOnion 庫實現 Grpc 介面的,底層序列化使用的是 MessagePack,速度也不比 Protocol Buffer 差。

2.1 服務定義

服務定義介面時,必須附加一個 GrpcSession 參數,這個參數用於調用方傳遞其 IAbpSession 值所使用。例如我有一個介面方法如下,用於返回服務方接收到的用戶 Id 值。

public interface ITestGrpcService : IService<ITestGrpcService>
{
    // 普通的 Grpc 介面定義
    UnaryResult<int> Sum(int x, int y);

    // 帶有 GrpcSession 的介面定義
    UnaryResult<long?> TestGrpcSession(GrpcSession session);
}

2.2 服務提供方

服務提供方在實現 ITestGrpcService 的時候,需要在代碼起始點就開始使用 using 語句包裹代碼。

public class TestGrpcService : ServiceBase<ITestGrpcService>, ITestGrpcService
{
    private readonly IAbpSession _abpSession;

    public TestGrpcService()
    {
        _abpSession = IocManager.Instance.Resolve<IIocManager>().Resolve<IAbpSession>();
    }

    public UnaryResult<int> Sum(int x, int y)
    {
        return UnaryResult(x + y);
    }

    public UnaryResult<long?> TestGrpcSession(GrpcSession session)
    {
        // 賦值前 Session 的值
        Console.WriteLine(_abpSession.UserId);

        // 臨時改變 Session 值
        using (_abpSession.Use(session.TenantId, session.UserId))
        {
            Console.WriteLine(_abpSession.UserId);
        }

        // 離開 using 語句時 Session 的值
        Console.WriteLine(_abpSession.UserId);

        return new UnaryResult<long?>(1000);
    }
}

2.3 服務調用方

服務調用方則直接在調用 Grpc 介面的時候,傳遞給介面當前服務的 Session 狀態。

public class TestApplicationService : ApplicationService
{
    private readonly IGrpcConnectionUtility _utility;

    public TestApplicationService(IGrpcConnectionUtility utility)
    {
        _utility = utility;
    }

    public void TestAction()
    {
        // 獲得指定的 Grpc 服務
        var service = _utility.GetRemoteService<ITestGrpcService>("Grpc 服務名稱");
        // 調用測試方法,傳遞當前調用方的 Session 值
        var userId = service.TestGrpcSession(AbpSession as AbpSessionBase).GetAwaiter().GetResult();
        
        Console.WriteLine("TestGrpcSession 方法結果:" + userId);
    }
}

2.4 最後的效果

當客戶端調用 GRPC 介面時,會將自身的 Session 狀態通過 GrpcSession 傳遞到服務端,這樣服務端就能夠共用客戶端的繪畫狀態。

3.Abp.Grpc 項目地址

Abp.Grpc 庫地址:https://github.com/GameBelial/Abp.Grpc

4.實現的 DEMO 地址

服務端:https://github.com/GameBelial/Abp.Grpc.Server.Demo

客戶端:https://github.com/GameBelial/Abp.Grpc.Client.Demo


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一, 時間模塊 1. 時間格式 時間戳格式 / float 數據類型 / 格林威治時間 (給機器看的) print(time.time()) 結構化時間 / 時間對象 (從給機器看轉換成給人看的過度) 能夠通過 . 屬性名來獲取對象中的值 print(time.strftime( ' %Y-%m-% ...
  • 1.導包其實就是在導包里的__init__文件以執行文件的sys.path為準(內部的導入是以頂級目錄作為開頭的,往後一層層找)1. 什麼是包 包就是一個包含有__init__.py文件的文件夾 包本質就是一種模塊,即包是用包導入使用的,包內部包含的文件也都是用來被導入使用 2 為何要用包 包是文件 ...
  • 這裡可以採用redirect以get形式向指定頁面發出get請求,指定頁面完成後會再次跳轉到redirect後邊指定的頁面 格式:需要請求的URL?redirect=請求URL完成後需要跳轉的地址 例如: response.sendRedirect("http://localhost:8080/te ...
  • 1 簡介 pipenv是requests作者的一個項目,整合了virtualenv、pip、pipfile, 用於更方便地為項目建立虛擬環境並管理虛擬環境中的第三方模塊。不需要再分別使用pip和virtualenv,直接使用pipenv即可。它使用Pipfile和Pipfile.lock 取代了re ...
  • 本文參考了官方文檔以及提供的示例代碼(官方代碼貌似有點誤導,所以寫了這一篇,並且文末有GayHub代碼地址) 官方文檔發佈於20180806,說明NavigationView剛發佈了沒幾天,還在開發中,所以裡面的介面啥的隨時會變! 隨時會變! 隨時會變! ,用在你的項目之前,請需要做好充足的心理準備 ...
  • 環境: .net 4.0 ashx一般處理程式 使用 html5 FormData ajax上傳文件 功能如下:如果用戶有登錄,則對文件進行處理;如果用戶沒登錄,則直接返回json,提示用戶未登錄 遇到問題: 用戶登錄:正常 用戶沒登錄:調試的時候,沒任何異常,瀏覽器顯示Failed to load ...
  • 多層實體轉xml,泛型轉xml都可用,完善中.... ...
  • 屏幕拖拽截圖、全屏截圖,cropperjs裁剪上傳等功能,詳細介紹請看博客,寫的很細: https://www.cnblogs.com/bq-blog/p/9455241.html ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...