@@ -1,7 +1,7 @@ | |||
| |||
Microsoft Visual Studio Solution File, Format Version 12.00 | |||
# Visual Studio 15 | |||
VisualStudioVersion = 15.0.26430.13 | |||
VisualStudioVersion = 15.0.26430.14 | |||
MinimumVisualStudioVersion = 10.0.40219.1 | |||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9B2AE124-6636-4DE9-83A3-70360DABD0C4}" | |||
EndProject | |||
@@ -19,6 +19,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | |||
ConfigureMSDTC.ps1 = ConfigureMSDTC.ps1 | |||
LICENSE.txt = LICENSE.txt | |||
README.md = README.md | |||
README.zh-cn.md = README.zh-cn.md | |||
EndProjectSection | |||
EndProject | |||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{9E5A7F49-8E31-4A71-90CC-1DA9AEDA99EE}" | |||
@@ -36,11 +37,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCore.CAP.EntityFramew | |||
EndProject | |||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{3A6B6931-A123-477A-9469-8B468B5385AF}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Kafka", "samples\Sample.Kafka\Sample.Kafka.csproj", "{2F095ED9-5BC9-4512-9013-A47685FB2508}" | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Kafka", "samples\Sample.Kafka\Sample.Kafka.csproj", "{2F095ED9-5BC9-4512-9013-A47685FB2508}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetCore.CAP.Kafka", "src\DotNetCore.CAP.Kafka\DotNetCore.CAP.Kafka.csproj", "{C42CDE33-0878-4BA0-96F2-4CB7C8FDEAAD}" | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCore.CAP.Kafka", "src\DotNetCore.CAP.Kafka\DotNetCore.CAP.Kafka.csproj", "{C42CDE33-0878-4BA0-96F2-4CB7C8FDEAAD}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetCore.CAP.RabbitMQ", "src\DotNetCore.CAP.RabbitMQ\DotNetCore.CAP.RabbitMQ.csproj", "{9961B80E-0718-4280-B2A0-271B003DE26B}" | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCore.CAP.RabbitMQ", "src\DotNetCore.CAP.RabbitMQ\DotNetCore.CAP.RabbitMQ.csproj", "{9961B80E-0718-4280-B2A0-271B003DE26B}" | |||
EndProject | |||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{10C0818D-9160-4B80-BB86-DDE925B64D43}" | |||
ProjectSection(SolutionItems) = preProject | |||
@@ -0,0 +1,171 @@ | |||
# CAP | |||
[![Travis branch](https://img.shields.io/travis/dotnetcore/CAP/master.svg?label=travis-ci)](https://travis-ci.org/dotnetcore/CAP) | |||
[![Travis](https://travis-ci.org/dotnetcore/CAP.svg?branch=master)](https://travis-ci.org/dotnetcore/CAP) | |||
[![AppVeyor](https://ci.appveyor.com/api/projects/status/4mpe0tbu7n126vyw?svg=true)](https://ci.appveyor.com/project/yuleyule66/cap) | |||
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/dotnetcore/CAP/master/LICENSE.txt) | |||
CAP 是一个在分布式系统(SOA、MicroService)中实现最终一致性的库,它具有轻量级、易使用、高性能等特点。 | |||
## 预览(OverView) | |||
CAP 是在一个 ASP.NET Core 项目中使用的库,当然他可以用于 ASP.NET Core On .NET Framework 中。 | |||
你可以把 CAP 看成是一个 EventBus,因为它具有 EventBus 的所有功能,并且CAP提供了更加简化的方式来处理 EventBus 中的发布和订阅。 | |||
CAP 具有消息持久化的功能,当你的服务进行重启或者宕机时它可以保证消息的可靠性。CAP提供了基于Microsoft DI 的 Producer Service 服务,它可以和你的业务服务进行无缝结合,并且支持强一致性的事务。 | |||
这是CAP集在ASP.NET Core 微服务架构中的一个示意图: | |||
![](http://images2015.cnblogs.com/blog/250417/201706/250417-20170630143600289-1065294295.png) | |||
> 图中实线部分代表用户代码,虚线部分代表CAP内部实现。 | |||
## Getting Started | |||
### NuGet 暂未发布 | |||
你可以运行以下下命令在你的项目中安装 CAP。 | |||
如果你的消息队列使用的是 Kafka 的话,你可以: | |||
``` | |||
PM> Install-Package DotNetCore.CAP.Kafka | |||
``` | |||
如果你的消息队列使用的是 RabbitMQ 的话,你可以: | |||
``` | |||
PM> Install-Package DotNetCore.CAP.RabbitMQ | |||
``` | |||
CAP 默认提供了 Entity Framwork 作为数据库存储: | |||
``` | |||
PM> Install-Package DotNetCore.CAP.EntityFrameworkCore | |||
``` | |||
### Configuration | |||
首先配置CAP到 Startup.cs 文件中,如下: | |||
```cs | |||
public void ConfigureServices(IServiceCollection services) | |||
{ | |||
...... | |||
services.AddDbContext<AppDbContext>(); | |||
services.AddCap() | |||
.AddEntityFrameworkStores<AppDbContext>() | |||
.AddKafka(x => x.Servers = "localhost:9453"); | |||
} | |||
public void Configure(IApplicationBuilder app) | |||
{ | |||
..... | |||
app.UseCap(); | |||
} | |||
``` | |||
### 发布 | |||
在 Controller 中注入 `ICapProducerService` 然后使用 `ICapProducerService` 进行消息发送 | |||
```cs | |||
public class PublishController : Controller | |||
{ | |||
private readonly ICapProducerService _producer; | |||
public PublishController(ICapProducerService producer) | |||
{ | |||
_producer = producer; | |||
} | |||
[Route("~/checkAccount")] | |||
public async Task<IActionResult> PublishMessage() | |||
{ | |||
//指定发送的消息头和内容 | |||
await _producer.SendAsync("xxx.services.account.check", new Person { Name = "Foo", Age = 11 }); | |||
return Ok(); | |||
} | |||
} | |||
``` | |||
### 订阅 | |||
**Action Method** | |||
在Action上添加 Attribute 来订阅相关消息。 | |||
如果你使用的是 Kafak 则使用 `[KafkaTopic()]`, 如果是 RabbitMQ 则使用 `[RabbitMQTopic()]` | |||
```cs | |||
public class PublishController : Controller | |||
{ | |||
private readonly ICapProducerService _producer; | |||
public PublishController(ICapProducerService producer) | |||
{ | |||
_producer = producer; | |||
} | |||
[NoAction] | |||
[KafkaTopic("xxx.services.account.check")] | |||
public async Task CheckReceivedMessage(Person person) | |||
{ | |||
Console.WriteLine(person.Name); | |||
Console.WriteLine(person.Age); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
``` | |||
**Service Method** | |||
如果你的订阅方法没有位于 Controller 中,则你订阅的类需要继承 `IConsumerService`: | |||
```cs | |||
namespace xxx.Service | |||
{ | |||
public interface ISubscriberService | |||
{ | |||
public void CheckReceivedMessage(Person person); | |||
} | |||
public class SubscriberService: ISubscriberService, IConsumerService | |||
{ | |||
[KafkaTopic("xxx.services.account.check")] | |||
public void CheckReceivedMessage(Person person) | |||
{ | |||
} | |||
} | |||
} | |||
``` | |||
然后在 Startup.cs 中的 `ConfigureServices()` 中注入你的 `ISubscriberService` 类 | |||
```cs | |||
public void ConfigureServices(IServiceCollection services) | |||
{ | |||
services.AddTransient<ISubscriberService,SubscriberService>(); | |||
} | |||
``` | |||
## 贡献 | |||
贡献的最简单的方法之一就是是参与讨论和讨论问题(issue)。你也可以通过提交的 Pull Request 代码变更作出贡献。 | |||
### License | |||
MIT |
@@ -24,18 +24,26 @@ namespace Sample.Kafka.Controllers | |||
} | |||
public string ServerPath => ((IHostingEnvironment)HttpContext.RequestServices.GetService(typeof(IHostingEnvironment))).ContentRootPath; | |||
[KafkaTopic("zzwl.topic.finace.callBack", IsOneWay = true, GroupOrExchange = "test")] | |||
[NonAction] | |||
public void KafkaTest() | |||
[KafkaTopic("zzwl.topic.finace.callBack", GroupOrExchange = "test")] | |||
public void KafkaTest(Person person) | |||
{ | |||
Console.WriteLine("kafka test invoked"); | |||
Console.WriteLine(person.Name); | |||
Console.WriteLine(person.Age); | |||
} | |||
[Route("~/send")] | |||
public async Task<IActionResult> SendTopic() | |||
{ | |||
await _producer.SendAsync("zzwl.topic.finace.callBack", "{\"msgBody\":\"{\\\"dealno\\\":null,\\\"businesstype\\\":\\\"1\\\",\\\"serialno\\\":\\\"435ldfhj345\\\",\\\"bankno\\\":\\\"650001\\\",\\\"amt\\\":20.0,\\\"virtualstatus\\\":1,\\\"paystatus\\\":1}\",\"callbackTopicName\":\"zzwl.topic.finace.callBack\",\"createId\":null,\"retryLimit\":0}"); | |||
await _producer.SendAsync("zzwl.topic.finace.callBack", new Person { Name = "Test", Age = 11 }); | |||
return Ok(); | |||
} | |||
public class Person | |||
{ | |||
public string Name { get; set; } | |||
public int Age { get; set; } | |||
} | |||
} | |||
} |
@@ -24,17 +24,17 @@ namespace Sample.Kafka | |||
public void ConfigureServices(IServiceCollection services) | |||
{ | |||
services.AddDbContext<AppDbContext>(); | |||
services.AddConsistency() | |||
.AddEntityFrameworkStores<AppDbContext>() | |||
.AddRabbitMQ(x => | |||
{ | |||
x.HostName = "192.168.2.206"; | |||
x.UserName = "admin"; | |||
x.Password = "123123"; | |||
}) | |||
.AddKafka(x => x.Servers = ""); | |||
services.AddCap() | |||
.AddEntityFrameworkStores<AppDbContext>() | |||
.AddRabbitMQ(x => | |||
{ | |||
x.HostName = "192.168.2.206"; | |||
x.UserName = "admin"; | |||
x.Password = "123123"; | |||
}); | |||
//.AddKafka(x => x.Servers = ""); | |||
// Add framework services. | |||
services.AddMvc(); | |||
} | |||
@@ -21,7 +21,7 @@ namespace DotNetCore.CAP.Test | |||
protected virtual void SetupMessageServices(IServiceCollection services, object context = null) | |||
{ | |||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); | |||
services.AddConsistency(); | |||
services.AddCap(); | |||
AddMessageStore(services, context); | |||
services.AddSingleton<ILogger<ICapMessageStore>>(new TestLogger<ICapMessageStore>()); | |||