springCloud和SpringBoot是配套的,不是所有的依赖都可以使用的,需要去官网查看相应的依赖搭配,演示使用的依赖版本是
springBoot:2.3.12RELEASE springCloud:Hoxton.SR12
以下图片显示为eureka-cli-01和eureka-cli-02
后期均改为eureka-cli-a和eureka-cli-b
创建一个springBoot项目,前面步骤都一样,最后导入依赖如下
创建完成后,我们打开pom.xml配置文件修改版本
修改完成后我们去application.yml
配置文件里面进行配置
#v eureka 默认端口号
server:
port: 8761
# 应用名称
spring:
application:
name: eureka-server
配置完成后,我们最后在启动类上加上注解@EnableEurekaServer
就可以了
然后我们启动项目,然后就可以在控制台看到启动成功信息
最后我们打开浏览器,访问http://localhost:8761
就可以看到服务注册了
也是创建一个SpringBoot项目,但是依赖导入的需要修改
创建完成后和服务端一样,手动修改下pom.xml
的springboot和springcloud依赖
修改完成后,我们去application.yml
配置文件进行配置
server:
port: 8080 # 客户端 端口号没有约束
spring:
application:
name: eureka-cli-a
# 注册的含义就是将自己的一些信息发送过去,发送到指定地址
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
修改完配置文件后,在启动类增加注解@EnableEurekaClient
注解,然后启动项目。
启动完成后,我们刷新服务端的页面,然后就可以看到会多出来一个服务
我们使用相同的方法,再搭建一个客户端方便后面测试
让a这个cli起两台,就是搭建个集群操作
2.1、方法一:再创建一个项目,然后再配置文件修改端口号(项目名称和地址不修改),步骤太简单,就不操作了
2.2、方法二:复制配置文件,然后启动的时候修改端口号
修改完后,我们点击Apply
,然后启动这个配置文件
启动完成后,我们再次刷新页面,就可以看到我们新添加的客户端了
eureka的配置分为三类:server client 实例的
server端 server 和 实例的配置
# eureka 默认端口号
server:
port: 8761
# 应用名称 不要使用特殊字符
spring:
application:
name: eureka-server
eureka:
server:
eviction-interval-timer-in-ms: 10000 # 服务端间隔多少毫秒做定期删除的操作
renewal-percent-threshold: 0.85 #续约百分比,超过85%的应用没有和你续约,那么eureka会保护服务 不会剔除任何客户端
instance:
hostname: localhost #主机名称 或者服务的ip
# 主机名称 : 应用名称 : 端口号
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
prefer-ip-address: true # 以ip的形式显示具体的服务信息
lease-renewal-interval-in-seconds: 5 #服务实例的续约时间
配置完成后,我们关闭所有服务,然后启动当前服务
启动完成后,我们刷新页面,查看我们配置的结果
客户端 client 和 实例的配置
server:
port: 8080 # 客户端 端口号没有约束
spring:
application:
name: eureka-cli-a
eureka:
client:
service-url: # 指定注册的地址
defaultZone: http://localhost:8761/eureka
register-with-eureka: true # 可以不往Eureka注册
fetch-registry: true # 应用是否去拉取服务列表到本地
registry-fetch-interval-seconds: 10 # 为了缓解服务列表的脏读问题 时间越短脏读越少 性能消耗大
instance:
hostname: localhost
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
prefer-ip-address: true # 显示ip
lease-renewal-interval-in-seconds: 10 # 实例续约的时间
配置完成后,启动项目,然后刷新页面,查看效果
去中心化模式集群中没有主从的概念
eureka会将数据进行广播和扩散
在搭建之前,我们要先理解,Eureka服务端,其实就是一个可以让别人注册的客户端,自己也可以注册自己
创建三个Eureka-server项目
创建的步骤全部都和第一个一样,创建springboot
项目,引入Eureka Server
依赖,启动类加上@EnableEurekaServer
注解
创建好后,我们开始一个一个修改配置文件
eureka-server的配置文件
# eureka 默认端口号
server:
port: 8761
# 应用名称 不要使用特殊字符
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://localhost:8762/eureka,http://localhost:8763/eureka
instance:
hostname: localhost #主机名称 或者服务的ip
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
另外两个和这个差不多,只不过把端口 和 defaultZone
的值修改一下
eureka-server-b的配置文件
# eureka 默认端口号
server:
port: 8762
# 应用名称 不要使用特殊字符
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka,http://localhost:8763/eureka
instance:
hostname: localhost #主机名称 或者服务的ip
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
eureka-server-c的配置文件
# eureka 默认端口号
server:
port: 8763
# 应用名称 不要使用特殊字符
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka
instance:
hostname: localhost #主机名称 或者服务的ip
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
修改完配置文件后,我们依次启动项目,控制台会报错,不用管。
启动完成后,我们访问http://localhost:8761
、http://localhost:8762
、http://localhost:8763
都可以看到相同的页面
但是这样并没有搭建成功,因为三个服务都是使用的localhost端口的,所以他默认会把三个服务都合为一个副本,就是DS Replicas
里面的值。
我们想要在一台电脑上搭建成功,可以这样。
打开运行窗口(win+r),输入drivers
打开文件夹,然后进入etc
目录,对hosts
文件进行编辑
在文件末尾,添加如下三行,然后保存
127.0.0.1 peer1
127.0.0.1 peer2
127.0.0.1 peer3
保存完毕后,我们再次修改三个服务的配置文件
eureka-serve配置文件
# eureka 默认端口号
server:
port: 8761
# 应用名称 不要使用特殊字符
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://peer2:8762/eureka,http://peer3:8763/eureka
instance:
hostname: peer1 #主机名称 或者服务的ip
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
eureka-serve-b配置文件
# eureka 默认端口号
server:
port: 8762
# 应用名称 不要使用特殊字符
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://peer1:8761/eureka,http://peer3:8763/eureka
instance:
hostname: peer2 #主机名称 或者服务的ip
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
eureka-serve-c配置文件
# eureka 默认端口号
server:
port: 8763
# 应用名称 不要使用特殊字符
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://peer1:8761/eureka,http://peer2:8762/eureka
instance:
hostname: peer3 #主机名称 或者服务的ip
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
修改完成后,我们再次重启项目(要先关闭,再启动),然后刷新页面可以看到如下结果
http://localhost:8761/
页面
http://localhost:8762/
页面
http://localhost:8763/
页面
到此,我们的集群才算是搭建完成,集群搭建完成后,我们把一个服务注册上去,服务的配置类也需要修改,改成如下
server:
port: 8080
spring:
application:
name: eureka-cli
eureka:
client:
service-url:
defaultZone: http://peer1:8761/eureka
register-with-eureka: true
fetch-registry: true
registry-fetch-interval-seconds: 10
instance:
hostname: localhost
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
prefer-ip-address: true
lease-renewal-interval-in-seconds: 10
因为我们设置了集群,所以理论上来说,只要给一个服务注册了,其他服务也应该有的
配置完毕,重启后,刷新三个页面,查看服务是否都注册成功
因为我们都是在一台电脑上起的,所以可以复制配置文件,修改端口号,起三台就可以了,步骤如下
关闭所有启动的项目,打开eureka-server
的配置文件,修改如下
# eureka 默认端口号
server:
port: 8761
# 应用名称 不要使用特殊字符
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://peer1:8762/eureka,http://peer2:8762/eureka,http://peer3:8763/eureka
instance:
# hostname: peer1 #主机名称 或者服务的ip
instance-id: ${spring.application.name}:${server.port}
prefer-ip-address: true
lease-renewal-interval-in-seconds: 5
然后我们点击idea右上角配置,打开启动项配置
我们选中左侧的第一个服务,然后点击复制,改名,改端口,依次启动就可以了
刷新页面,查看结果
当项目启动时(eureka的客户端),就会向eureka-server发送自己的元数据(原始数据)(运行的ip,端口port,健康的状态监控等,因为使用的是http/ResuFul,请求风格),eureka-server 会在自己内部保留这些元数据(内存中)。(有一个服务列表,使用的是ConcurrentHashMap
集合存放注册的服务)以restful风格,以http动词的请求方式,完成对url资源的操作。
项目启动成功了,除了向eureka-server注册自己成功,还会定时的向eureka-server汇报自己,心跳,表示自己还活着。(修改一个时间)
当项目关闭时,会给eureka-server报告,说明自己要下机了。
当项目超过了指定时间没有向eureka-server汇报自己,那么eureka-server就会认为此节点死掉了.会把它剔除掉,也不会放流量和请求到此节点了.
Eureka-server对外提供的是restfu1风格的服务
以http动词的形式对url资源进行操作get post put delete
http服务+特定的请求方式+特定的ur1地址
只要利用这些restful我们就能对项目实现注册和发现
只不过,eureka已经帮我们使用java语言写了client,让我们的项目只要依赖client 就能实现注册和发现!
只要你会发起Http请求,那你就有可能自己实现服务的注册和发现。不管你是什么语言!
通过服务的应用名称找到服务的具体实例的过程
所有开启的应用全部关闭,我们实现在客户端a中获取客户端b的信息
因为我们想要在一个客户端上调用另一个客户端的接口,所以要先获取客户端b的ip和端口,所以我们这次只需要开启一个服务,两个客户端即可,所以我们把服务端的配置文件改为原来的
# eureka 默认端口号
server:
port: 8761
# 应用名称 不要使用特殊字符
spring:
application:
name: eureka-server
eureka:
server:
eviction-interval-timer-in-ms: 10000 # 服务端间隔多少毫秒做定期删除的操作
renewal-percent-threshold: 0.85 #续约百分比,超过85%的应用没有和你续约,那么eureka会保护服务 不会剔除任何客户端
instance:
hostname: localhost #主机名称 或者服务的ip
# 主机名称 : 应用名称 : 端口号
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
prefer-ip-address: true # 以ip的形式显示具体的服务信息
lease-renewal-interval-in-seconds: 5 #服务实例的续约时间
改完后启动服务,然后再把客户端b的配置文件修改回来,然后启动
server:
port: 8081 # 客户端 端口号没有约束
spring:
application:
name: eureka-cli-b
eureka:
client:
service-url: # 指定注册的地址
defaultZone: http://localhost:8761/eureka
register-with-eureka: true # 可以不往Eureka注册
fetch-registry: true # 应用是否去拉取服务列表到本地
registry-fetch-interval-seconds: 10 # 为了缓解服务列表的脏读问题 时间越短脏读越少 性能消耗大
instance:
hostname: localhost
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
prefer-ip-address: true # 显示ip
lease-renewal-interval-in-seconds: 10 # 实例续约的时间
启动成功后,刷新网页,查看是否注册成功
注册成功后,我们把eureka-cli-a
项目的配置文件,修改为和上面的一样,修改一下端口号和应用名称即可
修改完成后,我们创建一个DiscoveryController
编写代码
package com.tcc.controller;
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.RestController;
import java.util.List;
/**
* @author 宇辰
* @date 2022/8/7 - 20:43
**/
@RestController
public class DiscoveryController {
@Autowired
private DiscoveryClient discoveryClient; // springCloud定义的接口
@GetMapping("test")
public String doDiscovery(String serviceName){
// 通过服务的应用名,找到服务的具体信息
List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
instances.forEach(System.out::println);
ServiceInstance serviceInstance = instances.get(0);
String ip = serviceInstance.getHost();
int port = serviceInstance.getPort();
System.out.println(ip+":"+port);
// 这里去找客户端02的ip和port
return instances.get(0).toString();
}
}
编写完毕后,启动eureka-cli
项目,然后在页面路径上调用接口,查看返回值,路径为http://localhost:8080/test?serviceName=eureka-cli-b
传过去的参数为b的客户端的接口,可以在服务端的页面内找到
访问完毕后,查看返回值,是否为b的信息
然后我们查看控制台的打印,是否获取成功
有了地址和端口号,我们只需要知道接口就可以调用其他项目的接口了。
RestTemplet
类发送http
请求调用接口(下一章ribbon使用)我们先新建一个restTemplet
项目,引入web依赖和lombok依赖,项目端口为9090
我们先在创建个controller,然后创建几个测试接口
package com.tcc.controller;
import com.tcc.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 宇辰
* @date 2022/8/8 - 8:58
**/
@RestController
public class TestController {
@GetMapping("testGet")
public String testGet(String name){
System.out.println(name);
return "OK";
}
/**
* post传参,两种
* json参数的核心 header content-type = application/json;charset=utf-8
*
* @param user
* @return
*/
@PostMapping("testPost1")
public String testPost1(@RequestBody User user){
return "姓名;" + user.getName() + ",年龄:" + user.getAge() + ",工资:" + user.getWages();
}
/**
* 接收表单参数
*
创建完毕后,我们随便找个地方创建测试类,进行测试
先new RestTemplet
创建一个发送请求的类
然后定义参数
获取返回值并打印
发送get请求
// 发送get请求
String url = "http://localhost:9090/testGet?name=张三";
String getTemplate = restTemplate.getForObject(url, String.class);
System.out.println(getTemplate);
发送post请求
String url = "http://localhost:9090/testPost1";
User user = User.builder()
.name("张三")
.age(20)
.wages(20D).build();
String postForObject = restTemplate.postForObject(url, user, String.class);
System.out.println(postForObject);
发送表单请求
// 发送表单请求
String url = "http://localhost:9090/testPost2";
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("name","李四");
map.add("age",22);
map.add("wages",200D);
String postForObject = restTemplate.postForObject(url, map, String.class);
System.out.println(postForObject);