项目结构
spring-cloud-parent:主项目
eureka-consumer:消费者
eureka-provider:生产者
eureka-server:提供者
eureka-server-1:提供者1
eureka-server-2:提供者2
spring-cloud-parent 父工程
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>com.hikktn</groupId>
<artifactId>spring-cloud-parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka-consumer</module>
<module>eureka-provider</module>
<module>eureka-server</module>
<module>eureka-server-1</module>
<module>eureka-server-2</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/>
</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 版本-->
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
</properties>
<!--引入Spring Cloud 依赖-->
<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>
</project>
eureka-consumer 子工程
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>
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.hikktn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>eureka-consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 9000
# eureka 配置
eureka:
instance:
# 主机名
hostname: localhost
# 是否将自己的ip注册到eureka中
prefer-ip-address: true
# 设置当前实例ip
ip-address: 127.0.0.1
# 设置web控制台显示的实例id
instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port}
client:
service-url:
# eureka 服务端地址,客户端使用该地址和enreka创建连接
defalutZone: http://localhost:8761/eureka
spring:
application:
# 设置当前应用的名称,将来在eureka中使用application获取地址
name: eureka-consumer
bean
package com.hikktn.entity;
import java.io.Serializable;
/**
* @ClassName Goods
* @Description 商品实体类
* @Author lisonglin
* @Date 2021/4/12 14:40
* @Version 1.0
*/
public class Goods implements Serializable {
private int id;
// 商品标题
private String title;
// 商品价格
private double price;
// 商品库存
private int count;
public Goods() {
}
public Goods(int id, String title, double price, int count) {
this.id = id;
this.title = title;
this.price = price;
this.count = count;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "Goods{" + "id=" + id + ", title='" + title + '\'' + ", price=" + price + ", count=" + count + '}';
}
}
配置类
package com.hikktn.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @ClassName RestTemplateConfig
* @Description TODO
* @Author lisonglin
* @Date 2021/4/12 15:24
* @Version 1.0
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
控制器
package com.hikktn.controller;
import com.hikktn.entity.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* @ClassName OrderController
* @Description 服务的消费方
* @Author lisonglin
* @Date 2021/4/12 14:51
* @Version 1.0
*/
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/goods/{id}")
public Goods findOne(@PathVariable("id") int id) {
System.out.println("comuser调用了");
//
List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER");
if (instances == null || instances.size() <= 0) {
return null;
}
ServiceInstance serviceInstance = instances.get(0);
// 获取ip
String host = serviceInstance.getHost();
// 获取端口
int port = serviceInstance.getPort();
System.out.println("ip:"+host+",port:"+port);
String url = "http://" + host + ":" + port + "/goods/findOne/" + id;
Goods goods = restTemplate.getForObject(url, Goods.class);
System.out.println(goods);
return goods;
}
}
启动类
package com.hikktn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @ClassName ProviderApp
* @Description TODO
* @Author lisonglin
* @Date 2021/4/12 14:37
* @Version 1.0
*/
@EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApp {
public static void main(String[] args){
SpringApplication.run(ConsumerApp.class,args);
}
}
eureka-provider 子工程
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">
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.hikktn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>enreka-provider</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 8080
# eureka 配置
eureka:
instance:
# 主机名
hostname: localhost
# 是否将自己的ip注册到eureka中
prefer-ip-address: true
# 设置当前实例ip
ip-address: 127.0.0.1
# 设置web控制台显示的实例id
instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port}:@project.version@
client:
service-url:
# eureka 服务端地址,客户端使用该地址和eureka创建连接
defalutZone: http://localhost:8761/eureka
spring:
application:
# 设置当前应用的名称,将来在eureka中使用application获取地址
name: eureka-provider
bean
package com.hiktn.entity;
import java.io.Serializable;
/**
* @ClassName Goods
* @Description 商品实体类
* @Author lisonglin
* @Date 2021/4/12 14:40
* @Version 1.0
*/
public class Goods implements Serializable {
private int id;
// 商品标题
private String title;
// 商品价格
private double price;
// 商品库存
private int count;
public Goods() {
}
public Goods(int id, String title, double price, int count) {
this.id = id;
this.title = title;
this.price = price;
this.count = count;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "Goods{" + "id=" + id + ", title='" + title + '\'' + ", price=" + price + ", count=" + count + '}';
}
}
dao
package com.hiktn.dao;
import com.hiktn.entity.Goods;
import org.springframework.stereotype.Repository;
/**
* @ClassName GoodsDao
* @Description TODO
* @Author lisonglin
* @Date 2021/4/12 14:42
* @Version 1.0
*/
@Repository
public class GoodsDao {
public Goods findOne(int id){
// 这里是从数据库中查询得出
return new Goods(1,"小米手机",1999.0,50);
}
}
service
package com.hiktn.service;
import com.hiktn.dao.GoodsDao;
import com.hiktn.entity.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ClassName GoodsService
* @Description TODO
* @Author lisonglin
* @Date 2021/4/12 14:44
* @Version 1.0
*/
@Service
public class GoodsService {
@Autowired
private GoodsDao goodsDao;
public Goods findOne(int id){
return goodsDao.findOne(id);
}
}
控制器
package com.hiktn.controller;
import com.hiktn.entity.Goods;
import com.hiktn.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName GoodsController
* @Description 服务的提供方
* @Author lisonglin
* @Date 2021/4/12 14:45
* @Version 1.0
*/
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private GoodsService goodsService;
@GetMapping("/findOne/{id}")
public Goods findOne(@PathVariable("id") int id){
return goodsService.findOne(id);
}
}
启动类
package com.hiktn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @ClassName ProviderApp
* @Description TODO
* @Author lisonglin
* @Date 2021/4/12 14:37
* @Version 1.0
*/
@SpringBootApplication
@EnableEurekaClient
public class ProviderApp {
public static void main(String[] args){
SpringApplication.run(ProviderApp.class,args);
}
}
eureka-server 子工程
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">
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.hikktn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 8761
# eureka 配置
eureka:
instance:
# 主机名
hostname: localhost
dashboard:
enabled: true
path:
client:
service-url:
# eureka 服务端地址,客户端使用该地址和enreka创建连接
defalutZone: http://${eureka.instance.hostname}:${server.port}/eureka
# 是否将路径注册到eureka,但在服务端不需要注册,客户端才需要注册
register-with-eureka: false
# 是否需要从eureka中抓取路径
fetch-registry: false
启动类
package com.hikktn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @ClassName ProviderApp
* @Description TODO
* @Author lisonglin
* @Date 2021/4/12 14:37
* @Version 1.0
*/
@SpringBootApplication
@EnableEurekaServer
public class ServerApp {
public static void main(String[] args){
SpringApplication.run(ServerApp.class,args);
}
}
测试单机
将三个服务启动
访问
集群搭建
更改eureka-provide的application.yml配置
client:
service-url:
# eureka 服务端地址,客户端使用该地址和eureka创建连接
# defalutZone: http://localhost:8761/eureka
# 高可用
defalutZone: http://eureka-server1:8761/eureka,http://eureka-server2:8762/eureka
更改eureka-consumer的application.yml配置
client:
service-url:
# eureka 服务端地址,客户端使用该地址和enreka创建连接
# defalutZone: http://localhost:8761/eureka
defalutZone: http://eureka-server1:8761/eureka,http://eureka-server2:8762/eureka
更改host文件,如果以后是多台机器,那么端口号就不需要更改,只是对应的ip地址需要更改
C:\Windows\System32\drivers\etc\hosts
# 测试springcloud高可用
127.0.0.1 eureka-server1
127.0.0.1 eureka-server2
eureka-server-1 子工程
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">
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.hikktn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server-1</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 8761
# eureka 配置
eureka:
instance:
# 主机名
hostname: eureka-server1
client:
service-url:
# eureka 服务端地址,客户端使用该地址和eureka创建连接
defalutZone: http://eureka-server2:8762/eureka
# 这里是为了方便测试,才设置true
# 是否将路径注册到eureka,但在服务端不需要注册,客户端才需要注册
register-with-eureka: true
# 是否需要从eureka中抓取路径
fetch-registry: true
spring:
application:
name: eureka-server-hity
启动类
package com.hikktn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @ClassName ProviderApp
* @Description TODO
* @Author lisonglin
* @Date 2021/4/12 14:37
* @Version 1.0
*/
@SpringBootApplication
@EnableEurekaServer
public class Server1App {
public static void main(String[] args){
SpringApplication.run(Server1App.class,args);
}
}
eureka-server-2 子工程
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">
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>com.hikktn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server-2</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
server:
port: 8762
# eureka 配置
eureka:
instance:
# 主机名
hostname: eureka-server2
client:
service-url:
# eureka 服务端地址,客户端使用该地址和enreka创建连接
defalutZone: http://eureka-server1:8761/eureka
# 是否将路径注册到eureka,但在服务端不需要注册,客户端才需要注册
register-with-eureka: true
# 是否需要从eureka中抓取路径
fetch-registry: true
spring:
application:
name: eureka-server-hity
启动类
package com.hikktn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @ClassName ProviderApp
* @Description TODO
* @Author lisonglin
* @Date 2021/4/12 14:37
* @Version 1.0
*/
@SpringBootApplication
@EnableEurekaServer
public class Server2App {
public static void main(String[] args){
SpringApplication.run(Server2App.class,args);
}
}
测试集群
注意:第二个eureka-server-2项目,因为我是复制的,需要重新编译一下,才能进行正常的运作,否则application.yml文件不会编译,启动时配置文件不加载,端口默认为8080,这时你就需要编译项目。
浏览器输入:http://eureka-server1:8761/
浏览器输入:http://eureka-server2:8762/
再次访问
这时,停掉eureka-server-1服务
再次访问,依然能够访问成功!
而eureka-server-1已经挂掉了
eureka-server-2依然能够访问,但是会出现警告,表示你的某个服务已经挂掉了。