DES 1977年1月,美国政府颁布:采纳IBM公司设计的方案作为非机密数据的正式数据加密标准(DES Data Encryption Standard) 。 目前在国内,随着三金工程尤其是金卡工程的启动,DES算法在POS、ATM、磁卡及智能卡(IC卡)、加油站、高速公路收费站等领域被广泛应用,以此来实现关键数据的保密,如信用卡持卡人的PIN的加密传输,IC卡与POS间的双向认证、金融交易数据包的MAC校验等,均用到DES算法。 DES算法的入口参数有三个:Key、Data、Mode。 其中Key为8个字节共64位,是DES算法的工作密钥; Data也为8个字节64位,是要被加密或被解密的数据; Mode为DES的工作方式,有两种:加密或解密。 DES算法是这样工作的: 如Mode为加密,则用Key 去把数据Data进行加密, 生成Data的密码形式(64位)作为DES的输出结果; 如Mode为解密,则用Key去把密码形式的数据Data解密,还原为Data的明码形式(64位)作为DES的输出结果。 在通信网络的两端,双方约定一致的Key,在通信的源点用Key对核心数据进行DES加密,然后以密码形式在公共通信网(如电话网)中传输到通信网络的终点,数据到达目的地后,用同样的Key对密码数据进行解密,便再现了明码形式的核心数据。这样,便保证了核心数据(如PIN、MAC等)在公共通信网中传输的安全性和可靠性。 通过定期在通信网络的源端和目的端同时改用新的Key,便能更进一步提高数据的保密性,这正是现在金融交易网络的流行做法。 3DES 3DES是DES加密算法的一种模式,它使用3条64位的密钥对数据进行三次加密。数据加密标准(DES)是美国的一种由来已久的加密标准,它使用对称密钥加密法。 3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法。 设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,P代表明文,C代表密表,这样, 3DES加密过程为:C=Ek3(Dk2(Ek1(P))) 3DES解密过程为:P=Dk1((EK2(Dk3(C))) K1、K2、K3决定了算法的安全性,若三个密钥互不相同,本质上就相当于用一个长为168位的密钥进行加密。多年来,它在对付强力攻击时是比较安全的。若数据对安全性要求不那么高,K1可以等于K3。在这种情况下,密钥的有效长度为112位。 AES AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高。 用AES加密2000年10月,NIST(美国国家标准和技术协会)宣布通过从15种候选算法中选出的一项新的密匙加密标准。Rijndael被选中成为将来的 AES。Rijndael是在1999年下半年,由研究员Joan Daemen 和 Vincent Rijmen 创建的。AES正日益成为加密各种形式的电子数据的实际标准。 美国标准与技术研究院(NIST)于2002年5月26日制定了新的高级加密标准(AES)规范。 AES算法基于排列和置换运算。排列是对数据重新进行安排,置换是将一个数据单元替换为另一个。 AES使用几种不同的方法来执行排列和置换运算。AES是一个迭代的、对称密钥分组的密码,它可以使用128、192和256位密钥,并且用128位(16字节)分组加密和解密数据。 与公共密钥加密使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换和替换输入数据。 算法 Key 位数 可逆? 其它 MD5 没有Key, 有区别16位和32位, 不可逆 (无) SHA (?) (?) 不可逆 (无) RSA 有(公Key,私KEY) (?) 可逆 公、私Key采用不同的加密算法 DES3 有 (?) 可逆 (无) AES 有 (?) 可逆 (无) BASE64 没有KEY (?) 可逆 (无) 哈希函数,比如MD5,SHA,这些都不是加密算法。要注意他们的区别和用途,很多网友都把md5说成是加密算法,这是严重不正确的啊。 哈希函数:MD5,SHA 是没有密钥的,相当与指纹的概念,因此也是不可逆的; md5是128位的,SHA有不同的算法,有128,256等位。。。如SHA-256,SHA-384 然后 就是 Base64,这更加不属于加密算法的范围了,它只是将byte[]数组进行了转换,为什么要转换呢?就是因为很多加密后的密文后者一些特殊的byte[]数组需要显示出来,或者需要进行传递(电子邮件),但是直接转换就会导致很多不可显示的字符,会丢失一些信息,因此就转换位Base64编码,这些都是可显示的字符。所以转换后,长度会增加。它是可逆的。 再就是 3DES,DES 这才是加密算法,因此也是可逆的,加解密需要密钥,也就是你说的key 最后是 RSA ,这是公钥密码,也就是加密和解密密钥不同,也是可逆的。 DES算法: DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,整个算法的主流程图如下: 其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则见下表: 58,50,12,34,26,18,10,2,60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8, 57,49,41,33,25,17, 9,1,59,51,43,35,27,19,11,3, 61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7, 即将输入的第58位换到第一位,第50位换到第2位,…,依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的 左 32位,R0 是右32位,例:设置换前的输入值为D1D2D3……D64,则经过初始置换后的结果 为:L0=D58D50…D8;R0= D57D49…D7。 经过16次迭代运算后。得到L16、R16,将此作为输入,进行逆置换,即得到密文输出。逆置换正好是初始置的逆运算,例如,第1位经过初始置换后,处于第40位,而通过逆置换,又将第40位换回到第1位,其逆置换规则如下表所示: 40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31, 38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29, 36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27, 34,2,42,10,50,18,58 26,33,1,41, 9,49,17,57,25, 放大换位表 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10,11, 12,13,12,13,14,15,16,17,16,17,18,19,20,21,20,21, 22,23,24,25,24,25,26,27,28,29,28,29,30,31,32, 1, 单纯换位表 16,7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10, 2,8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25, 在f(Ri,Ki)算法描述图中,S1,S2…S8为选择函数,其功能是把6bit数据变为4bit数据。下面给出选择函数Si(i=1,2……8)的功能表: 选择函数Si S1: 14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7, 0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8, 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0, 15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13, S2: 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10, 3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5, 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15, 13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9, […]
View DetailsC#实现通过Gzip来对数据进行压缩和解压
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
internal static byte[] Compress(byte[] data) { using (var compressedStream = new MemoryStream()) { using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) { zipStream.Write(data, 0, data.Length); } return compressedStream.ToArray(); } } internal static byte[] Decompress(byte[] data) { using (var compressedStream = new MemoryStream(data)) { using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress)) { using (var resultStream = new MemoryStream()) { zipStream.CopyTo(resultStream); return resultStream.ToArray(); } } } } |
from:https://www.cnblogs.com/frankyou/p/5910074.html
View DetailsNet C#中枚举的声明格式如下所示:
|
1 |
[attributes] [modifiers] enum identifier [:base-type] {enumerator-list} [;] |
FlagsAttribute属性就是枚举类型的一项可选属性。它的主要作用是可以将枚举作为位域处理(P.S. C#不支持位域)。所谓位域是单个存储单元内相邻二进制位的集合。通过为枚举添加这个属性,可以改变枚举的一些行为来满足我们的需要。
|
1 2 3 4 5 |
enum MyFlags { Flag1, Flag2, Flag3, Flag4}; MyFlags myFlag = MyFlags.Flag2 | MyFlags.Flag3; Console.WriteLine(myFlag);//Flag4 |
因为对于整数来说,| 操作就是将其转化为二进制再进行或运算。Flags.Flag2 | Flags.Flag3做的工作实际上是 0001 | 0010 = 0011 = 3再转换成(MyFlags)3就是Flag4了 如果枚举声明如下:
|
1 2 3 4 5 6 7 |
[FlagsAttribute] enum MyFlags{ Flag1 = 0, //000 Flag2 = 1, //001 Flag3 = 2, //010 Flag4 = 4 //100 }; |
则上述结果为Flag2,Flag3,这样做的意义在于我们可以实现“或”的关系。 就上例而言,myFlag可以更直观的表现为011,因此当我们想要检验它满足哪个枚举值时我们可以使用&操作:
|
1 2 3 4 5 6 7 8 9 |
if((myFlag & MyFlags.Flag2) == MyFlags.Flag2) { Console.WriteLine("true"); } if((myFlag & MyFlags.Flag3) == MyFlags.Flag3) { Console.WriteLine("true"); } |
011&001 = 001,011&010 = 010,因此这两个if都会成立,这就是这种枚举的意义吧。另外我们应当注意默认初始化的myFlag的值为0,与其作&运算不会有任何结果。 from:https://blog.csdn.net/zhulongxi/article/details/52371853
View Details如果对一个值可以包含多个,那么可以使用枚举,加上Flags 本文告诉大家如何写一个 Flags。 在写前,需要知道一些基础知识,取反、或、与,如果不知道的话,请去看看基础。 当然,这些太复杂了,我也不会在这里解释。 假如有类型
|
1 2 3 4 5 6 7 8 |
[Flags] <span class="hljs-keyword">public</span> <span class="hljs-keyword">enum</span> Show { A = <span class="hljs-number">0x00000001</span>, B = <span class="hljs-number">0x00000010</span>, C = <span class="hljs-number">0x00000100</span>, D = <span class="hljs-number">0x00001000</span>, } |
合并多个值 合并多个,使用 |
|
1 |
<span class="hljs-operator"><span class="hljs-keyword">Show</span> <span class="hljs-keyword">show</span>=<span class="hljs-keyword">Show</span>.A | <span class="hljs-keyword">Show</span>.B</span> |
判断是否存在某个值 一个简单方法是用 HasFlag,但是一个方法是用 &
|
1 2 3 4 |
<span class="hljs-operator"><span class="hljs-keyword">Show</span> <span class="hljs-keyword">show</span>=<span class="hljs-keyword">Show</span>.A | <span class="hljs-keyword">Show</span>.B;</span> <span class="hljs-operator"><span class="hljs-keyword">show</span>.HasFlag(<span class="hljs-keyword">Show</span>.A);</span> //其他 bool 包含=(<span class="hljs-operator"><span class="hljs-keyword">show</span> & <span class="hljs-keyword">Show</span>.A)!=<span class="hljs-number">0</span>;</span> |
去掉一个值
|
1 2 |
<span class="hljs-operator"><span class="hljs-keyword">Show</span> <span class="hljs-keyword">show</span>=<span class="hljs-keyword">Show</span>.A | <span class="hljs-keyword">Show</span>.B;</span> <span class="hljs-operator"><span class="hljs-keyword">show</span>=<span class="hljs-keyword">show</span> & (~<span class="hljs-keyword">Show</span>.A);</span> |
取反一个值
|
1 2 3 4 5 6 7 8 9 10 |
<span class="hljs-operator"><span class="hljs-keyword">Show</span> <span class="hljs-keyword">show</span>=<span class="hljs-keyword">Show</span>.A | <span class="hljs-keyword">Show</span>.B;</span> bool 包含=(<span class="hljs-operator"><span class="hljs-keyword">show</span> & <span class="hljs-keyword">Show</span>.A)!=<span class="hljs-number">0</span>;</span> if(包含) { <span class="hljs-operator"><span class="hljs-keyword">show</span>=<span class="hljs-keyword">show</span> & (~<span class="hljs-keyword">Show</span>.A);</span> } else { <span class="hljs-operator"><span class="hljs-keyword">show</span>=<span class="hljs-keyword">show</span> | <span class="hljs-keyword">Show</span>.A;</span> } |
参见:http://www.cnblogs.com/jhxk/articles/1738831.html
View Details1:安装后,Resharper会用他自己的英文智能提示,替换掉 vs2010的智能提示,所以我们要换回到vs2010的智能提示 2:快捷键。是使用vs2010的快捷键还是使用 Resharper的快捷键呢?我是使用re的快捷键 3: Resharper安装后,会做几件事情,这几件事情对于除此使用者,比较麻烦,因此归纳总结一下,以资参考。 (1)、会将选项——文本编辑器——C#——常规——自动列出成员 这个选择框的勾选去掉。这样当你使用某个方法的时候,便不会提示参数,是一个很郁闷的事情。 可以手动勾上。 (2)、会将选项——文本编辑器——C#——高级——显示实时语义错误、在编辑中用下划线标识错误这两个选项去掉。这个本来没有什么,但是如果卸载了Resharper, vs编辑器变不会实时提示错误。因此卸载Resharper后,需要把这两个选项重新勾选上。 4: use var use implicitly typed local variable declaration 5:按 alt+enter 能解决很多问题。下面是快捷键大全。 6: Alt+F7将你光标所在位置的变量的所有使用以列表的方式显示出来,显示结果的窗体可以像其他窗体那样停靠。 它的优点包括: 可以从所有使用中挑选只显示read usage或者write usage,有时我们只是想知道某个变量在哪里被改变了。找到的位置前的图标也告诉你这点。 可以在下方预览,即使我们列出所有使用,也不想跳转到每个使用它的地方,这时预览可以帮你大忙。 当你在代码编辑器中改动了某些使用时,比如删除了某行,那么在查找结果的窗体中,会用删除线表示出来。 默认的是寻找解决方案中所有的使用,并且按照命名空间来组织,非常便于选择。 我现在已经记不起来在没有Alt+F7之前我是怎么查找的。反正现在我几乎不怎么样Ctrl+F了,除非我忘记了某个变量的名字。如果是这样,多半这个名字需要refactor,那也是Resharper的另一大块功能所在。也许有人对这个功能嗤之以鼻,但是用过CAB的人都知道,订阅和发布某个事件的签名,完全是字符串,如果你不用搜索来找到它的话,你都不知道这个控件的鼠标点下去,到底有多少个处理程序在背后开始工作了。用了Alt+F7来搜索这个字符串,等于在查找背后所有的调用者。 不过提示你,当光标停留在一个类型上时,要慎用Alt+F7,假设是一个string,你应该能想象到得找到多少个使用 7:威力无比的Alt+Enter回车 万能的Alt+Enter能够帮你完成很多编写代码过程中的dirty work,总结起来大概是这么些: 帮你实现某个接口或抽象基类的方法; 提供你处理当前警告的一些建议; 为你提供处理当前错误的一些建议(不一定是真的错误); 为你简化当前的臃肿代码; 8: Ctrl + F11 当我们看别人的代码,或者是看自己的代码的时候,总是觉得代码太多,于是我们就用 region来把代码进行了封装注释,可是这样之后别人看代码就很郁闷,Resharper的 File Structure 功能,就可以把region和你的方法都展示出来。 说了这么多,其实就是把对象浏览器和region的长处结合起来,既可以清晰的分类,又能一目了然的找到需要的方法。Resharper这时帮上你的大忙了。用Ctrl+F11,就弹出一个像右边这样的窗口来。 这里面,按照你的region来显示,这样读你的代码的人也受益了。每个方法的参数,返回值都如UML一样列出来。 如果需要浏览到某个方法,直接双击它的名字; 如果要把某几个方法装进一个新的region,则可以选中方法,点工具栏上的像框的那个图标;点叉则会删除这个region并把相应的方法移到外面来。 如果要调整某个方法的位置,比如把它移到别的region里面去,只需要在这里拖动这个方法即可。 更可喜的是,你想要的从这里浏览、找到所有使用和重构的功能也在这里提供了,在某个方法上右键你就能开始操作。 9:重构才是王道(上) 重构是一种精神,证明你在致力于提供高效的、精炼的、健壮的代码,而不是凌乱的、晦涩的、漏洞百出的代码。 在Visual Studio 2005中,微软第一次提供了重构工具。但是不够,远远不够。我们需要的重构是非常广义的,我们想要对代码进行快速的调整,快到我在想什么我的工具就能做什么。这才是追求重构的境界。所以在这个意义上,几乎Resharper为你提供了巨大的生产力。 Visual Studio 2005提供的重构包括了如下: 封装字段 提取方法 提取接口 提升局部变量 移除参数 重命名 重新排列参数 这些方法在Resharper中全部都支持(但Resharper的重构远不止这些),它们对应的变成了: 封装字段 —— Introduce Field 提取方法 —— Extract Method 提取接口 —— Extract […]
View DetailsTODO 需求 首先我想跟大家分享一下我们团队的代码检查流程。 1. 项目经理随时会检查成员的代码,如果发现有不符合规范的代码,会在注释里面加todo。比如,假设leo的代码不符合规范,那么项目经理就会加注释: //todoleo: refactor below code to match the standard of defining a class in JS 2. 每个成员随时会检查属于自己的todo项,然后修改代码。比如,leo会把项目里所有todoleo的项列出来,然后一个一个检查。检查完了之后,将todo改成review。 3. 项目经理会检查所有的review。如果代码没有问题了,就会删除这个review(曾经的todo);如果代码仍然有问题,那么会再次改成todo。 开启TODO 1. 下载、安装、resharper。下载地址:http://www.jetbrains.com/resharper/。下载之后直接安装,安装后购买或者自行搜索keygen 2. 为每一个团队成员指定唯一的名字,通常为成员名字或者姓的拼音,只要简单易记就可以了。比如todoleo, tododaniel, todoben. 再将这些名字告诉每一个成员。 打开TODO窗口 3. 打开VS, 在菜单栏找到Resharper,然后打开RESHARPER/Windows/todo items。(此时你必须要打开一个项目才看得见) 4. 点击settings(如下图),这是会打开resharper对于todo item的设置。当然,你也可以通过菜单栏resharper-options-tools-todo items打开该设置。 定制TODO 5. 你可以选中一个小伙伴(pattern)或自带的Todo,再点击复制(duplicate),然后后再点击 Edit 修改。你也可以基于下图的设置来修改,注意红框框标记的地方。 TODO预览 6. 设置好了之后点击Save保存,退出设置。此时再打开todo-items,你可以看到filter下方有你自定义的过滤条件了。这些pattern会像resharper自带的todo,bug一样,在注释中加粗显示,特别醒目。 好了,上面就是全部的操作,非常简单吧。 我们团队已经使用这一代码检查流程有几个月了,在实践中发现这一流程非常有用,让每一个成员的工作变得独立,同时又能得到项目经理对代码质量的控制。 from:http://www.cnblogs.com/zhaoqingqing/p/3945107.html
View Details问题: 很多时候在Eclipse中启动Tmocat后,不能访问本机的localhost:8080主页,并且其他项目也不能访问。 原因: 打开Tomcat下的webapp后也找补到项目目录,这是因为Eclipse将发布路径重定向了,没有放到tomcat下的webapp中。 解决: 在Eclipse中集成Tomcat,在Eclipse中启动后能够访问localhost:8080和项目网站。 1.新建一个server File->New->Other->Server->Server->Next 我的tomcat是7.0.35,选择Apache下的Tomcat v6.0 Server,自己起一个Server Name点击Next 弹出对话框中配置Server,配置Tomcat安装路径和选择相应的Jre后,点Finsh。(Next会让你选择要运行的项目,先不必选) OK,一个Server创建完毕。 2.配置部署路径 在Eclipse的Server窗口双击刚建好的Tomcat v7.0,出现配置界面, 可以看到上图中选择的是 Use workspace metadata(does not modify Tomcat installion) 如果该tomcat中部署了项目的话,这红圈中的选项会灰掉不能修改,要修改必须得先把tomcat中的部署的服务都移除。 (修改方法是Server窗口中右键新建的Tomcat v7.0选择Add and Remove) 选择Use tomcat installation(Task control of Tomcat installation) 即选择tomcat的安装目录来作为项目的发布目录,选择该项后,Server path会变成tomcat的安装目录, 接下来,有个Deploy path部署目录,默认是wtpwebapps,改成tomcat的发布目录webapps 改完配置后保存关闭,在Eclipse中启动新建的tomcat v7.0后,就可以正常访问localhost:8080了。 from:https://blog.csdn.net/zheng__jun/article/details/52471304
View Details上节中我们谈到了Service Fabric最底层的两个概念,一个是针对硬件层面而言的Node Type和Node。另一个是Application。 Node Type是Node的集合,Node是对部署机器的概念抽象。对Service Fabric而言,Node可以是物理机,虚拟机,甚至现在最主流的Container。 在Node Type上运行的是Application。它是针对系统软件层面的抽象理解。一个Application中包含了多个Micro Service。甚至Service Fabric的所有基础服务,例如FailoverManager Service,Naming Service,也都是Micro Service。 Service Fabric所有分布式特性都对应于Micro Service展开。我们可以动态调整一个Micro Service需要在多少个Node上运行多少个实例来分摊负载压力,或者进行容灾备份。每一个实例都会监听不同的端口,由负载均衡层将请求分布至不同实例上。 实际场景 Stateful Service是其中的一种Micro Service。 在开始介绍Stateful Service之前,让我们来考虑下面这种很常见的业务场景。 你正在考虑实现网站里面的购物车功能。用户登录后会放置一些商品在自己的购物车中。 用户下次登录,前台页面会调用购物车服务,并需要从这个服务重新读取已经保存的购物车数据并用以显示。 如果是你会怎么实现? 如果在用户量不是特别大的一般情况下,我们会在数据库中添加一张购物车表,和用户表进行关联。该购物车表中会有一个用户ID字段,并且记录大量的用户购物车数据。 那么这样就会带来一些后续问题。 如果用户量持续增加,数据库表的性能会持续下降。 数据库表数据需要定期备份,以防数据丢失 如果数据库性能出现问题,需要将表进行拆表处理,甚至需要将表进行分区 购物车系统自身也需要针对数据库的任何调整进行处理,甚至它自身可能也需要做负载均衡 这种问题的根源在于,首先系统本身的设计不是面向可扩展的。另外数据库是一个性能潜在的瓶颈和威胁。 Stateful Service 让我们考虑这样一种全新的架构。 从一开始,购物车系统就由36个子服务来处理所有的请求(36个是因为用户ID的首字母是 0-9 a-z,一共36种)。 用户的请求,会根据用户ID首字母hash至某个特定的子服务来处理。 子服务把购物车数据通过轻量级数据库方式保存在自己内部,并且持久化到自己所在的存储设备上。 每个子服务还有3个备份,这些备份在不停同步保存的数据,同时这些备份永远运行在不同的Node上。 同时只有一个备份作为激活状态来负责处理请求,当激活备份出现问题,另外两个备份根据调度算法激活一个。 容灾子系统再创建一个新的备份,永远保证该子服务有3个健康的备份。 Stateful Service就是这样的一种解决方案。 回到上面的场景,购物车系统就是一个Stateful Service。 36个子系统就是这个Stateful Service的36个实例,我们叫Partition。 每个子系统下的备份就是Replica,一个partition有3个Replica。 当前激活的备份就是Active Replica,两个未激活的待命备份就是Secondary Replica。 同一个Partiion的每个Replica都一定运行在不同的Node上面。 Stateful Service代码通过IReliableCollection<T>,IReliableDictionary<T1, T2>等接口来进行数据保存和内部同步。 此外,Stateful Service还可以实现以下特性。 以上所有的数字都可以重新设置,你可以让购物车系统有几百个partition来负载更大的压力。你甚至可以让每个partition有5个甚至更多Replica来保证更多的健壮性。 外部系统不关心Stateful Service有多少个partition,它们通过partition key来进行调用。Partition Key和具体的对应Partition之间由Service Fabric的底层Micro Service进行解析。例如在你的业务中,你可能有几百万用户,但是只设置5个partition。当调用购物车Stateful Service时,外部系统只需要告知:用户ID(partition key),保存的数据。这个请求会自动根据用户ID及hash算法固定映射到5个partition中的一个。 Stateful Service的数据操作支持事务(Transaction)。因此你可以在失败时回滚(Rollback) 希望以上的介绍可以帮助大家更好的理解Stateful Service。 我们会在后面的章节中介绍Stateful Service的代码示例。 […]
View Details在上一节中,为大家简明扼要的介绍了微软针对现代分布式系统在Azure上实现的相关服务组件。紧接上文内容,本节将为大家介绍Azure Service Fabric的基本概念及相关组件的工作机制, 包括Micro Service, Node type, Node等等。虽然名称叫Azure Service Fabric但其可应用的平台远不止Azure平台本身,我们会在后续章节的使用场景中为大家专门描述Service Fabric在各大平台上的工作形式。 Microsoft Azure Service Fabric是微软开发的一套支撑高可用高伸缩云服务的框架,其核心部分是一个分布式系统平台,用于构建可扩展的可靠应用。在便于封装可部署代码的同时,支持创建无状态和有状态的微服务,通过云平台来伸缩他们,来应对高复杂度、低延迟、数据密集的情况。开发者和系统管理员可以免于处理复杂的基础设施问题,将精力更多地投入到所构建应用程序的实现上。 微服务Microservice 在具体介绍Service Fabric之前,不得不先提一下微服务的思想。因为使用Service Fabric的开发过程就是微服务的设计开发过程。有了Service Fabric,您只需要考虑开发微服务的功能,而无需过多考虑部署后的伸缩性和可用性的问题,这些问题都可以交给Service Fabric来帮您实现。 微服务的思想就是将复杂单体式应用程序解耦成多个各个独立的服务,在功能不变的情况下,被分解出来的多个可管理的服务可以通过约定的接口相互通信。这种方法为采用单体式编码很难实现的功能提供了模块化的解决方案。因为,单个服务可以更易于开发、维护。这种架构方式使每个单个服务都可以有专门的团队来开发,每个团队可以各自选择自己擅长的开发技术,通过约定接口来实现相互通信。每个服务可以独立实现、测试、部署和升级,开发者不再需要担心其他服务部署对本服务的影响。AB测试加快了部署的速度,从而实现持续集成持续部署。所有微服务作为一个整体为用户提供服务,同时各个微服务可以根据自身对资源的需求独立扩展,从而最大化服务器的资源利用率。 回到Service Fabric, 一个Service Fabric开发的应用程序由数个服务组成,每个服务可以作为个体独自修改、扩展和管理,同时可以按照一个完整的应用程序来管理。Service fabric的设计目的就是用微服务的方式来简化构建复杂应用的过程。 集群Cluster 集群是一组通过网络连接的虚拟或者物理主机,您的微服务就部署在集群中,集群的大小可以扩展到上千台主机。 节点Node 集群中的一台机器或者VM称为Node, 每个Node会被分配一个名称(string字符串)。Node还有其他一些属性,比如位置属性placement properties。可以通过每台机器或者VM都有一个自启动Windows系统服务FabricHost.exe,它随系统启动后会执行另外两个程序:Fabric.exe 和 FabricGateway.exe, 这两个程序就组成了一个完整的Node。出于测试目的,有时单台机器上也可以通过运行多个Fabric.exe 和 FabricGateway.exe的实例来拥有多个Node。 一个集群中的所有Node相互之间平等且可以直接互相通信。Node除了宿主在物理主机或VM中,还可以宿主在基于Windows的Docker容器中、本地部署的服务器中、其他公有云和私有云中,我们会在后续Service Fabric的使用场景中为大家详细介绍这一内容。 应用程序Application:Application Type和Service Type Service Fabric应用程序(Application)是一组服务(service)的集合,其中一个service是为Application提供指定功能的单元。您将通过定义一个Application Type和对应的几个Service Type来构建一个Service Fabric的Application. 当Application被部署到Service Fabric Cluster里面时,这些类型会被相应地初始化成application实例和service实例。这里类似我们OO地思想。 Application Type和Named Application: Application Type包含一组Service Type的集合,对应上文中的Service Fabric应用程序(Application)是一组服务(service)的集合。 Application Type的name和version定义在ApplicationManifest.xml文件中。在部署的时候,ApplicationManifest.xml会被拷贝到Service Fabric的image store中。通过在Cluster中创建Named Application来初始化Application的实例。Named Application通过"fabric:/MyNamedApp"的形式来命名。 Service Type和Named Service: Service Type的name和version定义在ServiceManifest.xml文件中。当创建好一个Named Application后,就可以创建Named service. 例如您在 "MyNamedApp" Named Application中创建一个 "MyDatabase" Named Service, Name Service被命名为 "fabric:/MyNamedApp/MyDatabase". 分区Partitions和复制replicas […]
View Details在上一节中,我们大致了解了分布式系统的整体架构。简而言之,因为单台机器性能总是有限(摩尔定律增长性能速率无法满足实际应用场景的增速),系统架构师通过各种方式将来自用户的请求分散至多个服务系统和服务器协同完成。 而在现今最火热的云时代,微软已经从云服务层面整体解决了所有分布式系统需要考虑和实现的难题。 下面我们将粗粒度介绍微软云Azure中所有和上一节各个环节相关的服务组件。我们会大致介绍其功能,并且在后续章节中详细介绍其使用方法。 动态DNS —— Azure Traffic Manager (ATM) https://azure.microsoft.com/en-us/services/traffic-manager/ 在上一节中,我们了解用户首先通过域名来获得服务器的IP入口。 同时我们也已经知道动态域名可以从地域靠近,线路优化,负载均衡IP等多种方式来解决其他服务无法达到的网络物理环境优化。 Azure Traffic Manager就是这样一个动态DNS解决方案。 最终用户请求业务域名 –> 域名CNAME映射至ATM域名 –> ATM根据配置从多个endpoint域名中返回一个作为其CNAME 我们可以通过如下方式来配置和指定Azure Traffic Manager的工作行为。 创建一个Azure Traffic Manager,从而得到一个ATM域名,类似 xxx.trafficmanager.windows.net。 将ATM域名作为自己域名(例如:www.contoso.com)的CNAME进行绑定,从而实现对最终用户屏蔽ATM域名的效果。 在ATM中配置多个endpoint站点域名,作为动态DNS目标结果。 配置ATM工作模式:Priority (failover 模式), Performance, Weighted Priority:ATM探针会定时探测所有endpoint站点是否可用,如果站点失效,自动将域名切换至下一个endpoint。 Performance:ATM全球探针会定时探测所有endpoint到全球各个主要网络节点的响应速度。并且定时记录并刷新该速度列表。当最终用户进行DNS解析请求时,该列表会作为参考标准返回对应最终用户性能最快的一个endpoint域名。 Weighted:在配置endpoint时进行权重配置,ATM会根据权重在解析时按不同权重比例返回结果。例如70%的时间返回endpoint A域名,另外其余时间返回endpoint B域名。 通过以上配置,Azure帮助架构师从域名层面进行了第一次负载均衡处理。 网络负载均衡 —— Azure Load Balancer (ALB) https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-overview 在上文中,ATM作为第一层系统,将业务域名最终映射到了endpoint域名。 从网络DNS角度考虑,endpoint域名最终必定是一个公用IP的ANAME。 但是我们知道,IP只是作为网络连接的接入地址,它和真正处理服务的服务器没有必然相关性。 因此在Azure中,从endpoint域名->IP->服务器之间又可以做如下拆分工作,事实上Azure Service Fabric也是这样做的。 创建Azure Virtual Machine Scale Set (我们会在本节下文讲到VMSS,在此你可以先简单理解为这是一个VM集群,可以进行一些统一的对外IP配置) 为VMSS配置一个公共的IP及Azure子域名,例如:207.46.154.78 / xxx.eastasia.cloudapp.azure.com 为该公共IP创建ALB,配置以下信息 IP池,用来告知ALB需要将请求负载均衡至VMSS中的多少台VM的IP列表。 端口映射,将公开端口映射至VMSS中具体每台VM监听的端口号。例如 207.46.154.78:80 –> 192.168.1.3:8080 探针策略,配置ALB如何探测后台IP端口是否可用,以免负载均衡至不可用服务器 根据以上配置,所有请求至 xxx.eastasia.cloudapp.azure.com 域名后都会经由ALB转发至真正的VM。 虚拟机扩展集群 —— Azure Virtual […]
View Details