文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringBoot整合SpringCloud的过程详解

2024-04-02 19:55

关注

1. SpringCloud特点

SpringCloud专注于为典型的用例和扩展机制提供良好的开箱即用体验,以涵盖其他情况:

2. 分布式系统的三个指标CAP

在介绍SpringCloud默认使用的注册中心前,先介绍分布式系统的三个指标,分别是:

CAP定律说的是,在一个分布式计算机系统中,一致性C,可用性A,分区容错性P这三种保证无法同时得到满足,最多满足两个:

1.放弃P

为了避免分区容错性问题的发生,一种做法是将所有与事务相关的数据都放在一台服务器上,虽然不能保证100%系统不会出错,但是不会碰到由分区带来的负面效果,这样的做法会严重影响系统的扩展性。

2.放弃A

放弃可用性,一旦遇到分区容错故障,受到影响的服务器需要等待一定的时间,因此会导致在等待期间系统无法对外提供服务。

3.放弃C

这儿说的放弃一致性,并不是完全放弃数据的一致性,而是放弃数据的强一致性,而保留数据的最终一致性。以网络购物为例,对只剩下一件库存的商品,如果同时接受到了两份订单,那么较晚的订单将被告知商品告罄。

文中部分CAP理论摘自:https://www.cnblogs.com/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

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集群中节点分为三类,承担不同的任务

Eureka:在Eureka集群中每个节点都是平等的,每个节点扮演相同的角色,它们通过相互注册的方式来感知对方的存在,当由注册消息时,它们会同步给集群内的其他节点

中文文档:https://www.springcloud.cc/spring-cloud-greenwich.html

4. SpringCloud Demo

Demo整体结构(父子项目)

4.1 registry

1)pom.xml

关键点在于导入eureka服务端依赖以及SpringCloud依赖


<dependencies>
        <!-- https://mvnrepository.com/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 {

    
    Integer userExist(Integer uId);

    
    UserInfo getUserInfo(Integer uId);

    
    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.common.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标注,并注入UserClient进行调用


@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:

到此这篇关于SpringBoot整合SpringCloud的文章就介绍到这了,更多相关SpringBoot整合SpringCloud内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯