目录
快速创建一个springcloud项目
主要提示:springcloud 是建立在 springboot基础上的,注意两者版本的兼容性。
该demo的 springboot版本:2.0.5.RELEASE
springcloud版本:Finchley.SR1
jdk版本:1.8
技术栈:spring cloud、eureka、zuul、config
一、文件目录
二、创建总工程
1.创建一个总的maven工程,然后将里边的src文件删除,保留pom.xml文件,其他配置文件可以隐藏起来,便于目录清晰。
2.在最大的工程下建立若干小的maven服务。下面依次举例。
总的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>
<packaging>pom</packaging>
<modules>
<--创建子微服务后,会自动在此处添加微服务的名称-->
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yy</groupId>
<artifactId>spring-cloud-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-demo</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>
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
</properties>
<dependencies>
</dependencies>
<--dependencyManagement可以管理整个功能的包的版本,在此处引入版本后,在具体的微服务中导报,不需再添加版本-->
<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>
三、创建Netflix Eureka服务注册中心
作用:服务注册和发现。其他微服务都将注册到eureka。
Spring Cloud还支持其他多种服务注册中心,如:Consul、Zookeeper。
1服务端:
1.1导包
<--springboot的包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<--cloud的包-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
1.2.配置文件application.yml
server:
port: 1000
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false #是否向 Eureka 注册服务。该应用为服务注册中心,不需要自注册,设置为 false(如有多个注册中心,可相互注册)
fetchRegistry: false # 是否检索服务。该应用为服务注册中心,职责为注册和发现服务,无需检索服务,设置为false
serviceUrl:
defaultZone: http://localhost:1000/eureka/ #注册中心的注册地址 ,其他微服务需要向这个地址注册
1.3.主类 EurekaServerApplication1000
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer//开启注册中心
public class EurekaServerApplication1000 {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication1000.class);
}
}
2.客户端配置
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/ #注册到中心地址,可配置多个。如:1000,1001两个注册中心(集群的方式)
验证:访问:localhost:1010 。如果其他服务注册再这上面,会显示出来。
四、创建网关zuul服务。
作用:1.微服务的关口,对外只暴露网关的端口和ip,发起请求到网关,然后由网关去连接对应的服务。
2.netflix-zuul 集成了 Ribbon和Hystix,所以有负载均衡和熔断机制。
3.过滤:可用来完成身份认证安全、审查与监控、动态路由、压力测试、负载分配等。如下图:(该点作为一个大模块在后面讲)
目录:
1.导包
<!--spring-boot-->
<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>
<!--netflix-zuul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
2.配置文件application.yml
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1010/eureka/ #注册中心地址
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: zuul-server #指定服务的id
server:
port: 1020
spring:
application:
name: zuul-server
zuul:
prefix: "/hrm" #统一前缀
ignored-services: "*" #隐射机制,除了自己,其他服务的配置都不会向外界暴露
routes:
system-server: "/system/**" #访问对应服务下,需添加的固定前缀(可添加多个服务,如下面的user_server)
user-server: "/user/**"
retryable: true #开启ribbond的重试机制,默认为false(ribbon实现了负载均衡,如果访问某服务的A节点超时后,会触发ribbon的重试机制)
#Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制
ribbon:
ConnectTimeout: 2000 # 连接超时时间(ms)
ReadTimeout: 2000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 3000 # 熔断超时时长:3000ms
3.主类ZuulServerApplication1020
@SpringBootApplication
@EnableZuulProxy //开启zuul的注解
@EnableDiscoveryClient //可被注册中心扫描到
public class ZuulServerApplication1020 {
public static void main(String[] args) {
SpringApplication.run(ZuulServerApplication1020.class);
}
}
四、zuul网关的过滤器
zuul:可用来完成身份认证安全、审查与监控、动态路由、压力测试、负载分配等。
1. ZuulFilter是过滤器的顶级父类。在这里我们看一下其中定义的4个最重要的方法:
public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> { public abstract String filterType(); 返回字符串,有四种类型: - pre:请求在被路由之前执行 - routing:在路由请求时调用 - post:在routing和errror过滤器之后调用 - error:处理请求时发生错误调用
public abstract int filterOrder();//通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。
boolean shouldFilter();//返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。 Object run() throws ZuulException;//过滤器的具体业务逻辑。
}
- 正常流程:
- 请求到达首先会经过pre类型过滤器,而后到达routing类型,进行路由,请求就到达真正的服务提供者,执行请求,返回结果后,会到达post过滤器。而后返回响应。
- 异常流程:
- 整个过程中,pre或者routing过滤器出现异常,都会直接进入error过滤器,再error处理完毕后,会将请求交给POST过滤器,最后返回给用户。
- 如果是error过滤器自己出现异常,最终也会进入POST过滤器,而后返回。
- 如果是POST过滤器出现异常,会跳转到error过滤器,但是与pre和routing不同的时,请求不会再到达POST过滤器了。
场景非常多:
- 请求鉴权:一般放在pre类型,如果发现没有访问权限,直接就拦截了
- 异常处理:一般会在error类型和post类型过滤器中结合来处理。
- 服务调用时长统计:pre和post结合使用。
2.自定义过滤器
@Component
public class LoginFilter extends ZuulFilter{
@Override
public String filterType() {
// 登录校验,肯定是在前置拦截
return "pre";
}
@Override
public int filterOrder() {
// 顺序设置为1
return 1;
}
@Override
public boolean shouldFilter() {
// login 路径要放行,不需要检查登录
//请求对象
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
//访问路径
if (request.getRequestURI().contains("login")){
return false;
}
return true;
}
@Override
public Object run() throws ZuulException {
// 登录校验逻辑。
// 1)获取Zuul提供的请求上下文对象
RequestContext ctx = RequestContext.getCurrentContext();
// 2) 从上下文中获取request对象
HttpServletRequest req = ctx.getRequest();
// 3) 从请求中获取token
String token = req.getParameter("access-token");
// 4) 判断
if(token == null || "".equals(token.trim())){
// 没有token,登录校验失败,拦截
ctx.setSendZuulResponse(false);
// 返回401状态码。也可以考虑重定向到登录页。
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
// 校验通过,可以考虑把用户信息放入上下文,继续向后执行
return null;
}
}
五、创建配置中心config服务。
目的:配置统一管理,上到到云端,服务端直接调用云端的配置。免费的云端如:github,码云
前提:
- Git的安装(省略)
- 和idea集成 和 操作(省略)
- 申请(云端账号,创建仓库)
1.服务端:创建config服务
1.1.导包(服务端的包)
<!--spring-boot 服务端的包-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!--spring-boot-->
<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>
1.2.配置application.yml
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1010/eureka/ #注册中心地址
instance:
prefer-ip-address: true #将IP注册到Eureka Server上
instance-id: config-server #用该名代替ip名
server:
port: 1030
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://gitee.com/yemanrenyy/hrm-parent.git #配置远程仓库地址
username: 17313115223 #仓库名称
password: YANG199232@ #仓库密码
1.3.配置主类ConfigServerApplication1030
@SpringBootApplication
@EnableConfigServer #开启config
@EnableDiscoveryClient
public class ConfigServerApplication1030 {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication1030.class);
}
}
- 其他服务使用config服务
- 上传配置到git配置中心
- 导包(客户端的包)
2.客户端
前提:已经将配置上传到git配置中心
2.1 导客户端的包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
2.2配置文件bootstrap.yml
- 将application.yml 配置删掉,改为bootstrap.yml
- (bootstrap.yml的优先级高于application.yml )
spring:
cloud:
config:
uri: http://localhost:1030 #配置中心的ip+端口
name: application-systemmanage #配置中心文件名的前面部分 (完整的是application-systemmanage-dev )
profile: dev #配置中心文件名的最后部分
label: master #分支
六.Ribbon 和 feign介绍
都是实现服务与服务的调用 和 集群的负载均衡。
调用而言:
Ribbon :通过RestTemplate调用其它服务的API,需自己拼接在请求的URL中,效率低下。基于Ribbon和Hystrix。
Feign:整合Ribbon和Hystrix,以接口方式进行调用,底层还是ribbon,它进行了封装,但是调用起来更方便。
Feign具有如下特性:
可插拔的注解支持,包括Feign注解和JAX-RS注解;
支持可插拔的HTTP编码器和解码器;
支持Hystrix和它的Fallback;
支持Ribbon的负载均衡;
支持HTTP请求和响应的压缩。
6.1、服务集成Ribbon。
需借助RestTemplate,SpringMvc提供的一个基于Rest风格的http调用工具。
A 调用B服务,则再A服务中进行如下操作。
6.1.1 导包
<!--引入ribbon负载均衡器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!--集成Hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
6.1.2 主类上开启Hustrix
@SpringBootApplication
@EnableDiscoveryClient
@EnableHustrix (@EnableCircuitBreaker //开启Hystrix效果一样)
public class OrderServerApplication3000 {
public static void main(String[] args) {
SpringApplication.run(OrderServerApplication3000.class);
}
}
6.1.3.创建配置类
//配置类放在这里就行,会自动调用
@Configuration
public class MyConfig {
//SpringMvc提供的一个基于Rest风格的http调用工具
@Bean
@LoadBalanced //ribbon的负载均衡标签,赋予RestTemplate有负债均衡的能力
public RestTemplate restTemplate(){
return new RestTemplate();
}
// 负载均衡 默认是沦序策略,这里可以更改为随机策略
@Bean
public IRule rule(){
return new RandomRule();
}
}
Ribbon的负载均衡策略:
RoundRobinRule(默认) | 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。 |
AvailabilityFilteringRule | 对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 注意:可以通过修改配置loadbalancer.<clientName>.connectionFailureCountThreshold来修改连接失败多少次之后被设置为短路状态。默认是3次。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上线,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。 |
WeightedResponseTimeRule | 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
|
|
|
|
| 随机选择一个可用的服务器。 |
Retry | 重试机制的选择逻辑 |
6.1.4 controller中的写法 。。(需要自己拼接url)
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/order/user/{id}")
@HystrixCommand(fallbackMethod = "getUserByIdFallback") //利用Hystrix执行回调方法
public JsonResult getUserById(@PathVariable("id") Long id){
//String url = "http://localhost:2000/user/"+id;
String url = "http://user-server:2000/user/"+id; //order服务调取user服务,服务名ser-server,user端口号2000, /user/"+id 为controller的访问路径
User user = restTemplate.getForObject(url, User.class);
return JsonResult.me().setObject(user).setMsg("成功");
}
//失败的回调方法
public JsonResult getUserByIdFallback(@PathVariable("id") Long id){
return JsonResult.me().setMsg("失败").setSuccess(false);
}
}
6.2、服务集成feign。
如 A 服务 调用B服务。
A服务配置:
a.导包(注意:引入feign的包后,就不能由ribbon的包)
<!--引入Feign负载均衡器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
b.主类加注解
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients("cn.itsource.client") //开启feign,后面跟所在包的路径
public class DeptServerApplication4000 {
public static void main(String[] args) {
SpringApplication.run(DeptServerApplication4000.class);
}
}
c.创建客户端。(写一个接口)
import cn.itsource.domain.User;
import cn.itsource.fallback.UserFeignClientFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* Feign是如何实现服务调用的:
* 1.通过@FeignClient(value="user-server")标签上的服务名字能够找到要调用的目标服务
* 2.通过接口中的方法的 @GetMapping的url路径找到目标服务的controller的方法 ,
* 所以要保证Feign客户端接口的方法和目标服务的对应的方法要完全一致。
/
@FeignClient(value = "user-server",fallback = UserFeignClientFallback.class) //前面是A服务的服务名,后面是回调的类
public interface UserFeignClient {
@GetMapping("/user/{id}")
public User getUserById(@PathVariable("id") Long id); //被调用的服务方法,但是没有方法体
}
d.回调的类
import cn.itsource.client.UserFeignClient;
import cn.itsource.domain.User;
import org.springframework.stereotype.Component;
//需实现调用的客户端
@Component
public class UserFeignClientFallback implements UserFeignClient {
@Override
public User getUserById(Long id) {
return new User(-1L,"喔嚯,失败了" );
}
}
e.配置上加
feign:
hystrix:
enabled: true #开启熔断支持
client:
config:
remote-service: #服务名,填写default为所有服务
connectTimeout: 30000
readTimeout: 30000
#feign集成hystrix
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 30000
f.controller直接调用客户端
@RestController
public class DeptController {
@Autowired
private UserFeignClient userFeignClient; //创建客户端对象
@GetMapping("/dept/user/{id}")
public User getUserById(@PathVariable("id") Long id){
User user = userFeignClient.getUserById(id);
return user;
}
}
七.集成Hystrix
Hystrix断路器:Hystrix就是处理依赖隔离的框架,同时也是可以帮我们做依赖服务的治理和监控,
Hystrix是保证微服务群健壮框架,做了隔离,熔断,降级等操作.最终达到不会由于某一个服务出问题而导致雪崩现象,让整体群死掉,实现高可用。
通过如下机制来解决雪崩效应问题。
资源隔离(限流):包括线程池隔离和信号量隔离,限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务调用。
熔断:当失败率达到阀值自动触发降级(如因网络故障/超时造成的失败率高),熔断器触发的快速失败会进行快速恢复。
降级机制:超时降级、资源不足时(线程或信号量)降级,降级后可以配合降级接口返回托底数据。
缓存:提供了请求缓存、请求合并实现。
使用:(如上面ribbon的回调,就是用了Hystrix)
a.导包
<!--集成Hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
b.主类上打注解。
@EnableHustrix (@EnableCircuitBreaker //开启效果一样)
c.方法上加注解HystrixCommand(fallbackMethod = "getUserByIdFallback"),后边是回调的方法
注意:
1.如果我们服务消费者实现的技术为ribbon,必须在服务提供者方通过Hystrix的断路器.
2.如果我们服务消费者实现的技术为feign,必须在服务消费者通过feign的断路器,feign断路器底层还是Hystrix的断路器.
3.如下熔断、超时是配置是服务端,如A服务配置了,去调用B服务,那就就配置在A服务
feign:
hystrix:
enabled: true #开启熔断支持
client:
config:
remote-service: #服务名,填写default为所有服务
connectTimeout: 3000
readTimeout: 3000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
八.解决跨域问题
在zuul上加一个配置类
package cn.itsource.hrm.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//1) 允许的域,不要写*,否则cookie就无法使用了
config.addAllowedOrigin("http://127.0.0.1:6001");
config.addAllowedOrigin("http://localhost:6001");
//2) 是否发送Cookie信息
config.setAllowCredentials(true);
//3) 允许的请求方式
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
// 4)允许的头信息
config.addAllowedHeader("*");
//2.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new
UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}
九、自定义全局异常
1.导包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.自定义异常
public class GlobalException1 extends RuntimeException {
public GlobalException(String message){
super(message);
}
}
3.拦截异常
ControllerAdvice:对controller增强的标签,可以在其他的controller执行前,后去做一些事情,所以监控所有的controller的异常
/**
* 对controller增强的标签ControllerAdvice
* 他可以在其他的controller执行前,后去做一些事情
* 那这个方法就可以在其他的controller执行报异常后执行相关的异常的方法
注意:异常从上到下,应该依次从小到大
*/
@ControllerAdvice
@ResponseBody
public class CommonExceptionHandler {
//处理自定义异常1
@ExceptionHandler(GlobalException1.class)
public AjaxResult globalExceptionHandler(GlobalException e){
e.printStackTrace();
return AjaxResult.me().setSuccess(false).setMessage(e.getMessage());
}
/处理自定义异常2
@ExceptionHandler(GlobalException2.class)
public AjaxResult globalExceptionHandler(GlobalException e){
e.printStackTrace();
return AjaxResult.me().setSuccess(false).setMessage(e.getMessage());
}
//处理其他异常
@ExceptionHandler(Exception.class)
public AjaxResult exceptionHandler(Exception e){
e.printStackTrace();
return AjaxResult.me().setSuccess(false).setMessage("程序异常啦,我们正在殴打程序员!!!");
}
}
十、eureka做集群
除了application.yml配置不一样,其他都一样。配置如下: 操作方式,eureka之间相互注册,其他服务要注册到所有的注册中心 eureka服务一:
server:
port: 1000
eureka:
instance:
hostname: peer1
client:
registerWithEureka: false #禁用注册中心向自己注册
fetchRegistry: false #不让注册中心获取服务的注册列表
serviceUrl:
defaultZone: http://peer2:1001/eureka/
#注册中心的注册地址 ,其他微服务需要向这个地址注册
eureka服务二:
server:
port: 1001
eureka:
instance:
hostname: peer2
client:
registerWithEureka: false #禁用注册中心向自己注册
fetchRegistry: false #不让注册中心获取服务的注册列表
serviceUrl:
defaultZone: http://peer1:1000/eureka/
#注册中心的注册地址 ,其他微服务需要向这个地址注册
其他
其他服务:
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/ #两个注册中心地址
instance:
prefer-ip-address: true
instance-id: order-server #服务名
十一、服务做集群
普通服务做集群,原理:除了配置文件,其他都一样。
配置:每个服务拥有自己的端口号和注册到注册中心的ip..,但是对外暴露的服务名是一样的。如下:
服务一:
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/ #注册中心地址
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: user-server1 #指定服务的id
server:
port: 2000
spring:
application:
name: user-server
服务二:
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1000/eureka/,http://peer2:1001/eureka/ #注册中心地址
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: user-server2 #指定服务的id
server:
port: 2001
spring:
application:
name: user-server