SpringCloud——Ribbon负载均衡
Ribbon是负载均衡器,主要作用是用于缓解服务器端的压力,使得收到的请求可以较为平均的分配到不同的服务器上,简而言之,即使得每个服务器的负载达到相对均衡的状态.
客户端与服务端的负载均衡
客户端负载均衡:
客户端自己拥有一个可用的服务器的列表,在发送请求前通过自生的负载均衡算法来决定选择哪个服务器来处理自己的请求。
服务器端负载均衡
与客户端负载均衡相比,不同的是,每个客户端在发送请求之前不会自己决定要选择哪个服务器来处理,而是所有的客户端的请求统一把请求发到负载均衡服务器,由服务器通过负载均衡算法来决定每一个请求对应的服务器是哪一个。
小结
结合实际,客户端负载均衡有点像是要排队的人,看那边的人少(即自己觉得合适)就会去哪个队伍排队。而服务器端负载均衡,则像是银行挂号的方式,你只需要通过负责挂号排队的机器告诉他你需要的服务,然后机器会自动给你一个号码,根据提示去对应的窗口即可。
Ribbon负载均衡案例
首先说一下需要有的角色:①Eureka服务注册中心,②服务提供者,③服务消费者,这三者对应的是一个项目的三个Module,以下代码省略了具体的conteoller,service,mapper等代码
创建父工程
-
pom文件配置
大家可以根据自己的需要来进行筛选
<?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>org.vernhe</groupId> <artifactId>vernhe_spring_cloud_demo</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>service</module> <module>consumer</module> <module>eureka</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> </parent> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> <mapper.starter.version>2.1.5</mapper.starter.version> <mysql.version>5.1.46</mysql.version> </properties> <dependencyManagement> <dependencies> <!-- springCloud --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- 通用Mapper启动器,可根据需要进行选择 --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>${mapper.starter.version}</version> </dependency> <!-- mysql驱动,可根据进行选择 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> </dependencies> </dependencyManagement> <!-- lombok插件,可根据进行选择 --> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Eureka服务注册中心
-
在父工程中的创建名字为eureka的Module
-
pom文件中添加eureka的依赖
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies>
-
启动类:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer //开启eureka服务 @SpringBootApplication public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
-
application.yml配置文件
server: port: 8888 #端口号默认8080,可自定义 spring: application: name: eureka-server eureka: client: service-url: defultZone: HTTP://127.0.0.1:8888/eureka register-with-eureka: false #不注册自己 fetch-registry: false
服务提供者
-
在父工程中的创建名字为consumer的Module
-
pom文件添加依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 通用Mapper启动器,可根据具体的情况决定是否保留 --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> </dependency> <!-- mysql驱动,可根据具体的情况决定是否保留 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- Eureka客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>
-
启动器
@SpringBootApplication @MapperScan("com.vernhe.user.mapper") @EnableDiscoveryClient //开启Eureka客户端发现功能 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
-
application.yml配置文件
server: port: 7777 spring: datasource: url: jdbc:mysql://localhost:3306/vernhe driver-class-name: com.mysql.jdbc.Driver username: root password: root application: name: user-service eureka: client: service-url: defaultZone: HTTP://127.0.0.1:8888/eureka
服务消费者
-
在父工程中的创建名字为service的Module
-
pom文件添加依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Eureka客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <!-- Ribbon 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> </dependency> </dependencies>
-
启动器
@SpringBootApplication @EnableDiscoveryClient public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean @LoadBalanced //开启负载均衡 public RestTemplate restTemplate(){ return new RestTemplate(); } }
-
application.yml配置文件
server: port: 9999 spring: application: name: eureka-server eureka: client: service-url: defultZone: HTTP://127.0.0.1:8888/eureka register-with-eureka: false #不注册自己 fetch-registry: false
-
controller
@RestController @RequestMapping("/consumer") public class ConsumerController { //使用负载均衡 @Autowired private RestTemplate restTemplate; //未使用负载均衡 @Autowired private DiscoveryClient discoveryClient; @RequestMapping("/{id}") @HystrixCommand //使用默认的defultFallback的时候,不需要参数 public String queryById(@PathVariable Long id){ //开启负载均衡算法前,通过ip地址与端口号来调用 /* List<ServiceInstance> instances = discoveryClient.getInstances("USER-SERVICE"); //根据配置文件中spring.application.name的属性值来获取服务列表 ServiceInstance serviceInstance = instances.get(0);//因为只有一个,因此就0下标 String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/user/" + id;//硬编码方式,不方便更改 */ //开启负载均衡算法后,通过服务名来调用 String url = "http://user-service/user/" + id; //返回结果 return restTemplate.getForObject(url,User.class).toString(); } }