首页 文章 精选 留言 我的

精选列表

搜索[和平之翼代码生成器],共10000篇文章
优秀的个人博客,低调大师

java开发之使用websocket实现web客户端与服务器之间的实时通讯

第一次写博客,有写的不好的地方欢迎大家指点。使用websocket实现web客户端与服务器之间的实时通讯。以下是个简单的demo。 import java.util.Date; public class WebSocketMessage { /** * 发送者ID */ private String senderId; /** * 接受者ID, 如果为0, 则发送给所有人 */ private String receiverId; /** * 会话内容 */ private String messageContent; /** * 发送时间 */ private Date sendTime; public String getSenderId() { return senderId; } public void setSenderId(String senderId) { this.senderId = senderId; } public String getReceiverId() { return receiverId; } public void setReceiverId(String receiverId) { this.receiverId = receiverId; } public String getMessageContent() { return messageContent; } public void setMessageContent(String messageContent) { this.messageContent = messageContent; } public Date getSendTime() { return sendTime; } public void setSendTime(Date sendTime) { this.sendTime = sendTime; } } import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller @RequestMapping("webSocket") public class WebSocketController { @RequestMapping(value = "messagePage/{userID}") public ModelAndView messagePage(@PathVariable String userID, HttpServletResponse response) { ModelAndView mav = new ModelAndView(); mav.addObject("userID", userID); mav.setViewName("web_socket"); return mav; } } import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import com.alibaba.fastjson.JSON; import com.utime.facade.model.systemplate.WebSocketMessage; @ServerEndpoint("/webSocketServer/{userID}") public class WebSocketServer { // 连接客户端数量 private static int onlineCount = 0; // 所有的连接客户端 private static Map<String, WebSocketServer> clients = new ConcurrentHashMap<String, WebSocketServer>(); // 当前客户端连接的唯一标示 private Session session; // 当前客户端连接的用户ID private String userID; /** * 客户端连接服务端回调函数 * * @param userID 用户ID * @param session 会话 * @throws IOException */ @OnOpen public void onOpen(@PathParam("userID") String userID, Session session) throws IOException { this.userID = userID; this.session = session; addOnlineCount(); clients.put(userID, this); System.out.println("WebSocket日志: 有新连接加入!当前在线人数为" + getOnlineCount()); } @OnClose public void onClose() throws IOException { clients.remove(userID); subOnlineCount(); System.out.println("WebSocket日志: 有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 接受到来自客户端的消息 * * @param message * @throws IOException */ @OnMessage public void onMessage(String message) throws IOException { System.out.println("WebSocket日志: 来自客户端的消息:" + message); WebSocketMessage webSocketMessage = JSON.parseObject(message, WebSocketMessage.class); // 发送消息给所有客户端 if ("0".equals(webSocketMessage.getReceiverId())) { for (WebSocketServer item : clients.values()) { item.session.getAsyncRemote().sendText(webSocketMessage.getMessageContent()); System.out.println("WebSocket日志: ID为"+ webSocketMessage.getSenderId() +"的用户给ID为"+ item.userID +"的客户端发送:" + webSocketMessage.getMessageContent()); } } else { // 发送消息给指定ID的客户端 for (WebSocketServer item : clients.values()) { if (item.userID.equals(webSocketMessage.getReceiverId())){ // 发消息给指定客户端 item.session.getAsyncRemote().sendText(webSocketMessage.getMessageContent()); System.out.println("WebSocket日志: ID为"+ webSocketMessage.getSenderId() +"的用户给ID为"+ item.userID +"的客户端发送:" + webSocketMessage.getMessageContent()); if (!webSocketMessage.getSenderId().equals(webSocketMessage.getReceiverId())) { // 发消息给自己 this.session.getAsyncRemote().sendText(webSocketMessage.getMessageContent()); System.out.println("WebSocket日志: ID为"+ webSocketMessage.getSenderId() +"的用户给ID为"+ this.userID +"的客户端发送:" + webSocketMessage.getMessageContent()); } break; } } } } /** * 服务端报错了 * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { System.out.println("WebSocket日志: 发生错误"); error.printStackTrace(); } /** * 客户端连接数+1 */ public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } /** * 客户端连接数-1 */ public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized Map<String, WebSocketServer> getClients() { return clients; } } <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fun"%> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> <c:set var="baseurl" value="${pageContext.request.contextPath}/"></c:set> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>web_socket</title> <script type="text/javascript" src="${baseurl}static/js/jquery-2.1.1.js"></script> <style type="text/css"> .connector {width: 500px;} </style> </head> <body> Welcome <br/> <input id="text" type="text"/> <button onclick="sendToOne(10008)">发消息给个人</button> <button onclick="sendToAll(0)">发消息给所有人</button> <hr/> <button onclick="closeWebSocket()">关闭WebSocket连接</button> <hr/> <div id="message"></div> </body> <script type="text/javascript"> var websocket = null; var host = document.location.host; //判断当前浏览器是否支持WebSocket if ('WebSocket' in window) { console.info("浏览器支持Websocket"); websocket = new WebSocket('ws://'+host+'/${baseurl}/webSocketServer/${userID}'); } else { console.info('当前浏览器 Not support websocket'); } //连接发生错误的回调方法 websocket.onerror = function() { console.info("WebSocket连接发生错误"); setMessageInnerHTML("WebSocket连接发生错误"); } //连接成功建立的回调方法 websocket.onopen = function() { console.info("WebSocket连接成功"); setMessageInnerHTML("WebSocket连接成功"); } //接收到消息的回调方法 websocket.onmessage = function(event) { console.info("接收到消息的回调方法"); console.info("这是后台推送的消息:"+event.data); setMessageInnerHTML(event.data); console.info("webSocket已关闭!"); } //连接关闭的回调方法 websocket.onclose = function() { setMessageInnerHTML("WebSocket连接关闭"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function() { closeWebSocket(); } //关闭WebSocket连接 function closeWebSocket() { websocket.close(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //发送消息给其他客户端 function sendToOne(receiverId) { var messageContent = document.getElementById('text').value; var message = {}; message.senderId = "${userID}"; message.receiverId = receiverId; message.messageContent = messageContent; websocket.send(JSON.stringify(message)); } //发送消息给所有人 function sendToAll() { var messageContent = document.getElementById('text').value; var message = {}; message.senderId = "${userID}"; message.receiverId = "0"; message.messageContent = messageContent; websocket.send(JSON.stringify(message)); } </script> </html> 写这个的目的只是为了自己做个记录。写的不好,后面会慢慢完善。

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

Java Spring Boot 2.0 实战之制作Docker镜像并推送到Docker Hub和阿里云仓库

内容摘要:大规模集群快速部署Java应用,需要制作Docker镜像,本次课程详细介绍如何制作Java程序的Docker镜像文件,深入解析DockerFile核心参数,以及实践演练把我们制作的Docker镜像推送到DockerHub仓库,国内可以使用阿里云Docker仓库加速,以及安全保护机制。今天我们都来实战Java Spring Boot 2.0,制作Java Docker镜像,然后推送到DockerHub和阿里云Docker仓库,推送到公共镜像仓库的原因是便于后期大规模服务器集群部署。 1、Docker安装如果你不熟悉安装,可以参考这个文章 《Java Spring Boot 2.0实战Docker容器与架构原理,视频与课件,基于Linux环境》https://yq.aliyun.com/articles/691596Mac可

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

java B2B2C Springcloud多租户电子商城系统-消息队列之ActiveMQ

什么是ActiveMQ? ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。 主要特点: 多种语言和协议编写客户端。语言: Java, C, C++, C#, Ruby, Perl, Python, PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性通过了常见J2EE服务器(如 Geronimo,JBoss 4, GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA支持通过JDBC和journal提供高速的消息持久化从设计上保证了高性能的集群,客户端-服务器,点对点支持Ajax支持与Axis的整合可以很容易得调用内嵌JMS provider,进行测试ActiveMQ的消息形式: 对于消息的传递有两种类型:一种是点对点的,即一个生产者和一个消费者一一对应;另一种是发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。 JMS定义了五种不同的消息正文格式,以及调用的消息类型,允许你发送并接收以一些不同形式的数据,提供现有消息格式的一些级别的兼容性。 · StreamMessage – Java原始值的数据流 · MapMessage–一套名称-值对 · TextMessage–一个字符串对象 · ObjectMessage–一个序列化的 Java对象 · BytesMessage–一个字节的数据流 ActiveMQ消息确认机制消息只有在被确认之后,才认为已经被成功消费,然后消息才会从队列或主题中删除。消息的成功消费通常包含三个阶段: (1)、客户接收消息;(2)、客户处理消息;(3)、消息被确认; 确认机制前面提过一下,共有四种: (1)、Session.AUTO_ACKNOWLEDGE;客户(消费者)成功从receive方法返回时,或者从MessageListener.onMessage方法成功返回时,会话自动确认消息,然后自动删除消息.(2)、Session.CLIENT_ACKNOWLEDGE;客户通过显式调用消息的acknowledge方法确认消息,。 即在接收端调用message.acknowledge();方法,否则,消息是不会被删除的.(3)、Session. DUPS_OK_ACKNOWLEDGE ;不是必须确认,是一种“懒散的”消息确认,消息可能会重复发送,在第二次重新传送消息时,消息头的JMSRedelivered会被置为true标识当前消息已经传送过一次,客户端需要进行消息的重复处理控制。(4)、 Session.SESSION_TRANSACTED;事务提交并确认。 需要JAVA Spring Cloud大型企业分布式微服务云构建的B2B2C电子商务平台源码 java版 b2b2c o2o电子商务云商平台-springcloud spring boot springmvc b2b2c多租户电子商务平台 框架源码下载地址

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

java B2B2C电子商务平台分析之十四-----注册中心 Consul

Consul 介绍Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等)。使用起来也较 为简单。Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。愿意了解源码的朋友直接求求交流分享技术:二一四七七七五六三三 Consul 的优势: 使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是 Paxos, 而 etcd 使用的则是 Raft。支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等。 zookeeper 和 etcd 均不提供多数据中心功能的支持。支持健康检查。 etcd 不提供此功能。支持 http 和 dns 协议接口。 zookeeper 的集成较为复杂, etcd 只支持 http 协议。官方提供 web 管理界面, etcd 无此功能。综合比较, Consul 作为服务注册和配置管理的新星, 比较值得关注和研究。特性: 服务发现健康检查Key/Value 存储多数据中心Consul 角色 client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群。server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网与其它数据中心通讯。 每个数据中心的 server 数量推荐为 3 个或是 5 个。Consul 客户端、服务端还支持夸中心的使用,更加提高了它的高可用性。 Consul 工作原理: 1、当 Producer 启动的时候,会向 Consul 发送一个 post 请求,告诉 Consul 自己的 IP 和 Port2、Consul 接收到 Producer 的注册后,每隔10s(默认)会向 Producer 发送一个健康检查的请求,检验Producer是否健康3、当 Consumer 发送 GET 方式请求 /api/address 到 Producer 时,会先从 Consul 中拿到一个存储服务 IP 和 Port 的临时表,从表中拿到 Producer 的 IP 和 Port 后再发送 GET 方式请求 /api/address4、该临时表每隔10s会更新,只包含有通过了健康检查的 ProducerSpring Cloud Consul 项目是针对 Consul 的服务治理实现。Consul 是一个分布式高可用的系统,它包含多个组件,但是作为一个整体,在微服务架构中为我们的基础设施提供服务发现和服务配置的工具。 技术架构图如下: 资料和源码来源

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

java B2B2C电子商务平台分析之十二-----Spring Cloud Sleuth

一、简介 Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只需要在pom文件中引入相应的依赖即可。愿意了解源码的朋友直接求求交流分享技术:二一四七七七五六三三 二、服务追踪分析 微服务架构上通过业务来划分服务的,通过REST调用,对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。 三、术语 Spring Cloud Sleuth采用的是Google的开源项目Dapper的专业术语。 Span:基本工作单元,例如,在一个新建的span中发送一个RPC等同于发送一个回应请求给RPC,span通过一个64位ID唯一标识,trace以另一个64位ID表示,span还有其他数据信息,比如摘要、时间戳事件、关键值注释(tags)、span的ID、以及进度ID(通常是IP地址)span在不断的启动和停止,同时记录了时间信息,当你创建了一个span,你必须在未来的某个时刻停止它。Trace:一系列spans组成的一个树状结构,例如,如果你正在跑一个分布式大数据工程,你可能需要创建一个trace。Annotation:用来及时记录一个事件的存在,一些核心annotations用来定义一个请求的开始和结束cs - Client Sent -客户端发起一个请求,这个annotion描述了这个span的开始sr - Server Received -服务端获得请求并准备开始处理它,如果将其sr减去cs时间戳便可得到网络延迟ss - Server Sent -注解表明请求处理的完成(当请求返回客户端),如果ss减去sr时间戳便可得到服务端需要的处理请求时间cr - Client Received -表明span的结束,客户端成功接收到服务端的回复,如果cr减去cs时间戳便可得到客户端从服务端获取回复的所有所需时间将Span和Trace在一个系统中使用Zipkin注解的过程图形化: 每个颜色的表明一个span(总计7个spans,从A到G),每个span有类似的信息 Trace Id = XSpan Id = DClient Sent此span表示span的Trance Id是X,Span Id是D,同时它发送一个Client Sent事件 spans 的parent/child关系图形化如下: spring cloud提供了spring-cloud-sleuth-zipkin来方便集成zipkin实现(指的是Zipkin Client,而不是Zipkin服务器),该jar包可以通过spring-cloud-starter-zipkin依赖来引入。 技术架构图如下:资料和源码来源

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

Java专家推荐之资深讲师徐雷,.NET转Java需要先了解Java的哪些框架?

社区将持续介绍优秀的Java专家,本期请到了阿里云大学讲师,资深架构师徐雷,在线为开发者解决问题,向徐雷提问请点击:https://yq.aliyun.com/promotion/755 徐雷,资深架构师 徐雷,花名:徐雷frank;资深架构师,MongoDB中文社区联席主席,吉林大学计算机学士,上海交通大学硕士。从事了 10年+开发工作,专注于分布式架构,Java Spring Boot、Spring Cloud、MongoDB、Redis。 喜欢专研技术问题,擅长讲课,《MongoDB实战》第2版、《24种云计算架构设计模式》译者,2018年5月受邀成为《阿里巴巴Java和MongoDB技术认证》讲师,2018年8月与阿里巴巴资深专家P9叶翔直播《阿里巴巴MongoDB高级实战课程》 徐雷在社区发布的视频: Java Spri

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

支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」

前言 《支付宝客户端架构解析》系列将从支付宝客户端的架构设计方案入手,细分拆解客户端在“容器化框架设计”、“网络优化”、“性能启动优化”、“自动化日志收集”、“RPC 组件设计”、“移动应用监控、诊断、定位”等具体实现,带领大家进一步了解支付宝在客户端架构上的迭代与优化历程。 本节将介绍支付宝 Android 客户端启动速度优化下的「垃圾回收」具体思路。 应用启动时间是移动 App 一个重要的用户体验环节,相对于普通的移动 App,支付宝过于庞大,必然会影响启动速度,一些常规的优化手段在支付宝中已经做得比较完善了,本篇文章尝试从 GC 的层面来进一步优化支付宝的启动速度。 背景 相对于 C 语言来说,Java 语言有一些特性,例如开发人员不用考虑内存的分配和回收,然而,进程内存管理又是必不可少的环节,妥协的结果是 Java 语言的设计者们把

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

「架构技术专题」架构核心指标之可扩展架构设计的三要素(4)

业界对于可扩展的系统架构设计有一个朴素的理念,就是: 通过加机器就可以解决容量和可用性问题 这一理念在“云计算”概念疯狂流行的今天,得到了广泛的认可!对于一个规模迅速增长的系统而言,容量和性能问题当然是首当其冲的。但是随着时间的向前,系统规模的增长,除了面对性能与容量的问题外,还需要面对功能与模块数量上的增长带来的系统复杂性问题以及业务的变化带来的提供差异化服务问题。而许多系统,在架构设计时并未充分考虑到这些问题,导致系统的重构成为常态,从而影响业务交付能力,还浪费人力财力! 对此,《可扩展的艺术》一书提出了一个更加系统的可扩展模型——AKF可扩展立方(Scalability Cube)。这个立方体中沿着三个坐标轴设置分别为:X、Y、Z。 X轴扩展 —— 关注水平的数据和服务克隆,也就是前文提到的“加机器解决问题”Y轴扩展 —— 关注应用中职责的划分,比如数据类型,交易执行类型的划分Z轴扩展 —— 关注服务和数据的优先级划分,如分地域划分 整个扩展模型,用下图来表示,其中原点代表完全无扩展的状态。 一.X轴扩展 X轴扩展与我们前面朴素理念是一致的,通过绝对平等地复制服务与数据,以解决容量和可用性的问题。我们以生产汽车的工厂来举例:假设一个车间能完整的生产一辆汽车,为了短时间内生产更多的汽车,我们可以建设更多的车间,任何新增车间除了工作的效率可能不同之外,都是一个新的复制品,也能提供与原来车间相同的工作,生产出完整的汽车。给复制品分配工作就是一个X轴扩展的一个完美示例,说明了X轴扩展的思路,即把工作无偏向的分配给复制品,每个复制品在不考虑生产效率的情况下,谁来做这项工作是无偏向的,各个复制品之间不共享任何内容。 而在工程技术上来讲,X轴扩展主要有以下两种技术方案: 1.负载均衡 故名思议,负载均衡就是将用户的访问请求通过负载均衡器,均衡分配到由各个“复制品”组成的集群中去。当某个复制品出现故障,也能轻易地将相应“工作”转移给其它的复制品来“代为完成”。这中间涉及到的工程技术点包括了反向代理,DNS轮询,哈希负载均衡算法(一致性哈希),动态节点负载均衡(如按CPU,I/O)等。它的难点在于要求集群中的“复制品”是不共享任何内容,也就是我们常说的无状态。 2.数据复制 数据复制是指在数据存储层进行绝对平等地数据迁移,用于解决存储层I/O瓶颈以及可用性上的问题。由于存在多个复制品存储,为了使得每个复制品提供无差异的数据服务,我们需要在复制品之间同步或异步地复制数据。数据复制的方式包括了主从同步(常见的读/写分离),双主同步等。因为数据存储天生就是有状态的,数据复制的难点在于一致性的保证上,为了一致性的保证,从而也衍生了很多复杂的技术,比如Paxos选举算法等。 二.Y轴扩展 Y轴扩展表示的是根据数据的类型或者交易执行的类型(或者两者都有)来划分工作职责。一般称为面向服务或面向资源的扩展。我们再以生产汽车的工厂来举例:如亨利.福特所做的一样,将汽车制造的工序按专业性分成不同车间和流水线,不再是一个车间负责完成100%的任务,制造一辆完整的汽车,而是让这每个车间都执行一些子任务,如安装发动机,喷漆,安装玻璃等等。这样的分工,益处是明显的,每个车间负责的任务更简单,从而能更专业更高效的完成生产。 与汽车工厂的分工类似,为了降低系统复杂度,Y轴扩展会将庞大的整体应用拆分为一组服务。每个服务实现一组相关的功能,如订单管理、客户管理等。在工程上常见的方案是服务化架构(SOA)。比如对于一个电子商务平台,我们可以拆分成不同的服务,组成下面这样的架构: 但通过观察上图容易发现,当服务数量增多时,服务调用关系变得复杂。为系统添加一个新功能,要调用的服务数也变得不可控,由此引发了服务管理上的混乱。所以,一般情况下,需要采用服务注册的机制形成服务网关来进行服务治理。系统的架构将变成下图所示: 同时,为了提升单个服务的可用性和容量,对每一个服务进行X轴扩展划分。 三.Z轴扩展 Z轴扩展通常是指基于请求者或用户独特的需求,进行系统划分,并使得划分出来的子系统是相互隔离但又是完整的。继续以生产汽车的工厂来举例:福特公司为了发展在中国的业务,或者利用中国的廉价劳动力,在中国建立一个完整的子工厂,与美国工厂一样,负责完整的汽车生产。这就是一种Z轴扩展。 对于系统而言,Z轴扩展一般是为了满足差异性的需求或者是为了安全隔离而采取的扩展措施。比如为了提供VIP用户服务,可以将系统完整地复制一份出来,与普通用户所使用的系统完全隔离开来;再如,针对不同的地域用户,系统自动切换到对应地域的子系统,为用户提供服务,都可以认为是Z轴扩展。同时,在系统的灰度部署上,我们也通常使用Z轴扩展来完成。 工程领域常见的Z轴扩展有以下两种方案: 1.单元化架构 在分布式服务设计领域,一个单元(Cell)就是满足某个分区所有业务操作的自包含闭环。如上面我们说到的Y轴扩展的SOA架构,客户端对服务端节点的选择一般是随机的,但是,如果在此加上Z轴扩展,那服务节点的选择将不再是随机的了,而是每个单元自成一体。如下图: 2.数据分区 为了性能数据安全上的考虑,我们将一个完整的数据集按一定的维度划分出不同的子集。 一个分区(Shard),就是是整体数据集的一个子集。比如用尾号来划分用户,那同样尾号的那部分用户就可以认为是一个分区。数据分区为一般包括以下几种数据划分的方式: 数据类型(如:业务类型)数据范围(如:时间段,用户ID)数据热度(如:用户活跃度,商品热度)按读写分(如:商品描述,商品库存) 当然,数据分区也是有代价的,它将增加数据运维的难度,关联搜索的复杂度增加等。 总结: 一个在可扩展性上设计良好的系统,会充分考虑三个维度上的可扩展性。X轴上扩展处理的是平台或系统执行的交易量或工作量增长,虽然X轴扩展能够很好处理交易量的增长,但当系统复杂度的大幅度增加,或用户数量增加以及差异化服务需求出现,X轴扩展就难以应付了,如是我们可以通过Y轴扩展来处理系统复杂度增长的问题以及Z轴扩展来处理差异性化需求的问题。而当采用的扩展坐标轴不止一条时,那么X轴扩展总是其它扩展方法的次级划分。同时,这三个维度扩展性,使得系统性能上改善有了更多的方向,对于系统性能优化,也是至关重要。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

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

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等操作系统。

用户登录
用户注册