码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Taurus.MVC 微服务框架 入门开发教程:项目集成:6、微服务间的调用方式:Rpc.StartTaskAsync。


    系统目录:

    本系列分为项目集成、项目部署、架构演进三个方向,后续会根据情况调整文章目录。

    开源地址:https://github.com/cyq1162/Taurus.MVC

    本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单。

    Taurus.MVC 微服务框架 入门开发教程:项目集成:1、服务端:注册中心、网关(提供可运行程序下载)。

    Taurus.MVC 微服务框架 入门开发教程:项目集成:2、客户端:ASP.NET Core(C#)项目集成:应用中心。

    Taurus.MVC 微服务框架 入门开发教程:项目集成:3、客户端:其它编程语言项目集成:Java集成应用中心。

    Taurus.MVC 微服务框架 入门开发教程:项目集成:4、默认安全认证与自定义安全认证。

    Taurus.MVC 微服务框架 入门开发教程:项目集成:5、统一的日志管理。

    Taurus.MVC 微服务框架 入门开发教程:项目集成:6、微服务间的调用方式:Rpc.StartTaskAsync。

    Taurus.MVC 微服务框架 入门开发教程:项目部署:1、微服务应用程序常规部署实现多开,节点扩容。

    Taurus.MVC 微服务框架 入门开发教程:项目部署:2、让Kestrel支持绑定多个域名转发,替代Ngnix使用。

    Taurus.MVC 微服务框架 入门开发教程:项目部署:3、微服务应用程序版本升级:全站升级和局部模块升级。

    Taurus.MVC 微服务框架 入门开发教程:项目部署:4、微服务应用程序发布到Docker部署(上)。

    Taurus.MVC 微服务框架 入门开发教程:项目部署:5、微服务应用程序发布到Docker部署(下)。

    Taurus.MVC 微服务框架 入门开发教程:项目部署:6、微服务应用程序Docker部署实现多开。

    Taurus.MVC 微服务框架 入门开发教程:项目部署:7、微服务节点的监控。

    Taurus.MVC 微服务框架 入门开发教程:架构演进:1、从单应用程序简单过渡到负载均衡。

    Taurus.MVC 微服务框架 入门开发教程:架构演进:2、负载均到模块拆分负载。

    Taurus.MVC 微服务框架 入门开发教程:架构演进:3、模块拆分负载到多级负载均衡。

    Taurus.MVC 微服务框架 入门开发教程:运行示例:https://github.com/cyq1162/Taurus.MVC.MicroService.Demo

    前言:

    以过多天的努力,终于提交了V3.1.1版本:

    复制代码
    -------------------------V3.1.1.0【升级微服务功能】((2022-09-09 - 2022-09-13)-----------------------------
    1、优化:调整Controller的名称空间:Taurus.Core =>Taurus.Mvc
    2、优化:控制器命名调整:允许控制器名称不以Controller结尾(DefaultController除外)。
    3、优化:Extend 更名:Plugin :原有Auth模块,独立出外部项目,变更为插件方式提供。
    4、优化:微服务网关代理调用。
    5、优化:微服务间的Key的网络调用请求头传参数名变更:microservice => mskey。
    6、优化:CheckAck、CheckToken、CheckMicroService、BeginInvode、EndInvode等方法(参数优化)。
    
    7、新增:IgnoreDefaultControllerAttribute 允许控制器忽略全局DefaultController事件。
    8、新增:提供微服务间的调用方式:Taurus.MicroService.Rpc。
    复制代码

    而新的版本,重要的内容,就是重新提供了Rpc间的方法调用,花了不少精力在处理并发的优化上面。

    对于微服务间的调用而言,Taurus.MVC微服务框架提供了以下方法:

    复制代码
    namespace Taurus.MicroService
    {
        /// 
        /// 一般用于客户端:服务间的RPC调用
        /// 
        public static partial class Rpc
        {
            /// 
            /// 根据微服务注册名称获取请求的主机地址【有多个时,由内部控制负载均衡,每次获取都会循环下一个】
            /// 【自动识别(先判断:是否客户端;再判断:是否服务端)】
            /// 
            /// 微服务注册名称
            /// 
            public static string GetHost(string name)
    
            /// 
            /// 根据微服务注册名称获取请求的主机地址【有多个时,由内部控制负载均衡,每次获取都会循环下一个】
            /// 
            /// 微服务注册名称
            /// 指定查询:true(客户端):false(服务端)
            /// 
            public static string GetHost(string name, bool isClient)
    
            /// 
            /// 执行一个异步的【通用】请求任务。
            /// 
            /// 任务请求
            /// 
            public static RpcTask StartTaskAsync(RpcTaskRequest request)
            {
                return Rest.StartTaskAsync(request);
            }
    
            /// 
            /// 对远程服务发起一个异步Get请求。
            /// 
            /// 远程的注册模块名
            /// 请求路径和参数
            /// 请求头
            /// 
            public static RpcTask StartGetAsync(string name, string pathAndQuery, Dictionary<string, string> header = null)
    
    
            /// 
            /// 对远程服务发起一个异步Get请求。
            /// 
            /// 请求的地址
            /// 可追加的请求头部分
            /// 
            public static RpcTask StartGetAsync(string url, Dictionary<string, string> header = null)
    
            /// 
            ///  对远程服务发起一个异步Post请求。
            /// 
            /// 微服务名称
            /// 请求路径
            /// 请求数据
            /// 请求头
            /// 
            public static RpcTask StartPostAsync(string name, string pathAndQuery, byte[] data, Dictionary<string, string> header = null)
    
            /// 
            /// 对远程服务发起一个异步Post请求。
            /// 
            /// 请求的地址
            /// post的数据
            /// 可追加的请求头部分
            /// 
            public static RpcTask StartPostAsync(string url, byte[] data, Dictionary<string, string> header = null)
    
        }
    }
    复制代码

    下面进行使用说明:

    1、Rpc.GetHost(...)方法说明:

    对于微服务而言,微服务一开就是好多个,不太应该用固定的host去访问。

    因此,框架提供方法,可以根据微服务的注册名称,获得负载均衡下的其中一个host地址。

    Rpc一般都在微服务应用中心(即客户端调用);

    服务端(网关,或注册中心)一般不使用,但框架仍贴心的提供重载方法,以便服务端也可以使用。

    框架提供此方法,获得请求Host后,使用者是可以根据情况,自行写代码调用,也可以使用以下框架封装好的代码。

    2、RpcTask:方法间的调用(异步任务)

    框架对ASP.NET、ASP.NET2.1-3.1-5、ASP.NET6及以上,分三种情景分别进行了优化封装。

    并严格进行了并发(>1000)下的测试与优化,保障了并发下的顺畅不卡顿。

    下面看使用示例方法:

    1、Get请求:

    复制代码
        public class RpcController : Taurus.Mvc.Controller
        {
            static int i = 0;
            public void CallGet()
            {
                i++;
                RpcTask task = Rpc.StartGetAsync("ms", "/ms/hello?msg=" + DateTime.Now.Ticks);
                System.Diagnostics.Debug.WriteLine("-----------------------------" + i);
                //可以处理其它业务逻辑
                string text = task.Result.IsSuccess ? task.Result.ResultText : task.Result.ErrorText;
                RpcTaskState state = task.State;
                if (string.IsNullOrEmpty(text) || !task.Result.IsSuccess)
                {
                    Response.StatusCode = 404;
                }
                Write(text);
            }
    }
    复制代码

    说明:

    1、task.Wait(...)方法,可以手动执行异步等待。
    
    2、task.Result(获取结果,内部也会进行等待返回)

    2、Post请求:

    复制代码
    public void CallPost()
            {
    
                i++;
                RpcTask task = Rpc.StartPostAsync("ms", "/ms/hello?id=" + DateTime.Now.Ticks, Encoding.UTF8.GetBytes("id=2&msg=" + DateTime.Now.Ticks));//,
                System.Diagnostics.Debug.WriteLine("-----------------------------" + i);
                task.Wait();
                string text = task.Result.IsSuccess ? task.Result.ResultText : task.Result.ErrorText;
                RpcTaskState state = task.State;
                if (string.IsNullOrEmpty(text) || !task.Result.IsSuccess)
                {
                    Response.StatusCode = 404;
                }
                Write(text);
            }
    复制代码

    3、Put请求:

    复制代码
            public void CallPut()
            {
                i++;
                RpcTask task = Rpc.StartTaskAsync(new RpcTaskRequest() { Method = "Put", Url = Rpc.GetHost("ms") + "/ms/hello2" });//,Encoding.UTF8.GetBytes("id=2&msg=" + DateTime.Now.Ticks)
                System.Diagnostics.Debug.WriteLine("-----------------------------" + i);
                task.Wait();
                string text = task.Result.IsSuccess ? task.Result.ResultText : task.Result.ErrorText;
                RpcTaskState state = task.State;
                if (string.IsNullOrEmpty(text) || !task.Result.IsSuccess)
                {
    
                    Response.StatusCode = 404;
                }
                Write(text);
            }
    复制代码

    4、Head请求:

    复制代码
            public void CallHead()
            {
                i++;
                RpcTask task = Rpc.StartTaskAsync(new RpcTaskRequest() { Method = "Head", Url = Rpc.GetHost("ms") + "/ms/hello2" });//,Encoding.UTF8.GetBytes("id=2&msg=" + DateTime.Now.Ticks)
                System.Diagnostics.Debug.WriteLine("-----------------------------" + i);
                task.Wait();
                string text = task.Result.IsSuccess ? CYQ.Data.Tool.JsonHelper.ToJson(task.Result.Header) : task.Result.ErrorText;
                RpcTaskState state = task.State;
                if (string.IsNullOrEmpty(text) || !task.Result.IsSuccess)
                {
                    Response.StatusCode = 404;
                }
                Write(text);
            }
    复制代码

    5、Delete请求:

    复制代码
            public void CallDelete()
            {
    
                i++;
                RpcTask task = Rpc.StartTaskAsync(new RpcTaskRequest() { Method = "Delete", Url = Rpc.GetHost("ms") + "/ms/hello2" });//,Encoding.UTF8.GetBytes("id=2&msg=" + DateTime.Now.Ticks)
                System.Diagnostics.Debug.WriteLine("-----------------------------" + i);
                task.Wait();
                string text = task.Result.IsSuccess ? task.Result.ResultText : task.Result.ErrorText;
                RpcTaskState state = task.State;
                if (string.IsNullOrEmpty(text) || !task.Result.IsSuccess)
                {
    
                    if (state == RpcTaskState.Running)
                    {
                        task.Wait();
                    }
                    Response.StatusCode = 404;
                }
                Write(text);
            }
    复制代码

    3、测试运行准备:

     为了测试,程序启动了:

    1、注册中心:(监听5000端口)

    2、微服务模块(ms)模块:启动了两个:(随机端口)

    3、微服务模块(rpc)模块,启动了1个:(监听4000端口)

    示例是在rpc模块中,调用ms模块的服务: 代码即上述RpcTask中的CallGet的代码。 

    4、测试运行结果:

    Rpc调用:请求示例结果:(浏览器显示是2毫秒) 

    Rpc模块请求时间:(控制台显示的请求时间,1.N毫秒左右):

    MS模块(被调用者)请求时间:(ms模块执行业务请求的时间,每次都在1毫秒以内)

    总结:

    1、框架Rpc架基于WebClient和HttpClient进行优化,主要优化点是进行端口和链接的复用。 

    2、性能整体在预期内,在并发下(>1000)仍然稳定流畅。

    3、使用简单。

  • 相关阅读:
    Redis-带你深入学习数据类型Hash【面试重点】
    k8s:Pod 基础概念
    【C++】标准流与命名空间简介 ( Visual Studio 2019 中创建 C++ 项目 | iostream 标准流 | std 标准命名空间 | cout 控制台输出 )
    目标检测常见数据增强算法汇总讲解(Mixup,Cutout,CutMix,Mosaic)
    你听说过推挽电路吗?避免交越失真
    Vue3响应系统的实现(一)
    6-2 pytorch中训练模型的3种方法
    upload-labs通关
    在腾讯云服务器OpenCLoudOS系统中安装maven(有图详解)
    LeetCode 面试题 16.01. 交换数字
  • 原文地址:https://www.cnblogs.com/cyq1162/p/16694749.html
  • 最新文章
  • 【JVM】编译执行与解释执行的区别是什么?JVM 使用哪种方式?
    用 Hashids 优雅解决 C 端自增 ID 暴露问题
    V8引擎 精品漫游指南--Ignition篇(上) 指令 栈帧 槽位 调用约定 内存布局 基础内容
    LLVM Pass快速入门(四):代码插桩
    milkup:桌面端 markdown AI续写和即时渲染
    基于项目工程构建SBOM(软件物料清单)的研究
    鸿蒙应用开发UI基础第二节:鸿蒙应用程序框架核心解析与实操
    .NET 中如何快速实现 List 集合去重?
    扣子Coze实战:从0到1打造抖音+小红书热点监控智能体
    浅谈数据访问层
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号