一、SpringCloud简介
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
二、微服务的注册与发现-Eureka
Eureka是Netflix开源的服务发现组件,本身是基于Rest的服务,它包含服务端和客户端两部分;在SpringCloud中将它集成在其中,从而实现了微服务的发现与注册;
Eureka Server
- 服务端-没有存储,内存保持,每服务实例需要发送心跳去续约
- 客户端-在内存中缓存着eureka的注册信息,因此不必每请求到eureka查找服务
- eureka之间会做注册服务同步,从而保证状态一致,客户端只需访问一个eureka
Service Provider
- 会向Eureka Server做Register(服务注册)、Renew(服务续约)、Cancel(服务下线)等操作
Service Consumer
- 会向Eureka Server获取注册服务列表,并消费服务。
三、Ribbon简介
Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为。为Ribbon配置服务提供者地址列表后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多的负载均衡算法,例如:轮询,随机等,也可自定义;
四、实例
本实例在idea中实现,为了实现简单,代码有重复,主要来讲解实例。架构如下:
- eureka-keepalived-server1: eureka 注册中心
- eureka-keepalived-server2:eureka 注册中心
- eureka-ribbon-client1:服务消费者
- eureka-ribbon-client2:服务生产者,提供两个节点的服务
4.1、eureka-keepalived-server1
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.man</groupId>
<artifactId>eureka-keepalived-server1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-keepalived-server1</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR2</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>
application.properties
server.port=8881
spring.application.name=eureka-server-1
#表示是否将自己注册在EurekaServer上,默认为true。由于当前应用就是EurekaServer,所以置为false
eureka.client.register-with-eureka=true
#表示表示是否从EurekaServer获取注册信息,默认为true。单节点不需要同步其他的EurekaServer节点的数据
eureka.client.fetch-registry=true
#指定主机名
eureka.instance.hostname=server1
#设置EurekaServer的地址,将自身注册到Server2
eureka.client.service-url.defaultZone=http://server2:8882/eureka
#是否开启基本的鉴权
security.basic.enabled=false
SpingCloudEurekaServerApplication1.java
package com.man;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class SpingCloudEurekaServerApplication1 {
public static void main(String[] args) {
SpringApplication.run(SpingCloudEurekaServerApplication1.class, args);
}
}
4.2、eureka-keepalived-server2 配置类似
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.man</groupId>
<artifactId>eureka-keepalived-server2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-keepalived-server2</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR2</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>
application.properties
server.port=8882
spring.application.name=eureka-server-2
#表示是否将自己注册在EurekaServer上,默认为true。由于当前应用就是EurekaServer,所以置为false
eureka.client.register-with-eureka=true
#表示表示是否从EurekaServer获取注册信息,默认为true。单节点不需要同步其他的EurekaServer节点的数据
eureka.client.fetch-registry=true
#指定主机名
eureka.instance.hostname=server2
#设置EurekaServer的地址,将自身注册到Server2
eureka.client.service-url.defaultZone=http://server1:8881/eureka
#是否开启基本的鉴权
security.basic.enabled=false
SpingCloudEurekaServerApplication2.java
package com.man;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class SpingCloudEurekaServerApplication2 {
public static void main(String[] args) {
SpringApplication.run(SpingCloudEurekaServerApplication2.class, args);
}
}
更改hosts文件,加入以下配置,让server1 与server2 同时指向127.0.0.1
127.0.0.1 server1 server2
eureka-keepalived-server1 与eureka-keepalived-server2 为了方便,搭了两个服务来说明eureka集群,启动两个应用,访问
http://server1:8881 和 http://server2:8882
4.3、eureka-ribbon-client1 服务消费端
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.man</groupId>
<artifactId>eureka-ribbon-client1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-ribbon-client1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR2</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>
application.properties
server.port=9991
spring.application.name=client-9991
eureka.client.service-url.defaultZone=http://server1:8881/eureka/,http://server2:8882/eureka/
EurekaRibbonClientApplication1.java
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaRibbonClientApplication1 {
public static void main(String[] args) {
SpringApplication.run(EurekaRibbonClientApplication1.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
RibbonController.java 到注册中心查找具体服务
@RestController
public class RibbonController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/loadInstance")
public String loadInstance(){
ServiceInstance choose=this.loadBalancerClient.choose("client-9999");
String url=choose.getServiceId()+":"+choose.getHost()+":"+choose.getPort();
System.out.println(url);
return url;
}
}
继续启动消费端eureka-ribbon-client1,已经注册到注册中心中
4.4、eureka-ribbon-client2 服务生产端
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.man</groupId>
<artifactId>eureka-ribbon-client2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-ribbon-client2</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR2</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>
application.properties
server.port=9992
spring.application.name=client-9999
eureka.client.service-url.defaultZone=http://server1:8881/eureka/,http://server2:8882/eureka/
EurekaRibbonClientApplication2.java
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaRibbonClientApplication2 {
public static void main(String[] args) {
SpringApplication.run(EurekaRibbonClientApplication2.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
ClientController.java
@RestController
public class ClientController {
@GetMapping("getUser")
public String getUser(){
System.out.println("获得用户成功");
return "获得用户成功";
}
}
启动服务生产端1
服务生产端2 需要更改application.properties 文件,server.port=9993 端口改为9993
server.port=9993
spring.application.name=client-9999
eureka.client.service-url.defaultZone=http://server1:8881/eureka/,http://server2:8882/eureka/
用maven打jar包,在idea 外,用命令启动
java -jar eureka-ribbon-client2.jar
查看注册中心
访问:http://localhost:9991/loadInstance
负载均衡实现。