浅议NetMQ常见模式和消息加密机制

c2f005eef9d92f3c46969735787d48a3.png

题图来自https://www.pexels.com/

 概述

在传统企业级开发中,消息队列机制已经成为一种非常常见的技术实现手段,而基于NetMQ则看起来有点像一朵“奇葩”,看起来从名字似乎是一个消息队列(Message Quene),但事实上更多的却是一个类似于socket机制的消息库。它虽然提供了消息队列的能力,但又与传统消息队列中间件如kafka、rabbitmq等有一定的区别。

不过,不管它是啥,它提供的一些类似于消息队列的机制,使得开发者能够快速在项目中使用起来,例如类似于发布订阅模式、推拉模式等机制,接入简便,功能也挺强大。而且当如果我们要实现消息加密时,还可能通过一些简单的操作实现,例如我们可以选择对内容进行Rsa加密,或者也许还有其他的实现方法?

TL;DR:本文首先介绍NETMQ及其常用的使用模式,进而讨论如何基于NETMQ实现消息的加密传输机制。

NetMq简介和基本特性

ZeroMQ

NETMQ是一种轻量级的消息队列组件,是著名的ZeroMQ的重要成员。2010年,AMQP的最初设计者Pieter Hintjens带领其团队退出了该开源项目,并发起成立了ZeroMQ这个新的消息库,并发展至今。Pieter Hintjens 后由于胆管癌复发,于2016年接受了安乐死。

在ZeroMQ的官方网站中,其介绍到ZeroMQ看起来似乎是一个消息队列框架,实际上更像一个并发处理框架。它除了提供了多种消息队列机制(如Pub-Sub、Pull-Push、Dealer、XPub-XSub机制)外,更是为开发者提供了跨多种传输能力的套接字,它不仅适用于进程间的消息传输,也同样适用于进程内、TCP和多播的传输机制,基于其提供的框架,开发者能快速的实现原子消息的传输能力。ZeroMQ的轻量级体现在其框架灵活简单,性能优异,无需依赖外部组件,即可轻松实现优秀的性能。它也支持异步I/O的传输机制,可为多核应用程序提供扩展,且能成为集群部署的核心传输组件。

ZeroMQ提供了多种语言实现,参见其官方网站,包括C语言,C#,Java等主流后端语言,都支持良好,同样,也支持包括Go、Node.JS等最近比较热门的新兴语言。ZeroMQ自然也支持不同语言间的数据传输,使其可以成为跨语言传输的一种消息协议。

6cd136212de05c0fc239d876b14df02f.png

ZeroMQ的Zero,代表一种极简文化,可以代表零代理层(与Mqtt等队列机制不同,ZeroMQ提供的是一种无代理层的队列机制),零延迟,零成本和零管理。ZeroMQ致力于打造极简的通信组件,通过消除组件的复杂性来提升其功能应用效果。

NETMQ和ClrZmq

对于C#开发者来说,可以使用NetMQ和ClrZmq两种不同的方式来获得ZeroMQ的魔力,前者是基于C#语言原生实现的ZeroMQ通信协议,后者则是通过C#调用基于C语言实现 的Libzmq库来使用。

相对而言,前者可能更受欢迎。NETMQ也同样继承了ZeroMQ的优雅性能和轻量化,开发者可通过Nuget下载NetMQ的的组件,通过几行代码就可以集成消息队列和套接字传输能力。如图所示,NetMQ获得了约175w的下载量,算是一个比较受欢迎的基础组件。

73167e950a69d7cb02122c21ac265017.png

而同样在nuget上,ClrZmq的下载量则远远少于NetMQ,仅仅8w多的下载量,可能说明它只是一种小众框架吧。值得一提的是,ClrZmq需要根据构建平台来选择不同的架构。

da38d93b8c33ee350f64d89a7c575745.png

NETMQ的组成部分

截止本文撰写时,NETMQ的版本为4.0.1.6,作为轻量级组件的一个评判标准,依赖项复杂度也是个重要指标,而NetMQ只依赖了AsyncIO、NaCI.NET、System.ServiceModel.Primitives、System.Threading.Tasks.Extension、System.ValueTuple五个组件,算是名副其实,此处重点介绍两个非System开头的组件。

AsyncIO:该组件是一个高性能的异步的消息套接字库,事实上在Nuget上,该消息库比NetMQ更受欢迎,基于该组件,可减少套接字开发的成本。

NaCI:该组件是一个加密组件,实现了包括Curve25519x、Salsa20、Poly1305加密算法。Curve25519是一种椭球曲线加密算法,被设计用于椭圆曲线迪菲-赫尔曼(ECDH)密钥交换方法。Salsa20是一种流加密算法。Poly1305是一种消息认证码,可用于检测消息的完整性和验证消息的真实性,现常在网络安全协议(SSL/TLS)中与salsa20或ChaCha20流密码结合使用。这三种算法都是由密码专家丹尼尔·J·伯恩斯坦设计的加密算法。

这两个组件都是由NETMQ的创建者somdoron[1](Doron Somech)创建,并引入到NETMQ中。

官方网站

NETMQ官方网站地址为https://netmq.readthedocs.io/,该网站提供了较为完整的学习示例,开发者可参考该示例快速学会该组件的用法。

常见模式实现

NETMQ提供了多种消息通信机制,例如发布订阅模式,推拉模式,

发布订阅模式(Pulish-Subscriber Pattern)

简介

发布-订阅是一种消息传递模式,其中消息的发送者(称为发布者)不会将消息编程为直接发送给特定的接收者(称为订阅者)。发布的消息按照主题进行特征化,作为发布者事先不用知道可能有哪些订阅者(如果有)。

类似地,订阅者可订阅多个主题,也可只订阅一个主题。订阅者也同样无需关注发布者是否真实存在,不过由于ZeroMQ本身没有代理层,且需要绑定服务端端口,事实上看起来似乎必须给定发布者。但由于ZeroMQ本身也可以作为一种微服务架构的基础设施[2],实际上也可以通过一些机制,例如消息代理,地址代理,DNS网关如ZeroConf,Gossip协议等机制,将发布者隐藏在消息网关背后,从而使得订阅者无需关注发布者具体在哪里。

代码示例

该需要首先创建一个发布者,并通过主题的形式发布消息。

class Program
{private static string _address = "";static void Main(string[] args){Console.WriteLine("Hello World!");_address = "tcp://127.0.0.1:5556"; //设置端口var task = Task.Factory.StartNew(async() =>{await BeginPublisherAsync();});var taskSubScriber = Task.Factory.StartNew(() =>{ BeginSubscriberSocket();}); while(Console.ReadKey().Key!=ConsoleKey.Escape);}/// <summary>/// 启动消息发布/// </summary>/// <returns></returns>private static async Task BeginPublisherAsync(){using (var publisher = new PublisherSocket()){publisher.Bind(_address);  //绑定端口while (true){publisher.SendMoreFrame("DotNET技术圈") // Topic.SendFrame("test"); // Messageawait Task.Delay(TimeSpan.FromSeconds(1));}}}/// <summary>/// 订阅消息/// </summary>private static void BeginSubscriberSocket(){using (var subscriber = new SubscriberSocket()){subscriber.Connect(_address);subscriber.SubscribeToAnyTopic();while (true){var topic = subscriber.ReceiveFrameString();var msg = subscriber.ReceiveFrameString();Console.WriteLine("收到消息: {0} {1}", topic, msg);}}} 
}

在上述代码中,发布者绑定了tcp://127.0.0.1:5556端口,并通过同步阻塞的方式,发布主题为Topic的消息内容。也可以指定主机的固定ip地址来进行消息发布,还能通过inproc://inproc-demo的方式进行进程内通信。

using  var subscriber = new SubscriberSocket()subscriber.Connect("tcp://127.0.0.1:5556");subscriber.Subscribe("TopicA"); //订阅到TopicA主题,也可通过SubscribeToAnyTopic订阅所有主题,也可通过UnSubcribe取消订阅相关主题while (true)
{var topic = subscriber.ReceiveFrameString();var msg = subscriber.ReceiveFrameString();Console.WriteLine("From Publisher: {0} {1}", topic, msg);
}

请求响应模式(Request-Response Pattern)

请求响应模式也是NETMQ众多消息模式中最为简单的一种模式,这种模式实际上有点像http协议,可通过一问一答的同步阻塞的模式进行消息的应答,当然,发送HTTP请求我们也可以不必接收响应,NETMQ的请求响应模式也同样如此。

示意图

68226d4f91b3bd80ceb6c64245bd1b72.png
private static void BeginResponseSocket(){using var responseSocket = new ResponseSocket(_address);string request=responseSocket.ReceiveFrameString();responseSocket.SendFrame("Hello DotNET技术圈");}    private static async Task BeginRequestSocketAsync()
{using var requestSocket = new RequestSocket();requestSocket.Connect(_address);while (requestSocket.TrySignalOK()){try{requestSocket.TrySendFrame("Hallo I am DotNET技术圈码农");requestSocket.TrySendFrame("Hallo I am DotNET技术圈码农");  ---这里会引发错误。。}catch(Exception ex){Console.Out.WriteLine(ex);}await Task.Delay(1000);}
}

由于该模式的同步阻塞特性,如果同时发送两条消息,可能会触发NETMQ重复发送异常,如:

e87e0a1f057b66ed06772bb0ea41c68c.png

推拉模式

推拉模式与我们传统意义上理解的类似于手机推送的模式有一些区别,ZeroMQ中说该模式主要将消息下发到提供了一组Push-Pull的套接字,实现消息下发。

值得一提的是,即便的同为ZeroMQ模式下不同语言的版本,对于相同模式的说明,文字描述也不尽相同,例如,在NetMQ的开发者文档中,

Well a PushSocket is normally used to push to a PullSocket, whilst the PullSocket will pull from a PushSocket. Sounds obvious right!

PushSocket 负责把消息推给PullSocket,同样PullSocket负责从PushSocket 拉消息。

这样的说明似乎什么都说了,但又似乎啥都没说,看看其他语言的实现,例如基于Python的PyZmq中,其描述为这样:

Push and Pull sockets let you distribute messages to multiple workers, arranged in a pipeline. A Push socket will distribute sent messages to its Pull clients evenly. This is equivalent to producer/consumer model but the results computed by consumer are not sent upstream but downstream to another pull/consumer socket.

推拉模式允许你基于通过管道的机制实现消息分发给多个工作者。单个PushSocket分发会将消息均匀的分发给其Pull客户端。这样的操作等效于生产者-消费者模型,但消费者计算的结果不是向上发送,而是向下游发送到另一个拉/消费者套接字。

两种不同的实现,在描述上区别还是显著不同,通过两者的对比,我们可以这样理解:Push-Pull模式下,两者都可以互为服务端或客户端,但无论如何,其消息都是单向传输的。消息总是沿着管道向下流动,沿着我们设计的方向传输,实现消息在不同节点间的负载均衡。

例如,可以实现如下的效果,通过一个Ventilator来生产数据,通过多个Pull来拉取数据,进而实现数据向下流动,可以参考NetMq官方文档来实现该代码。

b9f648330315bc51741ea9341b51c25e.png

基于推拉模式,可以设计非常负责的业务模型,例如类似于MapReduce的数据处理器[3]就是一个这样的教学工具。(当然,该工具只是一个演示ZeroMQ模式实现的分布式计算的Demo,可能不适合作为生产用途)。

代码示意

本示例中,仅仅简单介绍Push-Pull的用法,暂不涉及复杂的模式。

private static async Task BeginPushSocketAsync()
{using var pushSocket = new PushSocket(_address);while (true){pushSocket.SendFrame("Hello Clients");await Task.Delay(1000);}
}private static async Task BeginPullSocketAsync()
{using var pullSocket = new PullSocket(_address);while (true){string message = pullSocket.ReceiveFrameString();Console.WriteLine(message);await Task.Delay(1000);}
}

netmq加密传输机制实现

当我们使用NetMQ进行消息传输时,上述示例均没有对消息进行任何加密处理,这种策略可能导致一些不可控的安全性风险,例如在开发基于NetMQ的聊天室功能时,发布的信息若未采取任何加密措施,事实上可能意味着消息是以广播的形式对外发布,从而会造成某些隐私信息泄漏。或者,如果你需要向外Publish某些消息,未授权的订阅者订阅了你的数据,虽然可能数据中不包含直接的隐私数据,但同样可能会引起你的不适。

因此,从安全性的角度来说,无论你计划基于NetMQ实现何种场景,事实上可能都得考虑以尽可能安全的形式“发布”你的消息。目前我们可通过三种方式来实现消息的加密传输功能。第一种是使用基于Tls协议的NetMQ.Security组件,一种是基于非对称密钥算法,如RSA加密算法,还有一种是基于ZeroMQ所提供的两种加密方式,ECC椭球曲线加密算法和Z85加密算法,以对称密钥的方式。

基于Tls的NetMq.Security?

NetMQ.Security[4]也是由NetMQ的主要贡献者somdoron开发的组件,目前该组件处于不活跃的状态,截至目前仅有5次更新,上一次更新依然是4年前,通过一些早期帖子,作者Doron Somech也同样不认为该组件可以在生产环境下使用[5](😯),所以事实上可能不太适合作为专业团队的技术选型。

目前比较详细的介绍来自杰哥很忙[6],且优秀的杰哥对fork了该组件的代码[7],并开发了许多功能,由于主干仓库已经尘封太久了,开发者有兴趣可以参详参详。

使用时,我们可通过Nuget下载由NetMQ官方发布的组件,不过,似乎下载量有点惨淡,那么,此处就不再赘述了。。。。

5fefac8eb940165e3dee78102900cc02.png

非对称密钥算法-Rsa加密

对于文本来说,使用Rsa这种非对称算法族进行加密是一种非常常见的选择,RSA是由罗纳德·李维斯特[8](Ron Rivest)、阿迪·萨莫尔[9](Adi Shamir)和伦纳德·阿德曼[10](Leonard Adleman)在1977年一起提出的,当时他们三人都在麻省理工学院[11]工作。RSA 就是他们三人姓氏开头字母拼在一起组成的。

RSA算法的核心是极大整数做因数分解,换言之,对一极大整数做因式分解越困难,RSA算法越可靠。目前传统计算机只能破解较为简单的RSA密钥,如果使用的密钥长度足够长,理论上用RSA加密的信息也很难以被破解。在RSA算法中,密钥由私钥和公钥组成。由私钥负责对内容进行解密,并用公钥进行加密。分配公钥的过程必须足够安全,若被中间人攻击,则可能导致公钥失效。

影响RSA密钥安全性的要素首先是其密钥长度,目前推荐的RSA算法公钥长度为2048位。其次是RSA密钥的填充模式,共有三种填充模式,RSA_PKCS1_PADDING, RSA_PKCS1_OAEP_PADDING, RSA_NO_PADDING。填充技术实现的不好,RSA也不会安全,应尽量选择最安全的填充模式,例如RSA_PKCS1_PADDING。

原因如下[12]

1.RSA加密是确定的,即给定一个密钥,特定明文总会映射到特定的密文。攻击者可以根据密文中统计信息获取明文的一些信息。2.填充技术如果比较弱,那么较小的明文和小型公开指数e将易于受到攻击。3.RSA有个特性叫做延展性,如果攻击者可以将一种密文转换为另一种密文,这种新密文会导致对明文的转换变得可知,这种特性并没有解密明文,而是以一种可预测的方式操纵了明文,比如:银行交易系统中,攻击者根据新密文,直接去修改原密文中金额的数据,可以在用户和接受方无法感知的情况下进行修改。

RSA算法中提供了以下功能提供[13]

密钥对生成:生成随机私钥(通常大小为 1024-4096 位)和相应的公钥。•加密:使用公钥加密秘密消息(范围为 [0...key_length] 的整数),并使用秘密密钥将其解密。•数字签名签署消息(使用私钥)并验证消息签名(使用公钥)。•密钥交换:安全地传输一个秘密密钥,用于以后的加密通信。

RSA 可以使用不同长度的密钥:1024、2048、3072、4096、8129、16384 甚至更多位的密钥。3072 位及以上的密钥长度被认为是安全的。更长的密钥提供更高的安全性,但消耗更多的计算时间,因此需要在安全性和速度之间进行权衡。很长的 RSA 密钥(例如 50000 位或 65536 位)对于实际使用来说可能太慢,例如密钥生成可能需要几分钟到几个小时。

网上也有基于RSA进行NetMQ进行消息加密的示例[14],可供参考。其核心流程为,在进行消息发送时,使用RSA公钥进行加密,

MsgObject sendmsg = EventQueue.Dequeue ( ) ; 
sendmsg.Content = RSAEncryption.RSAEncrypt(sendmsg.Content); 
sendmsg.MachineName= msg.MachineName;
SendMessageQueue.Enqueue(sendmsg) ;

并在客户端接收到消息后,对正文进行RSA解密,解密代码略。

使用对称密钥加密算法-Ecc加密算法进行消息加密

RSA算法虽好,但由于私钥由客户端管理,公钥由服务端管理,且RSA必须密钥位数足够长才安全,例如2048位,使用这么长的密钥进行加密时间开销也令人吃不消的,有没有一种更简单、快速的算法来实现呢?

使用AES算法?

我们或许会想到AES算法,例如AES256算法这种“对称密钥加密算法[15]”。在“对称密钥加密算法”中,加密和解密使用秘密密钥或密码短语(从中派生出密钥)。

该秘密密钥用于加密和解密数据,通常是128位或256位,并被称为“加密密钥”。有时它以十六进制或 base64 编码的整数形式给出,或者通过密码到密钥派生方案派生,当输入数据被加密时,它被转换为加密的密文,当密文被解密时,它被转换回原始输入数据。

61799c404252eef8118a7e8d649d83b0.png

通常,对称加密过程使用一系列步骤,涉及不同的加密算法:

密码到密钥派生算法(如 Scrypt 或 Argon2):允许使用密码而不是密钥,并使密码破解变得困难而缓慢。

块到流密码转换算法(块密码模式如CBC或CTR )+消息填充算法如PKCS7 (在某些模式下):允许使用块密码算法(如AES)加密任意大小的数据。

块密码算法(如AES ):使用密钥安全地加密固定长度的数据块。

消息认证算法(如HMAC ):检查解密后得到的结果是否与加密前的原始消息匹配。

NETMQ的原生解决方案?

不过上述AES加密算法实质上也需要开发者手工处理消息体,存在的内存开销和时间可能对于用户来说依然无法接受,或许最好的办法依然是基于NETMQ框架来入手看看是否有什么“原生”的解决方案。

所幸ZeroMQ在设计之初就已经将安全作为其认为非常重要的一个方面,在这篇博客[16]中,ZeroMQ提到了其对于安全层的目标,包括:

•它使用起来必须非常简单,而且不可能出错。复杂性是密码学的第一大风险和第一大漏洞。每一个额外的选项都是一种出错的方式,最终导致一个不安全的系统。•对于实际工作,它必须足够快。如果安全性使系统变得太慢而无法使用,人们就会将其关闭,因为今天能够工作的务实需求胜过明天被入侵的风险。•它必须基于标准化协议,以便任何团队都可以重新实施、独立验证并在软件堆栈之外进行改进。•等等。

并从2013年起,在ZeroMQ版本(4.0.0)中就已经引入了安全架构设计,包括:

•一种新的有线协议ZMTP 3.0[17],为所有 ZeroMQ 连接添加了安全握手。•一种新的安全协议CurveZMQ[18],它通过 TCP 连接在两个 ZeroMQ 对等点之间实现“完美的前向安全”。我将在下面解释 CurveZMQ。•ZMTP 的一组安全机制:NULL、PLAIN 和 CURVE,每个机制都由它们自己的 RFC 描述。NULL 本质上是我们之前所拥有的。PLAIN 允许简单的用户名和密码验证。CURVE 实现了 CurveZMQ 协议。、•等等。

在ZeroMQ中集成的椭球曲线算法为Curve25519[19] ,目前,在我们所使用的NetMQ中也同样集成了该算法。在搞清楚原理后,我们再来使用该算法,发现一切就变得非常简单明了了。

var serverPair =   NetMQ.NetMQCertificate.CreateFromSecretKey(UTF8Encoding.UTF8.GetBytes(”这里是密钥“));;using var server = new PublishSocket();server.Options.CurveServer = true;server.Options.CurveCertificate = serverPair;server.Bind($"tcp://127.0.0.1:55367");using (var server = new SubscriberSocket()){var cert = NetMQ.NetMQCertificate.CreateFromSecretKey(UTF8Encoding.UTF8.GetBytes(”这里是密钥“));var curveServerCertificate = serverPair;var clientCertificate = new NetMQCertificate(); ---这里是客户端密钥,server.Options.CurveServerCertificate = curveServerCertificate; ---这里是使用服务端密钥server.Options.CurveCertificate = clientCertificate;  ---这里是客户端密钥}

结语

本文对NetMQ进行了简单的概述,包括其常见模式和加密传输机制,开发者若有兴趣,可通过NetMQ官网获得更多学习资料。如果开发者加密算法感兴趣,还可以通过这个网站(https://cryptobook.nakov.com)读到许多有关加密的基础知识。

References

[1] somdoron: https://github.com/somdoron
[2] 微服务架构的基础设施: https://zguide.zeromq.org/docs/chapter8/
[3] 类似于MapReduce的数据处理器: https://github.com/sdiehl/kaylee
[4] NetMQ.Security: https://github.com/NetMQ/NetMQ.Security
[5] 同样不认为该组件可以在生产环境下使用: https://groups.google.com/g/netmq-dev/c/3tcsLvxUWgc
[6] 杰哥很忙: https://www.cnblogs.com/Jack-Blog/p/9015783.html
[7] 该组件的代码: https://github.com/GuojieLin/NetMQ.Security
[8] 罗纳德·李维斯特: https://zh.wikipedia.org/wiki/罗纳德·李维斯特
[9] 阿迪·萨莫尔: https://zh.wikipedia.org/wiki/阿迪·萨莫尔
[10] 伦纳德·阿德曼: https://zh.wikipedia.org/wiki/伦纳德·阿德曼
[11] 麻省理工学院: https://zh.wikipedia.org/wiki/麻省理工学院
[12] 原因如下: https://blog.csdn.net/makenothing/article/details/88429511
[13] 以下功能提供: https://cryptobook.nakov.com/asymmetric-key-ciphers/the-rsa-cryptosystem-concepts
[14] 消息加密的示例: https://blog.actorsfit.in/a?ID=01400-85ae6267-6c93-41e3-b06b-5d9792a422ba/
[15] 对称密钥加密算法: https://cryptobook.nakov.com/symmetric-key-ciphers
[16] 这篇博客: https://jaxenter.com/using-zeromq-security-part-1-119346.html
[17] ZMTP 3.0: http://zmtp.org/
[18] CurveZMQ: http://curvezmq.org/
[19] Curve25519: http://cr.yp.to/ecdh.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS 5.5下搭建部署独立SVN服务器全程详解

SVN服务器有2种运行方式&#xff1a; 1、独立服务器 (例如&#xff1a;svn://xxx.com/xxx)&#xff1b; 2、借助apache (例如&#xff1a;http://svn.xxx.com/xxx)&#xff1b; 为了不依赖apache&#xff0c;我选择第一种方式&#xff1a;独立的svn服务器。SVN存储版本数据也…

35岁成MIT终身教授!北大数学“黄金一代”再获大奖

全世界只有3.14 % 的人关注了爆炸吧知识18岁时满分斩获国际奥林匹克数学竞赛金牌&#xff0c;本科就读北大数院期间19门课程成绩100分、7门99分&#xff0c;35岁成为麻省理工&#xff08;MIT&#xff09;终身教授……近日&#xff0c;数学“大神”恽之玮再获国际大奖——西蒙斯…

二维数组foreach嵌套遍历,判断连续3天以上的算有效数据

2019独角兽企业重金招聘Python工程师标准>>> $studycourseinfo $studycourseinfoModel->where($where)->limit($page->firstRow.,.$page->listRows)->order(create_time asc)->select(); //$studycourseinfos $studycourseinfoModel->where(…

linux mint 用户管理,Linux Mint 新工具:将网站转变为独立的应用

Linux Mint 目前正在积极推进 20.1 版本&#xff0c;日前官方博客介绍了新版本将会带来的一项有意思的新特性&#xff1a;WebApp 管理器。简单来讲&#xff0c;这一特性可以把网站转变成独立的应用&#xff0c;这与基于 Debian 和 Ubuntu 的发行版 Peppermint OS 名为 ICE 的功…

如何评价一个开源项目——协作影响力

本文由X-lab开放实验室博士生赵生宇创作 该篇博客紧跟上一篇关于活跃度的介绍这篇文章系统介绍了一种基于全域开发者协作网络的项目影响力评估方法&#xff0c;该方法对于分析整个开源生态有极大的帮助。在一次性评估出所有项目的协作影响力的同时&#xff0c;也可以对项目的协…

UITableView 界面小实例

最近一是很忙&#xff0c;没时间写东西&#xff0c;今天抽时间来总结一下这几天学到的东西 首先看看&#xff0c;程序现在的样子&#xff1a; 基本完成这些&#xff0c;还有一个webview就不截图了 记录一下要点&#xff0c;首先自定义tableview&#xff0c;这个是按照iphone3开…

linux 文档属于apache,Apache 安装和使用文档

Apache 安装和使用文档更新时间&#xff1a;2009年11月26日 00:34:37 作者&#xff1a;Apache安装和使用文档一、准备工作&#xff1a;1台PC机&#xff0c;安装linux操作系统 参考文档linux安装.docx2 gcc的安装 参考文档gcc的安装.zip3 apache的安装包httpd-2.0.63.tar.gz二…

在数学世界,都有这些美妙的数学公式......

全世界只有3.14 % 的人关注了爆炸吧知识什么是数学&#xff1f;华罗庚说&#xff1a;宇宙之大&#xff0c;粒子之微&#xff0c;火箭之速&#xff0c;化工之巧&#xff0c;地球之变&#xff0c;生物之谜&#xff0c;日用之繁&#xff0c;无处不用数学......回首往昔&#xff0c…

.NET 生态系统的蜕变之 .NET 6云原生

云原生的英文名是cloud native&#xff0c;native 就是土著的意思&#xff0c;也就是土著对当地的环境是非常适应的&#xff0c;在云的环境和传统的数据中心是非常不同的&#xff0c;云原生就是要用的云的技术来构建应用&#xff0c; 利用云的技术来降低种端服务的风险和提高可…

世界十大无法科学解释灵异事件(进来发表自己看发)

1、法老咒语&#xff08;世界最大灵异事件&#xff09; 2、葡萄牙灵异事件&#xff08;在网上引起了极大的轰动&#xff09; 3、伦敦塔闹鬼&#xff08;超著名&#xff09; 4、20世纪上海滩灵异事件&#xff08;孟小冬照片灵异事件&#xff09; 5、鬼脸&#xff08;墙壁上出…

宝塔linux面板假设nextcloud,宝塔面板部署NextCloud(14.0.3)逐一解决后台安全及设置警告...

刚刚把NextCloud更新到14.0.3&#xff0c;后台又出现了一堆警告&#xff0c;也是够烦的。之前写过 宝塔面板部署NextCloud逐一解决后台安全及设置警告&#xff0c;那个是基于Nextcloud 13.x的&#xff0c;所以就再补充记录一下解决如下的警告。Use of the the built in php mai…

ASP.NET Core启动地址配置方法及优先级顺序

前言默认情况下&#xff0c;ASP.NET Core使用下列2个启动地址:http://localhost:5000 https://localhost:5001同时&#xff0c;我们也可以通过配置或代码方式修改启动地址。那么&#xff0c;这几种修改方式都是什么&#xff1f;谁最后起作用呢&#xff1f;设置方法1.applicatio…

那些喜欢少妇的男生......

1 听说你喜欢少妇&#xff1f;▼2 没错&#xff01;就是它&#xff01;▼3 你还缺男朋友吗&#xff1f;▼4 还能怎么样&#xff1f;&#xff08;via&#xff1a;臭人脸上的鼻涕&#xff09;▼5 特效还能这样玩&#xff1f;▼6 哈哈哈哈哈&#xff08;via&#xff1a;Guide&…

Openfire3.10beta版源码在eclipse上部署编译

一、源码下载 最近由于需求&#xff0c;需进行openfire的插件开发&#xff0c;于是需将openfire的源码进行部署&#xff0c;目前最新的openfire稳定版本是3.9.3&#xff0c;官方下载地址是http://www.igniterealtime.org/downloads/index.jsp&#xff0c;下载页面如图&#xff…

首次公开!人教版1-9年级绝密编写:被重点中小学永久收录的数学教案和试题...

全世界只有3.14 % 的人关注了爆炸吧知识在中国的教育历史上&#xff0c;不少人都会有感慨&#xff1a;“我是读着人教版教材长大的”。&#xff08;人教版即由人民教育出版社出版。&#xff09;的确&#xff0c;由毛泽东主席亲笔题写社名的人民教育出版社&#xff0c;自1950年1…

如何通过 C# 自动捕获一个文件的变更?

咨询区 PaulB&#xff1a;请问在 C# 中如何实现当一个磁盘文件的变更&#xff0c;让我的程序马上能感知到&#xff1f;回答区 Dirk Vollmar&#xff1a;在 C# 中有一个 FileSystemWatcher 类&#xff0c;它专门用来做文件的变更感知&#xff0c;大概有如下四类通知事件&#xf…

安装分布式文件系统MooseFS

示意图#4种角色共有的安装步骤yum install gcc zlib zlib-devel fuse fuse-devel fuse-libs libpcap libpcap-devel net-tools useradd mfs -s /sbin/nologin cd /download/ tar xf moosefs-2.0.80.tar.gz cd moosefs-2.0.80 ./configure \ --prefix/usr/local/mfs \ --with-de…

太爽了!宅男醒来后,发现自己变成了……

全世界只有3.14 % 的人关注了爆炸吧知识小编这两天看了一本关于数学家的故事后开了一个脑洞&#xff1a;如果把那些数学大神的故事写成爽文会是什么样&#xff1f;以下内容&#xff0c;纯属娱乐和虚构。前方高能预警第一章 称王冠原来是这样的“阿基米德&#xff0c;国王叫你呢…

陈睿学长在CUIT建校70周年校庆上的演讲

【个人成长】| 总结/Edison Zhou1睿叔演讲背景10月23号&#xff0c;我的母校成都信息工程大学&#xff08;以下简称CUIT&#xff09;举行了建校70周年&#xff08;1951~2021&#xff09;校庆&#xff0c;B站&#xff08;哔哩哔哩&#xff09;董事长兼CEO陈睿&#xff08;睿叔&a…

poj2442Sequence(优先队列)

http://poj.org/problem?id2442 题解http://www.cnblogs.com/372465774y/archive/2012/07/09/2583866.html 本来写的二维数组 &#xff0c;直接対一维排序 不知道为嘛一直WA 只好该为一维的 就AC了 View Code 1 #include <iostream>2 #include<cstdio>3 #includ…