silky微服务的应用服务和服务条目
服务的定义
服务接口是微服务定义服务的基本单位,定义的应用服务接口可以被其他微服务引用,其他微服务通过rpc框架与该微服务进行通信。
通过ServiceRouteAttribute特性对一个接口进行标识即可成为一个应用服务接口。
例如:
[ServiceRoute]
public interface ITestAppService
{
}
虽然我们通过使用[ServiceRoute]特性可以对任何一个接口标识为一个服务,服务定义的方法会通过应用服务的模板和方法特性的模板生成对应的webapi(该方法没有服务特性标识为禁用外网)。但是良好的命名规范可以为我们构建服务省去很多不必要的麻烦(通俗的说就是:约定大约配置)。
一般地,我们推荐使用AppService作为定义的服务的后缀。即推荐使用IXxxxAppService作为应用服务接口名称,默认生成的服务模板为:api/{appservice},使用XxxxAppService作为应用服务实现类的名称。
路由特性(ServiceRouteAttribute)可以通过template对服务路由模板进行设置。路由模板可以通过{appservice=templateName}设置服务的名称。
| 属性名称 | 说明 | 缺省值 |
|---|---|---|
| template | 在对服务接口标识为服务路由时,可以通过[ServiceRoute("{appservice=templateName}")]指定应用服务接口的路由模板。templateName的缺省值名称为对应服务的名称 |
api/{appservice} |
服务条目
服务条目(ServiceEntry): 服务接口中定义的每一个方法都会生成微服务集群的一个服务条目。对微服务应用本身而言,服务条目就相当于MVC中的Action,应用服务就相当于Controller。
根据服务条目生成WebAPI
应用接口被web主机应用或是网关引用后,会根据服务应用接口的路由模板和服务条目方法的Http动词特性指定的路由信息或是方法名称生成相应的webapi,服务条目生成的WebAPI支持restfulAPI风格。
服务条目生成webapi的规则为:
禁止集群外部访问的服务条目(
[Governance(ProhibitExtranet = true)])不会生成webapi;可以通过
[ServiceRoute("{appservice=templateName}")]为应用接口指定统一的路由模板;如果服务条目方法没有被http谓词特性标识,那么生成的webapi的http请求动词会根据服务条目的方法名称生成,如果没有匹配到相应的服务条目方法,则会根据服务条目的方法参数;
服务条目方法可以通过http谓词特性进行标识,并且http谓词特性还支持对服务条目指定路由模板,路由模板的指定还支持对路由参数进行约束;
服务条目生成的webAPI = 应用接口条目路由模板 + “方法名称||Http特性指定的路由特性”
如果不存在Http谓词特性标识情况下,生成的webapi路由说明(例如,应用接口名称为:ITestAppService,路由模板未被改写):
| 方法名称 | 生成的webAPI路径 | Http请求动词 |
|---|---|---|
| GetXXX | /api/test | get |
| SearchXXX | /api/test/search | get |
| CreateXXX | /api/test | post |
| UpdateXXX | /api/test | put |
| DeleteXXX | /api/test | delete |
存在Http谓词情况下,生成的webapi的请求动词会根据服务条目标识的http谓词特性来决定,开发者还可以通过http谓词特性为服务条目的的路由进行调整,并且支持路由参数的形式,例如:
| 方法名称 | 生成的webAPI路径 | http谓词特性 | Http请求动词 |
|---|---|---|---|
| GetXXX | /api/test/{id} | [HttpGet("{id:strig}")] | get |
| DeleteXXX | /api/test/name/{name} | [HttpDelete("name/{name:strig}")] | delete |
| UpdateXXX | /api/test/email | [HttpPatch("email")] | patch |
| CreateXXX | /api/test/user | [HttpPost("user")] | post |
服务条目的治理特性
开发者可以通过配置文件对服务条目的治理进行统一配置,除此之外可以通过Governance特性为服务条目方法进行标识,通过其属性对服务条目进行治理。通过Governance特性对服务条目方法注解后,服务条目的治理属性将会被该特性重写。
服务条目治理的属性请参考服务条目治理属性配置。
缓存拦截
在服务应用接口被其他微服务应用引用后,可以通过缓存拦截特性(GetCachingIntercept)在rpc通信过程中,直接从分布式缓存中读取数据,避免通过网络通信,而从提高系统性能。
更多关于缓存拦截请参考缓存拦截。
服务条目的例子
[ServiceRoute]
public interface ITestAppService
{
/// 新增接口测试([post]/api/test)
[GetCachingIntercept("name:{0}")]
Task<TestOut> Create(TestInput input);
/// 更新接口测试([put]/api/test)
Task<string> Update(TestInput input);
/// 删除接口测试([delete]/api/test)
[RemoveCachingIntercept("ITestApplication.Test.Dtos.TestOut", "name:{0}")]
[Transaction]
Task<string> Delete([CacheKey(0)] string name);
/// 查询接口测试([get]/api/test/search)
[HttpGet]
Task<string> Search([FromQuery] TestInput query);
/// 以表单格式提交数据([post]/api/test/form)
[HttpPost]
string Form([FromForm] TestInput query);
/// 通过name获取单条数据([get]/api/test/{name:string},以path参数传参,并约束参数类型为string)
[HttpGet("{name:string}")]
[Governance(ShuntStrategy = AddressSelectorMode.HashAlgorithm)]
[GetCachingIntercept("name:{0}")]
Task<TestOut> Get([HashKey] [CacheKey(0)] string name);
/// 通过id获取单条数据([get]/api/test/{id:long},以path参数传参,并约束参数类型为long)
[HttpGet("{id:long}")]
[Governance(ShuntStrategy = AddressSelectorMode.HashAlgorithm)]
[GetCachingIntercept("id:{0}")]
Task<TestOut> GetById([HashKey] [CacheKey(0)] long id);
///更新部分数据,使用patch请求 ([patch]/api/test)
[HttpPatch]
Task<string> UpdatePart(TestInput input);
}
服务的实现
一般地,开发者应当将定义服务的接口和服务的实现分开定义在不同的程序集。应用服务接口程序集可以被打包成Nuget包或是以项目的形式被其他微服务应用引用,这样其他微服务就可以通过rpc代理的方式与该微服务应用进行通信。更多RPC通信方面的文档请参考。
一个服务接口可以有一个或多个实现类。只有应用接口在当前微服务应用中存在实现类,该微服务应用接口对应的服务条目才会生成相应的服务路由,并将服务路由信息注册到服务注册中心,同时其他微服务应用的实例会订阅到微服务集群的路由信息。
应用接口如果存在多个实现类的情况下,那么应用接口的实现类,需要通过ServiceKeyAttribute特性进行标识。ServiceKeyAttribute存在两个参数(属性)。
| 属性名称 | 说明 | 备注 |
|---|---|---|
| name | 服务实现类的名称 | 通过webapi请求时,通过请求头serviceKey进行设置;rpc通信中,可以通过ICurrentServiceKey的实例调整要请求的应用接口实现。 |
| weight | 权重 | 如果通信过程中,未指定serviceKey,那么,会请求权重最高的应用接口的实现类 |
实例:
/// 应用服务接口(如:可定义在ITestApplication.csproj项目)
[ServiceRoute]
public interface ITestAppService
{
Task<string> Create(TestInput input);
// 其他服务条目方法略
}
//------------------------------------//
/// 应用服务实例类1 (如:可定义在TestApplication.csproj项目)
[ServiceKey("v1", 3)]
public class TestAppService : ITestAppService
{
public Task<string> Create(TestInput input)
{
return Task.FromResult("create v1")
}
// 其他接口实现方法略
}
//------------------------------------//
/// 应用服务实例类2 (如:可定义在TestApplication.csproj项目)
[ServiceKey("v2", 1)]
public class TestV2AppService : ITestAppService
{
public Task<string> Create(TestInput input)
{
return Task.FromResult("create v2")
}
// 其他接口实现方法略
}
生成的swagger文档如下:

在rpc通信过程中,可以通过IServiceKeyExecutor的实例设置要请求的应用接口的serviceKey。
private readonly IServiceKeyExecutor _serviceKeyExecutor;
public TestProxyAppService(ITestAppService testAppService,
IServiceKeyExecutor serviceKeyExecutor)
{
_testAppService = testAppService;
_serviceKeyExecutor = serviceKeyExecutor;
}
public async Task<string> CreateProxy(TestInput testInput)
{
return await _serviceKeyExecutor.Execute(() => _testAppService.Create(testInput), "v2");
}
开源地址
- github: https://github.com/liuhll/silky
- gitee: https://gitee.com/liuhll2/silky
在线文档
silky微服务的应用服务和服务条目的更多相关文章
- silky微服务简介
代理主机 silky微服务定义了三种类型的代理主机,开发者可以根据需要选择合适的silky代理主机托管微服务应用.代理主机定义了一个Startup模块,该模块给出了使用该种类型主机所必须依赖的模块. ...
- silky微服务框架服务注册中心介绍
目录 服务注册中心简介 服务元数据 主机名称(hostName) 服务列表(services) 终结点 时间戳 使用Zookeeper作为服务注册中心 使用Nacos作为服务注册中心 使用Consul ...
- silky微服务框架的服务治理介绍
目录 服务治理的概念 服务注册与发现 负载均衡 超时 故障转移(失败重试) 熔断保护(断路器) 限流 RPC限流 HTTP限流 1. 添加配置 2. 注册服务 3.启用 AspNetCoreRateL ...
- Silky微服务框架之服务引擎
构建服务引擎 在注册Silky微服务应用一节中,我们了解到在ConfigureServices阶段,通过IServiceCollection的扩展方法AddSilkyServices<T> ...
- Silky微服务框架之模块
模块的定义 Silky是一个包括多个nuget包构成的模块化的框架,每个模块将程序划分为一个个小的结构,在这个结构中有着自己的逻辑代码和自己的作用域,不会影响到其他的结构. 模块类 一般地,一个模块的 ...
- silky微服务业务主机简介
目录 主机的概念 通用主机 web主机 业务主机类型 使用web主机构建微服务应用 使用通用主机构建微服务应用 构建具有websocket能力的微服务应用 构建网关 开源地址 在线文档 主机的概念 s ...
- silky微服务模块
目录 模块的定义和类型 在模块中注册服务 通过ServiceCollection实现服务注册 通过ContainerBuilder实现服务注册 使用模块初始化任务 使用模块释放资源 模块的依赖关系 构 ...
- DDD理论学习系列(8)-- 应用服务&领域服务
DDD理论学习系列--案例及目录 1. 引言 单从字面理解,不管是领域服务还是应用服务,都是服务.而什么是服务?从SOA到微服务,它们所描述的服务都是一个宽泛的概念,我们可以理解为服务是行为的抽象.从 ...
- 应用服务&领域服务
应用服务&领域服务 DDD理论学习系列——案例及目录 1. 引言 单从字面理解,不管是领域服务还是应用服务,都是服务.而什么是服务?从SOA到微服务,它们所描述的服务都是一个宽泛的概念,我们可 ...
随机推荐
- 解除你学习Python自动化测试框架的所有疑惑,开启学习直通车
学习框架第一步 前言 很多同学学完Python基础后出现迷茫......有同感的小伙伴,点赞关注........ 学习完Python还要学习什么? 什么是自动化测试框架? 如何搭建自动化测试框架? 甚 ...
- 深入浅出WPF-11.Template(模板)02
模板 DataTemplate和ControlTemplate的关系 通过上面的内容,控件只是一个数据和行为的载体,是一个抽象的概念,至于它长什么样子,或者它的数据是怎么展示的,都是由模板生成的.决定 ...
- idea使用gitee的小坑
1. 账号配置 账号配置登陆时提示 *** is not a valid login name: Email support only. 翻译:只能支持邮箱登录 解决方法:在gitee网站上查看自己配 ...
- Zookeeper 集群部署的那些事儿
简介 额...., &*$% 淘气! ZooKeeper 是 Apache 的一个顶级项目,为分布式应用提供高效.高可用的分布式协调服务. ZooKeeper本质上是一个分布式的小文件存储系统 ...
- 用最简单的方式理解 IoC 控制反转
思想引入 假设一个系统原先只设定有一个默认的方法去完成业务,这里举例这个原先设定开发的是 UserDaoImpl(可能有些牵强,但是不影响我们对逻辑的理解)这样一个业务. 后来有一天,需求变了,业务流 ...
- FastAPI 学习之路(十五)响应状态码
系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...
- 初始CSS01
CSS基础知识 CSS介绍 CSS全称为层叠样式表,与HTML相辅相成,实现网页的排版布局与样式美化. 使用方式 根据样式表在页面中呈现的方式不同,可以通过以下三种方式在页面中使用格式 内联样式 改样 ...
- 【SDOI2014】数数(补)
见 AC自动机(补坑了) [SDOI2014] 数数 简要题意: 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为子串.例如当S={22,333,0233}时 ...
- 热身训练2 The All-purpose Zero
The All-purpose Zero 简要题意: 长度为n的数组,每个数字为S[i],$0$是一种很神奇的数字,你想要的,它都可以变! 问这个序列的最长上升子序列长度为多少? 分析: 我们将除了 ...
- MyBatis源码分析(三):MyBatis初始化(配置文件读取和解析)
一. 介绍MyBatis初始化过程 项目是简单的Mybatis应用,编写SQL Mapper,还有编写的SqlSessionFactoryUtil里面用了Mybatis的IO包里面的Resources ...