zookeeper dubbo 怎么实现负载均衡
问题的由来:
大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。
(1) 当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。
此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。
并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。
(2) 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
这时,需要自动画出应用间的依赖关系图,以帮助架构师理清理关系。
(3) 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。
其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量
阿里的nacos中的管理页面是怎么实现的
Nacos 服务发现提供与其他服务发现产品不太一样的机制以及概念,在这里稍作介绍,下文中的内容都会多次提到这里介绍的概念,因此掌握这些概念,对于用好 Nacos 服务发现至关重要。
不同于 Consul, Eureka, Nacos 的服务发现使用的领域数据模型是服务 - 集群 - 实例这样的三层结构。
最上面是服务,注册端(服务发布者)和订阅端(服务消费者)使用服务来与其他服务做区分,服务发现中,服务是必须指定的。
集群则是中间一层,一个服务又会划分为多个集群,每个集群都有它的自定义配置,Nacos 提供了一个默认集群和相应的默认配置,在不需要多集群的场景下,可以不用指定集群。
最下一层是实例,每个集群又会包含多个实例,这样对服务进行发现时,可以发现多个集群的所有实例,也可以指定集群,来发现特定集群的实例。
环境准备
首先,需要有一个 Nacos Server 部署起来,目前 Nacos 支持单机模式,也支持集群模式,部署文档可以参考 Nacos 快速入门。
然后添加 Nacos 客户端最新版本依赖:
<dependency> <groupId&.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>[latest-version]</version></dependency>
你可以配置从中央仓库直接依赖,也可以将 Nacos 最新源码下载下来,本地构建客户端版本。
Hello World
我们先来进行一个最简单的服务注册与发现。
Nacos 支持从客户端注册服务实例和订阅服务,具体步骤如下:
配置 Nacos 客户端 Properties:Properties properties = new Properties();properties.setProperty(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
创建 Nacos Naming 客户端:NamingService namingService = NacosFactory.createNamingService(properties);
注册一个实例:namingService.registerInstance("nacos.test.1", Address.getLocalHost().getHostAddress(), 8080);
查找这个服务的实例:System.out.println(namingService.getAllInstances("nacos.test.1"));
至此一个最简单的 Nacos 服务发现的使用已经完成了。
这里要对一些细节稍作解释。
首先在第一步中,属性 PropertyKeyConst.SERVER_ADDR 表示的是 Nacos 服务端的地址,这个地址的格式为 IP:port,IP:port。
对于单机版,只需要指定一个 IP:port。
甚至您可以将端口省略,这样将会访问 Nacos 的默认端口 8848。
在第二步中,将创建一个 NamingService 实例,客户端将为该实例创建单独的资源空间,包括缓存、线程池以及配置等。
Nacos 客户端没有对该实例做单例的限制,请小心维护这个实例,以防新建了多于预期的实例。
第三步注册服务中,使用的是最简单的 API 注册方式,只需要传入服务名、IP、端口就可以。
第四步是获取服务下的所有实例列表,包括健康和不健康的。
构建自定义实例
在一些场景中,我们希望注册的实例中,有一些能够被分配更多的流量,而另外一些分配较少的流量,或者能够传入一些实例的元信息存储到 Nacos 服务端,例如 IP 所属的应用或者所在的机房,这样在客户端可以根据服务下挂载的实例的元信息,来自定义负载均衡模式。
别担心,我们有另外的注册实例接口,让你可以在注册的时候指定实例的属性:
/** * Register a instance to service with specified instance properties * * @param serviceName name of service * @param instance instance to register * @throws NacosException */ void registerInstance(String serviceName, Instance instance) throws NacosException;
这个方法可以在注册服务的时候,传入一个 Instanc 实例,而在 Instance 实例中,可以设置实例的若干属性:
public class Instance { /** * Unique ID of this instance. */ private String instanceId; /** * Instance ip */ private String ip; /** * Instance port */ private int port; /** * Instance weight */ private double weight = 1.0D; /** * Instance health status */ @JSONField(name = "valid") private boolean healthy = true; /** * Cluster information of instance */ @JSONField(serialize = false) private Cluster cluster = new Cluster(); /** * Service information of instance */ @JSONField(serialize = false) private Service service; /** * User extended attributes */ private Map<String, String> metadata = new HashMap<String, String>(); ....}
其中,InstanceId 是由服务端生成返回给客户端,用于唯一标识该实例。
IP、端口是实例的基本属性,除此之外,还有 weight 权重,可以设置该实例所分配流量的多少,这应该也比较好理解,权重越大,实例分配的流量就会越大。
healthy 字段代表该实例是否健康,这个值也是由服务端返回给客户端的。
cluster 和 service 分别表示该实例对应的集群和服务的一些信息,这些信息会在下面做介绍。
最后是实例的元数据,这个元数据一个 String 对 String 的 Map。
那么可以用如下代码来注册一个自定义实例:
Instance instance = new Instance();instance.setIp(Address.getLocalHost().getHostAddress());instance.setPort(8080);instance.setWeight(100);Map<String, String> metadata = new HashMap<String, String>(16);metadata.put("app", "nacos");metadata.put("site", "beijing");instance.setMetadata(metadata);namingService.registerInstance("nacos.test.1", instance);
构建自定义集群
Nacos 引入了集群的概念,在服务这个维度下面,可以对服务下的实例列表再做个划分。
这在阿里巴巴内部非常普遍。
一个典型的场景是这个服务下的实例,需要配置多种健康检查方式,有一些实例使用 TCP 的健康检查方式,另外一些使用 HTTP 的健康检查方式。
另一个场景是,这个服务下挂载的机器分属不同的环境,我们希望能够在某些情况下(包括演练)将某个环境的流量全部切走,这样可以通过配置一个环境属于一个集群,来做到一次性切流。
在客户端构建自定义集群,有一些陷阱需要小心。
当前我们只有注册实例的接口,实例内部的 cluster 字段可以配置集群的属性。
但是多个实例之间如果配置了不同的集群属性,这时候会发生什么呢?Nacos 只会接受第一次注册该集群所传入的集群属性,也就是说,先注册的实例,获得优先权,将它对应的集群信息注册到 Nacos 服务端。
只有 Nacos 服务端已经存在该集群的配置,后续的注册请求里的集群信息,都会被忽略。
为了确保你的应用保持预期的行为,请务必让同一个集群下的实例使用相同的集群配置。
下面来看看可以为集群定义哪些配置:
public class Cluster { /** * Name of belonging service */ private String serviceName; /** * Name of cluster */ private String name = ""; /** * Health check config of this cluster */ private AbstractHealthChecker healthChecker = new AbstractHealthChecker.Tcp(); /** * Default registered port for instances in this cluster. */ private int defaultPort = 80; /** * Default health check port of instances in this cluster. */ private int defaultCheckPort = 80; /** * Whether or not use instance port to do health check. */ private boolean useIPPort4Check = true; private Map<String, String> metadata = new HashMap<String, String>(); ...}
首先是集群对应的服务名,用来表示该集群所属的服务;然后是集群的名字、健康检查方式、默认的端口、默认的健康检查端口以及是否使用是的端口做健康检查。
我们先来说简单的,默认端口表示注册时实例默认的端口,这个在客户端并没有体现,但是当使用 API 注册实例的时候,端口是可以不传入的,此时就会用这个默认端口作为实例的端口。
然后是默认的健康检查端口,当健康检查方式中没有配置端口时,就会用这个端口来和实例通信,进行健康检查。
下一个属性是是否使用实例端口做健康检查,如果设为 true,则会使用实例注册的端口来和实例进行通信。
最后一个属性是集群的元数据,Nacos 支持多个维度的元数据,实例支持,集群支持,下面介绍的服务属性也支持。
健康检查方式,客户端心跳是一种模式,由客户端主动上报健康状态。
服务端检测是另外一种模式,Nacos 目前支持三种:TCP、HTTP 和 MYSQL。
TCP 方式会从 Nacos 服务端建立一个连接到实例,如果连接建立成功,则表示该实例健康。
HTTP 方式则会从 Nacos 服务端想实例发起一个 HTTP 请求,可以配置的属性有访问的相对路径,访问的 HTTP 头部,这个头部使用竖线进行分割,以及预期的请求返回码,默认为 200:
private String path = "";private String headers = "";private int expectedResponseCode = 200;
MYSQL 健康检查方式,则可以让 Nacos 往实例执行一条 MySQL 命令,可以配置的属性有用户名、密码和执行的命令。
执行结果如果不抛异常,则表示实例健康:
private String user;private String pwd;private String cmd;
构建自定义服务
同理,服务也可能需要自定义的配置,Nacos 的服务随着实例的注册而存在,并随着所有实例的注销而消亡。
目前除了使用 HTTP API 可以修改服务的属性外(这将在未来的篇章中进行介绍),就只能使用注册实例时传入服务属性来进行服务的自定义配置。
这里的服务与 Consul 或者 Eureka 不同,Consul 与 Eureka 的服务其实就是指的实例,而每个实例有一个服务名,通过这个服务名来获取相同服务名下的实例列表,服务本身并不是一个数据实体。
在真正的生产环境中,我们认为服务本身也是具有数据存储需求的,例如作用于服务下所有实例的配置、权限控制等。
虽然有一些配置可以放到实例级别,例如健康检查是否开启。
但是当服务的规模成千上万后,想要整体修改这些实例的健康检查开关,就是一个繁重的运维操作。
另一些配置,例如下文会提到的健康保护阈值,是一定是一个服务只有一个唯一的值的,多个值将会造成逻辑上的冲突。
/** * Service name */ private String name; /** * Protect threshold */ private float protectThreshold = 0.0F; /** * Application name of this service */ private String app; /** * Service group which is meant to classify services into different sets. */ private String group; /** * Health check mode. */ private String healthCheckMode; private Map<String, String> metadata = new HashMap<String, String>();
服务的属性存储在 Service 类中,自上而下,依次是服务的名称、服务的健康保护阈值、服务的应用名、服务的分组、服务的健康检查模式以及服务的元数据。
相关概念这里不再做一一陈述,你可以参考 Nacos 官网 概念介绍。
这里要提到的是服务的健康保护阈值,在阿里巴巴内部,这个值被广泛的设置和调优。
在这里对该属性的初衷做一个简单的介绍。
分布式服务场景下的一个问题是在部分实例不健康的情况下,是否能够将流所有流量引向其他健康实例?在一些情况下,这可能造成雪崩效应。
即本来健康的实例被多余的流量冲击,也变得不健康,然后导致健康的实例越来越少,最后整个服务崩溃。
此时可以使用这个健康保护阈值,当健康实例与所有实例的比例小于这个值的时候,则认为所有实例都是健康的,这样虽然部分流量流向了不健康的实例,但是剩余健康的实例还是能够正常访问的。
服务发现
Nacos 的服务发现,有主动拉取和推送两种模式,这与一般的服务发现架构相同。
在拉取方式中,提供了三个方法,一个是查询所有注册的实例,一个是只查询健康且上线的实例,还有一个是获取一个健康且上线的实例。
一般情况下,订阅端并不关心不健康的实例或者权重设为 0 的实例,但是也不排除一些场景下,有一些运维或者管理的场景需要拿到所有的实例。
目前的版本同时还支持根据服务端设定的负载均衡策略,来查询单个可用的实例。
就好像 DNS 解析一样,虽然每次都返回一个后端 IP,但是整体可以保证域名挂载的所有 IP 会按照一定的策略都能够被客户端解析到。
/** * Get all instances of a service * * @param serviceName name of service * @return A list of instance * @throws NacosException */List<Instance> getAllInstances(String serviceName) throws NacosException;/** * Get qualified instances of service * * @param serviceName name of service * @param healthy a flag to indicate returning healthy or unhealthy instances * @return A qualified list of instance * @throws NacosException */List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException;/** * Select one healthy instance of service using predefined load balance strategy * * @param serviceName name of service * @return qualified instance * @throws NacosException */Instance selectOneHealthyInstance(String serviceName) throws NacosException;
前两个查询方法会返回所有实例的列表,这允许用户通过额外的工作,将实例的权重或者元数据运用到负载均衡中。
对于一般的微服务场景,针对每个实例轮询,这样已经足够了。
事实上,不管是在 Eureka 还是 Consul 里,其原生客户端都是只负责服务的发现,并不支持负载均衡。
这样就需要第三方的 ribbon 或者 fabio 来完成负载均衡工作,此时它们的负载均衡,是完全放在客户端的。
Nacos 也会支持客户端侧的负载均衡,并支持用户扩展的负载均衡策略。
不过在阿里巴巴内部,通常只需要由服务端来配置负载均衡策略,所有的调用端不区分业务的使用同一套负载均衡策略。
因为实际上,调用端往往并不关心自身访问的服务的流量分配,而只需要一个可用的服务节点就可以了。
而服务提供端,则由于其部署规模很大和部署环境的复杂,需要对环境信息敏感的流量分配以及对流量的绝对控制权。
这时,往往需要提供端审慎的配置好统一的负载均衡策略,来保证所有订阅端按照这个策略来进行访问。
除了主动查询实例列表,Nacos 还提供订阅模式来感知服务下实例列表的变化,包括服务配置或者实例配置的变化。
可以使用下面的接口来进行订阅或者取消订阅:
/** * Subscribe service to receive events of instances alteration * * @param serviceName name of service * @param listener event listener * @throws NacosException */void subscribe(String serviceName, EventListener listener) throws NacosException;/** * Unsubscribe event listener of service * * @param serviceName name of service * @param listener event listener * @throws NacosException */void unsubscribe(String serviceName, EventListener listener) throws NacosException;
控制台使用
Nacos 0.3.0 版本上线了控制台,作为生产环境基本的运维工具,服务发现也通过控制台释放了部分的运维能力。
虽然控制台承担的是运维为主的工作,但是开发人员也需要通过控制台来查看当前服务的注册状态和健康状态等,服务发现的控制台页面介绍可以参考 https://nacos.io/en-us/blog/discovery-console.html。
虽然这篇文章中的一些页面通过社区的反馈而做了细微的调整,但是通过这篇文章应该可以掌握怎么使用服务发现的控制台了。
控制台的启动方式也很简单,将 Nacos 安装包下载安装启动(安装教程)之后,直接访问:http://localhost:8848/nacos/index.html 即可打开最新的控制台界面。
小 结
Nacos 目前的版本,集成了服务发现和配置管理的基本能力以及部分高级特性。
作为最小生产可用版本,Nacos 未来还会继续开放新特性,结合 SpringCloud、K8S、Dubbo 等生态,为开发者提供极致易用和稳定的服务管理和配置管理能力。
在可预期的几个版本内,将会支持元数据的管理及 DNS 的服务发现。
争取将使用 Nacos,作为服务发现和配置管理选型的最佳实践。
坤宇即将在本届 ArchSummit 全球架构师峰会为大家带来新的分享—阿里 10 年大规模微服务“软负载”技术体系原理及实践,他希望通过这个分享,和大家交流阿里巴巴这 10 年来在软负载体系的实践之路,并且共同看看该领域的未来趋势。
由 InfoQ 中国主办的 ArchSummit 全球架构师峰会即将于 12 月 7-8 日在北京国际会议中心举办,大会日程已新鲜出炉,听 100+ 知名企业的架构师分享架构实践,与一线技术大牛将现场深入交流,机会难得,千万不要错过了!在引用dubbo服务时 不需要指定端口吗
1.透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
2.软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
3. 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
我使用雷网主机,如何实现服务器的负载均衡?
服务器通常可以作很多用途,比如说WEB服务器,数据库服务器,DNS服务器等等之类的,以下从四个方面来讲术如何实现服务器的负责均衡?
雷网主机是国内专业的海内外IDC服务商,专业提供、新加坡服务器租用、美国服务器租用、香港服务器租用、香港服务器托管托管、大陆、美国VPS主机、VPS主机、企业邮箱、空间。
一、企业实现SQL Server数据库服务器负载均衡
MS SQL
Server数据库服务器是应用范围最广的数据库产品,并且越来越多地在大型和比较关键的应用系统中提供服务。
当企业应用越来越复杂、数据量越来越大的时候,SQL
Server数据库就不停的进行处理、存储、查询的工作。
当然,这个时候企业就要考虑到SQL
Server数据库服务器的性能和速度及安全性。
二、企业实现Web服务器负载均衡
为了将负载均匀的分配给内部的多个服务器上,就需要应用一定的负载均衡策略。
通过服务器负载均衡设备实现各服务器群的流量动态负载均衡,并互为冗余备份。
并要求新系统应有一定的扩展性,如数据访问量继续增大,可再添加新的服务器加入负载均衡系统。
对于WEB服务应用,同时有几台机器提供服务,每台机器的状态可以设为regular(正常工作)或backup(备份状态),或者同时设定为regular状态。
负载均衡设备根据管理员事先设定的负载算法和当前网络的实际的动态的负载情况决定下一个用户的请求将被重定向到的服务器。
而这一切对于用户来说是完全透明的,用户完成了对WEB服务的请求,并不用关心具体是哪台服务器完成的。
三、使用网络地址转换实现多服务器负载均衡
支持负载均衡的地址转换网关中可以将一个外部IP地址映射为多个内部IP地址,对每次TCP连接请求动态使用其中一个内部地址,达到负载均衡的目的。
很多硬件厂商将这种技术集成在他们的交换机中,作为他们第四层交换的一种功能来实现,一般采用随机选择、根据服务器的连接数量或者响应时间进行选择的负载均衡策略来分配负载。
然而硬件实现的负载控制器灵活性不强,不能支持更优化的负载均衡策略和更复杂的应用协议。
四、使用DNS服务器实现负载均衡
访问企业网服务器的用户急剧增加,一台服务器难以满足用户的访问需要,那么如何才能保证用户的正常访问呢?解决方法有很多,如使用Windows
2000或Windows Server
2003提供网络负载均衡服务,但该服务的设置非常复杂。
而通过DNS服务器实现网络负载均衡则是一种比较简单的方法。
回答希望对你有帮助,如还不清楚请咨询雷网主机的技术部。
|