首页 文章 精选 留言 我的

精选列表

搜索[1 X 认证],共10000篇文章
优秀的个人博客,低调大师

VICA 架构设计(1)

本文记录最近完成的一个通用实时通信客户端的架构。 背景 我们公司是做税务相关的软件,有针对大客户 MIS 系统,也有针对中小客户的 SaaS 平台。这些系统虽然都是 B/S 的,但是也需要使用 ActiveX 控件来调用本地的硬件设备打印相关的发票。 由于 ActiveX 控件只能在 IE 下使用,而且在为客户部署时,经常会出现各种各样的问题。所以 SaaS 平台在推广时,不能不配备一个相应的实施团队,为每一家客户解决这些问题。 为了更好地控制本地硬件资源,对接税控设备。我们决定开发一个统一的独立的客户端软件。这样,客户在使用我们的 SaaS 服务或 MIS 系统时,只需要在开票机中下载一个轻量级的客户端,安装后,该客户端会与服务端保持实时的连接,并以托盘的形式静默地在开票机器的后台长期运行。这样,其他的使用者就可以继续使用浏览器中的网页,远程控制这些开票机进行开票了。 客户端产品在公司的名称为 VICA(VAT Intelligent Client Assistant -增值税智能客户端助手)。以下将使用该名称。 架构目标 通用性 VICA 需要同时适配公司的所有 B/S 产品。接口方面要比较通用。 一切需要调用本地资源的功能,都可以通过 VICA 来完成。 平台化 由于公司的产品种类较多,需要调用本地资源的功能也比较多,有打印纸质发票、开具电子发票、抓取本地数据、调用局域网服务等…… 所以要求 VICA 实现平台化、插件化。VICA 本身只专注于更加底层的功能,如插件框架、长连接、自动重连、自动升级、通用提示、命令框架。而业务功能则都实现为相应的插件。这样,在不同产品的应用场景中,开发者可以选配不同的功能插件即可完成基础功能的搭建。另外,开发者还可以基于统一的开发规范,编写出更多适合自己业务的功能插件。 三高 VICA 是需要作为 SaaS 平台的客户端的。而 SaaS 平台作为互联网应用,其用户数是非常多的。所以 VICA 也需要支持“三高”:高并发、高可用、高性能。 接口要求 VICA 是一个内部产品,不直接对外。它的直接使用者,其实是各产品线中的开发人员。所以我们需要一个可以适配各产品线的接口。 目前公司的产品基本都是 .NET 来进行研发的,而且 MIS 产品也不需要部署过多的服务或应用,所以 VICA 在服务端需要能提供 .NET SDK。 部署要求 VICA 的服务端程序有一定的部署要求: 在 SaaS 中需要可以独立部署、独立扩展; 在 MIS 中需要可以独立部署,也需要能够和 MIS 集成在一起部署。 简单 VICA 对于客户而言,一定要保持其简单性。理论上,使用者只需要下载安装运行后,就很快隐藏到托盘,没有过多功能。这样,一是越是简单的功能,越不容易出错,需要更新的频率也就大大降低了。二是对于客户来说功能越少越好,这样不但易用,而且客户更加不易感知客户端的存在,这样他们更加注重浏览器端的配套的功能。 静默 由于在一些场景下,VICA 是运行在长期无人值守的开票机上,所以 VICA 中的所有功能,都应该是尽量不需要与用户交互的。 自动升级 作为一个客户端,自动升级的功能是必不可少的。这是该软件能逐渐成长的基础。 对于自动升级,我们要求在服务端能控制所有客户端是否需要强制升级,并支持静默升级。 技术选型 客户端技术选型 客户端选型比较简单,当前我们的队伍中只有 .NET 和 JAVA 人员。而在客户端开发方面,.NET 要更加方便一些。另外,我们需要支持 XP 以上的系统,所以我们选择了 .NET 4.0 版本,该版本可以支持 XP SP3 以上的系统。另外,为了方便后期做出更加美观的界面,所以我们选择了 WPF 界面技术。 服务端技术选型 服务端实现实时通信的框架中,Node 以高性能著称,我及团队内部一些同事也都有 Node 的开发经验。但是最终我们还是决定使用 .NET 平台以及一些开源组件来开发一套自己的高性能实时通信框架。原因如下: 我们需要将 VICA 服务端与 MIS 系统集成部署。 需要易用的 NET SDK。 我们的客户端是基于 Socket 连接,而非 WebSocket。所以二者皆可。 Node 的高性能主要依赖于其单线程、异步非阻塞模式:“为了能适应高并发的情况(成千上万的连接),你的服务器需要采用异步非阻塞模式。你可能已经在IO操作中实现了这种方式。但问题是,如果你的服务器代码的任何部分可能产生阻塞,你都需要开启一个线程。在这种级别的并发下,你不能去为每个连接创建线程。所以整个代码路径都需要异步非阻塞式的, 不仅仅在输入输出层。”。所以,我们需要在 VICA 服务端代码中,所有会造成线程阻塞的代码,都需要使用异步接口(如 IO 操作、MQ 的访问、远程服务的调用等)。 物理视图 上图以 VICA 在电子票应用中集成部署的场景,示例了物理部署后的重要组件: 浅黄色的两个组件,就是 VICA 平台。 浅绿色的组件,是基于 VICA 平台编写的插件。上图中,该插件完成了电子票的开票功能。 橙色部分,是电子票应用的业务相关组件。 逻辑视图 上图是 VICA 中的逻辑视图,描述 VICA 平台所提供的功能,以及客户端、服务端集成 VICA 时的调用关系。 Server:服务端; DBEN.EI:电子票相关的业务组件。 DBEN.VICA.Server:VICA 在服务器端的一些基础组件。以 SDK 的形式提供给开发者。 WPFClient:WPF 客户端; DBEN.VICA.ClientUI:客户端 UI 壳。 DBEN.VICA.Client:客户端一些通用功能类库。 DBEN.VICA.InvPlugin.UI:开票相关的界面插件,与 DBEN.VICA.InvPlugin 是配套的,不过这个插件只在客户端使用。 DBEN.VICA.InvPlugin:开票相关的业务插件,其中包含了发票相关的一些命令及逻辑。这个包会被客户端、服务端同时使用。 DBEN.VICA.Platform:VICA 平台所提供的功能。含:插件框架、通信框架、IOC容器、命令框架等基础组件,以及一些通用的内置命令,如登录命令。 通信框架 UML 图 通信框架是 VICA 中最核心的功能。 类图: 序列图: 命令框架 UML 图 命令框架在通信框架的基础上,使用命令模式,将客户端与服务端的通信、行为封装为易用的单个的命令,方便上层开发者对业务逻辑的封装、以及对通信框架的使用。 类图: 序列图: 小结 本篇是 VICA 架构设计的第一篇,只简单介绍了 VICA 的内部静态、动态结构,以及核心/基本功能的实现。 本文转自BloodyAngel博客园博客,原文链接:http://www.cnblogs.com/zgynhqf/p/5903907.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android Service的思考(1)

在Android框架中,Service是比较难以理解的一部分,傻蛋查阅了相关资料和经过一系列的代码测试,准备写一个系列文章,尝试着把Service由浅入深的梳理一遍,帮助大家更快的掌握Android Service。 首先我们先来看看怎么使用Service,然后再谈Android Service的内部机制。 在Android中Service的启动方式有两种,今天先发第一种。 Service的启动方式一: 启动:Context.startService(new Intent(context,xxx.class)); 停止:Context.stopService() ; 我画了一个Service启动的流程图,相信大家一看就懂。Activity通过Intent启动Service,如果Service还没有运行,则android先调用onCreate()然后调用onStart();如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次。 调用stopService就会触发Service的onDestroy()方法。 图片点击放大~ 傻蛋做了一个示例程序是一个音乐播放器,界面如下,功能很简单:播放、暂停、停止音乐、关闭Activity(这时Service仍然运行,继续播放音乐)、退出程序(停止音乐退出Activity)。 由于要控制Service的动作,傻蛋写了一个播放的通用类,这样以后还能用上,代码如下: ?[Copy to clipboard] Downloadzuiniuwang.java /** *MyMediaController.java *com.androidtest.service.mediaplayer * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-5-16Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.androidtest.service.mediaplayer; importjava.io.Serializable; importandroid.media.MediaPlayer; /** *ClassName:MyMediaController *Function:Mediaplayer的一个控制类,控制播放器的播放暂停停止等动作 *REASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-5-16 */ publicenumMyMediaControllerimplementsSerializable{ play{ @Override publicvoidexecute(){ if(mediaPlayer!=null&&!mediaPlayer.isPlaying()) mediaPlayer.start(); //TODOAuto-generatedmethodstub } }, pause{ @Override publicvoidexecute(){ //TODOAuto-generatedmethodstub if(mediaPlayer!=null&&mediaPlayer.isPlaying()){ mediaPlayer.pause(); } } }, stop{ @Override publicvoidexecute(){ //TODOAuto-generatedmethodstub if(mediaPlayer!=null){ mediaPlayer.stop(); try{ //在stop后如果要重新Start需要prepare一下 mediaPlayer.prepare(); //从头播放 mediaPlayer.seekTo(0); }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } } }; publicstaticMediaPlayermediaPlayer; publicabstractvoidexecute(); } 然后是控制播放的Activity ?[Copy to clipboard] Downloadzuiniuwang.java /** *MusicPlayer.java *com.androidtest.activity * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-5-15Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.androidtest.activity.musicplayer; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.util.Log; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importcom.androidtest.MyImageButton; importcom.androidtest.R; importcom.androidtest.service.mediaplayer.MyMediaController; importcom.androidtest.service.mediaplayer.NormalMusicService; /** *ClassName:MusicPlayerFunction:TODOADDFUNCTIONReason:TODOADDREASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-5-15 */ publicclassNormalMusicPlayerActivityextendsActivityimplementsOnClickListener{ privatestaticfinalStringTAG=NormalMusicPlayerActivity.class.getSimpleName(); privateIntentintent; @Override protectedvoidonCreate(BundlesavedInstanceState){ //TODOAuto-generatedmethodstub super.onCreate(savedInstanceState); this.setContentView(R.layout.music_player_layout); ButtonplayButton=(Button)this.findViewById(R.id.play); playButton.setOnClickListener(this); ButtonpauseButton=(Button)this.findViewById(R.id.pause); pauseButton.setOnClickListener(this); ButtonstopButton=(Button)this.findViewById(R.id.stop); stopButton.setOnClickListener(this); ButtoncloseActivityButton=(Button)this.findViewById(R.id.close); closeActivityButton.setOnClickListener(this); ButtonexitActivityButton=(Button)this.findViewById(R.id.exit); exitActivityButton.setOnClickListener(this); intent=newIntent("com.androidtest.service.mediaplayer.NormalMusicService"); } privatevoidplayAction(MyMediaControllerplayType){ Bundlebundle=newBundle(); bundle.putSerializable(NormalMusicService.INTENT_KEY,playType); intent.putExtras(bundle); NormalMusicPlayerActivity.this.startService(intent); } @Override publicvoidonClick(Viewview){ //TODOAuto-generatedmethodstub switch(view.getId()){ caseR.id.play: Log.d(TAG,"play......."); playAction(MyMediaController.play); break; caseR.id.pause: Log.d(TAG,"pause......."); playAction(MyMediaController.pause); break; caseR.id.stop: Log.d(TAG,"stop......."); playAction(MyMediaController.stop); break; caseR.id.close: Log.d(TAG,"close......."); this.finish(); break; caseR.id.exit: Log.d(TAG,"exit......."); stopService(intent); this.finish(); } } } 最后是Service类 ?[Copy to clipboard] Downloadzuiniuwang.java /** *MusicService.java *com.androidtest.service * *Function:TODO * *verdateauthor *────────────────────────────────── *2011-5-15Leon * *Copyright(c)2011,TNTAllRightsReserved. */ packagecom.androidtest.service.mediaplayer; importjava.io.Serializable; importandroid.app.Service; importandroid.content.Intent; importandroid.media.MediaPlayer; importandroid.os.IBinder; importandroid.util.Log; importcom.androidtest.R; /** *ClassName:MusicService *Function:TODOADDFUNCTION *Reason:TODOADDREASON * *@authorLeon *@version *@sinceVer1.1 *@Date2011-5-15 */ publicclassNormalMusicServiceextendsService{ privateStringTAG=NormalMusicService.class.getSimpleName(); privateMediaPlayermyMediaPlayer; publicstaticfinalStringINTENT_KEY="action"; @Override publicIBinderonBind(Intentarg0){ //TODOAuto-generatedmethodstub returnnull; } @Override publicvoidonCreate(){ //TODOAuto-generatedmethodstub Log.v(TAG,TAG+"onCreate()"); super.onCreate(); if(myMediaPlayer==null){ myMediaPlayer=MediaPlayer.create(this,R.raw.test); myMediaPlayer.setLooping(false); } } @Override publicvoidonStart(Intentintent,intstartId){ //TODOAuto-generatedmethodstub Log.v(TAG,TAG+"onStart()"); super.onStart(intent,startId); if(intent!=null){ MyMediaControllermediaControl=(MyMediaController)intent.getSerializableExtra(NormalMusicService.INTENT_KEY); mediaControl.mediaPlayer=myMediaPlayer; mediaControl.execute(); } } @Override publicvoidonDestroy(){ //TODOAuto-generatedmethodstub super.onDestroy(); Log.v(TAG,"onDestroy"); if(myMediaPlayer!=null){ myMediaPlayer.stop(); myMediaPlayer.release(); } } } 本文转自 最牛傻蛋 51CTO博客,原文链接:http://blog.51cto.com/zuiniuwang/718320,如需转载请自行联系原作者

优秀的个人博客,低调大师

Jenkins学习笔记 系列1

首先说下Jenkins能干什么?说下两个典型的应用场景。 Git/Repo + Gerrit + Jenkins 打造强大的Android持续集成环境。用户上传代码到Gerrit进行code review和入库,用户上传代码操作和入库都可以触发Jenkins获取代码进行自动构建。Jenkins也可以定时构建,构建结果可以通过邮件自动发 送给相关人员。当然用户提交代码到Gerrit时,Gerrit也会自动发邮件给具有代码检视权限的人员。 ##备注: repo介绍: Android使用Git作为代码管理工具,开发了Gerrit进行代码审核以便更好的对代码进行集中式管理,还开发了Repo命令行工具,对Git部分命令封装,将百多个Git库有效的进行组织。 Gerrit介绍: 一种免费、开放源代码的代码审查软件,使用网页界面。利用网页浏览器,同一个团队的软件程序员,可以相互审阅彼此修改后的程序代码,决定是否能够提交,退回或者继续修改。它使用Git作为底层版本控制系统。 关于git操作代码的一些操作: git add git commit 若需要将代码向本地仓库递交,则通过git add将文件加入索引区,再通过git commit方法可真正的将代码递交入库。 git push 若功能开发好后,需要将本地代码共享给项目组中的其他成员,若通过git push命令将本地已入库的代码向远程仓库合入 2. SVN/Git + Jenkins 以apk代码为例,Jenkins可以监测SVN/Git等代码配置库,一旦有人提交代码,就会自动获取代码进行构建,构建结果可以通过邮件在内的多种方式通知人员。 本文转自Tenderrain 51CTO博客,原文链接:http://blog.51cto.com/tenderrain/1597340,如需转载请自行联系原作者

优秀的个人博客,低调大师

.NET设计模式(1):开篇

.NET设计模式开篇 ——.NET设计模式系列之一 Terrylee , 2005 年 12 月 06 日 前言 加入 Design & Pattern团队 有几个月的时间了,惭愧的是从没有写过关于设计模式的随笔,得到wayfarer的同意,把企业库系列的随笔放在了团队的首页上。不是不想去写这样的随笔,也不是没有时间, 自己初学设计模式,去写设计模式的文章,有点班门弄斧的味道。园子里吕震宇老师的《设计模式系列》和 wayfarer 的《设计之道》堪称设计模式里的经典之作。可是正如 wafarer 所说的那样,受到发表欲的蛊惑,本着交流就是进步的想法,思考再三,还是决定写这样的随笔,来对设计模式做一些探索和总结,起名曰“探索设计模式”,有些言过其实,就当是记录自己学习设计模式的历程吧,不过还是希望能得到各位前辈的指点! 设计模式 设计模式是规则吗? 地上本没有路,走得人多了也就成了路。设计模式如同此理,它是经验的传承,并非体系;是被前人发现,经过总结形成了一套某一类问题的一般性解决方案,而不是被设计出来的定性规则;它不像算法那样可以照搬照用。 设计模式是架构吗? 架构和模式应该是一个属于相互涵盖的过程,但是总体来说架构更加关注的是所谓的High-Level Design,而模式关注的重点在于通过经验提取的“准则或指导方案”在设计中的应用,因此在不同层面考虑问题的时候就形成了不同问题域上的模式。模式的目标是,把共通问题中的不变部分和变化部分分离出来。不变的部分,就构成了模式,因此,模式是一个经验提取的“准则”,并且在一次一次的实践中得到验证,在不同的层次有不同的模式,小到语言实现,大到架构。在不同的层面上,模式提供不同层面的指导。 设计模式,软件的永恒之道? 这个问题没有答案,有的只是讨论,看一下一位前辈结合建筑学得出的几点心得吧: 和建筑结构一样,软件中亦有诸多的“内力”。和建筑设计一样,软件设计也应该努力疏解系统中的内力,使系统趋于稳定、有生气。一切的软件设计都应该由此出发。 任何系统都需要有变化,任何系统都会走向死亡。作为设计者,应该拥抱变化、利用变化,而不是逃避变化。 好的软件只能“产生”而不能“创造”,我们所能做的只是用一个相对好的过程,尽量使软件朝向好的方向发展。 需要设计模式吗? 答案是肯定的,但你需要确定的是模式的应用是否过度?我得承认,世界上有很多天才 的程序员,他可以在一段代码中包含 6 种设计模式,也可以不用模式而把设计做得很好。但 我们的目标是追求有效的设计,而设计模式可以为这个目标提供某种参考模型、设计方法。 我们不需要奉 GOF 的设计模式为圭臬,但合理的运用设计模式,才是正确的抉择。 很多人看过 GOF 的《 Design Patterns 》,对这 23 种模式也背得滚瓜烂熟。但重要的不是 你熟记了多少个模式的名称,关键还在于付诸实践的运用。为了有效地设计,而去熟悉某种 模式所花费的代价是值得的,因为很快你会在设计中发现这种模式真的很好,很多时候它令 得你的设计更加简单了。 其实在软件设计人员中,唾弃设计模式的可能很少,盲目夸大设计模式功用的反而更多。 言必谈“模式”,并不能使你成为优秀的架构师。真正出色的设计师,懂得判断运用模式的 时机。 还有一个问题是,很多才踏入软件设计领域的人员,往往对设计模式很困惑。对于他们 来说,由于没有项目的实际经验, OO 的思想也还未曾建立,设计模式未免过于高深了。其 实,即使是非常有经验的程序员,也不敢夸口对各种模式都能合理应用。[--摘自wayfare的设计之道] 后记 本文转自lihuijun51CTO博客,原文链接: http://blog.51cto.com/terrylee/67743 ,如需转载请自行联系原作者 关于设计模式的理论性的文章,已经写了很多了,我不想再继续重复抄写下去,仅记录下上面几段话,用它来作探索设计模式系列的一个开篇吧。[现已更名为.NET设计模式]

优秀的个人博客,低调大师

大型网站技术架构(1)

网站都是从小网站一步一步发展为大型网站的,而这之中的挑战主要来自于庞大的用户、安全环境恶劣、高并发的访问和海量的数据,任何简单的业务处理,一旦需要处理数以 P 计的数据和面对数以亿计的用户时,问题就会变的很棘手 下面我们就来说说这个演变过程: 初始阶段 大型网站都是由小型网站演变而来的,网站架构也一样 小型网站最开始没有太多人访问,只需要一台服务器就绰绰有余,就像这样: 应用程序、数据库、文件等所有资源都在一台服务器上,通常使用 Linux PHP MySQL Apache 就可以完成整个项目部署,然后再买个域名,租一个廉价的服务器就可以开始我们的网站之旅了 应用服务与数据服务分离 随着业务的发展,逐渐的一台服务器已经不能满足需求,这时我们可以将 应用与数据分离 分离之后我们使用到三台服务器:应用服务器、文件服务器和数据库服务器,如下所示: 对于这三台服务器要求各不相同: 应用服务器 要处理大量的业务逻辑,所以需要更好更快更强大的 CPU 数据库服务器 需要快速的进行磁盘检索和数据缓存,因此需要更快的硬盘和更大的内存 文件服务器 需要存储用户上传的文件资源,因此需要更大的硬盘存储空间 应用与数据分离后,各个的职责变得更加专一,网站的性能得到进一步的提升,但随着用户的继续增加,我们需要对网站架构进一步优化 使用缓存改善性能 网站的访问一样遵循二八定律:80% 的业务访问集中在 20% 的数据上面 因此我们要对这一小部分的数据进行缓存来减轻数据库的访问压力,以提高整个网站的数据访问速度,改善数据库的读写性能 网站的缓存可以分为两种:缓存在应用服务器上的本地缓存和缓存在专门的分布式缓存服务器上的远程缓存 本地缓存 的访问速度会快一些,但是受应用服务器内存限制,缓存数据量很有限,而且会出现内存争用的情况 远程分布式缓存 可以使用集群的方式,部署大内存的服务器作为专门的缓存服务器,可以在理论上做到不受内存容量限制的缓存服务 如下所示: 使用缓存后,数据访问压力得到了有效的缓解,但单一的应用服务器能够处理的请求连接数有限,在访问的高峰期,应用服务器又会成为网站性能的瓶颈 使用应用服务器集群改善网站并发处理能力 使用集群是网站解决高并发,海量数据问题的常用手段,当你纵向提升到一定程度后,那就该开始横向提升了 当一台服务器的处理能力不足时,与其换一台更强大的服务器,不如增加一台服务器去分担原有的服务器压力。对于大型网站而言,无论多么强大的服务器,都满足不了持续增长的业务需求,更高效的方式就是增加服务器来分担压力 对于网站架构而言,如果增添一台新的服务器可以改善负载压力,那么就可以使用同样的方式来应对源源不断的业务需求,从而实现系统的可伸缩性 通过负载均衡调度服务器,可以将用户请求分发到应用服务器集群里的任何一台服务器上,如果有更多的用户,可以增加更多的应用服务器,使应用服务器的负载压力不再成为网站的性能问题 数据库读写分离 在使用了缓存后,大多数的操作不经过数据库访问就能完成,但仍有一部分读操作(缓存访问未命中,缓存过期)和所有的写操作需要访问数据库,在网站的用户量达到一定时,数据库的负载问题就来了 目前大多数的数据库都支持主从热备份,通过配置两台服务器的主从关系,可以将一台数据库服务器的数据更新同步到另一台,网站利用这一功能,实现数据库读写分离,从而进一步改善数据库负载压力 应用服务器在写操作的时候,访问主数据库,主数据库通过主从复制机制把数据同步更新到从数据库,这样当应用服务器进行读操作的时候,就能访问从数据库获取数据 使用反向代理和 CDN 加速网站响应 CDN 和 反向代理 的基本原理都是缓存 CDN 部署在网络供应商的机房,用户在进行请求时,会从距离最近的网络供应商机房获取数据 反向代理 则部署在中心机房,当用户请求到达中心机房后,会首先访问反向代理服务器,如果反向代理服务器中缓存这用户请求的资源,就直接返回给用户 使用 CDN 和 反向代理 都是为了尽快返回给用户数据,一方面加快用户访问速度,另一方面也减轻了后端服务器的压力 使用分布式文件系统和分布式数据库系统 随着网站业务的继续发展,这时候就可以像分布式应用服务器一样,对数据库系统和文件系统进行分布式管理 分布式数据库 是网站数据库拆分的最后手段,一般我们可以采取业务分库,根据不同业务的数据库部署在不同的数据库服务器上 使用 NoSQL 和搜索引擎 这两个方式都是依赖于互联网的技术手段,应用服务器通过一个统一的数据访问模块来访问各种数据,从而减轻应用程序有多个数据源的麻烦 业务拆分 对于大型网站,我们可以分而治之,把整个网站的业务分为不同的模块,比如大型的交易购物完整可以分为首页、店铺、订单、买家等,分别交给不同的业务团队来负责 同时我们将一个网站根据模块划分拆分成多个应用,每个应用进行单独的部署和维护,应用之间通过超链接建立关系(指向不同的应用地址),最后通过相同的数据存储系统来构成一个互相关联的完整系统 分布式服务 随着业务拆分,整个系统越来越大,应用的整体复杂度呈指数级增加,部署维护越来越困难,并且所有的应用服务器都要与数据库服务连接, 在数万台服务器规模的情况下,这些连接的数目是服务器规模的平方,导致资源不足 这时候就要对相同的业务进行提取,独立部署,把这些可重用的业务和连接数据库等,提取出来作为公共业务服务,而应用系统只需要通过分布式服务访问公共业务服务完成业务操作 到这里,基本上大多数的技术问题都能得到解决,还有一些实时同步等具体业务问题也都可以通过现有的技术解决 作者:arno_好久不见 来源:51CTO

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册