Spring Boot整合高可用注册中心Eureka + 负载均衡Ribbon
Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的
。
Eureka包含两个组件:Eureka Server和Eureka Client。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册
,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个java客户端,用于简化与Eureka Server的交互
。
一、配置注册中心 eureka-server
创建一个moudel 提供服务注册服务。
1、pom引入依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>3.1.2</version>
</dependency>
2、yml文件做配置。
# 模拟两个注册中心服务 9000 9090 互相进行注册
server:
# 设置端口号9090 9000
port: 9090
# 配置服务名称eureka-server1 eureka-server2
spring:
application:
name: eureka-server1
eureka:
instance:
hostname: localhost
client:
# 是否允许从注册中心拉去服务
fetch-registry: true
# 是否将其注册进注册中心
register-with-eureka: true
# 在这例为了体现高可用性 ,我们将这两项打开
service-url:
# 默认的注册中心地址
defaultZone: http://localhost:9000/eureka/
3、启动类中使用注解@EnableEurekaServer开启服务。
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
4、启动服务,通过http://localhost:9000/eureka/
即可打开eureka界面,至此配置中心配置完成。
二、创建客户端服务,并注册到注册中心eureka-server中
创建 client-service 和 manager-service
客户端服务和管理员服务 两个module,可以互相远程调用对方接口。
1、引入service-client依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>3.1.2</version>
</dependency>
2、yml做相应配置。
2.1 client-service
server:
port: 9001
spring:
application:
name: client-service
datasource:
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql:///shopping_mall?useUnicode=true&characterEncoding=utf8&useSSL=false
username: root
password: root
# 配置服务注册
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:9000/eureka , http://localhost:9090/eureka/
instance:
prefer-ip-address: true
2.2 manager-service
server:
port: 9002
spring:
application:
name: manager-service
datasource:
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql:///shopping_mall?useUnicode=true&characterEncoding=utf8&useSSL=false
username: root
password: root
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
#配置注册中心地址
defaultZone: http://localhost:9000/eureka/ , http://localhost:9090/eureka/
instance:
prefer-ip-address: true
3、开启eurekaClient,启动类中添加注解@EnableEurekaClient
3.1 Manager
@SpringBootApplication
// 开启客户端服务
@EnableEurekaClient
public class ManagerServiceApplication {
@Bean
// 负载均衡
@LoadBalanced
// 远程调用工具类,便于调用其他服务接口
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ManagerServiceApplication.class, args);
}
}
3.2、client
@SpringBootApplication
//启动eurekaClient
@EnableEurekaClient
public class ClientServiceApplication {
@Bean
//引入负载均衡,默认轮询策略
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ClientServiceApplication.class, args);
}
}
4、至此客户端服务配置完毕 ,启动后刷新注册中心页面会看到两个服务已注册成功。
三、远程调用
1、使用restTemplat+注册中心
1.1 调用者 manager
@Controller
@RequestMapping("/manager")
public class ManagerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
/* 硬编码方式:使用远程时,返回类型是实体类时,必须要在该微服务下创建该实体类
* 用JSONObject String integer 等除了实体类时直接用即可。
**/
@RequestMapping("/getUser")
@ResponseBody
public User getUser(String userId){
JSONObject jsonObject = null;
jsonObject = restTemplate.getForObject("http://localhost:8001/client/user/"+userId,JSONObject.class);
User user = new User();
user = restTemplate.getForObject("http://localhost:8001/client/user/"+userId,User.class);
return user;
}
/*
从注册中心获取服务
**/
@ResponseBody
@RequestMapping("/getUserFromEureka")
public JSONObject getUserFromEureka(String userId){
// 获取client-service微服务的基本信息
List<ServiceInstance> instanceList = discoveryClient.getInstances("client-service");
System.out.println(instanceList.size());
/*
* [EurekaServiceInstance@35e23c5b instance = InstanceInfo
* [instanceId = WINDOWS-9A42ROV:client-service:8001,
* appName = CLIENT-SERVICE, hostName = 172.28.199.45, status = UP,
* ipAddr = 172.28.199.45, port = 8001, securePort = 443,
* dataCenterInfo = com.netflix.appinfo.MyDataCenterInfo@4372754b]
**/
for(ServiceInstance instance:instanceList){
System.out.println("----"+instance);
}
// 获取唯一的一个元数据
ServiceInstance serviceInstance = instanceList.get(0);
// 拼写远程微服务接口地址
String url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/client/user/"+userId;
// 加入ribbon后可以通过服务名称直接代替ip和端口
//String url = "http://client-service/client/user/"+userId;
JSONObject jsonObject = new JSONObject();
jsonObject = restTemplate.getForObject(url,JSONObject.class);
return jsonObject;
}
}
1.2 提供服务者 client
/**
* @Description: 操作用户信息
* @author: caopengqi
* @date: 2023/03/08 14:56:45
**/
@Controller
@RequestMapping("/client/user")
public class UserController {
@Autowired
private UserService userService;
//请求方式:client/user/参数值
/*
* @description: 该方法用于:查询单个用户的基本信息
* @params: [userId]
* @return: com.client.bean.User
* @author: cqopengqi
* @date: 2023/3/9
*
**/
@RequestMapping(value = "/{userId}",method = RequestMethod.GET)
@ResponseBody
public User getUserMsg(@PathVariable String userId){
System.out.println("进来了"+userId);
User user = new User();
user = userService.getUserMsg(userId);
System.out.println(user);
return user;
}