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 # 对当前实例的重试次数
编写逻辑代码:
简单的调研提供者中的接口
configpackage 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.调用服务测试接口