个人能建电商网站吗,张家港网站制作哪家好,常熟苏州网站建设,wordpress手机后台2008年11月#xff0c;我在博客园开通了个人帐号#xff0c;并在博客园发表了自己的第一篇博客。当然#xff0c;我写博客也不是从2008年才开始的#xff0c;在更早时候#xff0c;也在CSDN和系统分析员协会#xff08;之后名为“希赛网”#xff09;个人空间发布过一些… 2008年11月我在博客园开通了个人帐号并在博客园发表了自己的第一篇博客。当然我写博客也不是从2008年才开始的在更早时候也在CSDN和系统分析员协会之后名为“希赛网”个人空间发布过一些与编程和开发相关的文章。从入行到现在我至始至终乐于与网友分享自己的所学所得希望会有更多的同我一样的业内朋友能够在事业上取得成功也算是为我们的软件事业贡献自己的一份力量吧这也是我在博客园建博客时候的愿景专业、求是、解惑。因此我在撰写博客文章的时候都是以客观严谨的态度来阐述技术知识并尽可能地以更好的内容组织形式来提高文章的可读性同时尽可能地回答网友的提问。有很多博客园的粉丝跟我提过意见有的说我的博客更新太慢也有的说我有些系列文章有烂尾现象对于粉丝们的提问我只有一个回答那就是业余时间太有限我没有办法凭靠自己一个人的力量在有限的业余时间里在保证文章品质的前提下为社区提供越来越多的支持。在这一点上我选择的是宁缺毋滥宁可发布周期变长也不希望把没有质量的文章分享出来。另一方面我也发布了很多开源项目有些项目属于我自己一些个人小工具的代码备份也有一些项目比如Apworks、Byteart Retail、WeText甚至是我的新博客daxnet.me的源代码项目daxnet-blog都在我的Github Repo里。说实话我真的没有时间把每个项目中的细节技术以博客的方式一一介绍清楚因此一般我基本完成了自己比较满意的开源项目时我都会写一篇博客来介绍项目的内容和所使用的技术同时引导读者直接克隆我的项目代码进行参阅或者直接folk不用太担心许可协议问题除了Raspkate项目之外其它绝大部分项目都是MIT或者Apache的许可协议。总而言之不管形式如何我始终没有放弃过最初的愿景。 也是出于这样的坚持我希望能够更好地组织我的博客文章甚至是其它的一些原创作品以更为集中和高效的方式为读者提供更好的学习交流体验一直以来我都想过搭建属于自己的博客服务我也经过了很多尝试。早在2012年我使用Word Press在一个国外站点建立过博客系统可是后来因为国外服务供应商的原因网站没能继续维持下去之后我也经过好几次的尝试包括使用BlogEngine.NET等开源项目可是也都没能做好。出于对技术的热衷与追求这一次我终于下定决心使用自己所学的知识依托微软的.NET平台开发并部署了我自己的新博客系统【http://daxnet.me】。 站点功能 首先简要介绍一下目前的站点功能吧。右图就是本站的主页效果我做得很简洁没有用太多花哨的图片也没有用走马灯。明眼人一看就知道这是基于ASP.NET MVC而开发的Web应用程序使用了Bootstrap。不错基本答对需要强调的是这个博客站点以及后端的RESTful服务全部都是基于ASP.NET Core完成的.NET Core运行时版本为1.1.0运行在Docker容器中。哎说着说着又到技术上了功能还没介绍完呢。说到功能目前功能很简单主页列出了我自己原创或者翻译的所有文章读者可以注册用户帐号注册用户可以发表评论也可以在用户管理页面中更改自己的昵称。好了目前功能就这么多别看功能少我可是前前后后陆陆续续花了2个月的时间才做到目前这个样子。当然我会继续更新这个站点让它的功能变得更加完善。 提到ASP.NET Core有没有吊起你的技术胃口呢不用着急接下来我就介绍一下整个站点中各部分的技术选型看完后或许你会知道为什么我花了2个月的业余时间才整出来这么个简单的玩意儿。 站点技术介绍 整体架构 整个网站所采用的所有基础设施全部运行在微软云Windows Azure中使用了部分托管资源以及一些非托管的Azure VM。大致情况如下 图片存储服务由Azure Blob Storage Service托管数据库系统由Azure SQL Database托管未启用Geo-Replication因为没钱邮件服务由Azure SendGrid Account托管Pricing Tier为F1每月可以免费发送25000封邮件应用服务器基于Azure构建的Ubuntu 16.04.1 LTS虚拟机运行了两个Docker容器blog-web和blog-service分别托管前端Web站点和后端RESTful服务。后端RESTful API服务没有做任何认证和授权Web站点通过内部子网访问RESTful API服务Docker容器运行在非托管环境中持续集成系统Jenkins基于Azure构建的Windows Server 2012 R2一台Master和一台Ubuntu 16.04.1 LTSSlave。站点的前端和后端都在后者Ubuntu中完成编译、打包以及Docker镜像的发布实现了一步到位的部署方式代码库Github 有人会问为什么使用了非托管的Azure VM环境运行应用系统我也考虑过这个问题理论上讲基于云的系统架构最好选用托管的PaaS服务这样不仅可以得到纯天然的高可用性包括灾备比如AWS的跨AZ部署某些服务跨区域的可用性以及负载均衡而且还可以得到专业的技术支持。只有当存在老系统向云迁移的需求并需要迎合老系统的特定运行环境要求时才考虑使用IaaS服务。虽然虚拟机等这些资源是由Azure负责创建并运行的在这一层面Azure可以保证虚机的可用性但虚机内部运行的任何程序的状态以及所使用的数据Azure等云服务是无从得知的对这部分东西的监控也会变得很麻烦。出于安全考虑通常云服务供应商是不会也不应该获得类似虚机内部的客户程序的运行数据的使用虚拟机服务所产生的程序运行风险客户需要自己承担。这也就是著名的责任共担原则。 看起来用虚拟机运行应用不是太靠谱嘛然而我却选择这么使用了。有几个原因 为何不使用Azure Web App一方面Jenkins做自动化部署直接把编译好的应用推送到Azure Web App中好像不是太顺手要写一些PowerShell的代码可是我的编译系统是Linux不过现在已经有Linux版的PowerShell了而且Azure SDK Command Line Interface也有Linux版所以这个理由有点牵强更合理的解释是劳资不会另一方面我没有在服务端做认证和授权仅通过子网向外界提供服务所以我希望我的Web App也运行在子网内部然后向外暴露80端口供外界访问。这样一来Azure Web App又如何部署到我自己的子网内这是一个技术问题我相信一定有解决方案但是我也没太多时间和精力去细究如何实现自己的第一反应也无非是将前后端全部部署在Azure Web App中然后打开后端的认证机制。但这样做又要花一些额外的工夫。好吧还是这个理由劳资不会为何不使用Azure Container ServiceAzure Container Service会在你指定的Resource Group资源组中创建一整套网络部署包括好几台虚拟机、公网IP、两个负载均衡器等等我想你一定知道我为什么没有选择Azure Container Service了原因就是劳资没钱 理由够充分吧微软Windows Azure提供的这些服务都很赞我没选不是说它们不好用而是出于自己的实际情况考虑 某些服务的学习成本经济成本暂时没必要做到99.99999%的高可用率即使应用挂了恢复的成本很小数据完全不需要恢复托管的SQL Database、Blob Storage会保证我的数据不丢失应用程序恢复也很简单重新运行Docker容器就完事儿 OK从整体架构上看我的选择即是如此而已这样的选择当然不一定完全正确但我觉得至少合适仅供参考。下面附上本站点的整体架构图。 作几点注解 三台VM位于同一个Virtual Network的subnet中每台VM的虚拟网卡上都套有独立的Network Security GroupNSG在NSG上设置了Inbound/Outbound Endpoints严格限制了端口访问的IP地址。三台VM之间使用subnet IP地址访问Windows Server 2012 VM宿主了Jenkins Master以及Seq日志服务。它向公网暴露8080端口和5342端口分别用于访问Jenkins服务和Seq管理界面第一台Ubuntu VM运行了Jenkins Slave它不向公网暴露任何端口仅向Jenkins Master机器暴露22端口用于Jenkins Slave Agent的执行调度第二台Ubuntu VM运行了博客系统的两个Docker容器前端应用程序blog-web和后端RESTful API服务程序blog-service。web通过子网IP地址访问serviceVM仅向公网暴露80端口后台service无法从公网访问两个Docker容器所运行的应用blog-web和blog-service都可以访问托管的Azure SQL database、Azure Storage blob和SendGrid Account服务整个部署的拓扑结构有可能不太合理比如没有做负载均衡没有使用托管的应用宿主服务比如Azure Web App、Container Service等没有使用Scaleset。因为目前没必要而且没钱 接下来回到代码上我向大家介绍一些框架的技术选型以及几个ASP.NET Core可用的开源库项目。 前端 如今的前端技术日新月异各种Javascript的框架和JSX的技术使得前端开发变得更加方便高效所获得的用户体验也变得越来越好。例如Angular JS包括1和2两个版本、React Redux、Knockout.JS、Backbone等等。在实际项目中我们也运用了这其中绝大部分技术然而在我的这个博客系统中我没有使用单页面应用的解决方案而是继续使用前端Razor后端C#代码的方式对啦这就是ASP.NET Core MVC我没有使用任何MVVM的框架只是简单地使用了Bootstrap和jQuery对我来说这样选择的原因有以下几个 相对而言对ASP.NET MVC比较熟悉更容易尽快完成开发任务本身站点逻辑不是太复杂暂时没有必要使用这些前端框架打算体验一下ASP.NET Core的新特性 当然为了实现一些特定的功能我还是选用了一些开源代码和框架现给大家大致介绍一下。 关于首页的分页实现 首页实现了博客文章的服务端分页每次仅向服务器请求有限量的数据。分页控件是自己写的一套算法实现的并套用了Bootstrap的pager样式实现了响应式用户体验。分页控件使用了ASP.NET Core MVC中新的Tag Helper技术从算法上根据每页的大小和总博客数量对页号进行分段处理使得整个分页功能有个很好的用户体验。 关于验证码生成 验证码的生成在经典的ASP.NET应用程序中能够非常容易地实现。经典ASP.NET应用程序基于Full .NET Framework运行于Windows的IIS上依赖于Windows的图形库可以很方便地产生图片。然而ASP.NET Core应用程序则完全不同为了实现跨平台就无法使用System.Drawing命名空间下的类型当然你可以指定你的ASP.NET Core应用程序使用net45但是这样无法跨平台。在这里我使用了CoreCompact.System.Drawing这个库可以通过nuget搜索到 。它会依赖于Microsoft.Win32.Primitives库这个库定义了一些与Drawing相关的数据结构但是没有提供任何图形库的实现。有兴趣的读者不妨一试。 关于回复编辑器 没什么好说的使用了著名的CKEditor作为编辑器当然我选择性地启用/禁用了某些功能。 关于博客文章中的代码高亮 使用了著名的Alex Gorbatchev的SyntaxHighlighter博客园也是使用的这个库不过我用的可能不是最新版本。 关于回复中的时间信息 在每篇博客文章后面会显示网友的回复内容。这些内容会显示回复时间与当前时间的关系信息比如 上图显示这则回复内容是发表于25天前的。可别小看了这个部分的实现我是采用了一个叫做Humanizer的库。这个库很有意思它能提供一些非常实用的API比如给它一个英文名词它可以返回复数形式给它一个日期它能返回一个更贴近人类自然语言的表述。它还有很多其它的有趣的功能大家可以去了解一下。 关于博客发布的MetaWeblog API 博客系统支持使用Windows Live Writer发布博客它通过Shawn Wildermuth提供的WilderMinds.MetaWeblog实现了MetaWeblog API。通过Windows Live Writer可以直接将站点添加到帐号中 基本上前端所使用的一些技术和第三方框架就如上所述。下面来看看后台的一些技术选型。 后台 数据库与数据访问组件 正如上所述新博客系统后台使用Azure SQL Database也就是托管的SQL Server关系型数据库。为什么选择SQL Server而不选择MongoDB等目前流行的NoSQL方案作为一个博客网站我没有找到选择NoSQL的理由Azure上也有托管的MongoDB服务仅管它是委托由Bitnami负责运维的。另一方面虽然我选择了Azure SQL Database但我没有使用任何第三方的数据访问框架没有使用ORM包括目前流行的Dapper。没有选择ORM的理由一方面感觉ORM在这个场景里还是太重另一方面截止我进行技术选型时Entity Framework Core无法满足我的需求至少它无法从领域模型的角度去支持多对多的映射。那为何又没有选择Dapper呢主要原因还是一样无法满足我的需求。原生的Dapper类库需要写一些SQL脚本虽然轻量了但失去了对代码重构的支持Dapper.Contrib增加了一些更友好的API但仍然无法满足自己的需求。 几番思考我决定自己写一个小框架既可以支持自己定义的简单领域模型又可以支持基于Lambda的语法、支持数据库事务、支持异步API、支持多种类型的关系型数据库。这个小框架的代码位于DaxnetBlog.Common.Storage命名空间下使用了一些非常巧妙的技巧比如开发者可以使用Lambda表达式来定义查询条件框架会通过ExpressionVisitor访问者模式将Lambda表达式转换成SQL语句。下面的代码正是这个框架的使用代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var rowsAffected await this .storage.ExecuteAsync(async (connection, transaction, cancellationToken) { var account (await this .accountStore.SelectAsync(connection, acct acct.UserName userName, transaction: transaction, cancellationToken: cancellationToken)).FirstOrDefault(); if (account null ) { throw new ServiceException(HttpStatusCode.NotFound, Reason.EntityNotFound, $ 未能找到帐号名称为{userName}的用户帐号。 ); } account.DateLastLogin DateTime.UtcNow; return await this .accountStore.UpdateAsync(account, connection, acct acct.UserName userName, new ExpressionFuncAccount, object [] { acct acct.DateLastLogin }, transaction, cancellationToken); }); 这段代码用于更新指定帐号名称的用户的登录时间代码中没有穿插SQL语句而是使用Lambda表达式进行表述。代码中storage对象指代关系型数据库的实体而accountStore则表示对某种实体在此处是帐号实体的存储有点像领域驱动设计中的Repository的概念。这样的设计是为了实现职责分离accountStore不会依赖于storage也就是关系型数据库类型的实现。 日志 无论是前端还是后端我都使用了Serilog作为日志框架并将日志推送到Seq系统。具体做法我会在另外的博客文章中详细介绍在此就不多介绍了。下图就是本博客的日志输出为了省钱在Docker容器启动时通过环境变量将日志级别设置为Warning。 API文档 不多说Swagger。具体实现方式我也会在另外的文章中介绍。 缓存 暂时未使用缓存下一步会增加。 好了整个博客的架构以及前后端技术大概就介绍这么多如果要深入技术实践的每一个细节我想估计几个系列文章都讲不完。还是如本文最开始的时候所述博客代码开源大家可以学习交流。今后我仍然会争取多写一些文章来介绍相关技术。 我还会继续在博客园发表博客吗 当然会博客园一直是我与大家交流的主要场所将来也是。可以理解为了向大家提供更多高质量的“干货”博客园对博主们所发文章都会有一些限制博客主题行文也会有一些约束。作为我本人来说在博客这种形式下我或许应该可以以更多的方式来表现我的技术生涯甚至是自己的一些对生活中事物的思考这或许对他人的技术发展也会是一种启发在获得大家的反馈和回复以后我也能继续提高自己。与这些相关的内容我会发表在自己的博客中当然我想我自己的博客仍然会以技术类文章为主吧。 目前这个新博客显示了我曾经在博客园发表的博客当然只是为了充数使得主页不显得那么单调所有图片中还是保留博客园的链接。我打算给这个新博客定下三个月的试运营阶段这个过程准备考察一下系统的运行状况并总结一下微软Azure云的使用心得当然最重要的是衡量一下自己能否支付得起运营的这笔开销。整个试运营阶段我还会继续往系统加入更多功能。 如果运营失败也请大家多多包涵权当是我为社区多贡献了一个开源项目吧。 总结 本文首先阐述了我对社区贡献的一些实际情况并由此引出我自己全手工打造的基于ASP.NET Core实现的博客系统接下来介绍了这个系统的整体架构和部署以及前后端的一些技术选型最后对大家可能提出的问题进行了简要解答。马上又要进入新的一年了也快到了自己MVP Renew的时间无论Renew是否成功去年贡献量感觉不是太高我仍将继续坚持为社区多做贡献真正做到“专业、求是、解惑”。 原文地址 http://www.cnblogs.com/daxnet/p/6139317.html .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注