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

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

时间:2022-09-29 23:32:50浏览次数:83  
标签:task 服务 string Taurus Rpc MVC Result

系统目录:

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

开源地址:​​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
{
/// <summary>
/// 一般用于客户端:服务间的RPC调用
/// </summary>
public static partial class Rpc
{
/// <summary>
/// 根据微服务注册名称获取请求的主机地址【有多个时,由内部控制负载均衡,每次获取都会循环下一个】
/// 【自动识别(先判断:是否客户端;再判断:是否服务端)】
/// </summary>
/// <param name="name">微服务注册名称</param>
/// <returns></returns>
public static string GetHost(string name)

/// <summary>
/// 根据微服务注册名称获取请求的主机地址【有多个时,由内部控制负载均衡,每次获取都会循环下一个】
/// </summary>
/// <param name="name">微服务注册名称</param>
/// <param name="isClient">指定查询:true(客户端):false(服务端)</param>
/// <returns></returns>
public static string GetHost(string name, bool isClient)

/// <summary>
/// 执行一个异步的【通用】请求任务。
/// </summary>
/// <param name="request">任务请求</param>
/// <returns></returns>
public static RpcTask StartTaskAsync(RpcTaskRequest request)
{
return Rest.StartTaskAsync(request);
}

/// <summary>
/// 对远程服务发起一个异步Get请求。
/// </summary>
/// <param name="name">远程的注册模块名</param>
/// <param name="pathAndQuery">请求路径和参数</param>
/// <param name="header">请求头</param>
/// <returns></returns>
public static RpcTask StartGetAsync(string name, string pathAndQuery, Dictionary<string, string> header = null)


/// <summary>
/// 对远程服务发起一个异步Get请求。
/// </summary>
/// <param name="url">请求的地址</param>
/// <param name="header">可追加的请求头部分</param>
/// <returns></returns>
public static RpcTask StartGetAsync(string url, Dictionary<string, string> header = null)

/// <summary>
/// 对远程服务发起一个异步Post请求。
/// </summary>
/// <param name="name">微服务名称</param>
/// <param name="pathAndQuery">请求路径</param>
/// <param name="data">请求数据</param>
/// <param name="header">请求头</param>
/// <returns></returns>
public static RpcTask StartPostAsync(string name, string pathAndQuery, byte[] data, Dictionary<string, string> header = null)

/// <summary>
/// 对远程服务发起一个异步Post请求。
/// </summary>
/// <param name="url">请求的地址</param>
/// <param name="data">post的数据</param>
/// <param name="header">可追加的请求头部分</param>
/// <returns></returns>
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);"-----------------------------" + //可以处理其它业务逻辑
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端口)

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

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

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

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

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

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

4、测试运行结果:

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

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

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

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

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

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

总结:

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

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

3、使用简单。

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

开源地址:​​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
{
/// <summary>
/// 一般用于客户端:服务间的RPC调用
/// </summary>
public static partial class Rpc
{
/// <summary>
/// 根据微服务注册名称获取请求的主机地址【有多个时,由内部控制负载均衡,每次获取都会循环下一个】
/// 【自动识别(先判断:是否客户端;再判断:是否服务端)】
/// </summary>
/// <param name="name">微服务注册名称</param>
/// <returns></returns>
public static string GetHost(string name)

/// <summary>
/// 根据微服务注册名称获取请求的主机地址【有多个时,由内部控制负载均衡,每次获取都会循环下一个】
/// </summary>
/// <param name="name">微服务注册名称</param>
/// <param name="isClient">指定查询:true(客户端):false(服务端)</param>
/// <returns></returns>
public static string GetHost(string name, bool isClient)

/// <summary>
/// 执行一个异步的【通用】请求任务。
/// </summary>
/// <param name="request">任务请求</param>
/// <returns></returns>
public static RpcTask StartTaskAsync(RpcTaskRequest request)
{
return Rest.StartTaskAsync(request);
}

/// <summary>
/// 对远程服务发起一个异步Get请求。
/// </summary>
/// <param name="name">远程的注册模块名</param>
/// <param name="pathAndQuery">请求路径和参数</param>
/// <param name="header">请求头</param>
/// <returns></returns>
public static RpcTask StartGetAsync(string name, string pathAndQuery, Dictionary<string, string> header = null)


/// <summary>
/// 对远程服务发起一个异步Get请求。
/// </summary>
/// <param name="url">请求的地址</param>
/// <param name="header">可追加的请求头部分</param>
/// <returns></returns>
public static RpcTask StartGetAsync(string url, Dictionary<string, string> header = null)

/// <summary>
/// 对远程服务发起一个异步Post请求。
/// </summary>
/// <param name="name">微服务名称</param>
/// <param name="pathAndQuery">请求路径</param>
/// <param name="data">请求数据</param>
/// <param name="header">请求头</param>
/// <returns></returns>
public static RpcTask StartPostAsync(string name, string pathAndQuery, byte[] data, Dictionary<string, string> header = null)

/// <summary>
/// 对远程服务发起一个异步Post请求。
/// </summary>
/// <param name="url">请求的地址</param>
/// <param name="data">post的数据</param>
/// <param name="header">可追加的请求头部分</param>
/// <returns></returns>
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);"-----------------------------" + //可以处理其它业务逻辑
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端口)

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

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

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

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

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

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

4、测试运行结果:

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

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

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

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

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

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

总结:

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

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

3、使用简单。

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

开源地址:​​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
{
/// <summary>
/// 一般用于客户端:服务间的RPC调用
/// </summary>
public static partial class Rpc
{
/// <summary>
/// 根据微服务注册名称获取请求的主机地址【有多个时,由内部控制负载均衡,每次获取都会循环下一个】
/// 【自动识别(先判断:是否客户端;再判断:是否服务端)】
/// </summary>
/// <param name="name">微服务注册名称</param>
/// <returns></returns>
public static string GetHost(string name)

/// <summary>
/// 根据微服务注册名称获取请求的主机地址【有多个时,由内部控制负载均衡,每次获取都会循环下一个】
/// </summary>
/// <param name="name">微服务注册名称</param>
/// <param name="isClient">指定查询:true(客户端):false(服务端)</param>
/// <returns></returns>
public static string GetHost(string name, bool isClient)

/// <summary>
/// 执行一个异步的【通用】请求任务。
/// </summary>
/// <param name="request">任务请求</param>
/// <returns></returns>
public static RpcTask StartTaskAsync(RpcTaskRequest request)
{
return Rest.StartTaskAsync(request);
}

/// <summary>
/// 对远程服务发起一个异步Get请求。
/// </summary>
/// <param name="name">远程的注册模块名</param>
/// <param name="pathAndQuery">请求路径和参数</param>
/// <param name="header">请求头</param>
/// <returns></returns>
public static RpcTask StartGetAsync(string name, string pathAndQuery, Dictionary<string, string> header = null)


/// <summary>
/// 对远程服务发起一个异步Get请求。
/// </summary>
/// <param name="url">请求的地址</param>
/// <param name="header">可追加的请求头部分</param>
/// <returns></returns>
public static RpcTask StartGetAsync(string url, Dictionary<string, string> header = null)

/// <summary>
/// 对远程服务发起一个异步Post请求。
/// </summary>
/// <param name="name">微服务名称</param>
/// <param name="pathAndQuery">请求路径</param>
/// <param name="data">请求数据</param>
/// <param name="header">请求头</param>
/// <returns></returns>
public static RpcTask StartPostAsync(string name, string pathAndQuery, byte[] data, Dictionary<string, string> header = null)

/// <summary>
/// 对远程服务发起一个异步Post请求。
/// </summary>
/// <param name="url">请求的地址</param>
/// <param name="data">post的数据</param>
/// <param name="header">可追加的请求头部分</param>
/// <returns></returns>
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);"-----------------------------" + //可以处理其它业务逻辑
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端口)

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

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

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

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

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

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

4、测试运行结果:

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

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

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

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

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

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

总结:

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

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

3、使用简单。

标签:task,服务,string,Taurus,Rpc,MVC,Result
From: https://blog.51cto.com/cyq1162/5724449

相关文章

  • gRPC如何处理错误,以及gRPC错误代码。
    错误处理标准错误模型正如你在我们的概念文件和例子中所看到的,当一个gRPC调用成功完成后,服务器会向客户端返回一个OK状态(根据语言的不同,OK状态可能会或可能不会直接用于你......
  • Go中使用应用层传输安全(ALTS)的gRPC认证概述。
    ALTS认证Go中使用应用层传输安全(ALTS)的gRPC认证概述。概述应用层传输安全(ALTS)是由Google开发的相互认证和传输加密系统。它用于保护Google基础设施内的RPC通信的安......
  • grpc 核心概念、架构和生命周期
    介绍关键的gRPC概念,概述gRPC架构和RPC生命周期。不熟悉gRPC?请先阅读《gRPC简介》。关于特定语言的细节,请参见您所选择的语言的快速入门、教程和参考文档。 纵观全局服......
  • grpc介绍
     本页向您介绍gRPC和协议缓冲区。gRPC可以使用协议缓冲区作为其接口定义语言(IDL)和底层消息交换格式。如果你是gRPC和/或协议缓冲区的新手,请阅读这个!如果你只是想先深入......
  • 打印提示rpc服务器不可用 while creating the print servar win32 error:RPC
    这个问题的显著的表现,就是windows系统找不到打印机驱动,一般是断电或者设备突然中断导致的。PrintSpooler服务启动一下解决方案:     启动起来即可 ......
  • 十二、springMVC整合spring
    一、概述:需要进行spring整合springmvc吗?或者说还是否需要加入Spring的IOC容器?是否需要在web.xml文件中配置启动启动Spring IOC容器的ContextLoaderListener?需要整合......
  • 九、springMVC之文件上传
    一、配置方式web.xml:只配置了DispatcherServlet:1<?xmlversion="1.0"encoding="UTF-8"?>2<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"3xml......
  • 二、springMVC之RequestMapping和绑定参数注解
    一、概述:配置方式:同HelloWord的配置方式;目录结构: @RequestMapping:@RequestMapping除了可以使用请求URL映射请求外,还可以使用请求方法、请求参数及请求头映射请求;@RequestMa......
  • MVC实现金币添加
     其实代码部分没有什么变化,就是原来所有代码放到一起,mvc的话把他们分类了先建几个文件、脚本  Model层代码  Controller层代码 View层代码  此时co......
  • mybatis在spring mvc中的加载过程
    本地搭建了一套工程,把spring-5.2.x源码与mybatis-3.5.11源码做了整合,debug了一下mybatis-spring在springmvc中的加载过程。画了下面的图,删减了一些说明,图比较简练。后续......