SpringCloud之实现客户端的负载均衡Ribbon(二)
一 Ribbon简介
Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP的客户端的行为。为Ribbon配置服务提供者地址后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多负载均衡算法,例如轮询、随机等。当然,我们也可为Ribbon实现自定义的负载均衡算法。
在Spring Cloud中,当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。
下图展示了Ribbon与Eureka配合使用时的架构

搭建负载均衡Ribbon (ribbon-consumer)
接到上篇 “SpringCloud之服务注册与发现Eureka(一)”
继续在springcloud工程中添加模块ribbon-consumer,也是通过start.spring.io提供的模板创建

新的目录

生成的pom.xml文件为
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.xuan</groupId>
<artifactId>ribbon-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>ribbon-consumer</name>
<description>Demo project for Spring Boot</description> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>
修改启动文件RibbonConsumerApplication.java,注意增加RestTemplate 的bean注解。
package com.xuan.ribbonconsumer; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate; @EnableDiscoveryClient
@SpringBootApplication
public class RibbonConsumerApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate () {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(RibbonConsumerApplication.class, args);
}
}
增加测试的消费接口ConsumerController.java
package com.xuan.ribbonconsumer; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; @RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate; @RequestMapping(value = "/ribbon-consumer", method = RequestMethod.GET)
public String helloConsumer() {
return restTemplate.getForEntity("http://eureka-client/hello",
String.class).getBody();
}
}
注意要去实现提供者的“hello”接口,在后面在描述具体实现过程。
修改配置文件”application.properties“,让消费者注册中心注册,并且通过注册中心找到服务提供者。
spring.application.name=ribbon-consumer
server.port=9000
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/
为了观察是否进行了负载均衡,在eureka-client模块,增加一个服务提供者接口HelloController.java实现hello接口。
package com.xuan.eurekaclient; import com.netflix.appinfo.InstanceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController
public class HelloController {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class); @Autowired
private DiscoveryClient client; @Value("${server.port}")
String port; @RequestMapping(value = "hello", method = RequestMethod.GET)
public String index() {
StringBuffer uriList = new StringBuffer("Hello World " + port + " 端口为您服务!<br>");
return uriList.toString();
}
}
如果需要打印服务端的详细明细可以修改为:
package com.xuan.eurekaclient; import com.netflix.appinfo.InstanceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController
public class HelloController {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class); @Autowired
private DiscoveryClient discoveryClient; @Value("${server.port}")
String port; @RequestMapping(value = "hello", method = RequestMethod.GET)
public String index() {
StringBuffer uriList = new StringBuffer("Hello World " + port + " 端口为您服务!<br>"); List<ServiceInstance> list = discoveryClient.getInstances("eureka-client");
uriList.append("<br>discoveryClient.getServices().size() = " + discoveryClient.getServices().size());
for( String s : discoveryClient.getServices()){
List<ServiceInstance> serviceInstances = discoveryClient.getInstances(s);
for(ServiceInstance si : serviceInstances){
uriList.append("<br>services:" + s + ":getHost()=" + si.getHost());
uriList.append("<br>services:" + s + ":getPort()=" + si.getPort());
uriList.append("<br>services:" + s + ":getServiceId()=" + si.getServiceId());
uriList.append("<br>services:" + s + ":getUri()=" + si.getUri());
}
} return uriList.toString();
}
}
在eureka-client模块再增加两个配置文件,使用不同的端口,从而在一天电脑可以启动多个服务提供者,方便测试
增加”application-peer1.properties“文件
spring.application.name=eureka-client
server.port=8091
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/
增加”application-peer1.properties“文件
spring.application.name=eureka-client
server.port=8092
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/
添加完成后eureka-client模块的目录结构为:

设置IDEA编辑器的Edit Configurations,增加两个启动配置,修改过完后的列表和注意的地方:

配置和环境都设置完成后:就可以分别启动模块了:
1.EurekaServerApplication
2.EurekaClientApplication,EurekaClientApplication1,EurekaClientApplication2
启动后打开http://localhost:8080/显示如图:

最后启动RibbonConsumerApplication模块在打开http://localhost:8080/显示如下

消费者RibbonConsumer也注册成功了。
访问消费者提供的接口http://localhost:9000/ribbon-consumer,查看是否进行了负载均衡,刷新一次,端口就变化了一次,说明访问的是不同的服务提供者



源码下载地址:https://gitee.com/xuantest/SpringCloud-Ribbon
SpringCloud之实现客户端的负载均衡Ribbon(二)的更多相关文章
- SpringCloud系列七:使用Ribbon实现客户端侧负载均衡
1. 回顾 在前面,已经实现了微服务的注册与发现.启动各个微服务时,Eureka Client会把自己的网络信息注册到Eureka Server上. 但是,在生成环境中,各个微服务都会部署多个实例,因 ...
- 【微服务】之四:轻松搞定SpringCloud微服务-负载均衡Ribbon
对于任何一个高可用高负载的系统来说,负载均衡是一个必不可少的名称.在大型分布式计算体系中,某个服务在单例的情况下,很难应对各种突发情况.因此,负载均衡是为了让系统在性能出现瓶颈或者其中一些出现状态下可 ...
- SpringCloud学习系列之二 ----- 服务消费者(Feign)和负载均衡(Ribbon)使用详解
前言 本篇主要介绍的是SpringCloud中的服务消费者(Feign)和负载均衡(Ribbon)功能的实现以及使用Feign结合Ribbon实现负载均衡. SpringCloud Feign Fei ...
- SpringCloud学习笔记:负载均衡Ribbon(3)
1. RestTemplate简介 RestTemplate是Spring Resource中一个访问第三方RESTful API接口的网络请求框架. RestTemplate是用来消费REST服务的 ...
- Spring Cloud 入门教程(五): Ribbon实现客户端的负载均衡
接上节,假如我们的Hello world服务的访问量剧增,用一个服务已经无法承载, 我们可以把Hello World服务做成一个集群. 很简单,我们只需要复制Hello world服务,同时将原来的端 ...
- 客户端负载均衡Ribbon之二:Loadbalance的源码
Load Balance负载均衡是用于解决一台机器(一个进程)无法解决所有请求而产生的一种算法. 像nginx可以使用负载均衡分配流量,ribbon为客户端提供负载均衡,dubbo服务调用里的负载均衡 ...
- 服务注册发现Eureka之三:Spring Cloud Ribbon实现客户端负载均衡(客户端负载均衡Ribbon之三:使用Ribbon实现客户端的均衡负载)
在使用RestTemplate来消费spring boot的Restful服务示例中,我们提到,调用spring boot服务的时候,需要将服务的URL写死或者是写在配置文件中,但这两种方式,无论哪一 ...
- 0403-服务注册与发现-客户端负载均衡-Ribbon的基本使用
一.概述 问题1.上一篇文章已说明如何注册微服务,但是调用方如何调用,以及如何防止硬编码.即电影微服务调用用户微服务 问题2.用户微服务多个节点,调用服务方如何负载均衡 二.实现负载均衡方式 2.1. ...
- 客户端负载均衡Ribbon之源码解析
什么是负载均衡器? 假设有一个分布式系统,该系统由在不同计算机上运行的许多服务组成.但是,当用户数量很大时,通常会为服务创建多个副本.每个副本都在另一台计算机上运行.此时,出现 "Load ...
随机推荐
- python之路,正则表达式
python3 正则表达式 前言: (1). 处理文本称为计算机主要工作之一(2)根据文本内容进行固定搜索是文本处理的常见工作(3)为了快速方便的处理上述问题,正则表达式技术诞生,逐渐发展为一个单独技 ...
- Python之路,第十八篇:Python入门与基础18
python3 面向对象编程2 类方法: @classmethod 作用:1,类方法是只能访问类变量的方法: 2,类方法需要使用@classmethod 装饰器定义: 3,类方法的第一个参数是类的实 ...
- Unity查找物体的子物体、孙物体
Unity查找物体下的所有物体 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分 ...
- ECUST Div2 训练赛3 (只有代码)
题解见:http://ecustacm.cn/contest/11/announcements A #include<bits/stdc++.h> #define rep(i,a,b) f ...
- indexedDB为何物
https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API 在前一个阶段的工作中,项目组要开发一个平台,为了做出更好的用户体验,实现快 ...
- FZU软工第十一次作业-软件产品案例分析
目录 前言: 第一部分.调研,评测: 1.1.初次感觉: 1.2.企业号bug: 1.3.你觉得为什么这个产品组的人没有发现这些bug: 1.4.假设你们团队需要开发这套系统,需要注意哪些方面: 2. ...
- 回收机制GC
.NET 之 垃圾回收机制GC 一.GC的必要性 1.应用程序对资源操作,通常简单分为以下几个步骤:为对应的资源分配内存 → 初始化内存 → 使用资源 → 清理资源 → 释放内存. 2.应用程序对资源 ...
- linux简单快速启用web
================= jser.me/2013/11/22/快速启动web服务的两种方式.html Python的SimpleHTTPServer需要先安装python,然后执行 pyt ...
- 【转】Vue生命周期
Vue所有的生命周期钩子自动绑定在this上下文到实例中,因此你可以访问数据,对属性和方法进行运算.这意味着你不能使用箭头函数来定义一个生命周期方法.这是因为箭头函数绑定了父上下文,因此this与你期 ...
- Why aren't more desktop apps written with Qt?
Ref http://programmers.stackexchange.com/questions/88685/why-arent-more-desktop-apps-written-with-qt ...