1. SpringCloud特点
SpringCloud 专注于为典型的用例和扩展机制提供良好的开箱即用体验,以涵盖其他情况:
分布式/版本化配置 服务注册和发现 Eureka 路由 Zuul 服务到服务的呼叫 负载均衡 Ribbon 断路器 Hystrix 分布式消息传递
2. 分布式系统的三个指标CAP
在介绍 SpringCloud 默认使用的注册中心前,先介绍分布式系统的三个指标,分别是:
Consistency: 一致性,在分布式系统中,更新操作执行成功后所有的用户的读操作必须返回最新值;client写入,server同步至整个系统; Availability: 可用性,只要收到用户的请求,在一定的时间内服务器就必须给出回应,回应的结果可以是成功或是失败; Partition tolerance: 分区容错,即区间通信可能失败,在网络中断,消息丢失的情况下,仍对外提供服务;一般无法避免,可以认为CAP中的P总是成立
CAP 定律说的是,在一个分布式计算机系统中,一致性C,可用性A,分区容错性P这三种保证无法同时得到满足,最多 满足两个:
放弃P:
为了避免分区容错性问题的发生,一种做法是将所有与事务相关的数据都放在一台服务器上,虽然不能保证100%系统不会出错,但是不会碰到由分区带来的负面效果,这样的做法会严重影响系统的扩展性。
放弃A:
放弃可用性,一旦遇到分区容错故障,受到影响的服务器需要等待一定的时间,因此会导致在等待期间系统无法对外提供服务。
放弃C:
这儿说的放弃一致性,并不是完全放弃数据的一致性,而是放弃数据的强一致性,而保留数据的最终一致性。以网络购物为例,对只剩下一件库存的商品,如果同时接受到了两份订单,那么较晚的订单将被告知商品告罄。
文中部分CAP理论摘自: https://HdhCmsTestcnblogs测试数据/hxsyl/p/4381980.html
3. Eureka
基本介绍:
Eureka 是 SpringCloud 官方推荐用于服务注册和发现,一个基于REST的服务
SpringBoot 实现了 Netflix OSS 的集成,使用 Eureka 的原因之一是因为其可以利用 Spring Cloud Netflix 的其他组件:智能路由(Zuul)、客户端负载均衡 (Ribbon )等
基本组成:
Eureka 由多个 Instance (服务实例)组成,分为 Eureka Server 和 Eureka Client
其中 Eureka Client 又可细分为: Service Provider、Service Consumer
Eureka Server :服务端,提供服务的注册和发现; Eureka Client :客户端 Service Provider :服务提供方,将自身服务注册到Eureka,让消费方找到 Service Consumer :服务消费方,从Eureka获取注册服务列表,从而消费服务Eureka和Zookeeper:
1)由CAP理论的角度来看
Zookeeper : ZK保证CP ,突出强一致性,但无法保证每次访问服务可用性,比如ZK会出现这样一种情况:当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举,在ZK选举leader期间整个ZK集群都是不可用的,这就导致了在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得ZK集群失去master节点是较大概率会发生的事儿,虽然服务最终会恢复,但是漫长的选举时间导致的注册长期不可用是难以容忍的。
Eureka : Eureka保证AP ,Eureka在设计时就优先保证可用性。对于Eureka中的节点,每个节点都是平等的,几个节点挂掉也不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。但Eureka不保证强一致性,即查到的信息可能不是最新的。此外Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就会认为客户端和注册中心出现了网络故障,但会保证当前节点依然可用,不会像ZK导致整个注册服务瘫痪。
2)由节点分工的角度来看
Zookeeper :ZK集群中节点分为三类,承担不同的任务
Leader :事务请求唯一的调度者和处理者(除了查询请求) Follower :处理非事务请求,参与Leader选举投票 Observer:处理非事务请求,但不参与Leader选举投票Eureka :在 Eureka 集群中每个节点都是平等的,每个节点扮演相同的角色,它们通过相互注册的方式来感知对方的存在,当由注册消息时,它们会同步给集群内的其他节点
4. SpringCloud Demo
Demo整体结构 (父子项目)
api :Bean、DTO、POJO等以及Service接口 controller :服务消费方,前端交互 provider :服务提供方,服务实现 registry :服务注册中心
4.1 registry
1) pom.xml
关键点在于 导入eureka服务端依赖 以及 SpringCloud 依赖
<dependencies> <!-- https://mvnrepository测试数据/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server --> <!-- eureka服务端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <version>2.2.5.RELEASE</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
2) application.properties
进行Eureka服务端的相关配置 spring.application.name=SpringCloudDemoRegistry # server端口,自己喜欢 server.port=8888 # Eureka Server服务url以及默认zone,结尾必须eureka eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/ # eureka的自我保护机制,k8s环境下建议false eureka.server.enable-self-preservation=false # false表示自己端就是注册中心,我的功能就是维护服务实例,不需要从server获取注册的服务信息 eureka.client.fetch-registry=false # false表示不将自己注册到Eureka Server eureka.client.register-with-eureka=false
3) EurekaregistryApplication
使用 @EnableEurekaServer 激活相关配置,使 registry 模块作为注册中心 Server
@EnableEurekaServer //声明为注册中心服务端 @SpringBootApplication public class EurekaregistryApplication { public static void main(String[] args) { SpringApplication.run(EurekaregistryApplication.class, args); } }
4.2 api
1) entity
实体类以部门和用户信息为例,由于演示使用了 Lombok 省点代码,用于实现基本的 CRUD
Department.class
@Data @ToString @NoArgsConstructor @AllArgsConstructor public class Department { private Long id; private Integer dId; private String dName; private Date updateTime; }
UserInfo.class
@Data @ToString @NoArgsConstructor @AllArgsConstructor public class UserInfo { private Long id; private Integer uId; private Integer dId; private String uName; private String uPhone; @Email(message = "非法邮件格式") //Validator格式校验 private String uEmail; private String uAddress; private Date updateTime; private Department department; }
2) UserService
UserService 为服务接口,声明需要提供和消费的方法,写了几个简单查询
public interface UserService { /** * 判断用户是否存在,0为不存在,返回值与uId相等则存在 * @param uId * @return */ Integer userExist(Integer uId); /** * 获取用户个人基本信息 * @param uId * @return */ UserInfo getUserInfo(Integer uId); /** * 获取用户个人详情信息 * @param uId * @return */ UserInfo getUserDetailsInfo(Integer uId); }
4.3 provider
1) pom.xml
关键点是 引入eureka客户端依赖 、 openfeign依赖 、 SpringCloud 依赖
<dependencies> <!-- Springboot的依赖省略... --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
2) application.properties
配置 Eureka 、 Mybatis 以及 DataSource 数据源等信息
spring.application.name=SpringCloudDemoProvider # Server端口 server.port=9999 # Eureka服务url eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/ eureka.client.register-with-eureka=true eureka.client.fetch-registry=true # Mybatis mybatis.mapper-locations= classpath:com.maziyao.provider.mapper/*.xml mybatis.type-aliases-package= com.maziyao测试数据mon.entity # DataSource数据源配置 spring.datasource.type=com.zaxxer.hikari.HikariDataSource # DataSource spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/boot-demo?serverTimezone=UTC spring.datasource.username=root spring.datasource.password=root
3) EurekaproviderApplication
provider 启动类使用 @EnableEurekaClient 声明为 EurekaClient 客户端,作为 ServiceProvider
@EnableEurekaClient @SpringBootApplication @EnableAspectJAutoProxy @MapperScan("com.maziyao.provider.mapper") @ComponentScan(basePackages = { "com.maziyao.provider.rest", "com.maziyao.provider.redis", "com.maziyao.provider.service", "com.maziyao.provider.config" }) public class EurekaproviderApplication { public static void main(String[] args) { SpringApplication.run(EurekaproviderApplication.class, args); } }
4) service
UserServiceImpl 作为 UserService 接口实现类 ,@Service 用于标注 业务层 组件
自动注入 mapper 层的 mapper 接口并调用,mapper的SQL语句下面就略了,很简单
需要注意的是,对于 数据访问层 组件 mapper ,使用 @Repository 进行标注
@Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public Integer userExist(Integer uId) { return userMapper.userExist(uId); } @Override public UserInfo getUserInfo(Integer uId) { return userMapper.getUserInfo(uId); } @Override public UserInfo getUserDetailsInfo(Integer uId) { return userMapper.getUserDetailsInfo(uId); } }
5) rest
重点是rest包下的 UserServer , 要知道Eureka是一个基于REST的服务
使用 @RestController 标注并声明为 userServer ,这个是 SpringBoot 注解,用于标注 控制层 组件
@RestController("userServer") public class UserServer { public static final Logger logger = LoggerFactory.getLogger(UserServer.class); @Autowired private UserService userService; @ResponseBody @RequestMapping(value = "/exist",method = RequestMethod.GET) public Integer existUserByUid(@RequestParam("uId")Integer uId){ return userService.userExist(uId); } @ResponseBody @RequestMapping(value = "/userInfo",method = RequestMethod.GET) public UserInfo getUserInfo(@RequestParam("uId")Integer uId){ return userService.getUserInfo(uId); } @ResponseBody @RequestMapping(value="/userDetailsInfo",method = RequestMethod.GET) public UserInfo getUserDetailsInfo(@RequestParam("uId")Integer uId){ return userService.getUserDetailsInfo(uId); } }
4.4 consumer
1) pom.xml
在 Controller 的 pom.xml 中也需要导入 EurekaClient 的依赖,对于 Provider 和 Controller 都为 Client
<dependencies> <!-- SpringBoot依赖省略... --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.2.5.RELEASE</version> </dependency> </dependencies>
2) application.properties
在 application.properties 中配置 Eureka 相关信息
spring.application.name=springCloudDemoController # Server端口 server.port=8899 # 注册中心url eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/ eureka.client.register-with-eureka=true eureka.client.fetch-registry=true
3) EurekacontrollerApplication
与 Provider 的启动类一致,声明启动类为 Eureka 的客户端
并使用 @EnableFeignClients 开启 Feign ,声明性的web服务客户端
@EnableEurekaClient @EnableFeignClients @SpringBootApplication @EnableAspectJAutoProxy @ComponentScan({ "com.maziyao.controller.config", "com.maziyao.controller.controller", "com.maziyao.controller.rest" }) public class EurekacontrollerApplication { public static void main(String[] args) { SpringApplication.run(EurekacontrollerApplication.class, args); } }
4) rest
controller 作为前端交互层,即控制层,此处 UserClient 声明调用方法
使用 @FeignClient 声明服务提供方在 application.properties 中配置的 spring.application.name
以及绑定服务提供方对应 rest 包下的 UserServer 类的 @RestController("userServer")
@FeignClient(name = "springCloudDemoProvider",contextId = "userServer") public interface UserClient { @ResponseBody @RequestMapping(value = "/exist",method = RequestMethod.GET) public Integer existUserByUid(@RequestParam("uId")Integer uId); @ResponseBody @RequestMapping(value = "/userInfo",method = RequestMethod.GET) public UserInfo getUserInfo(@RequestParam("uId")Integer uId); @ResponseBody @RequestMapping(value="/userDetailsInfo",method = RequestMethod.GET) public UserInfo getUserDetailsInfo(@RequestParam("uId")Integer uId); }
5) UserController
控制层,使用 @RestController 标注,并注入 UserClien t进行调用
@RestController public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private UserClient userClient; @ResponseBody @RequestMapping(value = "/exist",method = RequestMethod.GET) public Integer existUserByUid(@RequestParam("uId") Integer uId){ return userClient.existUserByUid(uId); } @ResponseBody @RequestMapping(value = "/userInfo",method = RequestMethod.GET) public UserInfo getUserInfoByUid(@RequestParam("uId")Integer uId){ return userClient.getUserInfo(uId); } @ResponseBody @RequestMapping(value = "/userDetailsInfo",method = RequestMethod.GET) public UserInfo getUserDetailsInfoByUid(@RequestParam("uId")Integer uId){ return userClient.getUserDetailsInfo(uId); } }
4.5 POSTMAN一下
注意: 最后记得 mvn install ,需要先将 registry 运行起来,再分别运行 provider 和 controller
启动registry:
启动provider:
启动consumer:
result:
到此这篇关于 Java -SpringBoot 整合 SpringCloud 的文章就介绍到这了,更多相关 SpringBoot 整合 SpringCloud 内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
原文链接:https://HdhCmsTestcnblogs测试数据/torima/p/15277106.html
查看更多关于Java SpringBoot整合SpringCloud的详细内容...