当前位置: 代码迷 >> 综合 >> SpringCloud初探之Eureka
  详细解决方案

SpringCloud初探之Eureka

热度:93   发布时间:2023-09-06 12:55:13.0

Eureka

1.1.原理图(重要)

原理说明

Eureka:就是服务注册中心(可以是一个集群),对外暴 露自己的地址

提供者:启动后向Eureka注册自己信息(地址,提供什么服务)

消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新

心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态

1.2.快速上手

环境:

通过SpringBoot搭建

eureka-server 注册中心

user-service 服务提供者(生产者)

user-consumer 消费者

实现过程:

在环境搭建好之后,eureka_cr-server启动后对外提供自己的IP地址(暴露地址)

user_cr-service通过eureka_cr-server提供的IP地址将自己的信息注册到eureka_cr-server中,并定期通过http请求刷新自己的状态,

user_cr-consume订阅注册中心中的服务,并定期通过服务的名称(服务的名称指的是消费者的名称,即application.name)获取到所有对应的服务地址列表(提供者的地址列表),调用提供者的服务

1.eureka_cr-server(注册中心)

创建项目:

1.使用脚手架创建SpringBoot项目

2.填写好项目的信息,点击next

4.选择依赖,自动导入依赖,next --> finish

注意:如果没有采用自动选择依赖,需要自己在pom文件中手动添加依赖

		<!--Eureka注册中心--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>

项目创建好后:

1.在启动类上添加 @EnableEurekaServer该注解的作用是开启注册中心服务

package com.czxy;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication
//开启EurekaServer
@EnableEurekaServer
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class, args);}
}

2.将application.properties改成application.yml,在yml文件中添加注册中心相关的配置

server:port: 10086 # 端口
spring:application:name: eureka-server # 应用名称,会在Eureka中显示
eureka:client:register-with-eureka: false # 是否注册自己的信息到EurekaServer,默认是truefetch-registry: false # 是否拉取其它服务的信息,默认是trueservice-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。defaultZone: http://127.0.0.1:${server.port}/eureka

3.ok,EurekaServer就编写完了

2.user_cr-service(提供者)

创建项目

1.在原项目的基础上,右键点击创建选择new project

2.使用脚手架创建SpringBoot项目

3.填写好项目的信息后直接next

4.什么都不用选择直接next

5.他是单独的一个项目,记得要删除他的上级文件名,如图所示(参考)

项目创建好后配置:

1.在pom文件中加入Eureka客户端的依赖,因为user-service是提供者,与数据库交换的,还需要引入其他相关的包(完整的)

 <!-- 统一版本维护 --><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><mybatis.starter.version>1.3.2</mybatis.starter.version><mapper.starter.version>2.0.2</mapper.starter.version><mysql.version>5.1.32</mysql.version><pageHelper.starter.version>1.2.5</pageHelper.starter.version><durid.starter.version>1.1.10</durid.starter.version></properties><dependencies><!-- SpringBoot整合SpringMVC的启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- SpringBoot整合jdbc和事务的启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- mybatis启动器 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.starter.version}</version></dependency><!-- 通用Mapper启动器 --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>${mapper.starter.version}</version></dependency><!-- 分页助手启动器 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>${pageHelper.starter.version}</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><!-- Eureka客户端 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- Druid连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${durid.starter.version}</version></dependency></dependencies><!-- SpringCloud的依赖 --><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><!-- Spring的仓库地址 --><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository></repositories>

2.在项目的启动类上添加注解

package com.czxy;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication
//开启 EurekaClient
@EnableEurekaClient
public class UserRcServiceApplication {public static void main(String[] args) {SpringApplication.run(UserRcServiceApplication.class, args);}
}

3.将application.properties改成application.yml,在yml文件中添加提供者相关的配置(直接拷贝进去就可以了)

# 端口配置
server:port: 8888 # 端口
# Spring 数据连接接源配置
spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/day1203?useUnicode=true&characterEncoding=utf8username: rootpassword: root
# 日期格式化jackson:date-format: yyyy-MM-ddtime-zone: GMT+8mvc:date-format: yyyy-MM-dd HH:mm:ss
# 生产者的名字application:name: user-servicemain:allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
# 设置编码类型http:encoding:charset: UTF-8enabled: trueforce: truemessages:encoding: UTF-8
eureka:client:service-url: # EurekaServer地址defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eurekainstance:instance-id: ${spring.application.name}:${server.port}prefer-ip-address: true # 当调用getHostname获取实例的hostname时,返回ip而不是host名称ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找lease-expiration-duration-in-seconds: 2 # 如果90s内不到续约,就默认服务已经挂掉了lease-renewal-interval-in-seconds: 1 # 每隔30s向服务器发送一次心跳(续约)

编写逻辑代码:

因为我们只是测试,所以我直接来一个根据主键ID查询对应的记录的方法

domian

package com.czxy.domain;import java.io.Serializable;
import javax.persistence.*;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Table(name = "user")
public class User implements Serializable {/*** 用户ID*/@Id@Column(name = "uid")@GeneratedValue(generator = "JDBC")private Integer uid;/*** 用户名*/@Column(name = "username")private String username;/*** 密码*/@Column(name = "password")private String password;/*** 性别*/@Column(name = "sex")private String sex;/*** 年龄*/@Column(name = "age")private Integer age;@Column(name = "remarks")private String remarks;private static final long serialVersionUID = 1L;
}

dao

package com.czxy.dao;import com.czxy.domain.User;
import tk.mybatis.mapper.common.Mapper;@org.apache.ibatis.annotations.Mapper
public interface UserMapper extends Mapper<User> {
}

servier

package com.czxy.service;import com.czxy.domain.User;import java.util.List;public interface UserService{List<User> findUserById(List<Integer> ids);
}

service-Impl

package com.czxy.service.impl;import com.czxy.domain.User;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import com.czxy.dao.UserMapper;
import com.czxy.service.UserService;import java.util.ArrayList;
import java.util.List;@Service
public class UserServiceImpl implements UserService{@Resourceprivate UserMapper userMapper;@Overridepublic List<User> findUserById(List<Integer> ids) {List<User> users = new ArrayList<>();for (Integer id : ids) {users.add(userMapper.selectByPrimaryKey(id));}return users;}
}

controller

package com.czxy.controller;import com.czxy.domain.User;
import com.czxy.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** @Author ScholarTang* @Date 2019/12/10 1:09 PM* @Desc 处理用户相关的业务*/@Slf4j
@CrossOrigin(origins = "*",maxAge = 3600)
@RestController
public class UserController {@Autowiredprivate UserService service;/*** TODO 根据主键ID查询对应的记录* @param ids* @return*/@GetMapping("/findUserById/{ids}")public ResponseEntity<List<User>> findUserById (@PathVariable(name = "ids") List<Integer> ids) {log.info("ids:{}",ids);List<User> users = service.findUserById(ids);return ResponseEntity.ok(users);}
}
3.user_cr-consumer(消费者)

创建项目:

创建项目的方式与user_cr-service的创建方式一样

创建项目完成后:

1.在项目的启动类上添加@EnableEurekaClient注解或者@EnableDiscoveryClient,这两个注解的功能是一样的

package com.czxy;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication
//开启EurekaClient
@EnableEurekaClient
public class UserCrConsumerApplication {public static void main(String[] args) {SpringApplication.run(UserCrConsumerApplication.class, args);}}

2.在pom文件中添加如下依赖

 				 <!-- SpringBoot整合SpringMVC的启动器 RestTemplate包所在依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Eureka客户端 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>

3.将application.properties改成application.yml,在yml文件中添加消费者相关的配置

server:port: 8889
spring:application:name: user-consumer # 应用名称
# # 设置编码类型http:encoding:charset: UTF-8enabled: trueforce: truemessages:encoding: UTF-8cloud:loadbalancer:retry:enabled: trueeureka:client:service-url: # EurekaServer地址defaultZone: http://127.0.0.1:10086/eurekaregistry-fetch-interval-seconds: 5instance:prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostnameip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找instance-id: ${spring.application.name}:${server.port}lease-expiration-duration-in-seconds: 2 # 如果90s内不到续约,就默认服务已经挂掉了lease-renewal-interval-in-seconds: 1 # 每隔30s向服务器发送一次心跳(续约)user-service:ribbon:# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡(随机)ConnectTimeout: 250 # Ribbon的连接超时时间ReadTimeout: 1000 # Ribbon的数据读取超时时间OkToRetryOnAllOperations: true # 是否对所有操作都进行重试MaxAutoRetriesNextServer: 1 # 切换实例的重试次数MaxAutoRetries: 1 # 对当前实例的重试次数

编写逻辑代码:

简单的调研提供者中的接口
config

package com.czxy.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;import java.nio.charset.Charset;/*** @Author ScholarTang* @Date 2019/12/10 3:20 PM* @Desc RestTemplate配置类*/@Configuration
public class RestTemplateConfig {/*** 将RestTemplate对象交给Spring容器管理** @return*/@Beanpublic RestTemplate restTemplate() {RestTemplate restTemplate = new RestTemplate();restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));return restTemplate;}
}

controller

package com.czxy.controller;import com.alibaba.fastjson.JSON;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.util.List;/*** @Author ScholarTang* @Date 2019/12/10 3:21 PM* @Desc*/@RestController
public class GetDataController {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;/*** 服务调用,测试接口* @param ids* @return*/@GetMapping("/findUserById/{ids}")public ResponseEntity<List<User>> findUserById (@PathVariable(name = "ids") String ids) {//根据服务的名称,获取对应的所以提供者服务的地址列表List<ServiceInstance> instances = discoveryClient.getInstances("user-service");//拿到第一个ServiceInstance instance = instances.get(0);//拼接urlString url = instance.getUri() + "/" + ids;String usersByJsonData = restTemplate.getForObject(url, String.class);List<User> users = (List<User>) JSON.parse(usersByJsonData);return ResponseEntity.ok(users);}
}

domain

package com.czxy.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;/*** @Author ScholarTang* @Date 2019/12/10 3:22 PM* @Desc 用户类*/@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {/*** 用户ID*/private Integer uid;/*** 用户名*/private String username;/*** 密码*/private String password;/*** 性别*/private String sex;/*** 年龄*/private Integer age;private String remarks;
}
4.启动服务器测试

1.先开启注册中心的服务

2.接着时服务提供者

3.最后是消费者

4.服务都开启后访问http://localhost:10086,如图所示,说明提供者和消费者都注册到EurekaService中了

5.调用服务测试接口