SQL Server 跨库同步数据
最近有个需求是要跨库进行数据同步,两个数据库分布在两台物理计算机上,自动定期同步可以通过SQL Server代理作业来实现,但是前提是需要编写一个存储过程来实现同步逻辑处理。这里的存储过程用的不是opendatasource,而是用的链接服务器来实现的。存储过程创建在IP1:192.168.0.3服务器上,需要将视图v_custom的客户信息同步到IP2:192.168.0.10服务器上的t_custom表中。逻辑是如果不存在则插入,存在则更新字段。
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
create PROCEDURE [dbo].[p_pm_项目平台客户批量同步到报销平台]( @destserver nvarchar(50), @sourceserver nvarchar(50) ) AS BEGIN SET NOCOUNT ON; --不存在则添加链接服务器,外部查询必须指明IP地址,例如 select * from [IP].[database].[dbo].[table] if not exists (select * from sys.servers where server_id!=0 and data_source=@destserver) begin exec sp_addlinkedserver @server=@destserver end if not exists (select * from sys.servers where server_id!=0 and data_source=@sourceserver) begin exec sp_addlinkedserver @server=@sourceserver end begin try set xact_abort on begin transaction --http://www.cnblogs.com/chnking/archive/2007/04/04/699891.html INSERT INTO [192.168.0.10].[dbCRM].[dbo].[t_custom] (客户ID, 客户名称, 客户简称, 输入码, 查询码, 地址, 录入登录名, 录入时间, 修改登录名, 修改时间, 审批状态ID, 审批状态名称, 是否审批结束, 审批操作时间, 项目管理客商编码, 序号) SELECT A.客户ID,A.客户名称, A.客户简称, dbo.fn_pm_GetPy(A.客户名称), A.客户编号+','+A.客户名称+','+dbo.fn_pm_GetPy(A.客户名称)+','+A.客户简称+','+dbo.fn_pm_GetPy(A.客户简称), A.地址, 'admin', getdate(), null, null, 'D65F87A8-79C8-4D1C-812D-AE4591E056A8', '已审批', 1, A.审批操作时间, A.项目管理客商编码, 0 FROM [dbPM].[dbo].[v_custom] A WHERE A.客户ID NOT IN ( SELECT 客户ID FROM [192.168.0.10].[dbCRM].[dbo].[t_custom]); ----------------------------------存在更新----------------------------------- update A set A.客户名称=B.客户名称, A.客户简称=B.客户简称, A.输入码=dbo.fn_pm_GetPy(B.客户名称), A.查询码=B.客户编号+','+B.客户名称+','+dbo.fn_pm_GetPy(B.客户名称)+','+B.客户简称+','+dbo.fn_pm_GetPy(B.客户简称), A.地址=B.地址, A.修改登录名='admin', A.修改时间=getdate(), A.项目管理客商编码 =B.项目管理客商编码 from [192.168.0.10].[dbCRM].[dbo].[t_custom] A,[dbPM].[dbo].[v_custom] B where A.客户ID=B.客户ID; commit transaction end try begin catch select ERROR_NUMBER() as errornumber,ERROR_MESSAGE() as errormsg,ERROR_LINE() as errorline rollback transaction end catch END |
如果没有正确配置,经常会出现 消息 7391,级别 16,状态 2,过程 xxxxx,第 XX 行 。无法执行该操作,因为链接服务器 "xxxxx" 的 OLE DB 访问接口 "SQLNCLI" 无法启动分布式事务。 可以参照如下的配置: 具体可以参看:http://www.cnblogs.com/chnking/archive/2007/04/04/699891.html from:https://www.cnblogs.com/isaboy/p/sql_server_job.html
View Details把数据行转换为相应的实体
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
/// <summary> /// 把数据行转换为相应的实体 /// </summary> /// <typeparam name="T">实体</typeparam> /// <param name="dataRow">数据行</param> /// <returns></returns> public static T DataRowToModel<T>(DataRow dataRow) where T : new() { // 返回值容器 var model = new T(); // 例外检查 if (dataRow == null) { return model; } // Model属性 var t = model.GetType(); var properties = t.GetProperties(); // 循环赋值 foreach (var propertyInfo in properties) { // 属性名 var propertyName = propertyInfo.Name; // 检查Model属性是否存在于列名中 if (!dataRow.Table.Columns.Contains(propertyName)) { continue; } // 数据库为null时跳过 if (dataRow[propertyName] == DBNull.Value) { continue; } // 设置Model的值 propertyInfo.SetValue(model, dataRow[propertyName]); } return model; } } |
View Details
git – 简明指南
助你入门 git 的简明指南,木有高深内容 ;) 作者:罗杰·杜德勒 感谢:@tfnico, @fhd 和 Namics 如有纰漏,请在 github 提报问题 安装 下载 git OSX 版 下载 git Windows 版 下载 git Linux 版 创建新仓库 创建新文件夹,打开,然后执行 git init 以创建新的 git 仓库。 检出仓库 执行如下命令以创建一个本地仓库的克隆版本: git clone /path/to/repository 如果是远端服务器上的仓库,你的命令会是这个样子: git clone username@host:/path/to/repository 工作流 你的本地仓库由 git 维护的三棵“树”组成。第一个是你的 工作目录,它持有实际文件;第二个是 暂存区(Index),它像个缓存区域,临时保存你的改动;最后是 HEAD,它指向你最后一次提交的结果。 添加和提交 你可以提出更改(把它们添加到暂存区),使用如下命令: git add <filename> git add * 这是 git 基本工作流程的第一步;使用如下命令以实际提交改动: git commit -m "代码提交信息" 现在,你的改动已经提交到了 HEAD,但是还没到你的远端仓库。 推送改动 你的改动现在已经在本地仓库的 HEAD 中了。执行如下命令以将这些改动提交到远端仓库: git push origin master 可以把 master 换成你想要推送的任何分支。 如果你还没有克隆现有仓库,并欲将你的仓库连接到某个远程服务器,你可以使用如下命令添加: git remote add origin <server> 如此你就能够将你的改动推送到所添加的服务器上去了。 分支 分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master 是“默认的”分支。在其他分支上进行开发,完成后再将它们合并到主分支上。 创建一个叫做“feature_x”的分支,并切换过去: git checkout -b feature_x 切换回主分支: git checkout master 再把新建的分支删掉: git branch -d feature_x 除非你将分支推送到远端仓库,不然该分支就是 不为他人所见的: git […]
View DetailsWindows操作系统下搭建Git服务器和客户端。
本文将介绍如何在Windows操作系统下搭建Git服务器和客户端。服务器端采用的是Bonobo Git Server,一款用ASP.NET MVC开发的Git源代码管理工具,界面简洁,基于Web方式配置,简单易用。客户端是采用的TortoiseGit工具,UI操作,省去输入命令的麻烦,对于windows用户来说更易于使用。 所需软件: Git服务器端: BONOBO GIT SERVER,下载最新版:http://bonobogitserver.com/ Git客户端: msysgit,下载最新的软件:https://msysgit.github.io/ TortoiseGit,下载最新的软件:https://code.google.com/p/tortoisegit/ 如果以上连接无法正常访问, 序号1:可百度搜索:GIT64位或GIT32位等关键字找到相应的版本进行下载. 序号2:可百度搜索:TortoiseGit 64位或者GIT32位等关键字找到相应的版本进行下载. 一:配置服务器端 以下案例服务器环境是基于Windows10 + IIS7 + Bonobo Git Server 5.2 + WebDAV ,其他版本的操作系统或IIS略有不同 在Windows10下打开IIS7功能。开始-》控制面板-》程序-》启用或关闭windows功能,勾选Internet Information Services的选项。不会的可以谷歌或百度下。 2.下载好的Bonobo Git Server。是一个.zip压缩包文件,是用ASP.NET MVC开发的网站。 3.解压上步下载的压缩包到C:\inetpub\wwwroot。 4.修改APP_Data文件夹权限。允许IIS用户修改网站代码中的(C:\inetpub\wwwroot\Bonobo.Git.Server\App_Data)文件夹,所以需要做如下配置: 在APP_Data文件夹上右键选择“属性” 到“Security”(安全)的Tab页点击“Edit”(编辑) 给IIS_IUSRS赋予Write和Modify权限。(我通常是直接选择:完全控制) =》如果上步骤没找到IIS_IUSRS用户。那就点击添加→左下角高级→右边点击立即查找,最后添加即可,这样就可以在 “组或用户名”列表中显示了. 以上配置好之后, 我们首先打开IIS管理器。 1.选择:网站右击添加网址,然后弹出一个添加网站的界面, 自己拟定一个网站名称,然后物理路径也就是刚才那个解压好的文件包的路径。最好一步自定义一个端口号确定即可。 2.上步操作之后, 我们可以在网站列表中看到刚才添加好的网站。然后我们点击》 应用程序池,找到我们刚发布的网站,看看.NET Framework 版本是否是4.0。 如果不是,请右击网站,点击》基本设置,选择4.0即可,托管管道模式选择》集成 。 3. 最后一步:选择网站右击》管理网址》浏览,(或者右边中间的位置有个:浏览网站)如果能看到如下界面, 说明我们已经部署成功了。默认管理员账号密码均为:admin 如果对英文不习惯的,可以先通过admin账号密码登陆进去。再到上面菜单栏找到Settings》Language》Chinese(Simplified,PRC)即可。 到此我们的Git服务器已经搭建完成. 不过下面有个问题提醒: 》如果是第一次使用 IIS管理器, 很有可能报各种错, 其中有个错误好像是要给IIS注册>FrameWork 4.0。 下面简单介绍下IIS注册FrameWork4.0的步骤。或者直接百度》IIS注册FrameWrok 4.0方法。 1.打开dos命令窗口,打开窗口时请以管理员的身份打开。 开始->输入cmd->找到cmd.exe->右键cmd.exe->以管理员身份打开(弹出菜单)->打开dos命名窗口。 2.打开framework4.0所在目录,一般情况下在此目录下:C:\Windows\Microsoft.NET\Framework\v4.0.30319 3.在dos窗口中,后面按空格键,然后输入 -i 参数。(C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i)输入完毕后,回车即安装framework4.0到iis上。 from:https://www.cnblogs.com/ws1996/p/6257190.html
View Details在Windows上搭建Git Server
Git在版本控制方面,相比与SVN有更多的灵活性,对于开源的项目,我们可以托管到Github上面,非常方便,但是闭源的项目就会收取昂贵的费用。 那么私有项目,如何用Git进行代码版本控制呢?我们可以自己构建Git服务器。一般来说,在Linux上搭建Git的教程比较多,但是如何在Windows Server平台下搭建Git服务器呢? 对于很多.NET用户来说,代码编写的工具是Visual Studio,该工具是不支持SSH协议的,通过搜索和对比,发现Gitblit可以很方便的搭建服务,他是用Java编写的,所有安装的前提是安装Java运行时环境。 第1步:下载Java并安装Java.我这里下载的是jdk1.7.0_79 第2步:配置Java环境变量 右键” 计算机” => ”属性” => ”高级系统设置” => ”高级” => “环境变量” => “系统变量”。 新建:变量名:JAVA_HOME;变量值:C:\Program Files\Java\jdk1.7.0_79【具体要根据你自己的安装路径,我的是安装在D盘的】 新建:变量名:CLASSPATH;变量值:%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar 添加:找到PATH变量,选择编辑。把%JAVA_HOME%/bin;%JAVA_HOME%/jre/bin添加到”变量值”的结尾处。 第3步:验证Java是否安装成功。 在命令窗口中,输入javac, 回车,如果出现如下信息,说明安装成功。 第4步:下载Gitblit.下载地址:http://www.gitblit.com/ 第5步:解压缩下载的压缩包即可,无需安装。路径为 C:\gitblit-1.8.0 第6步:创建用于存储项目代码的文件夹。这里为G:\GitProject\webui 第7步:配置gitblit,文件在C:\gitblit-1.8.0\data下,打开gitblit.properties ,里面有 include = defaults.properties,说明配置信息在defaults.properties中 2.找到git.repositoriesFolder(资料库路径),赋值为G:\GitProject\webui。 3.找到server.httpPort,设定http协议的端口号 4.找到server.httpBindInterface,设定服务器的IP地址。这里就设定你的服务器IP。 5.找到server.httpsBindInterface,设定为localhost 另外注意看看server.shutdownPort ,其默认值为 8081,是否被占用,如果占用请修改。 6.保存,关闭文件。 第8步:运行gitblit.cmd 批处理文件。运行结果如下,运行成功。 在浏览器中输入:http://192.168.180.159:10010/ ,默认可以用admin和admin进行登录,然后改密即可。 […]
View Details删除本地git的远程分支和远程删除git服务器的分支
在项目中使用git管理代码后,有些时候会创建很多不同名称的分支,以此区分各个分支代码功能。 而随着代码的合并,以前的分支就可能不再需要保存了,所以就要对没有用的分支进行删除,包括紧急回滚时从中抽取某一个版本记录所创建的临时分支。 这时候就可以使用下面的命令: 1.列出本地分支: git branch 2.删除本地分支: git branch -D BranchName 其中-D也可以是--delete,如: git branch --delete BranchName 3.删除本地的远程分支: git branch -r -D origin/BranchName 4.远程删除git服务器上的分支: git push origin -d BranchName 其中-d也可以是--delete,如: git push origin --delete BranchName 注意:git命令区分大小写,例如-D和-d在不同的地方虽然都是删除的意思,并且它们的完整写法都是--delete,但简易写法用错大小写会执行失败。
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 |
D:\work\src\XXXXXX\Uniqlo (dev) λ git branch Branch_45822f1f5e18ad8967503c58feaf55416dfc387f * dev dev_with_BT2016 master D:\work\src\XXXXXX\Uniqlo (dev) λ git branch -D Branch_45822f1f5e18ad8967503c58feaf55416dfc387f Deleted branch Branch_45822f1f5e18ad8967503c58feaf55416dfc387f (was 45822f1). D:\work\src\XXXXXX\Uniqlo (dev) λ git branch -r -D origin/Branch_45822f1f5e18ad8967503c58feaf55416dfc387f Deleted remote-tracking branch origin/Branch_45822f1f5e18ad8967503c58feaf55416dfc387f (was 45822f1). D:\work\src\XXXXXX\Uniqlo (dev) λ git branch * dev dev_with_BT2016 master D:\work\src\XXXXXX\Uniqlo (dev) λ git push origin -d Branch_45822f1f5e18ad8967503c58feaf55416dfc387f To http://192.168.22.103:8080/XXXXXX/Uniqlo.git - [deleted] Branch_45822f1f5e18ad8967503c58feaf55416dfc387f |
参考自:http://chevy.iteye.com/blog/2208119 from:https://www.cnblogs.com/VAllen/p/git-remote-delete-origin-branches.html
View DetailsSpring Boot(四):Thymeleaf 使用详解
简单说,Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点:
1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 Thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
2.Thymeleaf 开箱即用的特性。它提供标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL表达式效果,避免每天套模板、改 Jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
3.Thymeleaf 提供 Spring 标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
分布式最终一致方案梳理
摘要: 前言目前的应用系统,不管是企业级应用还是互联网应用,最终数据的一致性是每个应用系统都要面临的问题,随着分布式的逐渐普及,数据一致性更加艰难,但是也很难有银弹的解决方案,也并不是引入特定的中间件或者特定的开源框架能够解决的,更多的还是看业务场景,根据场景来给出解决方案。根据笔者最近几年的了解,总… 前言 目前的应用系统,不管是企业级应用还是互联网应用,最终数据的一致性是每个应用系统都要面临的问题,随着分布式的逐渐普及,数据一致性更加艰难,但是也很难有银弹的解决方案,也并不是引入特定的中间件或者特定的开源框架能够解决的,更多的还是看业务场景,根据场景来给出解决方案。根据笔者最近几年的了解,总结了几个点,更多的应用系统在编码的时候,更加关注数据的一致性,这样系统才是健壮的。 基础理论相关 说起事务,目前的几个理论,ACID事务特性,CAP分布式理论,以及BASE等,ACID在数据库事务中体现,CAP和BASE则是分布式事务的理论,结合业务系统,例如订单管理,例如仓储管理等,可以借鉴这些理论,从而解决问题。 ACID 特性 A(原子性)事务的原子操作单元,对数据的修改,要么全部执行,要么全部不执行; C(一致性)在事务开始和完成时,数据必须保持一致状态,相关的数据规则必须应用于事务的修改,以保证数据的完整性,事务结束时,所有的内部数据结构必须正确; I(隔离性)保证事务不受外部并发操作的独立环境执行; D(持久性)事务完成之后,对于数据的修改是永久的,即使系统出现故障也能够保持; CAP C(一致性)一致性是指数据的原子性,在经典的数据库中通过事务来保障,事务完成时,无论成功或回滚,数据都会处于一致的状态,在分布式环境下,一致性是指多个节点数据是否一致; A(可用性)服务一直保持可用的状态,当用户发出一个请求,服务能在一定的时间内返回结果; P(分区容忍性)在分布式应用中,可能因为一些分布式的原因导致系统无法运转,好的分区容忍性,使应用虽然是一个分布式系统,但是好像一个可以正常运转的整体 BASE BA: Basic Availability 基本业务可用性; S: Soft state 柔性状态; E: Eventual consistency 最终一致性; 最终一致性的几种做法 单数据库情况下的事务 如果应用系统是单一的数据库,那么这个很好保证,利用数据库的事务特性来满足事务的一致性,这时候的一致性是强一致性的。对于java应用系统来讲,很少直接通过事务的start和commit以及rollback来硬编码,大多通过spring的事务模板或者声明式事务来保证。 基于事务型消息队列的最终一致性 借助消息队列,在处理业务逻辑的地方,发送消息,业务逻辑处理成功后,提交消息,确保消息是发送成功的,之后消息队列投递来进行处理,如果成功,则结束,如果没有成功,则重试,直到成功,不过仅仅适用业务逻辑中,第一阶段成功,第二阶段必须成功的场景。对应上图中的C流程。 基于消息队列+定时补偿机制的最终一致性 前面部分和上面基于事务型消息的队列,不同的是,第二阶段重试的地方,不再是消息中间件自身的重试逻辑了,而是单独的补偿任务机制。其实在大多数的逻辑中,第二阶段失败的概率比较小,所以单独独立补偿任务表出来,可以更加清晰,能够比较明确的直到当前多少任务是失败的。对应上图的E流程。 业务系统业务逻辑的commit/rollback机制 这一点说的话确实不难,commit和rollback是数据库事务中的比较典型的概念,但是在系统分布式情况下,需要业务代码中实现这种,成功了commit,失败了rollback。 业务应用系统的幂等性控制 为啥要做幂等呢? 原因很简单,在系统调用没有达到期望的结果后,会重试。那重试就会面临问题,重试之后不能给业务逻辑带来影响,例如创建订单,第一次调用超时了,但是调用的系统不知道超时了是成功了还是失败了,然后他就重试,但是实际上第一次调用订单创建是成功了的,这时候重试了,显然不能再创建订单了。 查询 查询的API,可以说是天然的幂等性,因为你查询一次和查询两次,对于系统来讲,没有任何数据的变更,所以,查询一次和查询多次一样的。 MVCC方案 多版本并发控制,update with condition,更新带条件,这也是在系统设计的时候,合理的选择乐观锁,通过version或者其他条件,来做乐观锁,这样保证更新及时在并发的情况下,也不会有太大的问题。例如update table_xxx set name=#name#,version=version+1 where version=#version# ,或者是 update table_xxx set quality=quality-#subQuality# where quality-#subQuality# >= 0 。 单独的去重表 如果涉及到的去重的地方特别多,例如ERP系统中有各种各样的业务单据,每一种业务单据都需要去重,这时候,可以单独搞一张去重表,在插入数据的时候,插入去重表,利用数据库的唯一索引特性,保证唯一的逻辑。 分布式锁 还是拿插入数据的例子,如果是分布是系统,构建唯一索引比较困难,例如唯一性的字段没法确定,这时候可以引入分布式锁,通过第三方的系统,在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁,这样其实是把多线程并发的锁的思路,引入多多个系统,也就是分布式系统中得解决思路。 删除数据 删除数据,仅仅第一次删除是真正的操作数据,第二次甚至第三次删除,直接返回成功,这样保证了幂等。 插入数据的唯一索引 插入数据的唯一性,可以通过业务主键来进行约束,例如一个特定的业务场景,三个字段肯定确定唯一性,那么,可以在数据库表添加唯一索引来进行标示。 API层面的幂等 这里有一个场景,API层面的幂等,例如提交数据,如何控制重复提交,这里可以在提交数据的form表单或者客户端软件,增加一个唯一标示,然后服务端,根据这个UUID来进行去重,这样就能比较好的做到API层面的唯一标示。 状态机幂等 在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机,就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机,这时候,如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,理论上是不能够变更的,这样的话,保证了有限状态机的幂等。 异步回调机制的引入 A应用调用B,在同步调用的返回结果中,B返回成功给到A,一般情况下,这时候就结束了,其实在99.99%的情况是没问题的,但是有时候为了确保100%,记住最起码在系统设计中100%,这时候B系统再回调A一下,告诉A,你调用我的逻辑,确实成功了。其实这个逻辑,非常类似TCP协议中的三次握手。上图中的B流程。 类似double check机制的确认机制 还是上图中异步回调的过程,A在同步调用B,B返回成功了。这次调用结束了,但是A为了确保,在过一段时间,这个时间可以是几秒,也可以是每天定时处理,再调用B一次,查询一下之前的那次调用是否成功。例如A调用B更新订单状态,这时候成功了,延迟几秒后,A查询B,确认一下状态是否是自己刚刚期望的。上图中的D流程。 总结 上面的几点总结,更多的在业务系统中体现,在超复杂的系统中,数据的一致性,不是说简单的引入啥中间件能够解决的,更多的是根据业务场景,来灵活应对。 from:https://www.cnblogs.com/BrightMoon/p/5622618.html
View Details关于架构优化和设计,架构师必须知道的事情
概述 这篇译文最早发布在infoQ下面的一个微信公众号:“聊聊架构”上,想着我在园子几乎沉寂了接近两年之久,于是借机复活。哈哈哈,这是一篇关于架构的译文,会介绍比较多的一些工具、以及框架,给对架构感兴趣的同学一个知识扩充。 近几年来随着互联网的飞速发展,新的架构实践方式不断涌现,但是有一件事情是永恒不变的,那就是-“架构之道”;关于如何设计出灵活、高可用性以及能够快速适应变化的系统架构,我们依旧还有很大的发挥空间。本文会介绍关于如何构建前沿的、易维护的、安全的架构的几个要点,同时你也可以把它当作系统设计的准则或者用它来验证现有的架构是否合理。 就像我们经常所说的:没有最好的架构,只有最合适的架构。一个好的架构师,可以根据具体的需求、所拥有的资源等因素综合考虑而设计出最优的架构方案。特别是现在,业务的飞速变化、数据无处不在等这些因素的影响下,技术和框架也需要在变化的过程中不断地打磨和提升以适应新的业务需要。可能当时是最好的架构,但是后来我们还是要跟着业务的变化去做改进。这并不是一件坏事情,我们只要做好应对变化的准备即可。 与代码无关 架构师这个词的意义非常广泛,有些架构师是指在公司负责编写软件的某些模块的人。当然多数公司并没有这样的职位,他们会有一些技术leader来负责具体的功能。我们这里所要讲的架构师不会太过于关注代码的细节,而是更关注系统各个模块之间如何协同、交互等一些更全局的一些事情。他们主要关注一些可能经常会被人遗忘但是又会为系统带来恶劣影响的部分,职责是确保所有的功能都能够以较好的质量及时被交付。这种人对于软件产品的成功有着举足轻重的地位,当然他们往往在一个公司里面可能同时负责好几个项目。 想象一下,两个不同的架构师来建造一艘太空飞船。第一个选择用纸来糊一个样子比较好看的,然后把这艘飞船放到一个漂亮、大小合适的玻璃橱窗里面保护起来。飞般看起来可能像下面的这个样子: 第二个架构师决定用乐高模型来拼一个太空飞船,它们可以随意组合并且比较坚固,所以并不需要额外的特殊保护。 两艘飞船看起来都是挺不错的,但是第一个用了较长的时间来完成并且后来当他们需要对这艘飞船做改进的时候,问题就暴露出来了。 第一位架构师几乎炸了,因为每一次的改动时候,他们必须要移除那个保护罩,并且需要重新再造一艘完整的飞船。虽然他们已经有了所有的模型,再加上造飞船对他来说已经很熟悉,但是他们还是花了很长的时间去完成每一次改造,另外还需要再做一个新的保护罩才能装的下那艘新的飞船。 但是对于第二位架构师来说,这一切都是不需要的。他只需要对产生影响的一些组件进行改造,制作新的组件,当一切准备就绪再添加到原来的飞船即可。 再后来,第二位架构师希望能更进一步的优化他们的制作过程,因为他们现在投入了很多的时间在上面。在经过一段时间的研究之后,他们决定尝试用一种新的材料和方法来制作这艘飞船。也就是3D打印,他们申请了一台3D打印机,制作了所有的模型,这样他们就可将一些常规的任何通过3D打印机自动完成了。 当然,这只是一个很简单的例子。但是我们能从中学到什么呢?虽然两位架构师在最开始的时候都能成功的完成最初始的功能,但是他们都面临着变化所带来的系统的调整。在集成阶段,复杂性开始显现出来,和最开始的目标无关,最终整个设计是否足够灵活、可调整、以及模块化起着至关重要的作用。 软件的架构至关重要,仅仅有较好的代码来完成功能不足以成为一个优秀的解决方案。因为它不仅仅涉及到代码,还有我们所写的各个模块之间如果交互和集成、数据如何存储、我们怎么样来进行开发和测试、以及在引进变动的时候的难易程度等等。 这些事情都是和编写代码无关,但是需要我们来花时间考虑, 并且是整个系统最后是否成功的决定性因素。 需要考虑的细节 还有一些原则比如:模块化、轻耦合、无共享架构;减少各个组件之前的依懒、注意服务之间依懒所有造成的链式失败及影响等。 DDD给我们提供了在不同的特定领域上下文以及业务功能的基础上拆分组件的指导方法。 把服务独立出来提供特定的功能,同时方便在应对变化的时候能够不影响其它的服务。 在大多数情况下,如果需要同步更新很多个服务则说明系统的耦合还不够低。当然,再完美的原则也会有例外的时候。比如当你想把系统部署在一些IoT设备上的时候,你可能要一次性部署所有的组件。这是允许的,但是,请尽量考虑服务之间的耦合及灵活性以应对将系统部署在不同平台上的需求。 即便如此,我们也不可能完全避免耦合,它总是会出现在某些场景下。这就需要我们提取一些抽象层将服务之间的交互定在契约上来避免复杂,提升灵活性。这就需要我们有一种辨别能力,能够找到那些必须放在一起来做处理而不能拆解的功能。如果这些功能是值得放在一起的,那我们就可以将它独立成一个微服务,遵循高聚合的设计原因。 我们要记住的是,系统的设计要做到比较容易地增加或者修改原来的组件。无状态的架构是系统高扩展性的基石。 特别需要注意服务和组件之间如何交互,了解不同的协议的优缺点,包括速度以及可用性,来帮助我们来决定哪一种是最适合我们的。 基础设施、配置、测试、开发、运维 为配置管理定义策略,因为同时发生的配置变化对系统所有造成的影响也是很重要的,所以需要由全局层面的的自动化更新方案来完成。 在如今,对于一个数据敏感的大型解决方案来说如果没有自动化的一些基础设施和稳固的开发、测试和部署流程,那就和自杀无异。我们需要花费一定时间来计划和准备开发、测试、生产环境,可能还需要一些额外的环境以备不时之需。 测试流程和策略也是非常重要的。一些最佳实践使用Blue-Green开发、金丝雀部署、A/B测试等。尽量保持测试环境与生产环境是一致的,至少硬件结构上来说应该是一样的。一定要做压力和负载测试,并且尽可能快的在生产上进行这样的测试,这样能够更快速、精确的帮我们找到线上的问题。 可调整的架构同时也意味着服务要可以被灵活独立的部署以及简单的基础运维操作。 利用不可变基础设施的优势 不可变基础架构,就是说系统一旦部署,就不再更变升级。当服务/应用需要升级时,只要部署一个新版系统,摧毁旧版就好了。在这个过程中,系统对外服务是几乎是持续的。(译者注) 保证打包/持续集成进程是基于统一的途径,并且不会对正在运行的服务进行任何更改(比如 禁用ssh),所有的更新都应该通过定义好的自动化配置和打包操作将它们应用到所有的对应的系统上,来避免配置遗漏。比如手工某个环境上修改配置,可能会漏掉其它环境的配置。 开发团队不应该过度关注基础设施,因为有一天可能基础设施也会发生改变,所以与业务相关的开发不要和基础设施有过重的绑定。 代码之间的东西(in-between the code) "in-between the code" 可以统一的概括为一些基础设施所提供的功能,比如:服务发现、请求路由、网络通迅层、代理、负载均衡等等。很多生产上的错误并不是因为代码的业务逻辑错误或者每个独立组件本身的问题,而是由于这些把各个组件协调起来的一些通用基础设施。 随着系统的变化越来越快,更要注意我们所更改的一些组件,考虑可用性和扩展性。制定最小风险的计划来应对出现的问题。 无处不在的坑 做一个偏执狂。为失败而设计架构 – 列举所有可能失败的地方。和团队头脑风暴对所有可能失败的地方进行质疑然后提出保护方案。 如果连接建立失败怎么办? 如果花费的时间超出预计怎么办? 如果请求返回不清楚的数据或者不正确的答案怎么办? 如果请求返回的数据不是约定好的怎么办? 如果出现很高的并发能应对吗? 如果服务挂、机组、整个数据中心挂掉了怎么办? 如果数据库损坏了怎么办? 如果部署的时候失败了怎么办? 如果在部署成功之后生产环境上某些功能失败了怎么办? 集成性这方面的错误可以有千万种可能,那么我们应该如何来避免? 使用一些技术比如:熔断(circuit breaker)、超时设定(timeouts)、握手信号(handshaking)、舱壁(bulkheads)来帮助我们保护这些系统集成之前的问题。 熔断模式(circuit breaker)可以参考电路熔断,如果一条线路电压过高,保险丝会熔断,防止火灾。放到我们的系统中,如果某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。 舱壁模式(bulkheads)该模式像舱壁一样对资源或失败单元进行隔离,如果一个船舱破了进水,只损失一个船舱。比如采用微服务是首选,比如Docker。Docker是进程隔离的,单个 Docker失效不会影响其他Docker容器。或者把大的并行处理工作,由多个线程池来负荷分担。 当然,如果当它开始工作的时候,说明我们的系统出现了比较大的问题,需要我们去调查分析。 注意那些不能看到代码的组件、依懒项以及共享的资源。除了有正确的开发和测试流程以外,还应该尽量使用和真实生产环境一样的数据、以及硬件网络配置来进行测试。 跟踪系统的响应来防止一些比较常见的问题比如服务不可用的情况,留意系统的平均响应时间,当它有异常的时候需要寻找原因以及采取相应的行动。 搭建日志、监控、以及系统操作的自动化操作平台。由于微服务相对来说较独立,可以更方便检测失败 所以监控起来会更容易一些。一些比较不错的方式是在收集和分析日志的时候使用关联ID、通用日志数据格式等。注意日志数据可能会非常庞大,所以要考虑日志的时间周期,定义对日志进行归档。另外还有一些不错的工具可以将数据可视化在页面中,可以更直观的看到一些重要的进程。 为了保证服务的更新不会影响客户端的使用,对于服务的版本控制也是非常重要的。有些情况下同时运行不同版本的服务也是很常见的情形,我们要做好长期向后兼容的准备。 务必要记住的事情 大多数情况下我们并不是从零开始去构建,而是在现有的系统上继续添砖加瓦,而原有的系统在开发、运维、以及架构灵活性上都存在一些问题。想必很多优秀的开发人员在经历这样的情况的时候,都会想去拆解、重构整个系统,但是我们需要谨慎地来完成这个事情。当系统以错误的方式成拆分成组件或者服务单元之后也是一件很危险的事情 。 大多数系统在一开始的时候都是一个单体应用,后来不断地被拆解成为微服务。下面有一些基本的理念可以在我们做拆解地时候当作参考: 在开始拆分前了解具体的业务需求和业务领域 注意一些和其它业务共享的功能和数据,它们需要被正确地模块化 这种迁移和升级适合一步一步、一点一点地来完成,仅仅做当前最合适的事情 在开始之前很好地理解业务领域的范围及边界,因为对边界的调整将是非常昂贵的 对于改造有清晰的结构此次会涉及到哪些团队的调整 人、团队、和组织的影响 这个话题太大,大到我们需要专门写一篇文章来细述。在这里简单地概括一下,在本文中我们所提到的架构的灵活性以及稳健的开发、测试、运维等流程都会影响企业的组织结构。合适的组织结构能够给团队更大的灵活性并且更有机会持续地创新,在这种组织结构下,团队可以根据自己的节奏来工作。 组织不应该按技术来拆分团队,比如前端团队、移动端团队、后端团队或者根据不同的技术语言拆分团队等,而是应该按照微服务来拆分团队(也可以理解为按独立的业务单元来拆分)。这样在一个团队里面就会包含各种不同的技术,可以用不同的语言来实现服务,这也给团队更多的自由和自主权。 如何实践? 容器化和集群工具 Docker Docker Swarm […]
View Details暴力英语学习法 + 严格的目标管理 = 成功快速靠谱的学好英语
这篇文章发布已经快4年了,不知道大家英语学的怎么样呢? 最近想组一个微信群一起学习英语,有兴趣的同学可以加我的微信,说明一下来意~ 园子里时不时就吹起一阵学英语的浪潮,不少同鞋表示一直想学,或者一直在学,就是效果不明显(你躺枪了么?)相信自己或者身边的人都或多或少吃了英语弱的当(你懂的,我们重点在说薪水的问题:)。而各种英语成功学,方法论,版本是一个接一个层出不穷。今天我们不说为什么要学好英语,好处太多而且已经广为流传了,我们主要结合目标管理来讨论一下如何坚定不移的,快速的学好英语。以我自己的亲身经历作样板,以下情况全部属实,绝无虚构。 先说说我在开始学英语之前的情况: 时间:2012年2月,已工作4.5年 词汇量:小于1500,(初中英语成绩特别好,高中以后全部打混,再加上工作时间完全不接触英语,所以最后基本上就剩下1500不到的词汇量) 其它英语能力:总之就是不能听,不能读,不能写,当然,更不能说,连最基本的8种时态都记不怎么清了。 再说说现在的情况: 截止时间:2013年6月,持续学习时间15个月(现在并没有停止英语的学习,只是没有以前强度那么大了) 词汇量:8000+ 其它英语能力 读:能够无障碍浏览英文网站(包括技术论坛,新闻科技网站),不用借助词典阅读原版技术书籍(CLR via c#一类的) 写:平时工作上邮件,开发文档,技术文档,需求文档都是用英文写 说:每周主持2次以上和美国同事开会,有问题随时呼叫他们 听:80%理解VOA常速,NPR,CNN新闻,Channel9 Videos,以及印度口音(印度人的发音不好,可是不能阻止别人英语很好!) 其它:今年6月份因公出差,到西雅图工作一个月 之所以列出上面的对比,是希望可以让你知道,我这样的基础都能学好英语,你又何尝不可呢?不是要谈目标管理吗?我不是标题党,接下来我们就结合这个例子来看看怎样做是好的目标管理,我会把我学习英语的方法总结出来,这是一个模子,可以套到任何地方。不管你是打算学英语,还是写博客,还是换工作,或者找对象:)。 本文包括一套完全的英语学习方法(听,说,读,写)以及本人学习过程中的经验,心态的分享。 给自己的英语学习订一个目标 建立一套完整的计划 学习任务之一:从哪里开始? 学习任务之二:音标学习 学习任务之三:四级单词攻克计划 学习任务之四:继续新概念之旅 学习任务之五:新概念第三册 学习任务之六:疯狂阅读计划 学习任务之七:两周专项写作提升 学习任务之八:听力/口语/阅读/写作之综合提高 过程监控 结果检查 心态分享 暴力记单词法 资源下载 目标管理之目标 目标管理不是一个独立的个体,它包括订立目标,制作计划,过程管理,以及结果评估。之所以叫目标管理,是因为目标是一切的开始,也是一切的终结,没有目标,一切都是空谈,就好像你连去哪里都不知道,又如何知道你走在正确还是错误的道路上呢? 重中之重是目标,那么怎么样才能算是一个好的目标呢?热血澎湃的说:“我要学好英语!” 这算是一个目标吗?当然不算,如果这都算一个目标,那"我晚上想吃酸辣土豆丝,很想!"也可以算目标了,这最多就算是一个想法或者欲望而已。要知道想法和欲望这种东西,甚至不用动脑就能产生了,可以说有时候它就是一种冲动而已,我们每天都是好多种这种冲动,所以要将冲动变为现实那是很难的一件事情。那么如何才算是一个好的目标? 请不要怪我学术派,让我借SMART原则一用。 目标必须是具体的(Specific) 目标必须是可以衡量的(Measurable) 目标必须是可以达到的(Attainable) 目标必须和其他目标具有相关性(Relevant) 目标必须具有明确的截止期限(Time-based) 关于具体 为什么说“我要学好英语”不是一个目标,首先第一个它就不具体。什么情况叫好?每个人对好的定义都不一样,在不具体的情况下,人总是很容易找到一堆借口来推脱或扯皮。我们可以找一些具体的指标,比如说背多少个单词,看多少本英文原著,学几册新概念,要达到可以和外国人正常交流等,要听得懂VOA常速,要能不借助词典浏览英文技术文章等等。只有目标具体了,我们才能有参照点的去要求自己。 关于量化 目标要具体最简单的办法就是将其量化,比如说一定要熟悉6级所有单词,那么根据火星词汇记载6级是5600个单词,那就一定要把5600这个数量列出来,先把这个数字记住了,它会在潜意识上增强你的决心,更重要的时候在检查进度的时候比较容易,比如说时间过去了一个月,你背了3000个,还有2600个,是不是再花2600/(3000/30)=26天就背完了? 平均每天100个单词,有没有背?这是一种比较好的检查进度的方式。 关于可达成 我当初给自己制定的计划时间是2年,为什么是2年而不是2个月呢?因为那太不现实了,这就是可达成,先衡量自己在什么位置,有多少时间,才能够设定具体的目标。当然也可以调换一下,自己的位置和目标可知,来推算需要多少时间可以到底那个位置。 关于相关性 相关性就没什么好说的了,学好英语和程序员的职业生涯息息相关。 关于时间限制 时间限制非常重要,如果没有时间限制基本是很难达成的。这也是为什么很多人没有学好英语的原因之一,你只说要学好英语,一个月过去了,二个月过去了,可能你就背了几个单词,慢慢的你连单词都不想背了,最后就果断放弃了。所以一定要设定一个时间期限,然后把这个时间铭记在心,这样可以加强自己我监督。这个时间期限不光可以设在总体的目标上,后面我们会将大的目标分解成很多小的阶段目标,每一个小的阶段目标都必须要有时间期限,这样我们才能定时的去检查我们自己的进度,时刻提醒自己有没有掉队或者跑错方向。 另外我还有几点自己的总结: 如果可能,请告诉你身边经常接触的人你的目标,这样等于是无形找人监督你(万一他某天突然问你英语学的怎么样了?你好意思说放弃了么)。 与身边的人分享你的进度,告诉他你进行的怎么样了,可以在每一个阶段完成的时候请大家喝奶茶或者吃饭什么的,相当于是奖励你自己了。 为你的目标找一个借口,或许这个借口就是你真实的目标也不一定,但是当你到底终点的时候这个已经不重要了。重点是一定要找到自己的兴趣点,比如说你非常想加工资,你就告诉自己,英语学好了你就可以加工资了,而且还能加好多工资,你肯定会像打鸡血了一样的。又或者说你想出国工作,那你就得告诉自己,你连英语都说不来,想出国工作?门都没有啊!!! 如果能找到同伴,那样最好,可以互相监督。但是这个不是必要的,像个男人一样,有些事情是需要你一个人扛起来的! 目标的分解 我们有了一个总体的目标之后,要习惯将它分解成一个一个的小目标。按照时间的维护可以分为: 短期目标(每一天,每一周,每一月) 长期目标(每一季度,每半年,每一年) 最终目标 按照内容的维护可以分为: 词汇量目标 听力能力目标(听力理解范围) 阅读能力目标(每分钟阅读单词数) 写作目标 口语表达目标 目标是会发生变化的 就是我们的需求一样,它是一定会变的!当然它和需求不一样的情况是,大多数情况下它都是变得更好,更高。刚开始工作需要被逼着看邮件,后来发现英语好了,做程序员待遇基本翻倍,于是加强了听和说的的锻炼。换了工作之后,发现原来可以出国,去看看外面的天也是一件很不错的事,于是把听和说又提高了一个台阶。到现在学英语已经完全成为了一种爱好一种习惯了,喜欢每天早上大声的读英文,听自己的口音,喜欢听美式和英式口音的区别。喜欢和外国人交流,想了解他们的文化,他们的历史。当一种行为变成一种爱好或者习惯,便一发不可收拾了。 总之,先根据自己的情况来设定目标,然后再把它细化。找一个最贴近你的目标,也许你暂时不用口头交流,那你只需要提高词汇量,加强语法和阅读训练就可以了。至于后面怎么样,我可以肯定的告诉你,目标是会发生变化的! 目标管理之计划 当我们有了一个清晰的目标之后,接下来的事情就是它需要一个完美的计划。这里我们可以借助我们软件开发过程中的WBS(任务分解结构)的方法来帮助我们制定计划。当然软件开发的时候是多个人协同合作,而学英语是需要我们自己一个人来完成的。 在这里,我们只是将它分解成6块而已,我的建议是最好一段时间专攻一项,因为我们毕竟是利用工作以外的时间来学习,专攻一项的话效果比较明显,自己也可以很清楚的看到进步。只有看到进步了,才会觉得有希望,连希望都看不到的时候,我想没有多少人可以坚持下去。所以要让自己看到进步,这很重要,哪怕只有一点的小进步,也会给你增加信心,这都是你坚持下去的动力。 学习任务之一:从哪里开始? 我想计划的难题可能是这个,因为如果起点找的不对,就很容易半途而废,所以这个起点很重要。我们要结合自己的特点以及现在的水平去找这个开始的点,千万不能别人是那样做的,你也那样做。 就我而已,因为基础实在是太差,连生活基础会话都说不来。所以我当时选择了《新概念第一册》,当然我不是自己学( 基础太差是没法自学的,光背几个单词也解决不了问题,还容易气馁),也没有去报班,报班的情况要不就是一周两三结课,这样效果太慢。要不就是连续几天封闭式上完,对我来说都不合适,所以我在网上下载了新东方老师以前的上课视频,也是从头到尾针对课文作讲解的,非常的详细。 在找到起点之后,接下来,我们就要作一个短期的计划和目标。这个是一定要的,大家看到新概念第一册总共是144课,但是老师是只讲单数课的,复数课自己复习。所以在我的电脑里面是有72节的视频课程,每一节的视频是1个小时,也就是说学完新概念第一册需要72小时。下面是我的计划表: 除了看视频以外,我们还要做以下3件事: 每一课后面的习题也是要做的,既然是基础,就一定要礼实。 背诵课文,这个任务可以在早上做,比较好实现。新概念第一册和第二册的课文都不难,很好背。 记每一课的单词,有了课文的背景,单词是很好背的,而且第一册是最基础的1700个,全是见过的。 学习任务之二:音标学习 […]
View Details