# Service-Framework
**Repository Path**: idealmatrix/service-framework
## Basic Information
- **Project Name**: Service-Framework
- **Description**: Tech Micro Service Framework是一个Web微服务框架和异步任务框架,采用微内核设计,具备良好的扩展性,对外提供统一的Http/Https服务和异步任务处理服务。
- **Primary Language**: C#
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 3
- **Created**: 2025-10-31
- **Last Updated**: 2025-10-31
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# TSF(Tech Service Framework)
## 1. 项目说明
**TSF(Tech Service Framework)**是一个**web服务**和**异步任务**运行框架,对外提供统一的Http/Https服务,内部实现了基于消息的异步处理。通过元数据和统一的IOC机制,实现了服务发现、服务包加载和运行的全生命周期管理。
● TSF提供了通过Http/Https访问内部服务的能力,是一个Web服务框架
● 支持将业务逻辑以自定义扩展插件的方式注入到Service Gateway中运行
● 数据传输协议:Json、Protobuf、Xml
● 传输数据支持加密,加密方式可配置。
● 支持安全访问控制:Token认证、黑白名单、防重放
● 支持数据缓存,缓存方式:本地缓存和分布式缓存
● TSF提供了Web版本的服务管理器:服务统一管理发布
● 支持业务标准的HTTP请求URL格式,满足第三方对接的需要
● 支持请求扩展,自定义解析HttpRequest,构造请求上下文参数
● 支持请求结果集的灵活扩展,提供默认的扩展实现,满足App的数据需求
● 支持五种身份认证方式:接受、忽略、必须、匿名无会话、匿名有会话
● 提供Mock Server功能,支持前后端分离后的调试开发模式
● 提供了限流功能,可对服务设置自定义流控策略,控制服务访问流量
---
## 2. 架构图

---
## 3. 目录结构
```plaintext
TSF/
├── Component/ # 公共组件
│ ├── Cache/ # 分布式缓存
│ ├── Cluster/ # 集群服务
│ ├── Config/ # 配置中心
│ ├── DACService/ # 数据访问
│ ├── DataLock/ # 数据锁
│ ├── Debug/ # 调试组件
│ ├── Error/ # 异常组件
│ ├── Event/ # 事件服务
│ ├── FlowControl/ # 流控组件
│ ├── I18NService/ # 国际化
│ ├── Kernel/ # 公共方法
│ ├── Log/ # 日志组件
│ ├── Monitor/ # 监控组件
│ ├── MQService/ # MQ组件
│ ├── Schedule/ # 定时任务
│ ├── Session/ # 会话组件
├── Framework/ # TSF框架
│ ├── T.SF.Console/ # TSF容器
│ ├── Config/ # 配置目录
│ ├── Database.config # 数据库配置
│ ├── bindinglist.json # web服务端口绑定
│ ├── sfmetadata.json # 公共服务元数据
│ ├── sgmetadata.json # sg服务元数据
│ ├── macmetadata.json # mac服务元数据
│ ├── App.config # 公共配置()
├── MAC/ # 异步服务框架
├── SG/ # web服务框架
```
---
## 4. 开发调试
### 环境准备
1. 开发工具:Visual Studio 2022(.NET 9 / C# 13)
2. 依赖中间件(按需启用)
- PostgerSQL (非本地模式下的元数据信息获取)
- Redis (启用web服务流控)
- RabbitMQ (异步服务)
### 启动项目
1. 将 T.SF.Console 设为启动项目;
2. 确认 App.config / Database.config / sgmetadata.json / sfmetadata.json / macmetadata.json / bindinglist.json 有效;
3. 运行(F5)。
4. Post方式访问 http://127.0.0.1:9000/api/Invoke?SID=CTP-HelloWorld&a=1&b=100
### 网关服务开发
1. 新建一个类库项目,包含一个业务实现类,可参考SG\Demo\T.Demo.SGPlugin\HelloWorldService.cs,示例如下源码
public int Add(int a, int b)
{
return a + b;
}
2. 编译生成DLL,如本例T.Demo.SGPlugin.dll
3. 编辑T.SF.Console.exe所在主目录Configs子目录下的sgmetadata.json文件,增加一个新的SG服务元数据注册信息,其中
ID:要保持文件中唯一
userdefineassemble:为编译生成的DLL文件名
clusterid:集群类型,可定义为TTP,或具有业务含义的英文名
groupinfo:服务组名,如果一个类注册了多个SG服务元数据,需要使用相同的服务组名
userdefineclass:本Demo中的HelloWorldService类全名
invokemethod属性值为HelloWorldService类方法名Add
入参列表中注册参数a、b的相关信息,注意,必须与方法名中参数保持一致,属性值参考如下
{
"id": "CTP-HelloWorld",
"name": "合计",
"appid": "TTP",
"clusterid": "TTP",
"groupinfo": "TTP",
"developer": "测试",
"serializetype": 0,
"iscache": 0,
"cachetype": 0,
"validminutes": 0,
"whitelist": null,
"blacklist": null,
"maxqueuesize": 0,
"isencryption": 0,
"encrypttype": 0,
"passemble": "",
"pclass": null,
"ishsf": 0,
"hsfid": null,
"invokemethod": "Add",
"userdefineassemble": "T.Demo.SGPlugin",
"userdefineclass": "T.Demo.SGPlugin.HelloWorldService",
"invokemethodhelper": null,
"ismonitor": 1,
"islogsysaction": 0,
"debugresult": null,
"isauthtoken": "0",
"isenabledebug": 0,
"responseextension": "",
"customurl": null,
"ischecktimestamp": 1,
"defaulttimeout": 1000,
"isinternal": 0,
"isflowcontrolenable": 0,
"inParams": [
{
"ID": "00000000-0000-0000-0000-000000000001",
"ParamKey": "a",
"ParamType": "System.Int32",
"ParamOrder": 0,
"ParamAssembly": "mscorlib"
},
{
"ID": "00000000-0000-0000-0000-000000000002",
"ParamKey": "b",
"ParamType": "System.Int32",
"ParamOrder": 1,
"ParamAssembly": "mscorlib"
}
],
"invokeExtensions": []
}
4. 将T.Demo.SGPlugin.dll复制到T.SF.Console.exe所在主目录的Services\SG\CTP-HelloWorld子目录下。
注意,如果是一个新的DLL,且设置服务组属性值为空,或其他不重复的组名,需在Services目录下新增一个以注册的SG服务ID命名的子目录并放置DLL
5. 重启T.SF.Console.exe
6. Post方式访问 http://127.0.0.1:9000/api/Invoke?SID=CTP-HelloWorld&a=2&b=3
### 异步服务开发
1. 开发并注册一个新的SG服务元数据,用来演示发送RabbitMQ消息,Demo代码如下
public string SendAsyncTask(string content)
{
var sender = TaskService.GetTaskSender();
var task =sender.CreateAsynTask("CTP-HelloWorldTask", "CTP-HelloWorldTask");
task.Data["Content"] = content;
sender.Send(task);
return "异步任务已发送";
}
注意,要增加对T.ServiceFramework.TaskCenter.Service的项目引用。
元数据注册及DLL放置参考上例
2. SG服务元数据注册信息参考如下
{
"id": "CTP-InvokeAsyncTask",
"name": "发送异步任务",
"appid": "TTP",
"clusterid": "TTP",
"groupinfo": "TTP",
"developer": "测试",
"serializetype": 0,
"iscache": 0,
"cachetype": 0,
"validminutes": 0,
"whitelist": null,
"blacklist": null,
"maxqueuesize": 0,
"isencryption": 0,
"encrypttype": 0,
"passemble": "",
"pclass": null,
"ishsf": 0,
"hsfid": null,
"invokemethod": "SendAsyncTask",
"userdefineassemble": "T.Demo.SGPlugin",
"userdefineclass": "T.Demo.SGPlugin.HelloWorldService",
"invokemethodhelper": null,
"ismonitor": 1,
"islogsysaction": 0,
"debugresult": null,
"isauthtoken": "0",
"isenabledebug": 0,
"responseextension": "",
"customurl": null,
"ischecktimestamp": 1,
"defaulttimeout": 1000,
"isinternal": 0,
"isflowcontrolenable": 0,
"inParams": [
{
"ID": "00000000-0000-0000-0000-00000000005",
"ParamKey": "content",
"ParamType": "System.String",
"ParamOrder": 0,
"ParamAssembly": "mscorlib"
}
],
"invokeExtensions": []
}
3. 开发并注册一个新的MAC服务元数据,实现ITaskExecutor接口,用来演示消费RabbitMQ消息,Demo代码如下
public class HelloWorldTaskExecutor2 : ITaskExecutor
{
public void Execute(TaskDataMap content)
{
var c = Convert.ToString(content["Content"]);
Console.WriteLine("【CTP-HelloWorldTask2】异步任务处理: " + c);
}
}
4. 编辑T.SF.Console.exe所在主目录Configs子目录下的macmetadata.json文件,增加一个新的MAC服务元数据注册信息,其中
ID:要保持文件中唯一
name建议与ID保持一致
taskexecutor:为编译生成的类名,DLL命名形式,即类的FullName
clustertype:集群类型,可定义为TTP,或具有业务含义的英文名
taskgroup:服务组名,如果一个类注册了多个SG服务元数据,需要使用相同的服务组名
{
"id": "CTP-HelloWorldTask2",
"name": "CTP-HelloWorldTask2",
"displayname": "异步任务Demo",
"taskexecutor": "T.Demo.MACPlugin.HelloWorldTaskExecutor2,T.Demo.MACPlugin",
"multistageconfig": "0",
"tasksource": "",
"monitorlevel": "1",
"isbatch": 0,
"batchsize": 0,
"messagechanel": "1",
"taskcenterinstance": "Host01",
"messagetypeclass": "",
"clustertype": "TTP",
"mqconnectionkey": "TTP.MQ.RabbitMQ.ConnectionString.HA",
"istracemessage": 0,
"isdisabled": 0,
"taskgroup": "",
"owner": "测试",
"isallowcontrol": 0,
"taskmetadatatype": 0,
"messagechanelname": "",
"isserializable": 0,
"isleastonce": 0,
"ismostonce": 0,
"validtime": 0,
"enablesubrequestid": 0,
"isidleconsume": 0
}
5. 将T.Demo.SGPlugin.dll复制到T.SF.Console.exe所在主目录的Services\MAC\CTP-HelloWorldTask子目录下
6. 重启T.SF.Console.exe
7. Post方式访问 http://127.0.0.1:9000/api/Invoke?SID=CTP-InvokeAsyncTask2&content=HelloWorld
8. 在T.SF.Console.exe的Console窗口可以看到RabbitMQ消息被消费,输出【CTP-HelloWorldTask】异步任务处理:HelloWorld
---
## 5. 公共组件使用
### 5.1 缓存组件
Cache组件封装了一系列对Redis操作的api,是访问Redis的统一入口。组件内部还包含了连接池管理、监控上报等功能。Cache组件内部引用了ServiceStack.Redis开源组件。在使用本组件之前,请先了解Redis的基本原理。
#### 5.1.1 配置文件Demo
配置属性说明
name:连接池名称
useSentinel:是否使用哨兵模式(非哨兵模式可忽略)
sentinelMasterGroupName:主从分组名称(非哨兵模式可忽略)
writeServerList:读写服务的连接串,多个串使用逗号分隔(哨兵模式此配置不起作用)
readServerList:只读服务的连接串,多个串使用逗号分隔(哨兵模式此配置不起作用)
maxWritePoolSize:读写服务连接池中的最大连接数
maxReadPoolSize:只读服务连接池中的最大连接数
autoStart:是否自动初始化连接池
databaseNumber:指向的分区
#### 5.1.2 调用方式
初始化CacheServcie
CacheService service = CacheService.GetInstance("DefaultPool");
简单模式
using (var client = service.GetClient())
{
bool result1 = client.SetEntry(key, value, TimeSpan.FromSeconds(100));
string result2 = client.GetValue(key);
}
【注意】务必使用using来获取client从而最终释放client,否则会出现连接池被占满的情况
Pipeline模式
using (var client = service.GetClient())
{
using (var pipeline = client.CreatePipeline())
{
pipeline.QueueCommand(p => p.SetEntry(key, value));
pipeline.QueueCommand(p => p.ExpireEntryIn(key, TimeSpan.FromSeconds(2)));
pipeline.Flush();
}
}
Transaction模式
using(var client = service.GetClient())
{
using (var trans = client.CreateTransaction())
{
trans.QueueCommand(p => p.SetEntry(key, value));
trans.QueueCommand(p => p.SetEntry(key1, value1));
trans.Commit();
}
}
### 5.2 集群服务SDK
#### 5.2.1 SDK方法
获取当前进程ID
var hostID = AppClusterLocalClient.GetInstance().HostID;
获取当前进程所属集群ID
var clusterID = AppClusterLocalClient.GetInstance().ClusterID;
获取当前进程所属集群类型
var clusterType = AppClusterLocalClient.GetInstance().ClusterType;
获取当前进程所属集群类型列表
List clusterTypes = AppClusterLocalClient.GetInstance().ClusterTypes;
注意:该接口返回的是一个List,一般TSF进程会包含多个集群类型,普通的HSF、SG和MAC进程仅包含一个集群类型
获取当前数据中心ID
var currentDataCenterID = AppClusterLocalClient.GetInstance().GetCurrentDataCenterId();
获取主数据中心ID
var mainDataCenterID = AppClusterLocalClient.GetInstance().GetMainDataCenterID();
获取当前服务单元ID
var currentServiceSetID = AppClusterLocalClient.GetInstance().GetCurrentServiceSetId();
获取指定数据中心域名(Nginx地址)
返回MA数据中心内部Nginx地址,形如sgima.teld.local:10080
var internalDomain = AppClusterLocalClient.GetInstance().GetDataCenterDomain("MA",true);
返回MA数据中心内部Nginx地址,形如sgi.teld.cn
var publicDomain = AppClusterLocalClient.GetInstance().GetDataCenterDomain("MA",false);
根据服务单元ID获取数据中心信息
返回指定Set的数据中心ID和外部域名键值对形式,形如{"MA","sgi.teld.cn"}
KeyValuePair kv = AppClusterLocalClient.GetInstance().GetDataCenterId("MCT.A1");
#### 5.2.2 调用示例
##### 5.2.2.1 示例1
var node = AppClusterQueryClient.Current.GetCurrentAppNode();
推荐使用
var hostId = AppClusterLocalClient.GetInstance().HostID;
以下方式实时交互服务端,不建议频繁调用,尤其循环调用
var hostId = AppClusterQueryClient.Current.GetCurrentAppHostID();
如果只是为获取集群ID,推荐使用
var clusterId = AppClusterLocalClient.GetInstance().ClusterID;
以下方式实时交互服务端,不建议频繁调用,尤其循环调用
var cluster = AppClusterQueryClient.Current.GetCurrentAppCluster();
如果只是为获取当前数据中心ID,推荐使用
var datacenterId = AppClusterLocalClient.GetInstance().GetCurrentDataCenterId();
以下方式实时交互服务端,不建议频繁调用,尤其循环调用
var dataCenter = AppClusterQueryClient.Current.GetDataCenterByHostID(hostID)
#### 5.2.2.2 示例2
获取当前数据中心内外部Nginx地址
var currentIDCID = AppClusterLocalClient.GetInstance().GetCurrentDataCenterId();
var internalDomain = AppClusterLocalClient.GetInstance().GetDataCenterDomain(currentIDCID, true);
var publicDomain = AppClusterLocalClient.GetInstance().GetDataCenterDomain(currentIDCID, false);
### 5.3 配置中心SDK
#### 5.3.1 SDK封装
///
/// 配置获取封装类
///
public class ConfigManager
{
///
/// 获取配置值
///
/// 配置名
/// 集群标识
/// 宿主标识
/// 配置值
public static string GetValue(string key, string appCluster = "", string appHost = "")
{
}
///
/// 获取配置节
///
/// 配置节类型
/// 配置名
/// 集群标识
/// 宿主标识
/// 配置值
public static T GetSection(string key, string appCluster = "", string appHost = "") where T : class
{
}
}
#### 5.3.2 使用示例
string configValue = ConfigManager.GetValue(“TTP.Database.TeldBoss.ConnectionString”);
RedisConfig configSection = ConfigManager.GetSection(“TTP.Redis.ConnectionString”);
### 5.4 数据访问组件
#### 5.4.1 api使用
string dbFlag = "teldbase";--配置文件中配置的连接字符中的name值
ITeldDatabase db = DatabaseHelper.GetDatabase(dbFlag);
初始化DaoServcie
DaoService service = DaoService.GetInstance("Sqlmap_DataPermissions");
IDataPermissionsDao dao = service.GetDao();
Sql操作
IDictionary dicFilter = new Dictionary();
dic.Add("ID", “123”);
IList< DataPermissionsEntity> list = dao.GetPagedDataPermissions(dicFilter);
Trasaction操作
using (IDaoTransaction trans = service.BeginTransaction())
{
dao.InsertDataPermission(permission);
dao.InsertDataPermissionDetail(details);
trans.Complete();
}
#### 5.4.2 配置
##### 5.4.2.1 配置文件参考
teldunity >
##### 5.4.2.2 配置中心参考
### 5.5 数据锁组件
DataLock组件提供了分布式的锁服务,其底层是基于Redis的锁封装而成的。因此组件内部引用了Cache组件。在使用本组件之前,请先了解Redis锁的实现以及Cache组件的开发。
#### 5.5.1 接口
static bool IsLock(ICacheClient client, string key)
static bool AddLockImmediately(ICacheClient client, string key, TimeSpan timeout)
static IDisposable AddLock(ICacheClient client, string key, TimeSpan timeout)
static void RemoveLock(ICacheClient client, string key)
#### 5.5.2示例
CacheService service = CacheService.GetInstance("DefaultPool");
using (var client = service.GetClient())
{
// 非阻塞加锁
bool isLocked = DataLockService.AddLockImmediately(client, key, TimeSpan.FromSeconds(100));
if(isLocked)
{
try
{
// do something
}
finally
{
DataLockService.RemoveLock(client, key);
}
}
// 阻塞加锁
using(var lock = DataLockService.AddLock(client, key, TimeSpan.FromSeconds(100)))
{
// do something
}
}
### 5.6 异常组件
Exception组件基于System.Exception封装了统一的TeldException类,其包含了异常编号、异常信息等数据。还提供了自定义Exception的方式,用于封装特定场景的异常。
#### 5.6.1 使用TeldException
public void TeldExceptionTest()
{
var i=0;
try
{
var result = 100 / i;
}
catch(DivideByZeroException e)
{
throw new TeldException(“AppCode-ModuleCode-0101”,”Attempted to divide by zero.”, e);
}
}
#### 5.6.2 自定义Exception
[Serializable]
public class TaskException:TeldException
{
public TaskException():base(){}
public TaskException(TaskExceptionType type):base(TaskExceptionHandler.GetExceptionCode(type)){}
public TaskException(TaskExceptionType type, System.Exception innerException):base(TaskExceptionHandler.GetExceptionCode(type), innerException){}
}
[Serializable]
public enum TaskExceptionType()
{
InBalidTask,
InValidTaskStore,
UnSetTaskStore,
SendException,
MQSendException
}
public static string GetExceptionCode(TaskExceptionType type)
{
switch(type)
{
Case TaskExceptionType.InValidTask:
Return “Task-Validator-0101”;
Case TaskExceptionType.InValidTaskStore:
Return “Task-Store-0102”;
……
}
}
public static string GetExceptionMessage(TaskExceptionType type)
{
switch(type)
{
Case TaskExceptionType.InValidTask:
Return “不合法的任务”;
Case TaskExceptionType.InValidTaskStore:
Return “不可用的任务存储”;
……
}
}
public static void Validate(ITask task)
{
if(task == null)
{
Var exception = new ArgumentNullException(“ITask”);
Throw new TaskException(TaskExceptionType.InValidTask, exception);
}
}
### 5.7 事件中心SDK
### 5.7.1 对接说明
事件中心分为事件发布和事件接收两部分。
事件发布基于事件中心SDK,请下载最新版nuget:Teld.Event.2.0.48.0进行事件发布的开发
事件接收基于MAC的自定义任务,请下载最新版nuget:Teld.Task.2.0.30.1进行自定义任务插件的开发
事件中心使用RabbitMQ作为消息载体,事件发布端需要配置RabbitMQ或对接配置中心。
事件发布SDK需要调用HSF服务来校验事件的合法性,发布端要包含HSF的相关dll和相关配置
#### 5.7.2 事件中心对接步骤
a)CMDB申请:任务元数据
b)基于事件中心SDK进行事件发布的开发
c)基于任务中心Spi进行自定义任务插件的开发
d)任务元数据sql补丁和自定义任务插件的发布
e)事件发布补丁的发布
#### 5.7.3 SDK说明
##### 5.7.3.1 事件发布
bool Teld.EventCenter.Client.EventBus.Publish(DistributeEvent message)
DistributeEvent
参数 类型 是否必填 说明
EventCode string 是 事件编号
EventObject string 是 事件内容
Sender string 是 事件发送者
SendTime Datetime 是 发送时间
Teld.EventCenter.Client.EventBus.GetInstance().Publish(new DistributeEvent { EventObject = "123", EventCode = "DistributeEvent1", Sender = "tester", SendTime = DateTime.Now });
##### 5.7.3.2 任务中心自定义任务插件的开发
public class CustomEventExecutor : ITaskExecutor
{
public void Execute(TaskDataMap content)
{
string sender = Convert.ToString(content["Sender"]);
DateTime sendTime = Convert.ToDateTime(content["SendTime"]);
string eventObject = Convert.ToString(content["Message"]);
//todo: 业务逻辑
}
}
### 5.8 流控组件
调用Demo
var strategy = new FlowControlStrategy
{
ID = "Test ID",
Name = "Test Name",
StrategyType = FlowControlStrategyType.TPS,
Threshold = 100,
FlowControlConfigJSON = "{}",
Descriptions = "Test Description",
TimeSpan = FlowControlTimespan.Second,
IsRefusedRequest = false,
Ext1 = "Test Ext1",
Ext2 = "Test Ext2",
Ext3 = "Test Ext3",
CreateTime = DateTime.Now,
Creator = "Test Creator",
LastModifyTime = DateTime.Now,
LastModifier = "Test Modifier",
DecisionType = DecisionType.dtCompatible,
HoneypotData = "Test HoneypotData",
HoneypotImpl = "Test HoneypotImpl"
};
int count = 1;
var result = FlowControlService.FlowControl(strategy, count);
### 5.9 国际化组件
调用Demo
TermService.Current.GetText("T_Standard_TTP_SG_Name", "服务名称");
///根据词条编号获取对应的词条翻译并格式化输出
string str1 = TermService.Current.GetText("T_Standard_TTP_SG_Name", "服务名称");
///根据词条编号获取对应的词条翻译并格式化输出
string str2 = TermService.Current.GetTextFormatted("T_Standard_TTP_SG_Count", "共获取到{0}个SG元数据", 10);
//共获取到10个SG元数据
### 5.10 Kernel组件
#### 5.10.1 上下文ContextService
##### 5.10.1.1 注册上下文
在程序第一次访问上下文之前先注册上下文
IContextHandler handler = new DefaultContextHandler();
ContextService.RegisterContextHandler(handler);
##### 5.10.1.2 操作上下文
DefaultContext context = new DefaultContext();
context.contextId=“xxx”;
ContextService. SetContext(context);
……
DefaultContext context = ContextService.GetContext();
#### 5.10.2 帮助类
类名 用途
BarCodeHelper 条形码操作帮助类
ChineseCalendarHelper 农历操作帮助类
ClassHelper 类型操作帮助类
ConvertHelper 类型转换帮助类
DataTableHelper DataTable帮助类
DateTimeHelper 时间操作帮助类
DESEncryptHelper DES加解密帮助类
DirFileHelper 目录文件帮助类
ExcelHelper Excel帮助类
FileDownloadHelper 文件下载帮助类
FileHelper 文件操作帮助类
FileUploadHelper 文件上传帮助类
FTPHelper FTP操作帮助类
GZipHelper GZip操作帮助类
HashtableHelper Hashtable帮助类
HTMLHelper HTML帮助类
ImageHelper 图片操作帮助类
IPScanerHelper IP操作帮助类
Md5Helper MD5操作帮助类
ObjCompareHelper 对比对象帮助类
PinyinHelper 拼音帮助类
RequestHelper 页面请求帮助类
RMBHelper RMB大小写操作类
RSAHelper RSA加解密帮助类
SMTPHelper SMTP帮助类
StringHelper 字符串操作帮助类
ValidateHelper 正则校验帮助类
WordHelper Word操作帮助类
XMLHelper XML操作帮助类
### 5.11 日志组件
#### 5.11 1 ILog接口定义
public interface ILogService
{
//同步记录日志
void SendMsg(ILog msg, bool autoCacheLog = true, bool autoCreateTopic = false);
//异步记录日志
void SendMsgAsync(ILog msg, bool autoCacheLog = true, bool autoCreateTopic = false);
void SendMsgs(List msgs, bool autoCacheLog = true, bool autoCreateTopic = false);
void SendMsgsAsync(List msgs, bool autoCacheLog = true, bool autoCreateTopic = false);
}
#### 5.11 2 LogLocalClient类方法
发送上报异常日志。注意:此方法不再上报根因。如果上报根因,请使用方法SendAndReportException。
static void Send(params ExceptionLog[] logs)
参数说明
logs:异常日志列表
发送异常日志并上报根因异常。如果是自己封装的信息,务必把原始异常设置为InnerException,否则无法根因分析。不设置InnerException时,根因分析系统将视此异常为故障点。
static void SendAndReportException(ExceptionLog log, Exception ex)
参数说明
log:异常日志实体
ex:异常实体
发送异常日志并上报根因异常。
static void SendAndReportException(Exception ex, string appCode, string moduleCode, string exceptionCode, ErrorLevel level, string invoker = "", string userId = "", string clientIP = "")
参数说明
ex:异常实体
appCode:应用编号
moduleCode:模块编号
exceptionCode:异常编号
exceptionLevel:异常等级
invoker:触发来源
userId:用户ID
clientIP:客户端IP
发送自定义的业务日志
void SendLogs(params ILog[] logs)
参数说明
logs:日志列表
日志发送开启事务
LogSendTransaction BeginSendTransaction()
注意: LogLocalClient类实现了IDisposable接口
1.如果不使用事务模式,不必使用using语法
2.如使用事务模式,建议使用using语法,这样当代码中未显式调用Commit()时会自动Rollback
#### 5.11 2 LogLocalClient调用Demo
##### 5.11 2.1 发送日志并上报根因
ExceptionLog log = new ExceptionLog()
{
ClientIP = "127.0.0.1",
CreateTime = DateTime.Now,
ExpCode = "TTP-SGP-0001",
ExpInfo = "",
ExpType = "ExceptionLog",
ModuleCode = "SGP",
AppVersion = "1.0.0",
Context = "testContext",
Ext1 = "test",
ServerIP = "T-BJ-TTP-01",
UserID = Guid.NewGuid().ToString(),
Invoker = "SG"
};
LogLocalClient.SendAndReportException(log, new Exception("空引用异常"));
##### 5.11 2.2 发送业务日志
ASCLog log = new ASCLog()
{
ClientIP = "127.0.0.1",
CreateTime = DateTime.Now,
ExpCode = "TTP-SGP-0001",
ExpInfo = "",
ExpType = "ExceptionLog",
ModuleCode = "SGP",
AppVersion = "1.0.0",
Context = "testContext",
Ext1 = "test",
ServerIP = "T-BJ-ASC-01",
UserID = Guid.NewGuid().ToString(),
Invoker = "SG"
};
LogLocalClient.SendLogs(log);
##### 5.11 2.3 带事务的上报日志-提交
var log = LogDataBuilder.CreateExceptionLog();
using (var client = new LogLocalClient())
{
using (var trans = client.BeginSendTransaction())
{
client.SendLogs(log);
trans.Commit();
}
}
### 5.12 监控组件组件
#### 5.12.1 MonitorClient组件方法
//
/// 上报服务监控数据(字符型)
///
/// 监控元数据ID
/// 值
/// 监控数据维度信息
/// 上下文
public static void Send(string monitorMetadataID, string value, Dictionary tags = null, Dictionary context = null)
///
/// 上报服务监控数据(浮点型)
///
/// 监控元数据ID
/// 值
/// 监控数据维度信息
/// 上下文
public static void Send(string monitorMetadataID, double value, Dictionary tags = null, Dictionary context = null)
///
/// 上报服务监控数据(整型)
///
/// 监控元数据ID
/// 值
/// 监控数据维度信息
/// 上下文
public static void Send(string monitorMetadataID, long value, Dictionary tags = null, Dictionary context = null)
#### 5.12.2 调用Demo
#### 5.12.2.1 不带维度
private static readonly string RedisTPS_MonitorMetaDataID = "Teld.Redis";
private static readonly string RedisResponseTime_MonitorMetaDataID = "Teld.Redis.ResponTime";
public void MonitorClientTPSDemo()
{
//上报Redis访问次数数据:1次
MonitorClient.Send(RedisTPS_MonitorMetaDataID, 1);
}
public void MonitorClientTimeDemo()
{
//上报Redis访问耗时数据:27ms
MonitorClient.Send(RedisResponseTime_MonitorMetaDataID, 27);
}
#### 5.12.2.2 自定义维度
private static readonly string RedisTPS_MonitorMetaDataID = "Teld.Redis";
private static readonly string RedisResponseTime_MonitorMetaDataID = "Teld.Redis.ResponTime";
public void MonitorClientTPSDemo()
{
var tag = new Dictionary()
{
{ "ProcessName","Teld.Boss.CM.Service"},
{ "DbNumber","0"}
};
//上报Redis访问次数数据:1次
MonitorClient.Send(RedisTPS_MonitorMetaDataID, 1, tag);
}
public void MonitorClientTimeDemo()
{
var tag = new Dictionary()
{
{ "ProcessName","Teld.Boss.CM.Service"},
{ "DbNumber","0"}
};
//上报Redis访问耗时数据:27ms
MonitorClient.Send(RedisResponseTime_MonitorMetaDataID, 27, tag);
}
### 5.13 MQ组件
#### 5.13.1 MQ组件初始化
string messageText = string.Empty;
IMQService service = null;
private IMQConnection sendConnection;
private IMQConnection receiveConnection;
service = MQServiceProvider.GetDefaultMQService();
messageText = "abc" + DateTime.Now.ToShortTimeString();
sendConnection = service.CreateConnection();
receiveConnection = service.CreateConnection();
#### 5.13.2 发送消息
///
/// 发送消息
///
/// 队列名称
private void SendMessage(string queueName)
{
//发送消息
var messageCreator = service.GetMessageCreator();
var message = messageCreator.CreateMessage(messageText);
var session = sendConnection.CreateSession();
var queue = session.DeclareQueue(queueName);
var producer = session.CreateProducer();
producer.Send(message, queue);
producer.Send(message, queue);
producer.Send(message, queue);
session.Close();
}
#### 5.13.3 接收消息
///
/// 接收消息
///
/// 队列名称
/// 消息
private IMessage ReceiveMessage(string queueName)
{
var session = receiveConnection.CreateSession();
var consumer = session.CreateQueueConsumer(queueName);
var queue = session.DeclareQueue(queueName);
var message = consumer.Receive(queue, new TimeSpan(0, 0, 1));
message = consumer.Receive(queue, new TimeSpan(0, 0, 1));
message = consumer.Receive(queue, new TimeSpan(0, 0, 1));
consumer.Close();
session.Close();
return message;
}
#### 5.13.4 删除队列
///
/// 删除队列
///
/// 队列名称
private void DeleteQueue(string queueName)
{
var session = sendConnection.CreateSession();
session.DeleteQueue(queueName);
}
### 5.14 请求代理组件
#### 5.14.1 注册代理方法
private RequestContainer _requestContainer;
_requestContainer.RegisteFunc("TestFunc", () => "Test");
var result = _requestContainer.GetResult("TestFunc");
#### 5.14.2 注册代理Action
private RequestContainer _requestContainer;
bool actionCalled = false;
_requestContainer.RegisteAction("TestAction", () => actionCalled = true);
_requestContainer.Invoke("TestAction");
#### 5.14.3 注册代理带参数的方法
private RequestContainer _requestContainer;
_requestContainer.RegisteFunc("TestFunc", (int x) => x * 2);
var result = _requestContainer.Invoke("TestFunc", 5);
#### 5.14.4 注册代理带参数的Action
private RequestContainer _requestContainer;
int actionResult = 0;
_requestContainer.RegisteAction("TestAction", (int x) => actionResult = x * 2);
_requestContainer.Invoke("TestAction", 5);
#### 5.14.5 注册代理异常
private RequestContainer _requestContainer;
_requestContainer.RegisteAction("TestAction", () => throw new Exception("Test exception"));
_requestContainer.Invoke(isThrowExcetion: false);
### 5.15 计划任务组件
#### 5.15.1 实现计划任务接口
internal class HelloWorldJob : ITJob
{
public async Task Execute(IJobExecutionContext context)
{
// Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}]{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} - HelloWorld");
if (context.JobConfigs != null)
{
foreach (var kv in context.JobConfigs)
{
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}]{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} -{kv.Key}:{kv.Value}");
}
}
}
}
#### 5.15.2 启动一个计划任务
IScheduleService scheduleService = new DefaultScheduleService();
scheduleService.Start("test");
### 5.16 会话组件
Session组件封装了对会话的操作。由于启用了分布Session,组件内部引用了缓存组件并将Session存于Redis中,因此在使用本组件之前,请先学习了解缓存组件的开发。
获取/设置SessionID
AppContext.Current.SessionID = sessionID;
获取/设置Session超时时间
AppContext.Current.SessionTimeout = 20; //单位:分钟
获取/设置Session内容
AppContext.Current.Session["uid"] = Guid.NewGuid().ToString();
String uid = AppContext.Current.Session["uid"].ToString();
---
## 6. 联系方式
**邮箱**:sz1stcool@outlook.com
**QQ**:704329448

---
## 7. 许可
The MIT License (MIT)
Copyright © Microsoft Corporation. All rights reserved.
Copyright (c) 2007, Clarius Consulting, Manas Technology Solutions, InSTEDD.
Copyright (c) 2018 stakx
Copyright Marko Lahma
Copyright 2014, Google Inc. All rights reserved.
Copyright 2004-2017 The Apache Software Foundation.
Copyright (c) 2004-2022 Castle Project
Copyright © SKB Kontur 2016-present
Copyright © 2007-2020 VMware, Inc. or its affiliates.
Copyright © James Newton-King 2008
Copyright © 2008-2018 ServiceStack, Inc
Copyright 2016-2020 Confluent Inc., Andreas Heider
Copyright © 2015 Autofac Contributors
Copyright (c) 2025-present, Teld
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.