Spring Cloud知识点全总结(二)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Spring Cloud知识点全总结

下面就简单列一下order-service子项目的代码:


server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
    username: root
    password: zc20020106
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  type-aliases-package: com.haiexijun.user.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    com.haiexijun: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS


controller层:


package com.haiexijun.order.web;
import com.haiexijun.order.pojo.Order;
import com.haiexijun.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("order")
public class OrderController {
   @Autowired
   private OrderService orderService;
    @GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        // 根据id查询订单并返回
        return orderService.queryOrderById(orderId);
    }
}


service层:


package com.haiexijun.order.service;
import com.haiexijun.order.mapper.OrderMapper;
import com.haiexijun.order.pojo.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 4.返回
        return order;
    }
}


pojo和mapper:


package com.haiexijun.order.pojo;
import lombok.Data;
@Data
public class User {
    private Long id;
    private String username;
    private String address;
}
package com.haiexijun.order.pojo;
import lombok.Data;
@Data
public class Order {
    private Long id;
    private Long price;
    private String name;
    private Integer num;
    private Long userId;
    private User user;
}
package com.haiexijun.order.mapper;
import com.haiexijun.order.pojo.Order;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
@Repository
public interface OrderMapper {
    @Select("select * from tb_order where id = #{id}")
    Order findById(Long id);
}


我们分别启动这两个项目(一定要都运行起来),分别访问不同的端口,进行数据访问:


d168741cd1c745c3b268de4beeb7c06e.png

d163e25a24d04006a0627bdb9714eb41.png


到这来,我们就完成了项目的准备工作。同时实现了服务拆分。下一节就来学习如何做远程调用。


3.微服务远程调用


在学习之前先来引出案例需求:

我们要实现根据订单Id查询订单的同时,把订单所属的用户信息一起返回。


现在我们的订单服务还不能做到这一点,而且我们不能直接通过访问用户服务的数据库获得信息,要去访问用户服务获取才对。


ceb214c5eac24479a18dab4cd5a18bf4.png


但是问题来了,我们以前没有学过从一个服务到另外一个服务的远程调用。下面就来分析一下,如何进行远程调用。


f58e8f6912b94950b50cff5a739f8522.png


远程调用方式分析:

我们的user服务通过@GetMapping(“/user/{id}”)对外暴露了一个restful的接口,只要我们在浏览器里面输入对应的地址,就可以拿到用户信息。我们的order订单服务如果也能像浏览器一样发起一个http的请求,用户服务也应该返回一个对应的信息给我们。这时候,订单模块再结合本地数据库查询出来的订单信息,就组合出了最终的目标了。


所以我们的问题就变成了如何在Java代码当中发起HTTP请求,如果能发起HTTP请求,就可以调用其他服务的restful接口了。


Spring它提供了一个工具叫做RestTemplate ,这个工具就是Spring提供给我们来发HTTP请求的。我们要使用这个工具,就要先在配置类里面注册,而启动类就是一个配置类。所以我们可以在order-service的OrderApplication中通过@Bean注解注册RestTemplate。


package com.haiexijun.order;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@MapperScan("com.haiexijun.order.mapper")
@SpringBootApplication
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
    /**
     * 创建RestTemplate,并注入Spring容器
     * @return
     */
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}


完成了这一步以后,我们接下来就可以利用它来发HTTP请求了。

所以我们下面要对订单的查询业务进行修改:


package com.haiexijun.order.service;
import com.haiexijun.order.mapper.OrderMapper;
import com.haiexijun.order.pojo.Order;
import com.haiexijun.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RestTemplate restTemplate;
    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.利用RestTemplate发起HTTP请求,查询用户
        String url="http://localhost:8081/user/"+order.getUserId();
        User user= restTemplate.getForObject(url, User.class);
        // 3.封装user 到 order里面去
        order.setUser(user);
        // 4.返回
        return order;
    }
}


我们重启项目后,下面来运行两条查询订单试试:


d9e41feef1eb4268906fe495133e79e1.png

1cf5af7700344da28ce5bb7d4bee6cde.png


到这里,我们就实现了,跨服务的远程调用。


4.服务的提供者与消费者


这一节又是讲解概念的一节,会了解什么是服务的提供者与消费者。


服务提供者:一次业务中,被其他微服务调用的服务就称之为服务的提供者。(提供接口给其他微服务)


服务消费者:一次业务中,调用其他微服务的服务就称之为服务的消费者。(调用其他微服务提供的接口)


我们上一节的案例中,user-service是服务提供者提供者,而order-service是服务消费者。


现在就会引发出一个问题了,现在服务A调用了服务B,而服务B调用了服务C,那服务B是什么角色呢?这时,比相对与A而言是提供者,而相对于C而言是消费者。所以一个服务既可以是提供者,又可以是消费者。


三. Eureka注册中心


在这一节里,我们会聊一聊之前案例里面存在的一些问题,以及Eureka如何解决这些问题,然后会介绍Eureka具体如何去使用。


1.Eureka原理分析


先来回顾一下之前的案例,在之前的案例当中,我们有一个订单服务和用户服务。订单服务需要远程调用我们的用户服务,它采用的方式是发起一次HTTP请求。不过在我们的代码当中,我们是将user-service的IP和端口硬编码在代码当中的。


07f87eed0757499a9a23dc5a4a65ff56.png


但这样的写法是存在一定的问题的。比如说我们开发的时候,我们会分开发环境、测试环境和生产环境等等等。每一次环境的变更,可能服务的地址也会发生改变。如果你采用硬编码的方式写死了,难道每一次都要重新修改代码然后编译打包吗?而且,为了应对更高的并发,我们的user服务可能会部署成多实例,形成一个集群,端口和地址可能就不一样了。这时候,我们到底改写谁的地址呢?如果选择其中一个实例,那其他几个的意义岂不是就没有了吗?


6a14487967b04c31b072d6743cef1606.png


所以这里一定不能采用硬编码的方式。那问题也来了,如果我不做硬编码,那这三个服务的地址我该如何去获取呢?而且万一以后又有第四台和第五台呢?如果拿到了他们的地址,我该如何挑选其中一台去使用呢?如果你挑中了一台,你怎么知道这台现在依然是健康的呢?万一它挂了呢?是不是一堆的问题啊?


但是啊,我们的 Eureka是可以解决这些问题的!


Eureka的作用:


在Eureka的结构当中,它分成了2个概念(角色),第一个角色是eureka-server 注册中心 ,它的作用是记录和管理这些微服务。而第二个角色是我们的服务提供者和服务消费者,但不管是提供者还是消费者,都是微服务,我们把它叫做eureka-client 客户端 。


我们的user-service和order-service在启动的时候会做一件事情,它会把自己的信息注册给eureka。注意:是每开一个服务启动时都会注册。eureka会把你的服务信息给记录下来。


0f1e3084b3ba470db1189e7d7bb60a93.png


那么全都记下来了,所有的服务信息都在注册中心里面了。如果这个时候我们有一个服务想要消费,它不需要自己去记录信息,直接找eureka就好了。如果eureka找到发现有,而且还有3个呢,就会把信息给服务消费者。


服务消费者拿到了服务提供者的信息,发现有三个,这个时候就会用到我们以前学过的负载均衡的知识点,从这三个里面挑一个出来。


606806eb673247188230b516c0698d31.png


那可能会想了,那你调用的这一个会不会是挂了的啊?这肯定不会,因为我们的服务每隔30秒都会向eureka发一次心跳续约 ,来确认自己的状态。如果哪一天,它不跳了。eureka就会把那个服务移除,服务消费者自然也不会得到挂掉的那个服务。


b83c52dfc8294b5ba82f2dce29e2fda3.png


2.搭建eureka服务


我们来做三件事情,第一就是搭建eureka注册中心 ,第二步我们会完成服务的注册,把所有的服务都注册到eureka,第三步我们会去做服务发现,会让order-service取拉去服务列表,得到user-service的所有实例,利用负载均衡去挑一个。下面我们就来一步一步完成:


搭建EurekaServer 注册中心


(1)eureka的搭建需要创建一个独立的微服务,所以等一会儿我们会在Spring Cloud父项目下创建一个新的项目(new一个maven的Module),这个子项目名叫eureka-server,然后子项目会引入下面的依赖:


    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>


(2)创建启动类,添加@EnableEurekaServer注解


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


(3)在application.yml配置文件中添加如下的配置(这里最好复制,不然容易出错):


server:
  port: 10086  # 服务端口
spring:
  application:
    name: eureka-server # 服务的名称
eureka:
  client:
    service-url:  # eureka的地址信息,如果是eureka集群的话,用逗号隔开
      defaultZone: http://127.0.0.1:10086/eureka


下面就可以运行起来了。


86a6da7f09594540ad3e69d3fc4cfcc9.png


dea的功能很强大,我们点击之后会跳转到Eureka的界面,如下图所示:


dc6e5c0291f241a5aaa93d3bd5a44c44.png


这个界面的Instances currently registered with Eureka就是注册到Eureka中的实例的列表。上面我们看见了,eureka也注册了自己的实例。


3.服务注册


服务注册只要经过以下两个步骤就够了:

(1)在user-service的pom文件中,引入下面的eureka-client依赖:


        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

(2)编写user-service的application.yml文件,内容如下:

server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
    username: root
    password: zc20020106
    driver-class-name: com.mysql.cj.jdbc.Driver
  application: #服务的名称
    name: userservice
mybatis:
  type-aliases-package: com.haiexijun.user.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    com.haiexijun: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
eureka:
  client:
    service-url:  # eureka的地址
      defaultZone: http://127.0.0.1:10086/eureka


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5月前
|
监控 负载均衡 Java
深入理解Spring Cloud中的服务网关
深入理解Spring Cloud中的服务网关
|
5月前
|
Java 开发工具 git
实现基于Spring Cloud的配置中心
实现基于Spring Cloud的配置中心
|
5月前
|
设计模式 监控 Java
解析Spring Cloud中的断路器模式原理
解析Spring Cloud中的断路器模式原理
|
5月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
14997 33
|
5月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
521 15
|
5月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
115 3
|
5月前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
191 5
|
5月前
|
Java API 开发工具
Spring Boot与Spring Cloud Config的集成
Spring Boot与Spring Cloud Config的集成
|
5月前
|
存储 安全 Java
实现基于Spring Cloud的分布式配置管理
实现基于Spring Cloud的分布式配置管理