01.Eureka学习
父工程
dependencyManagement
对以来版本进行管理
<?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>comexample</groupId>
<artifactId>springCloudTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>eureka-service</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.12.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
<lombok.version>1.18.26</lombok.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
<mysql.version>8.0.33</mysql.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
服务注册
注册中心
新建一个springboot项目作为eureka服务的注册中心
<?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>comexample</groupId>
<artifactId>springCloudTest</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>eureka-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-service</name>
<description>eureka-service</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.12.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
配置application.yml
server:
# 应用服务 WEB 访问端口
port: 8080
spring:
application:
# 应用名称
name: eureka-service
eureka:
instance:
hostname: localhost
client:
# 是否将自己注册到注册中心
register-with-eureka: false
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
在启动类中标注
@EnableEurekaServer
注解启动项目,访问
http://localhost:8080/
,即可访问注册中心
服务的提供者
新建一个项目作为服务的提供者
<?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>comexample</groupId>
<artifactId>springCloudTest</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>provide-demo1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>provide-demo1</name>
<description>provide-demo1</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
logging:
pattern:
dateformat: MM-dd HH:mm:ss:SSS
mybatis-plus:
# 配置mybatis-plus 打印sql日志
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# mybatis-plus下划线转驼峰配置,默认为true
map-underscore-to-camel-case: true
global-config:
db-config:
# 配置全局默认主键类型,实体类不用加@TableId(value ="id",type = IdType.AUTO)
id-type: auto
# 1代表已经删除,0代表没有删除
logic-delete-value: 1
logic-not-delete-value: 0
# xml文件路径
mapper-locations: classpath:/mapper/**/*.xml
# 配置mybatis-plus 包路径
type-aliases-package: com.example.demo.domain
server:
# 应用服务 WEB 访问端口
port: 8081
spring:
application:
# 应用名称
name: provide-demo1
datasource:
# 数据库驱动
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据源名称
name: defaultDataSource
# 数据库用户名&密码
username: root
password: 123456
# 数据库连接地址
url: jdbc:mysql://localhost:3306/provider?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
eureka:
client:
# 是否将自己注册到注册中心
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:8080/eureka/
// 开启服务注册
@EnableEurekaClient
@MapperScan("com.example.mapper")
@SpringBootApplication
public class ProvideDemo1Application {
public static void main(String[] args) {
SpringApplication.run(ProvideDemo1Application.class, args);
}
}
此时,启动
provider-demo1
后,再次访问eureka注册中心可查看到该服务
服务的消费者
新建
consumer-demo
,步骤与新建服务的提供者一样
logging:
pattern:
dateformat: MM-dd HH:mm:ss:SSS
mybatis-plus:
# 配置mybatis-plus 打印sql日志
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# mybatis-plus下划线转驼峰配置,默认为true
map-underscore-to-camel-case: true
global-config:
db-config:
# 配置全局默认主键类型,实体类不用加@TableId(value ="id",type = IdType.AUTO)
id-type: auto
# 1代表已经删除,0代表没有删除
logic-delete-value: 1
logic-not-delete-value: 0
# xml文件路径
mapper-locations: classpath:/mapper/**/*.xml
# 配置mybatis-plus 包路径
type-aliases-package: com.example.demo.domain
server:
# 应用服务 WEB 访问端口
port: 9091
spring:
application:
# 应用名称
name: consumer-demo
datasource:
# 数据库驱动
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据源名称
name: defaultDataSource
# 数据库用户名&密码
username: root
password: 123456
# 数据库连接地址
url: jdbc:mysql://localhost:3306/consumer?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
eureka:
client:
# 是否将自己注册到注册中心
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:8080/eureka/
同理,消费者也注册到Eureka中了
RestTemplate
使用
RestTemplate
,通过消费者调用提供者的接口在调用接口之前,需要先将对应mysql的数据库准备好
provider
/*
Navicat Premium Data Transfer
Source Server : mysql-demo
Source Server Type : MySQL
Source Server Version : 80013 (8.0.13)
Source Host : localhost:3306
Source Schema : provide
Target Server Type : MySQL
Target Server Version : 80013 (8.0.13)
File Encoding : 65001
Date: 04/08/2023 23:10:12
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for provider
-- ----------------------------
DROP TABLE IF EXISTS `provider`;
CREATE TABLE `provider` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`age` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of provider
-- ----------------------------
INSERT INTO `provider` VALUES (1, '小王', '男', 12);
INSERT INTO `provider` VALUES (2, '大黄', '男', 15);
INSERT INTO `provider` VALUES (3, '阿丽', '女', 18);
SET FOREIGN_KEY_CHECKS = 1;
consumer
/*
Navicat Premium Data Transfer
Source Server : mysql-demo
Source Server Type : MySQL
Source Server Version : 80013 (8.0.13)
Source Host : localhost:3306
Source Schema : consumer
Target Server Type : MySQL
Target Server Version : 80013 (8.0.13)
File Encoding : 65001
Date: 04/08/2023 23:12:05
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for consumer
-- ----------------------------
DROP TABLE IF EXISTS `consumer`;
CREATE TABLE `consumer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of consumer
-- ----------------------------
INSERT INTO `consumer` VALUES (1, '皇妃', '湖北');
INSERT INTO `consumer` VALUES (2, '皇子', '湖南');
SET FOREIGN_KEY_CHECKS = 1;
使用
mybatisX
插件快速生成domain、mapper、service新建一个
common
项目,将通用的工具类以及依赖可放入其中,最后在服务的提供者
和消费者
中引入common依赖即可
json依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.31</version>
</dependency>
工具类R
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import java.util.HashMap;
import java.util.Map;
/**
* @author:93879
* @date:2023/06/09/23:31
* @description:
*/
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
/**
* 存元素 和setData的区别是 这个方法可以指定key的值
*/
@Override
public R put(String key, Object value) {
super.put(key, value);
return this;
}
public R setData(Object data) {
put("data", data);
return this;
}
/**
* 获取数据
* 远程调用服务时,另一个服务也会返回R类型的数据,这个方法可以获取key为data的value值
* 利用fastjson进行反序列化
*/
public <T> T getData(TypeReference<T> typeReference) {
Object data = get("data"); //默认是map
String jsonString = JSON.toJSONString(data);//转为json字符串
T t = JSON.parseObject(jsonString, typeReference);//转为对象
return t;
}
/**
* 利用fastjson进行反序列化
*/
public <T> T getData(String key, TypeReference<T> typeReference) {
Object data = get(key); //默认是map
//转为json字符串
String jsonString = JSON.toJSONString(data);//转为json字符串
//转成需要的对象
T t = JSON.parseObject(jsonString, typeReference);//转为对象
return t;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
//无参构造
public R() {
put("code", 200);
put("msg", "success");
}
//返回错误码500的错误,错误内容:未知异常,请联系管理员
public static R error() {
return error(500, "未知异常,请联系管理员");
}
//返回错误码500的错误,错误内容需要自己传入
public static R error(String msg) {
return error(500, msg);
}
//返回自定义错误码,自定义错误内容
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
//返回正常,内容需要自己传入
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
//存入多条返回消息
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
//默认返回 0 success
public static R ok() {
return new R();
}
//获取code(状态码)的值
public Integer getCode() {
return (Integer) this.get("code");
}
}
编写
providerController
@RestController
@RequestMapping("provider")
public class ProviderController {
@Autowired
private ProviderService providerService;
@GetMapping("/{id}")
public Provider findById(@PathVariable("id") Long id){
return providerService.getById(id);
}
@GetMapping("/list")
public List<Provider> findAll(){
return providerService.list();
}
}
接下来可以尝试使用
消费者
进行消费了
配置RestTemplate
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @Author: 93879
* @Date: 2023/08/04/23:07
* @Description:
*/
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getTemplate() {
return new RestTemplate();
}
}
consumerController
import com.example.service.ConsumerService;
import com.example.util.R;
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;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* @Author: 93879
* @Date: 2023/08/05/8:09
* @Description:
*/
@RestController
@RequestMapping("consumer")
public class ConsumerController {
private static final String PROVIDER_URL = "http://localhost:8081/provider/";
@Autowired
private ConsumerService consumerService;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/provider/{id}")
public R findProvider(@PathVariable("id") Integer id){
Object data = restTemplate.getForObject(PROVIDER_URL + id.toString(), Object.class);
return R.ok().setData(data);
}
@GetMapping("/providers/list")
public R findProvider(){
List data = restTemplate.getForObject(PROVIDER_URL + "list", List.class);
return R.ok().setData(data);
}
}
服务调用成功
但是这个时候朋友们就有疑惑了,所以Eureka干嘛了?就只是注册一下服务吗?
其实上面的代码有很大的
问题
,因为连提供者的url都是写成静态变量嵌入代码内的所以接下来需要对代码进行修改,不指定url,而是通过服务名来访问
consumerController
private static final String PROVIDER_URL = "http://PROVIDE-DEMO1/provider/";
ApplicationContextConfig
@Configuration
public class ApplicationContextConfig {
@Bean
// 开启负载均衡
@LoadBalanced
public RestTemplate getTemplate() {
return new RestTemplate();
}
}
本来以为没有配置集群时候,是不需要开启负载均衡的
但是也要开启,否则报错如下
08-05 08:38:45:271 ERROR 15288 --- [nio-9091-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://PROVIDE-DEMO1/provider/list": PROVIDE-DEMO1; nested exception is java.net.UnknownHostException: PROVIDE-DEMO1] with root cause
java.net.UnknownHostException: PROVIDE-DEMO1
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:196) ~[na:1.8.0_281]
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:162) ~[na:1.8.0_281]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394) ~[na:1.8.0_281]
at java.net.Socket.connect(Socket.java:606) ~[na:1.8.0_281]
at java.net.Socket.connect(Socket.java:555) ~[na:1.8.0_281]
Eureka集群
eureka集群的配置是将多个eureka注册中心互相注册
新建第二个eureka-service项目
修改hosts文件C:\Windows\System32\drivers\etc\hosts
向
hosts
文件内添加如下内容,用以区分两个服务
127.0.0.1 eureka1.server
127.0.0.1 eureka2.server
eureka-service1
server:
# 应用服务 WEB 访问端口
port: 8081
spring:
application:
# 应用名称
name: eureka-service1
eureka:
instance:
hostname: eureka1.server
client:
# 是否将自己注册到注册中心
register-with-eureka: false
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: false
service-url:
defaultZone: http://eureka2.server:8082/eureka/
eureka-service2
server:
# 应用服务 WEB 访问端口
port: 8082
spring:
application:
# 应用名称
name: eureka-service2
eureka:
instance:
hostname: eureka2.server
client:
# 是否将自己注册到注册中心
register-with-eureka: false
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: false
service-url:
defaultZone: http://eureka1.server:8081/eureka/
启动这两个
eureka-service
服务
服务注册成功
修改服务提供者和消费者的yml,注册至eureka集群
eureka:
client:
# 是否将自己注册到注册中心
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/
可以看到此时两个eureka注册中心都注册了provider和consumer
尝试调用consumer接口后成功
1.注册至eureka的服务并不是以服务名来命名,而是主机名
2.访问服务时希望提示ip地址
配置yml
provider
eureka:
instance:
instance-id: provider1-service
client:
# 是否将自己注册到注册中心
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/
consumer
eureka:
instance:
# 注册至eureka中心的名字,默认是主机名
instance-id: consumer-service
# 是否显示ip
prefer-ip-address: true
client:
# 是否将自己注册到注册中心
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/
现在需要新建一个提供者,将提供者也设置成集群
consumerController
private static final String PROVIDER_URL = "http://PROVIDE-DEMO/provider/";
provider-demo1
logging:
pattern:
dateformat: MM-dd HH:mm:ss:SSS
mybatis-plus:
# 配置mybatis-plus 打印sql日志
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# mybatis-plus下划线转驼峰配置,默认为true
map-underscore-to-camel-case: true
global-config:
db-config:
# 配置全局默认主键类型,实体类不用加@TableId(value ="id",type = IdType.AUTO)
id-type: auto
# 1代表已经删除,0代表没有删除
logic-delete-value: 1
logic-not-delete-value: 0
# xml文件路径
mapper-locations: classpath:/mapper/**/*.xml
# 配置mybatis-plus 包路径
type-aliases-package: com.example.demo.domain
server:
# 应用服务 WEB 访问端口
port: 8091
spring:
application:
# 应用名称
name: provide-demo
datasource:
# 数据库驱动
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据源名称
name: defaultDataSource
# 数据库用户名&密码
username: root
password: 123456
# 数据库连接地址
url: jdbc:mysql://localhost:3306/provider?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
eureka:
instance:
instance-id: provider1-service
client:
# 是否将自己注册到注册中心
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/
provider-demo2
logging:
pattern:
dateformat: MM-dd HH:mm:ss:SSS
mybatis-plus:
# 配置mybatis-plus 打印sql日志
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# mybatis-plus下划线转驼峰配置,默认为true
map-underscore-to-camel-case: true
global-config:
db-config:
# 配置全局默认主键类型,实体类不用加@TableId(value ="id",type = IdType.AUTO)
id-type: auto
# 1代表已经删除,0代表没有删除
logic-delete-value: 1
logic-not-delete-value: 0
# xml文件路径
mapper-locations: classpath:/mapper/**/*.xml
# 配置mybatis-plus 包路径
type-aliases-package: com.example.demo.domain
server:
# 应用服务 WEB 访问端口
port: 8092
spring:
application:
# 应用名称
name: provide-demo
datasource:
# 数据库驱动
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据源名称
name: defaultDataSource
# 数据库用户名&密码
username: root
password: 123456
# 数据库连接地址
url: jdbc:mysql://localhost:3306/provider?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
eureka:
instance:
instance-id: provider2-service
client:
# 是否将自己注册到注册中心
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/
记住将多个提供者的服务名配置成同一个
为了区分到底调用的是
提供者1
还是提供者2
,稍微改改代码即可
![]](https://img-blog.csdnimg.cn/400ea29625ee4ef3ab689be81b3061ed.png)
所以这里需要涉及到
负载均衡
的策略了(默认轮询
)
服务发现
可以通过服务发现来获取该服务的信息
mport com.example.domain.Provider;
import com.example.service.ProviderService;
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 java.util.HashMap;
import java.util.Map;
/**
* @Author: 93879
* @Date: 2023/08/05/7:57
* @Description:
*/
@RestController
@RequestMapping("provider")
public class ProviderController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/discovery")
public Map<String,Object> discovery(){
Map<String, Object> map = new HashMap<>();
map.put("services",discoveryClient.getServices());
for (ServiceInstance instance : discoveryClient.getInstances("PROVIDE-DEMO")) {
map.put("Host",instance.getHost());
map.put("Port",instance.getPort());
map.put("Uri",instance.getUri());
map.put("InstanceId",instance.getInstanceId());
map.put("ServiceId",instance.getServiceId());
map.put("Metadata",instance.getMetadata());
map.put("Scheme",instance.getScheme());
}
return map;
}
}
Eureka自我保护
保护模式主要用于一 组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,
Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式:
可能导致的问题
1.某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存
2.属于分布式CAP里面的AP分支(保证高可用、分区容错性),在Consul里讲到
禁用自我保护
eureka-service
eureka:
instance:
hostname: eureka1.server
# 注册至eureka中心的名字,默认是主机名
instance-id: eureka-service1
# 是否显示ip
prefer-ip-address: true
client:
# 是否将自己注册到注册中心
register-with-eureka: false
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: false
service-url:
defaultZone: http://eureka2.server:8082/eureka/
server:
# 关闭自我保护机制
enable-self-preservation: false
eviction-interval-timer-in-ms: 2000
provider/consumer
eureka:
instance:
# 注册至eureka中心的名字,默认是主机名
instance-id: consumer-service
# 是否显示ip
prefer-ip-address: true
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease- renewal-interval- in-seconds: 3
#Eureka,服务端在收到最后-次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
lease-expiration-duration-in-seconds: 5
client:
# 是否将自己注册到注册中心
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。 单节点无所谓, 集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka1.server:8081/eureka/,http://eureka2.server:8082/eureka/