一 kafka介绍

kafka是基于zookeeper的一个分布式流平台,既然是流,那么大家都能猜到它的存储结构基本上就是线性的了。硬盘大家都知道读写非常的慢,那是因为在随机情况下,线性下,硬盘的读写非常快。kafka官方文档,一直拿传统的消息队列来和kafka对比,这样大家会触类旁通更快了解kafka的特性。最熟悉的消息队列框架有ActiveMQRabbitMQ.熟悉消息队列的,最熟悉的特性就是队列和发布订阅功能,因为这是大家最常用的,kafka实现了一些特有的机制,去规避传统的消息队列的一些瓶颈,比如并发,rabbitMQ在多个处理程序下,并不能保证执行顺序,还是必须自己去处理独占,而kafka使用consumer group的方式,实现了可以多个处理程序处理一个topic下的记录。如图:

每个分区的记录保证能被每个组接受,这样可以并发去处理一个topic的记录,而且扩展组,则可以随意根据应用需求去扩展你的应用程序,但是每个组的消费者不能超过分区的数量。

kafka Distribution 提供了容错的功能,每一个partition都有一个服务器叫leader,还有零个或者一个以上的服务器叫follower,当这些follower都在同步数据的时候,leader扛起所有的写和读,当leader挂掉,follower会随机选取一个服务器当leader,当然必须有几个follower同步时 in-sync的。还有kafka虽然的那个记录具有原子性,但是并不支持事务。

因为这一篇并不是专门讲解kafka,所以点到为止。

二     扩展服务 开发

以前讲过,netcore的一个很重要的特性就是支持依赖注入,在这里一切皆服务。那么如果需要kafka作为日志服务的终端,就首先需要kafka服务,下面咱们就开发一个kafka服务。

首先,服务就是需要构建,这是netcore开发服务的第一步,我们首先建立一个IKafkaBuilder.cs接口类,如下:

homusing Microsoft.Extensions.DependencyInjection;

namespace Walt.Freamwork.Service
{
public interface IKafkaBuilder
{
/// <summary>
/// Gets the <see cref="IServiceCollection"/> where Logging services are configured.
/// </summary>
IServiceCollection Services { get; }
}
}

再实现它,KafkaBuilder.cs

using Microsoft.Extensions.DependencyInjection;

namespace Walt.Freamwork.Service
{
public class KafkaBuilder : IKafkaBuilder
{
public IServiceCollection Services {get;} public KafkaBuilder(IServiceCollection services)
{
Services=services;
}
}
}

再利用扩展方法为serviceCollection类加上扩展方法:

 using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Walt.Framework.Service.Kafka; namespace Walt.Framework.Service
{ public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds logging services to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection AddKafka(this IServiceCollection services)
{
return AddKafka(services, builder => { });
} public static IServiceCollection AddKafka(this IServiceCollection services
, Action<IKafkaBuilder> configure)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
} services.AddOptions();
configure(new KafkaBuilder(services));
services.TryAddSingleton<IKafkaService,KafkaService>(); //kafka的服务类
return services;
}
}
}
KafkaService的实现:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Confluent.Kafka;
using Microsoft.Extensions.Options; namespace Walt.Framework.Service.Kafka
{
public class KafkaService : IKafkaService
{ private KafkaOptions _kafkaOptions;
private Producer _producer;
public KafkaService(IOptionsMonitor<KafkaOptions> kafkaOptions)
{
_kafkaOptions=kafkaOptions.CurrentValue;
kafkaOptions.OnChange((kafkaOpt,s)=>{
_kafkaOptions=kafkaOpt;
System.Diagnostics.Debug
.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(kafkaOpt)+"---"+s); });
_producer=new Producer(_kafkaOptions.Properties);
} private byte[] ConvertToByte(string str)
{
return System.Text.Encoding.Default.GetBytes(str);
} public async Task<Message> Producer(string topic,string key,string value)
{
if(string.IsNullOrEmpty(topic)
||string.IsNullOrEmpty(value))
{
throw new ArgumentNullException("topic或者value不能为null.");
} var task= await _producer.ProduceAsync(topic,ConvertToByte(key),ConvertToByte(value));
return task;
} }
}

那么咱们是不是忘记什么了,看上面的代码,是不是那个配置类KafkaOptions 还没有说明?

这个位置添加kafka的配置类KafkaConfigurationOptions:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Walt.Freamwork.Service; namespace Walt.Freamwork.Configuration
{
public class KafkaConfigurationOptions : IConfigureOptions<KafkaOptions>
{ private readonly IConfiguration _configuration; public KafkaConfigurationOptions(IConfiguration configuration)
{
_configuration=configuration;
} public void Configure(KafkaOptions options)
{
//这里仅仅自定义一些你自己的代码,使用上面configuration配置中的配置节,处理程序没法自动绑定的
                  一些事情。
}
}
}

然后,将配置类添加进服务:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Walt.Framework.Service; namespace Walt.Framework.Configuration
{
public static class KafkaConfigurationExtensioncs
{
public static IKafkaBuilder AddConfiguration(this IKafkaBuilder builder
,IConfiguration configuration)
{ InitService( builder,configuration);
return builder;
} public static void InitService(IKafkaBuilder builder,IConfiguration configuration)
{
builder.Services.TryAddSingleton<IConfigureOptions<KafkaOptions>>(
new KafkaConfigurationOptions(configuration)); //配置类和配置内容 builder.Services.TryAddSingleton
(ServiceDescriptor.Singleton<IOptionsChangeTokenSource<KafkaOptions>>(
new ConfigurationChangeTokenSource<KafkaOptions>(configuration)) );//这个是观察类,如果更改,会激发onchange方法 builder.Services
.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<KafkaOptions>>
(new ConfigureFromConfigurationOptions<KafkaOptions>(configuration))); //这个是option类,没这个,配置无法将类绑定 builder.Services.AddSingleton(new KafkaConfiguration(configuration));
}
}
}

ok,推送nuget,业务部分调用。

三     kafka服务调用

在project中引用然后restore:

引入命名空间:

调用:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Walt.Framework.Log;
using Walt.Framework.Configuration;
using Walt.Framework.Service; namespace Walt.TestMcroServoces.Webapi
{
public class Program
{
public static void Main(string[] args)
{ var host = new WebHostBuilder()
.ConfigureAppConfiguration((hostingContext, configContext) =>{
var en=hostingContext.HostingEnvironment;
if(en.IsDevelopment())
{
configContext.AddJsonFile($"appsettings.{en.EnvironmentName}.json");
}
else
{
configContext.AddJsonFile("appsettings.json");
}
configContext.AddCommandLine(args)
.AddEnvironmentVariables()
.SetBasePath(Directory.GetCurrentDirectory()).Build(); }).ConfigureServices((context,configureServices)=>{
configureServices.AddKafka(KafkaBuilder=>{
KafkaBuilder.AddConfiguration(context.Configuration.GetSection("KafkaService"));
});
}) //kafka的调用。
.ConfigureLogging((hostingContext, logging) => { logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"))
.AddCustomizationLogger(); }).UseKestrel(KestrelServerOption=>{
KestrelServerOption.ListenAnyIP();
})
.UseStartup<Startup>().Build();
host.Run();
Console.ReadKey();
}
} }

然后提交git,让jenkins构建docker发布运行:

jenkin是是非常牛的一款构建工具,不仅仅根据插件可以扩展不同环境,还支持分布式构建.

这是我们用jenikins构建的的:

让它跑起来:

调用看看:

这个方法是输出Properties数组的,这个配置结构只是演示,后面的结构要变,因为要放kafka的配置,比如连接服务ip等,

改动也很简单,在配置好configuration和service后,改动这个类KafkaOptions和配置文件中kafka节点中的json结构就行。:

四 集成kafka

kafka的接口不多,看看都有那些:

https://docs.confluent.io/current/clients/confluent-kafka-dotnet/api/Confluent.Kafka.Producer.html

ConsumerProducer是咱们发布消息和消费消息的两个主类,代码在上文已经实现的service。

客户端代码:

使用my-replicated-topic-morepart这儿topic,还是希望多分区,因为后面consumer使用分布式计算读取。

consumer先在客户端监听:

product端的调用代码:

执行这个接口后,再看consumer接收到的消息:

最后一步,将咱们kafka日志部分替换为真实的kafka环境,看结果:

那么最后的配置是这样的:

{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Debug",
"Microsoft": "Debug"
},
"KafkaLog":{
"Prix":"这是我的自定义日志提供程序"
}
},
"KafkaService":{
"Properties":{
"bootstrap.servers":"192.168.249.106:9092"
}
}
}

log使用这个kafka服务就很简单了,在前面文章中实现的log扩展类中,直接构造函数注入这个kafkaService,就可以以使用了。

asp.net core mcroservices 架构之 分布式日志(三):集成kafka的更多相关文章

  1. asp.net core mcroservices 架构之 分布式日志(一)

    一 简介 无论是微服务还是其他任何分布式系统,都需要一个统一处理日志的系统,这个系统 必须有收集,索引,分析查询的功能.asp .net core自己的日志是同步方式的,正如文档所言: 所以必须自己提 ...

  2. asp.net core mcroservices 架构之 分布式日志(二)之自定义日志开发

    netcore日志原理 netcore的日志是作为一个扩展库存在的,每个组件都有它的入口,那么作为研究这个组件的入口是最好的,首先看两种方式: 这个是源码例子提供的. var loggingConfi ...

  3. asp.net core microservices 架构之分布式自动计算(三)-kafka日志同步至elasticsearch和kibana展示

    一 kafka consumer准备 前面的章节进行了分布式job的自动计算的概念讲解以及实践.上次分布式日志说过日志写进kafka,是需要进行处理,以便合理的进行展示,分布式日志的量和我们对日志的重 ...

  4. asp.net core microservices 架构之 分布式自动计算(二)

    一  简介                   上一篇介绍了zookeeper如何进行分布式协调,这次主要讲解quartz使用zookeeper进行分布式计算,因为上一篇只是讲解原理,而这次实际使用, ...

  5. asp.net core microservices 架构之 分布式自动计算(一)

       一:简介   自动计算都是常驻内存的,没有人机交互.我们经常用到的就是console job和sql job了.sqljob有自己的宿主,与数据库产品有很关联,暂时不提.console job使 ...

  6. .net core microservices 架构之 分布式

    .net core microservices 架构之 分布式  一:简介   自动计算都是常驻内存的,没有人机交互.我们经常用到的就是console job和sql job了.sqljob有自己的宿 ...

  7. ASP.NET Core使用Elasticsearch记录NLog日志

    ASP.NET Core使用Elasticsearch记录NLog日志 1.新建一个 ASP.NET Core项目 2.安装Nuge包 运行:Install-Package NLog.Web.AspN ...

  8. ASP.NET Core 使用 Redis 实现分布式缓存:Docker、IDistributedCache、StackExchangeRedis

    ASP.NET Core 使用 Redis 实现分布式缓存:Docker.IDistributedCache.StackExchangeRedis 前提:一台 Linux 服务器.已安装 Docker ...

  9. 从零开始实现ASP.NET Core MVC的插件式开发(三) - 如何在运行时启用组件

    标题:从零开始实现ASP.NET Core MVC的插件式开发(三) - 如何在运行时启用组件 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/112 ...

随机推荐

  1. gitlab + jenkins + docker + k8s

    总体流程: 在开发机开发代码后提交到gitlab 之后通过webhook插件触发jenkins进行构建,jenkins将代码打成docker镜像,push到docker-registry 之后将在k8 ...

  2. https过程

    HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息.TLS/SSL协议不仅仅是一套加密传输的协议,更是一件经过艺术家精心设计的艺 ...

  3. 使用Python实现基于图像识别的iOS自动化测试

    相对于Android来说,iOS比较封闭.这一点,在设计和评估自动化测试方案的时候感觉尤其强烈.iOS平台上没有特别好用的自动化测试工具.苹果针对iOS提供了UI Automation的Instrum ...

  4. 【WIN7】windows\system32 下的几乎所有文件的简单说明【2】

    1: System32的详解 C:\WINDOWS\system32... 2:   3: 这个 system32 文件夹中包含了大量的用于 Windows 的文件. 这里主要用于存储 DLL 文件, ...

  5. C# ---sender

    在某个方法中: 第一种写法: private void btn4_Click_1(object sender, RoutedEventArgs e) { btn1_Click(null, null); ...

  6. 20145201 《Java程序设计》第三周学习总结

    20145201 <Java程序设计>第三周学习总结 教材学习内容总结 本周学习了课本第四.五章内容,即认识对象和对象封装. 第四章 认识对象 4.1类与对象 定义类 要产生对象必须先定义 ...

  7. NOIP 选择客栈

    描述 丽江河边有n家很有特色的客栈,客栈按照其位置顺序从1到n编号.每家客栈都按照某一种色调进行装饰(总共k种,用整数0~ k-1表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费. 两 ...

  8. 判断当前html是否在微信中打开

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  9. some words

    For we meet in an hour of change and challenge,              in a dacade of hope and fear,   in an a ...

  10. 入门教程:.NET开源OpenID Connect 和OAuth解决方案IdentityServer v3 创建简单的OAuth2.0服务器,客户端和API(三)

    本教程的目的在于创造尽可能简单的identityserver安装作为一个oauth2授权服务器.这应该能够让你了解一些基本功能和配置选项(完整的源代码可以发现在这里).在后面的文档中会介绍更多的高级功 ...