首页 文章 精选 留言 我的

精选列表

搜索[基础搭建],共10000篇文章
优秀的个人博客,低调大师

视频服务降价34%,基础设施降价25%,阿里云北京云栖大会再次释放技术红利

12月20日,在2017云栖大会·北京分会上,阿里云宣布将进一步释放科技带来的普惠红利,用更低的价格,更智能的产品,推动中国企业的数字化进程,阿里云认为,只有充分的将技术红利释放给企业,才能与企业一起共创云时代的未来。 本次降价涵盖了视频,ECS企业级实例。 据悉,所有的降价调整都已经生效,用户可以随时在官网以新的价格购买阿里云产品。 阿里云宣布,视频产品最高降价34%,包括视频点播,直播的流量及带宽价格。 随着社交媒体、网络直播、VR、AR的兴起,用户对于视频的多元化、场景化、临场感、体验的追求更加极致,而阿里云在视频领域独有的创新技术,帮助企业能够实现更好的视频体验,提供一站式视频点播、直播服务,集内容采集、上传加速、存储录制、码转/截图/水印、鉴黄服务、以及美颜等功能。 独有的窄带高清技术,能够帮助用户在同等的清晰度下,最高节省30%

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

虚拟化基础架构Windows 2008篇之11-WSUS服务器的安装与配置

无论是数据中心还是在企业网络中,大多数Windows操作系统都要及时地更新补丁。对于家庭用户来说,或者对于大多数的企业用户来说,习惯于从Windows Update站点在线升级,或者使用第三方的工具(例如360)从Microsoft站点下载升级(360本身不提供补丁及镜像)。但是,当网络中的服务器及工作站数量较多,并且产品较多时,都从Microsoft网站升级,一是速度慢,二是会占用大量的互联网带宽。另外,尤其是在云计算的数据中心,配置新的虚拟服务器是很简单、容易的事情,例如配置一台虚拟机只需要2、3分钟甚至更短的时间,但更新补丁可能会需要几十分钟甚至更长的时间,而其中补丁下载也会占用比较长的时间。 本章介绍Microsoft系统更新服务—WSUS,介绍怎样在数据中心或企业网络中部署升级服务器,为数据中心或企业网络提供快速的补丁更新服务。在Windows Server 2008之前,WSUS是一个产品,需要从Microsoft网站下载,而从Windows Server 2008之后的服务器操作系统中已经集成了这个产品(实际上是一个链接,在添加该服务的时候安装程序会从Microsoft网站下载最新的安装程序)。下面将开始介绍WSUS的系统需求、安装配置以及使用。 3.1 WSUS 3.0概述与系统需求 WSUS是Windows Server Update Services的简称,是微软推出的网络化补丁分发方案。通过WSUS,可以集中下载所有的微软产品更新,使客户端可以从WSUS服务器快速、方便地下载所需要的更新,而不必连接到微软网站去下载,从而节省带宽、提高效率。WSUS服务器的特点如下: · WSUS是一款免费产品,由微软推出,产品的安全性、兼容性毋庸置疑。 · WSUS对计算机的要求不多,只要有足够的硬盘空间即可。 · WSUS支持Microsoft众多的操作系统、应用程序与服务器类产品,例如Windows XP、Windows Server 2003、Windows 7、Windows Server 2008、Office XP、Office 2003、Office 2007、SQL Server、Exchange等。 · WSUS服务器不需要加入到“域”,只要是网络内的一台服务器即可。 客户端采用WSUS服务器进行补丁的升级与管理工作,不需要对客户端做过多复杂的设置。如果是域中的工作站,可以用“组策略”统一设置。所有加入到域的计算机都可以自动从WSUS服务器升级。没有加入到域的计算机,可以通过导入注册表文件完成设置。 通常情况下,Windows操作系统从Microsoft Update站点或者其他合作站点下载Microsoft产品的补丁(见图3-1),然后手动安装。家庭用户或者中小企业用户大多使用这种方式。但是,如果网络规模较大,计算机数量较多,就会占用大量的网络带宽,从而影响其他的网络应用。另外,Windows补丁并不是一起发布的,可能每隔一段时间发布几次补丁,如果手动下载更新,就会占用管理员和用户很多时间。 图3-1 普通用户升级方式 WSUS是企业内部的升级服务器,它可以从Microsoft Update站点下载所有的Microsoft更新,而工作站则从WSUS服务器升级(见图3-2),这样不仅大大减少了带宽的占用,并且可以管理工作站使其“自动”升级。 图3-2 WSUS体系结构 如果企业网络规模比较大,采用一台WSUS服务器不能满足需要,可以采用“多级”WSUS的体系结构,即为不同网络配置“下游”WSUS服务器,从“上游”WSUS服务器下载更新,而“上游”WSUS服务器直接从Microsoft Update站点下载更新,如图3-3所示。 图3-3 多级WSUS体系结构 3.2 WSUS 3.0的安装与配置 WSUS 3.0 SP1安装程序可以从如下站点下载: http://www.microsoft.com/downloads/zh-cn/details.aspx?familyid=f87b4c5e-4161-48af-9ff8-a96993c688df&displaylang=zh-cn 在下载的时候,文件名为WSUSSetup_30SP1_x64.exe是64位版本,文件名为WSUSSetup_30SP1_x86.exe是32位版本,请根据服务器操作系统的产品选择合适的版本。 【说明】在做这个实验的时候,由于WSUS服务器需要从Microsoft的网站下载更新,所以,请保证Windows 2008虚拟机可以访问Internet,用户需要根据自己的网站情况,在虚拟机中设置IP地址及DNS。 3.2.1 安装WSUS服务器 WSUS服务器需要IIS与Microsoft .NET Framework 3.0的支持。如果要安装WSUS服务器,首先需要安装IIS,主要步骤如下: (1)在“服务器管理器”对话框中添加“功能”,在“选择功能”对话框中选中“.Net Framework 3.0功能”复选框,如图3-4所示。 图3-4 添加.Net Framework功能 (2)在安装完.Net Framework后,添加“角色”,安装IIS服务,至少要选择“静态内容”、ASP.NET、“6.0 管理兼容性”、“Windows 身份验证”服务,如图3-5所示。 图3-5 安装IIS及其相关角色 在安装完.NET Framework与IIS服务之后,就可以安装WSUS 3.0 SP1了,主要步骤如下: (1)运行WSUS 3.0 SP1的安装程序,进入WSUS 3.0 SP1的安装向导,如图3-6所示。 (2)在“安装模式选择”对话框中,选择“包括管理控制台的完整服务器安装”单选按钮,然后单击“下一步”按钮,如图3-7所示。 图3-6 WSUS安装向导 图3-7 安装模式选择 (3)在“许可协议”对话框中选择“我接受许可协议条款”单选按钮,然后单击“下一步”按钮,如图3-8所示。 (4)在“使用管理UI所需的组件”对话框中,单击“下一步”按钮,如图3-9所示。 (5)在“选择更新源”对话框中,选择保存WSUS更新文件的位置。在默认情况下,安装程序会自动选择一个空间最大的分区,并且保存在WSUS文件夹中,如图3-10所示。 (6)在“数据库选项”对话框中,选择保存WSUS 3.0数据库的文件位置,如图3-11所示。 图3-8 “许可协议”对话框 图3-9 使用管理UI所需的组件 图3-10 “选择更新源”对话框 图3-11 “数据库选项”对话框 (7)在“网站选择”对话框中,指定用于WSUS 3.0服务的网站。如果安装WSUS 3.0的服务器不用做其他用途,可以选择“使用现有IIS默认网站”单选按钮,这样,所有的WSUS客户端将使用TCP的80端口访问和更新补丁,如图3-12所示。如果安装WSUS 3.0的服务器的IIS默认网站有其他用途,可以选择“创建Windows Server Update Services 3.0 SP1网站”单选按钮,这样,所有WSUS客户端将使用TCP的8530端口访问和更新补丁,如图3-13所示。推荐选择后者,为WSUS服务器创建单独的管理网站。 图3-12 选择默认 图3-13 创建网站 (8)在“准备安装Windows Server Update Services 3.0 SP1”对话框中显示了安装信息,单击“下一步”按钮继续,如图3-14所示。 (9)在“正在完成Windows Server Update Services 3.0 SP1安装向导”对话框中,单击“完成”按钮,完成安装如图3-15所示。 图3-14 显示安装信息 图3-15 安装完成 3.2.2 WSUS 3.0的配置向导 在完成WSUS安装之后,首先会进入“Windows Server Update Services配置向导”对话框,接下来将介绍WSUS服务器端的配置,步骤如下: (1)在图3-15中单击“完成”按钮后弹出“Windows Server Update Services配置向导”对话框,“在您开始之前”页中单击“下一步”按钮,如图3-16所示。 (2)在“加入Microsoft Update改善计划”对话框中,根据需要选择是否加入Microsoft Update改善计划,如图3-17所示。 图3-16 配置向导 图3-17 加入Microsoft Update改善计划 不管是否加入“Microsoft Update改善计划”,都不影响WSUS 3.0的使用(本例中加入了Microsoft Update改善计划)。 (3)在“选择‘上游服务器’”对话框中,选择当前WSUS服务器从中同步的“上游”服务器。如果这是网络中的一台WSUS服务器,请选择“从Microsoft Update进行同步”单选按钮,如图3-18所示。如果网络中已经存在“上游WSUS服务器”,请选择“从其他Windows Server Update Services服务器进行同步”单选按钮,并且在“服务器名”文本框中输入上游WSUS服务器的IP地址或计算机名,在“端口号”文本框中输入上游WSUS服务器的端口号,如图3-19所示(本例中采用的是从Microsoft Update进行同步) 图3-18 从Microsoft Update进行同步 图3-19 从其他服务器同步 (4)在“指定代理服务器”对话框中,设置当前WSUS服务器访问Internet的方式。如果当前计算机需要使用代理服务器访问Microsoft Update(或者WSUS上游服务器),请选中“在同步时使用代理服务器”复选框并且正确设置代理服务器的参数;如果当前计算机不需要代理服务器,请保持默认值,如图3-20所示(本例中未采用代理服务器)。 (5)在“连接到上游服务器”对话框中,单击“开始连接”按钮,当前WSUS服务器将从Microsoft Update(选择图3-21所示的设置)或者上游服务器获得更新信息。 图3-20 指定代理服务器 图3-21 连接Microsoft Update 连接完成后,单击“下一步”按钮。 (6)在“选择‘语言’”对话框中,选择所需语言(默认情况下,选择当前服务器使用的语言,本例为“中文-简体”),如图3-22所示。如果当前WSUS服务器是从“上游”WSUS服务器更新,将显示“下载上游服务器支持的所有语言的更新”或“仅下载这些语言的更新(上游服务器只支持标有星号的语言)”;如果当前WSUS服务器是从“Microsoft Update更新”,将显示“下载包括新语言在内的所有语言的更新”或“仅下载这些语言的更新”。通常情况下,只让WSUS下载与WSUS服务器相同语言的更新即可。 (7)在“选择‘产品’”对话框中,选择当前WSUS服务器将要下载的产品更新。对于管理员来说,可以根据自己所管理的网络中安装的Microsoft操作系统、Server、应用程序等进行选择。在本例中,因为是实验的管理,只选择Virtual PC,如图3-23所示。 图3-22 选择语言 图3-23 选择产品 【说明】在安装完WSUS之后,可以随时根据需要增加或减少选择更新的Microsoft产品。 (8)在“选择‘分类’”对话框中,指定要同步的更新分类,如图3-24所示。 (9)在“设置同步计划”对话框中,选择“自动同步”单选按钮,设定当前WSUS服务器与上游WSUS服务器同步的方式与同步的时间。通常情况下,请选择网络空闲的时间,例如每天的午夜,如图3-25所示。 图3-24 选择产品分类 图3-25 设定同步时间 (10)在“完成”对话框中,选中“启动Windows Server Update Services管理控制台”复选框,取消选中“开始初始同步”复选框,如图3-26所示。 (11)在“后续步骤”对话框中,单击“完成”按钮,完成WSUS的安装,如图3-27所示。 图3-26 “完成”对话框 图3-27 完成WSUS的安装 服务器端的WSUS升级服务器的安装与配置已基本完成,下面将介绍客户端的安装与配置。 3.2.3 配置WSUS服务器 为了让WSUS服务器“完全自动”从Microsoft的更新服务器获得更新并自动审批,或者想要修改WSUS的更新配置,可以按照如下的步骤进行: (1)从“管理工具”中执行Microsoft Windows Server Update Services 3.0 SP1,进入WSUS管理控制台,在左侧的窗格中选择“选项”,在右侧可以对WSUS服务器进行配置。单击“自动审批”链接,如图3-28所示。 图3-28 自动审批 (2)在“自动审批”对话框中,单击“安全更新程序、关键更新程序”链接(见图3-29),在弹出的“选择‘更新分类’”对话框中选择“所有分类”,如图3-30所示。 图3-29 修改自动审批 图3-30 选择所有分类 设置之后,单击“确定”按钮,返回到WSUS管理控制台。这样,以后当WSUS服务器上游“更新服务器”或“Microsoft更新服务器”有更新时,WSUS服务器将完成“自动审批”的工作。 (3)返回到WSUS管理控制台后,单击“更新文件和语言”链接,如图3-31所示。 图3-31 更新文件和语言 (4)打开“更新文件和语言”对话框,在“更新文件”选项卡中选中“下载快速安装文件”复选框,如图3-32所示。如果要修改更新语言,可以在“更新语言”选项卡中修改,如图3-33所示。 图3-32 下载快速安装文件 图3-33 更新语言 (5)返回到WSUS管理控制台后,单击“产品和分类”链接,打开“产品和分类”对话框,可以在“产品”选项卡中指定要同步更新的产品,如图3-34所示,在“分类”选项卡中指定要同步的更新分类,如图3-35所示。 图3-34 更新产品 图3-35 更新分类 (6)设置之后,在左侧任务窗格中单击服务器计算机名,在右侧单击“立即同步”链接,WSUS服务器将开始从Microsoft更新服务器检索可用的更新并自动下载,如图3-36所示。在“同步状态”中显示了同步状态,在“下载状态”中显示了当前需要下载的文件更新数量、已下载更新大小、一共需要下载的更新大小,同时在“连接”中显示了当前WSUS服务器的更新端口、服务器版本等。 本文转自 dengaosky 51CTO博客,原文链接:http://blog.51cto.com/dengaosky/1861557,如需转载请自行联系原作者

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

分布式消息队列中间件系列研究之阿堂教程(基础篇-Local模式)

为了考虑web架构的伸缩性,扩展性及重用性,目前许多大型门户网站及大平台,如淘宝网,天猫网,京东商城,当当网,及腾讯,Facebook等电商或社交网站,均大量采用中间件的设计,中间件又细分为业务流中间件,服务中间件,消息队列中间件,缓存中间件,数据库中间件,可以这样说,中间件在整个web架构设计中占有十分重要的地位,中间件设计的好坏直接影响到大型门户网站架构水平的高低和优劣。由于时间和精力的关系,这里阿堂主要是分享下对消息队列中间件的应用认识和理解。 消息中间件在web分布式架构设计及性能优化方面有着非常重要的地位,目前,在很多大型网门户网站和商业大平台都有及为广泛的应用,如淘宝网,天猫网,京东商城,当当网,及腾讯,Facebook等电商或社交网站,都在大量使用。常见的开源消息中间件有mom4j,OpenJMS,UBerMQ,Hermes JMS, Presumo,JORAM,JMS4Spread,Open Message Queue,FFMQ,MQSSave/MQSLoad,HornetQ,Apache Qpid,Spring AMQP,Kafka,play-rabbitmq,队列消息系统 FQueue,ActiveMQ,Somnifugi ,MantaRay,MetaQ等。关于它们的差异和作用,在网上有相应的介绍,这里阿堂就不再说明了。有兴趣的网友们可以自行去研究。 今天阿堂,主要和大家分享研究的是对Metaq这款分布式消息中间件的应用。 MetaQ(全称Metamorphosis)是一个高性能、高可用、可扩展的分布式消息中间件,思路起源于LinkedIn的Kafka,但并不是Kafka的一个Copy。MetaQ具有消息存储顺序写、吞吐量大和支持本地和XA事务等特性,适用于大吞吐量、顺序消息、广播和日志数据传输等场景,目前在淘宝和支付宝有着广泛的应用。 MetaQ是一款完全的队列模型消息中间件,服务器使用Java语言编写,可在多种软硬件平台上部署。客户端支持Java、C++编程语言。单台服务器可支持1万以上个消息队列,通过扩容服务器,队列数几乎可任意横向扩展。每个队列都是持久化、长度无限(取决于磁盘空间大小)、并且可从队列任意位置开始消费。 它具有的优势如下 (1)文本协议设计,非常透明,支持类似memcached stats的协议来监控broker。 (2)纯Java实现,从通讯到存储,从client到server都是重新实现。 (3)提供事务支持,包括本地事务和XA分布式事务。 (4)支持HA复制,包括异步复制和同步复制,保证消息的可靠性。 (5)支持异步发送消息。 (6)消费消息失败,支持本地恢复。 (7)多种offset存储支持,数据库、磁盘、zookeeper,可自定义实现。 (8)支持group commit,提升数据可靠性和吞吐量。(目前kafka已实现) (9)支持消息广播模式。 (10)一系列配套项目:Python/Ruby/C/C++客户端、Twitter Storm的Spout、Tail4j等。 关于消息队列应用的场景,实际上在商业应用中很多网站都在大量应用。阿堂这里随更举几个例子,大家就明白了。12306铁路购票网站,想必大家耳熟能详,去年及以前由于12306网站架构设计不好,经常出现网站并发访问量大时出现网站崩溃,提示服务出错或者说网站根本登录不进去,或者说抢到票时提交没有反应了。今年12306抢票网站就采用“消息队列中间件”来重构了12306网站,采用消息队列的排队机制,抢票时会提示“只有多少张票,目前已经有多少人在排队抢购了,票源不足”,比如说某车次只有10张票了,你前面已经有11人排队抢票了,当然输到你时就没有票了。这样一方面可以缓冲瞬时大量的高并发访问购票,二来对用户来说体验也比较好,因为人家是在你前面排队了,先来先得嘛。还有小米官网抢购手机时,也是用的这种“消息队列中间件”设计,先抢先得。还有一些电商平台的“秒杀抢购”,都是在使用“消息队列中间件”来设计的web架构,这样就可以解决瞬时涌入的大量高并发访问造成的网站压力。看到上面阿堂的举例,大家应该对“消息队列中间件”在大型网站中的重要性有了一个比较感官的认识了。 为了了解MetaQ的使用,下面让我们先要了解和理解其中的一些重要概念解释。 消息生产者 也称为Message Producer,一般简称为producer,负责产生消息并发送消息到meta服务器。消息消费者 也称为Message Consumer,一般简称为consumer,负责消息的消费,meta采用pull模型,由消费者主动从meta服务器拉取数据并解析成消息并消费。Topic 消息的主题,由用户定义并在服务端配置。producer发送消息到某个topic下,consumer从某个topic下消费消息。分区(partition) 同一个topic下面还分为多个分区,如meta-test这个topic我们可以分为10个分区,分别有两台服务器提供,那么可能每台服务器提供5个分区,假设服务器id分别为0和1,则所有分区为0-0、0-1、0-2、0-3、0-4、1-0、1-1、1-2、1-3、1-4。 分区跟消费者的负载均衡机制有很大关系,具体见集群和负载均衡。Message消息,负载用户数据并在生产者、服务端和消费者之间传输。Broker就是meta的服务端或者说服务器,在消息中间件中也通常称为broker。消费者分组(Group) 消费者可以是多个消费者共同消费一个topic下的消息,每个消费者消费部分消息。这些消费者就组成一个分组,拥有同一个分组名称,通常也称为消费者集群Offset 消息在broker上的每个分区都是组织成一个文件列表,消费者拉取数据需要知道数据在文件中的偏移量,这个偏移量就是所谓offset。Offset是绝对偏移量,服务器会将offset转化为具体文件的相对偏移量。详细内容参见#消息的存储结构 为了说明metaq的使用,阿堂附上一个测试demo与大家分享,关于集群模式,阿堂会在下篇文章中继续分享 下面是阿堂在Local单机模式的测试效果图 1.安装,启动zookeeper 2.安装启动metaq服务器 3.在myeclipse编写代码测试 测试代码如下 public class Productor { public static void main(String[] args) throws Exception { final MetaClientConfig metaClientConfig = new MetaClientConfig(); final ZKConfig zkConfig = new ZKConfig(); zkConfig.zkConnect = "192.168.1.101:2181"; metaClientConfig.setZkConfig(zkConfig); MessageProducer producer = sessionFactory.createProducer(); final String topic = "test"; producer.publish(topic); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String line = "网络时空(阿堂)"; while ((line = reader.readLine()) != null) { // send message SendResult sendResult = producer.sendMessage(new Message(topic, line.getBytes())); // check result if (!sendResult.isSuccess()) { System.err.println("Send message failed,error message:" + sendResult.getErrorMessage()); } else { System.out.println("Send message successfully,sent to " + sendResult.getPartition()); //System.out.println("分区="+sendResult.getPartition().getPartition()); //System.out.println("broker="+sendResult.getPartition().getBrokerId()); } } } } --------------------------------------------------------------- public class Consumer { public static void main(String[] args) throws Exception { final MetaClientConfig metaClientConfig = new MetaClientConfig(); final ZKConfig zkConfig = new ZKConfig(); zkConfig.zkConnect = "192.168.1.101:2181"; metaClientConfig.setZkConfig(zkConfig); MessageSessionFactory sessionFactory = new MetaMessageSessionFactory(metaClientConfig); final String topic = "test"; final String group = "meta-example"; MessageConsumer consumer = sessionFactory.createConsumer(new ConsumerConfig(group)); consumer.subscribe(topic, 1024 * 100, new MessageListener() { public void recieveMessages(Message message) { System.out.println("Receive message " + new String(message.getData())); //System.out.println("分区 = "+message.getPartition().getPartition()); //System.out.println("broker = "+message.getPartition().getBrokerId()); } public Executor getExecutor() { return null; } }); consumer.completeSubscribe(); } } 本文转自 www19 51CTO博客,原文链接:http://blog.51cto.com/doujh/1715274,如需转载请自行联系原作者

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

面向服务体系架构的业务规划和建模方法系列之二--基础概念辨析

现将这些比较有价值的资料分享出来,希望给搞SOA的同行一个系统的参考。PDF格式,可在文后点击“附件下载”阅读全文。 本篇内容简介及部分截图: ◇服务 ◇体系结构 ◇治理 ◇生命周期 ◇业务 ◇业务流程 ◇RUP及软件开发流程和方法 ◇模型、UML、资产与模式 附件:http://down.51cto.com/data/2352581 本文转自肖勇51CTO博客,原文链接http://blog.51cto.com/xiaoyong/156265:,如需转载请自行联系原作者

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

【读书笔记《Android游戏编程之从零开始》】10.游戏开发基础(View 游戏框架)

对于玩家来说,游戏是动态的;对于游戏开发人员来说,游戏是静态的,只是不停地播放不通的画面,让玩家看到了动态的效果。 进入Android之前,首先要熟悉三个重要的类:View(视图)、Canvas(画布)、Paint(画笔)。通过画笔,可以在画布上画出各种精彩的图形、图片等等,然后通过视图可以将画布上的内容展现在手机屏幕上。 其次要熟悉“刷屏”的概念。绘制在画布中的图像不管是图片还是图形,都是静态的,只有通过不断的展现不同的画布,才能实现动态的效果。在手机上,画布永远只是一张,所以不可能通过不断地播放不同的画布来实现动态效果,这时就需要对画布进行刷新来实现动态效果。 刷新画布如同使用一块橡皮擦,擦去之前画布上的所有内容,然后重新绘制画布,如此反复,形成动态效果,而擦拭画布的过程则称为刷屏(刷新屏幕)。 Android 游戏开发中常用的三种视图是 View 、 SurfaceView 和 GLSurfaceView 。下面简单介绍下这三种视图的含义: View :显示视图,内置画布,提供图形绘制函数、触屏事件、按键事件函数等; SurfaceView :基于 View 视图进行拓展的视图类,更适用于 2D 游戏开发; GLSurfaceView : 基于 SurfaceView 视图再次进行拓展的视图类,专用于 3D 游戏开发的视图。View 游戏框架实例 1.实例效果如下: 1.步骤 新建一个项目 GameView,创建完毕后首先自定义一个视图类 “MyView” 继承 View 类,代码如下: package com.example.ex4_4; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; public class MyView extends View { private int textX=20,textY=20; /** * 重写父类构造函数 * @param context */ public MyView(Context context) { super(context); //设置焦点 setFocusable(true); } /*** * 重写按键按下事件 * @param keyCode 当前用户点击的按键 * @param event 按键的动作事件队列,此类还定义了很多静态常量键值 */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { //判定用户按下的键值是否方向键的"上下左右"键 if(keyCode==KeyEvent.KEYCODE_DPAD_UP) { //"上"按键被点击,应该让文本的Y坐标变小 textY-=2; }else if(keyCode==KeyEvent.KEYCODE_DPAD_DOWN) { //"下"按键被点击,应该让文本的Y坐标变大 textY+=2; }else if(keyCode==KeyEvent.KEYCODE_DPAD_LEFT) { //"左"按键被点击,应该让文本的X坐标变小 textX-=2; }else if(keyCode==KeyEvent.KEYCODE_DPAD_RIGHT) { //"右"按键被点击,应该让文本的X坐标变大 textX+=2; } return super.onKeyDown(keyCode, event); } /** * 重写按键抬起事件 */ @Override public boolean onKeyUp(int keyCode, KeyEvent event) { //invalidate();不能在当前子线程中循环调用执行 //postInvalidate(); 可以在子线程中循环调用执行 invalidate();//重新绘制画布 return super.onKeyUp(keyCode, event); } /** * 重写触屏事件函数 */ @Override public boolean onTouchEvent(MotionEvent event) { //获取用户手指触屏的X坐标赋值与文本的X坐标 int x = (int)event.getX(); //获取用户手指触屏的Y坐标赋值与文本的Y坐标 int y = (int)event.getY(); textX=x; textY=y; //重绘画布 invalidate(); return true; } /** * 重写父类绘图函数 */ @Override protected void onDraw(Canvas canvas) { //创建一个画笔实例 Paint paint = new Paint(); //设置画笔颜色 paint.setColor(Color.WHITE); //设置画笔文本大小 paint.setTextSize(18); //绘制文本 canvas.drawText("Hi,你好!", textX, textY, paint); super.onDraw(canvas); } } 修改MainActivity类,显示绘制的View public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MyView(this)); } } 修改配置文件,设置应用程序为全屏,这里设置主题为黑色背景并隐去了状态栏和应用标题 android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" 具体可以看代码。其实就是继承View类,然后重写父类的方法。 本文转自叶超Luka博客园博客,原文链接:http://www.cnblogs.com/yc-755909659/p/4143352.html,如需转载请自行联系原作者

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

【读书笔记《Android游戏编程之从零开始》】20.游戏开发基础(游戏数据存储)

对于数据的存储,Android 提供了4种保存方式。 (1)SharedPreference 此方法适用于简单数据的保持,文如其名,属于配置性质的保存,不适合比较大的情况,默认存放在手机内存里 (2)FileInputStream/FileOutputStream 此方式比较适合游戏的保存和使用,流文件数据存储可以保持较大的数据,而且通过此方式不仅能把数据存储在手机内存中,也能将数据保存到手机额SDcard中。 (3)SQLite 此方式也适合游戏的保存和使用,不仅可以保存较大的数据,而且可以将自己的数据存储到文件系统或者数据库当中,如SQLite数据库,也能将数据保存到SDcard 中。 (4)ContentProvider 此方式不推荐用于游戏保存,虽然此方式能存储较大数据,还支持多个程序之间的数据进行交换,但游戏中基本就不可能去访问外部应用程序的数据。 1.SharedPreference SharedPreference 实例是通过Context 对象得到的: Context.getSharePreference(String name,int mode) 作用:利用Context 对象获取一个SharedPreference 实例 参数1:生成保持记录的文件名 参数2:操作模式 SharedPreference 实例的操作模式一共有四种: Context.MODE_PRIVATE:新内容覆盖原内容。 Context.MODE_APPEND:新内容追加到原内容后。 Context.MODE_WORLD_READABLE:允许其他应用程序读取。 Context.MODE_WORLD_WRITEABLE:允许其他应用程序写入,会覆盖原数据。 SharedPreference 常用函数: getFloat(String key,float defValue) getInt(String key,int defValue) getLong(String key,long defValue) getString(String key,String defValue) getBoolean(String key,boolean defValue) SharedPreference 常用函数的作用是获取存储文件中的值,根据方法不同获取不同对应的类型值,一般第一个参数为索引Key值,第二个参数为在存储文件中找不到对应 value 值时,默认的返回值。 对应的,在对存储文件的数据进行存入操作时,首先需要利用 SharedPreference 实例得到一个编辑对象: SharedPreference.Editor edit; 得到编辑对象后就可以对 SharedPreference 中的数据进行操作。 SharedPreference.Editor.putFloat(arg0,arg1) SharedPreference.Editor.putInt(arg0,arg1) SharedPreference.Editor.putLong(arg0,arg1) SharedPreference.Editor.putString(arg0,arg1) SharedPreference.Editor.putBoolean(arg0,arg1) 以上方法的作用是对存储的数据进行操作(写入、保存),其中第一个参数是需要保存数据额Key值索引,第二个参数是需要保存的数据。 到此进行了保存和修改,还需要将其编辑的数据进行提交方可完成存入和修改: SharedPreference.Editor.commit() 如果想删除存储文件中的一条数据,可以使用以下函数: SharedPreference.Editor.clear() 下面用一个简单小游戏进行说明,先看下效果图: 新建项目,游戏框架为 SurfaceView游戏框架,修改 MySurfaceView类如下: View Code 2.流文件存储 利用前面 SharedPreference 的例子,去除 SharedPreference 存储部分,改用流文件形式进行保存,只需要修改其中“保存”和“读取”操作,也就是修改“按键事件”: /** * 按键事件监听 */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // 用到的读出、写入流 FileOutputStream fos = null; FileInputStream fis = null; DataOutputStream dos = null; DataInputStream dis = null; // 上键保存游戏状态 if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { try { // 利用Activity 实例打开流文件得到一个写入流 fos = MainActivity.instance.openFileOutput("save.yc", Context.MODE_PRIVATE); // 将写入流封装在数据写入流中 dos = new DataOutputStream(fos); //写入一个int 类型(将圆形所在格子的下表写入流文件中) dos.writeInt(creentTileIndex); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally{ //即使保存时发生异常也要关闭流 try { if(fos!=null) fos.close(); if(dos!=null)dos.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } // 下键读取游戏状态 } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { try { if(MainActivity.instance.openFileInput("save.yc")!=null) { try { //利用Activity 实例打开流文件得到一个读出流 fis = MainActivity.instance.openFileInput("save.yc"); //将读出流封装在数据读入流中 dis = new DataInputStream(fis); //读出一个int 类型赋值与圆形所在格子的下标 creentTileIndex =dis.readInt(); } catch (Exception e) { // TODO: handle exception }finally{ if(fis!=null)fis.close(); if(dis!=null)dis.close(); } } } catch (Exception e) { // TODO: handle exception } // 圆形的移动 } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { if (creentTileIndex > 0) { creentTileIndex -= 1; } } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { if (creentTileIndex < 8) { creentTileIndex += 1; } } return super.onKeyDown(keyCode, event); } 不管是读入还是写入,都是通过Activity 打开流文件得到输入输出流。当需要写入流文件时,如果打开的流文件不存在,那么Android 会自动生成对应的流文件;而当需要读入流文件时,首先应判断流文件是否存在,一旦流文件不存在,就会抛出异常。 这里的流形式的保存操作比较简单,需要注意的是: ● 读流时,一定要记得判断是否存在需要操作的流文件; ● 写入和读入的数据类型要配对,顺序也不能错;例如:写入时,先写入了一个 Int值,然后又写入了一个String 值;那么读入时,也应该先读 Int 类型,然后再读 String 类型; ● 流一旦打开一定要关闭,为了避免流操作出现异常,需确保正常关闭流,应该将关闭操作写在finally 语句中; ● file 流使用 Data 流进行了封装,这样做的原因是可以获得更多的操作方式,便于对数据的处理。 以上是使用流文件的保存方式,但是也只是将保存后的流文件默认放在了系统内存里。一般游戏的数据可能会有很多,所以不应该放在手机内存中,而是放在 SDCard 中,这样就不要担心系统因游戏保存的数据过多导致内存不足等问题。 将流文件保存在 SDCard 中的详细步骤如下: (1)声明读取权限: Android 中的一些操作,比如:读取通讯录信息、发送信息、使用联网、GPRS等功能都需要在项目 AndroidManifest.xml 中声明使用权限,然后才可以正常使用其功能。 当然在很多时候,是不知道是否需要声明添加权限的,其实这个也不用知道,因为如果用到这些需要声明权限的功能,且恰好没有声明的情况下,在LogCat 中是会报异常的,其异常则提醒需要添加对应的权限。 写入权限如下: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> (2)创建目录和存储文件 使用 SDCard 的方式进行存储数据,写入的时候 Android 不会跟存储系统默认路径那样默认生成存储文件,所以必须自己来创建;如果存储的文件有自定义路径的话,那么这个路径也需要手动添加。 假定存储文件在 SDCard 的路径为 /sdcard/yc/save.yc 。 ① 首先需要创建路径 /sdcard/yc File path = new File(" /sdcard/yc");// 创建目录 if(!path.exists())// 目录存在返回true { path.mkdirs();// 创建一个目录 } boolean File.exists() 作用:判断是否存在当前目录 返回值:当前目录存在返回true boolean File.mkdirs() 作用:创建一个目录 返回值:当创建成功返回true ②然后创建存储文件:/sdcard/yc/save.yc File path_File = new File(" /sdcard/yc/save.yc");// 创建文件 if(!path_File.exists())// 文件存在返回true { path_File.createNewFile();// 创建一个文件 } boolean File.createNewFile() 作用:创建一个文件 返回值:创建成功返回true (3)通过加载指定路径的存储文件获取输入输出流 ● 输入流:FileInputStream fis = new FileInputStream(File file); ● 输出流:FileOutputStream fos = new FileOutputStream(File file); 除此之外还需要知道一点,因为有时手机并没有安装 SDCard ,或者当前SDCard 处于被移除的状态时,为了避免这两种情况带来的异常,需要通过下面方法获取当前手机设备SDCard 的状态: String Environment.getExternalStorageStorageState() 作用:获取当前SDCard的状态 返回值:当前 SDCard 不存在时,返回null ;当 SDCard 处于移除状态时,返回“removed”; 所以当默认手机设备存在 SDCard 时,保存在 SDCard 中 ;当 SDCard 不存在或者正处于被移除的状态时,默认将数据保存在手机内存中。上面的“按键事件”修改如下: View Code 3.SQLite 轻量级数据库 此方式也适合游戏的保存和使用,不仅可以保存较大的数据,而且可以将自己的数据存储到文件系统或者数据库当中,如SQLite数据库,也能将数据保存到SDcard 中。 SQLite是一款轻量级数据库,它的设计目的是嵌入式,而且它占用的资源非常少,在嵌入式设备中,只需要几百KB! SQLite的特性: 轻量级:使用 SQLite 只需要带一个动态库,就可以享受它的全部功能,而且那个动态库的尺寸想当小。 独立性:SQLite 数据库的核心引擎不需要依赖第三方软件,也不需要所谓的“安装”。 隔离性:SQLite 数据库中所有的信息(比如表、视图、触发器等)都包含在一个文件夹内,方便管理和维护。 跨平台:SQLite 目前支持大部分操作系统,不至电脑操作系统更在众多的手机系统也是能够运行,比如:Android。 多语言接口:SQLite 数据库支持多语言编程接口。 安全性:SQLite 数据库通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但只能有一个可以写入数据. 优点:1.能存储较多的数据。2.能将数据库文件存放到SD卡中! 什么是 SQLiteDatabase? 一个 SQLiteDatabase 的实例代表了一个SQLite 的数据库,通过SQLiteDatabase 实例的一些方法,我们可以执行SQL 语句,对数 据库进行增、删、查、改的操作。需要注意的是,数据库对于一个应用来说是私有的,并且在一个应用当中,数据库的名字也是惟一的。 什么是 SQLiteOpenHelper ? 根据这名字,我们可以看出这个类是一个辅助类。这个类主要生成一个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的方法getWritableDatabase(),或者getReadableDatabase()方法的时候,如果当时没有数据,那么Android 系统就会自动生成一个数据库。SQLiteOpenHelper 是一个抽象类,我们通常需要继承它,并且实现里边的3 个函数 什么是 ContentValues 类? ContentValues 类和Hashmap/Hashtable 比较类似,它也是负责存储一些名值对,但是它存储的名值对当中的名是一个String 类型,而值都是基本类型。 什么是 Cursor ? Cursor 在Android 当中是一个非常有用的接口,通过Cursor 我们可以对从数据库查询出来的结果集进行随机的读写访问。 同样利用前面 SharedPreference 的例子,去除 SharedPreference 存储部分,改用SQLite进行保存。 ① 首先新建一个类MySQLiteOpenHelper继承SQLiteOpenHelper;写一个构造,重写两个函数: View Code ② 在MySurfaceView类中创建对应的实例 private MySQLiteOpenHelper myOpenHelper;// 创建一个继承SQLiteOpenHelper类实例 private SQLiteDatabase db; ③ 在SurfaceView初始化函数中实例一个数据库辅助器 // 实例一个数据库辅助器 myOpenHelper = new MySQLiteOpenHelper(MainActivity.instance); ④ 最后修改按键监听事件,其实只需要修改其中“保存”和“读取”操作,代码如下: /** * 按键事件监听 */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { db = myOpenHelper.getWritableDatabase(); // 实例数据库 // 上键保存游戏状态 if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { // ---------------------- SQL语句删除-------------- String DELETE_DATA = "DELETE FROM " + MySQLiteOpenHelper.TABLE_NAME; db.execSQL(DELETE_DATA); // ---------------------- SQL语句插入-------------- String INSERT_DATA = "INSERT INTO " + MySQLiteOpenHelper.TABLE_NAME + "(" + MySQLiteOpenHelper.Param2 + ") values (" + creentTileIndex + ")"; db.execSQL(INSERT_DATA); // 下键读取游戏状态 } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { // 数据查询 Cursor cur = db.rawQuery("SELECT * FROM " + MySQLiteOpenHelper.TABLE_NAME, null); if (cur != null) { cur.moveToNext(); creentTileIndex = cur.getInt(1); } } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { if (creentTileIndex > 0) { creentTileIndex -= 1; } } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { if (creentTileIndex < 8) { creentTileIndex += 1; } } return super.onKeyDown(keyCode, event); } 说明: 在Android中查询数据是通过Cursor类来实现的,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。它提供了很多有关查询的方法,具体方法如下: 以下是方法和说明: move 以当前的位置为参考,将Cursor移动到指定的位置,成功返回true, 失败返回false moveToPosition 将Cursor移动到指定的位置,成功返回true,失败返回false moveToNext 将Cursor向前移动一个位置,成功返回true,失败返回false moveToLast 将Cursor向后移动一个位置,成功返回true,失败返回 false。 movetoFirst 将Cursor移动到第一行,成功返回true,失败返回false isBeforeFirst 返回Cursor是否指向第一项数据之前 isAfterLast 返回Cursor是否指向最后一项数据之后 isClosed 返回Cursor是否关闭 isFirst 返回Cursor是否指向第一项数据 isLast 返回Cursor是否指向最后一项数据 isNull 返回指定位置的值是否为null getCount 返回总的数据项数 getInt 返回当前行中指定的索引数据 本文转自叶超Luka博客园博客,原文链接:http://www.cnblogs.com/yc-755909659/p/4223999.html,如需转载请自行联系原作者

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

《私有云计算整合、虚拟化和面向服务的基础设施》一2.4存储虚拟化

2.4存储虚拟化 存储虚拟化是存储模块的主要焦点(参见图2-2),它抽象了服务器应用访问数据时的逻辑表现与数据的物理位置,实现了位置无关性(云计算的基本特征之一)。虚拟系统负责管理卷到实际物理位置的映射过程,使逻辑实体以卷的形式展现给用户。虚拟化软件或虚拟化设备负责维护映射表,它也是元数据的一部分。映射粒度小至物理磁盘的一部分,大至整个物理磁盘,在这样的环境中,单个信息块由其LUN,也即物理磁盘,以及LUN内的偏移地址一起确定,这一偏移地址也称为逻辑块地址(Logical Block Address,LBA)[16]。逻辑实体通常指虚拟磁盘,物理磁盘之间的地址空间映射由它们各自的LUN确定。说明:物理磁盘也可以仅为存储的一部分,例如从底层磁盘子系统中的RAID阵列切出来的一块。从另一个角度来看,传统存储管理通常采用到主机系统的DAS

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

SQL Server数据库基础的级联删除、级联更新与三层架构之窥

一、定义 级联删除是指删除包含主键值的行的操作,该值由其它表的现有行中的外键引用。在级联删除中,还删除其外键值引用删除的主键值的所有行。 级联更新是指更新主键值的操作,该值由其它表的现有行中的外键引用。在级联更新中,更新所有外键值与新的主键值相匹配。 三层架构是指一种架构思想。通常他将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的目的是为了“高内聚、低耦合”的思想。 二、特点 大家都知道,级联删除与级联更新操作,都是指主表的信息删除或更新后,外键表中的相应信息随主表保持一致,也同样做出删除或更新操作,不然就会发生错误,保持数据的事务性。 而关于三层架构的分层问题,我们之前就讨论过。看似简单,但是越是往细处想,越是发现疑点重重,很多知识都掌握的似是而非。 之前,我们谈论过,我们的架构设计,一般DAL层是与表一一对应的。这是一种规则,可以使DAL层与BLL层之间的关系更加清晰、简洁。但是,我们知道,在实际应用中,真正实现一个逻辑对应一个表是比较困难的,我们的业务不可能彼此孤立,而只能相对孤立。 因此,我认为:我们在设计之初,大方向依然按照DAL与表一一对应的原则进行设计。这里有一点需要注意:所写的SQL语句,一定是要放在存储过程里面的,因为存储过程是预编译类型。业务修改时,我们只需要修改对应存储过程,实现对修改封闭的原则。 三、比较 通过上面的分析,我们可以得出:级联操作与三层机构设计思想是彼此矛盾的。前者只适用于多表间的操作关系,而后者的宏观路线是单对单。 然而,我认为,通过编写存储过程或者触发器来实现级联操作,这样可以使得三层架构的设计更加灵活多变、更加具有弹性。 我们来看机房收费系统中的一个功能:充值功能。我们在充值的时候,不仅要更新卡表内余额,同时也要增加充值记录。 我们之前的做法是,在DAL层对应卡表编写进行更新余额,在充值记录表中添加相应记录。然后在BLL层实现他们的协调工作。 这样做有一个很大的弊端,充值的过程是一个顺序过程,现更新,在添加记录。如果中途断电,那么数据就会不完整了。 看下面的例子,首先是数据库关系图 编写下面触发器,实现起来就非常方便了。 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author:刘正权 -- Create date: 2012年5月7日 -- Description:充值时,更新最新的余额的同时,增加充值记录 -- ============================================= CREATE TRIGGER trigCharge ON card Update AS BEGIN Update chargerecord set c.ChargeCash=i.ChargeCash from chargerocord c,Deleted d, Inserted i where c.CId=d.id END GO 四、结论 我认为,级联操作与三层架构或者多层架构的思想是不矛盾的。想反,它使得分层更加灵活多变。 ====================================分割线================================ 最新内容请见作者的GitHub页:http://qaseven.github.io/

资源下载

更多资源
腾讯云软件源

腾讯云软件源

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

Spring

Spring

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

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册