谈谈微服务

单体应用和分布式在我之前了解中间件的时候,详情可以点击这里,接下来咱们说说微服务。

微服务是由 Martin Fowler 发现的。

他说微服务其实是一种架构风格,我们在开发一个应用的时候这个应用应该是由一组小型服务组成,每个小型服务都运行在自己的讲程内;小服务之间 HTTP 的方式进行互联互通。

单体和分布式

微服务架构的常见问题

—且采用微服务系统架构,就势必会遇到这样几个问题:

  • 这么多小服务,如何管理他们?(服务治理注册中心[服务注册发现剔除])nacos
  • 这么多小服务,他们之间如何通讯?(restful rpc dubbo feign)httpclient(“url;参数),springBoot restTemplate(“url”参数),feign
  • 这么多小服务,客户端怎么访问他们?(网关)gateway
  • 这么多小服务,一旦出现问题了,应该如何自处理?(容错)
  • 这么多小服务,一旦出现问题了,应该如何排错?(链路追踪)

对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对每一个问题提供了相应的组件来解决它们。

5d4ce623e4b06e49190c5c0a

Spring Cloud 是什么

分布式系流中的常见模式给了 Spring Cloud 一个清的定位,即“模式”,也就是说 Spring Cloud 是针动分布式系统开发所的通用抽象,是标准模式的实现。这个定义非前抽象,看完之后并不能知道 Spring Cloud具体包合什么内在。再看一下 Spring 官方给出的架构图,就可以对这套模式有更清晰的认识

diagram-microservices-88e01c7d34c688cb49556435c130d352.svg

常见的微服务架构

虽然这些组件都没见过,但是还是了解了解吧

dubbo

zookeeper +dubbo + SpringMVclSpringBoot

  • 配套通信方式: rpc
  • 注册中心: zookeeper / redis
  • 配置中心: diamond

Spring Cloud

Spring 全家桶 + 轻松嵌入第三方组件(Netflix)

  • 配套通信方式: http restful
  • 注册中心:eruka / consul
  • 配置中心: config
  • 断路器:hystrix
  • 网关:zuul
  • 分布式追踪系统:sleuth + zipkin

体验:分布式架构的服务调用

上面提到,服务之间的通信方式有很多种。下面这种调用方式将使用 http 协议进行服务之间的调用。

服务:可以理解成是功能模块。

创建一个父项目,可以使用 Spring Initializer 来构建,也可以使用 maven 来构件。父项目的 maven 依赖如下所示

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>Order</module>
        <module>stock</module>
    </modules>
    
    <groupId>top.bestguo.springcloud</groupId>
    <artifactId>springcloudalibaba</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloudalibaba</name>
    <description>Demo project for Spring Boot</description>
   
    <dependencies>
        <!-- springboot场景启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

父项目中,不需要 src 文件夹,将其删除。

接下来是两个 Module ,一个为 Order ,一个为 Stock ,他们俩的依赖都是一样的

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloudalibaba</artifactId>
        <groupId>top.bestguo.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

在这两个 Module 中,都分别创建一个配置类,用于注册 RestTemplate 组件,注册的内容如下

@Configuration
public class MyConfig {
    
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
       return builder.build();
    }
    
}

然后新建控制类,一个是在 order ,另一个是在 stock 。

order

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping("/add")
    public String add() {
        System.out.println("下单成功");
        String forObject = restTemplate.getForObject("http://localhost:8011/stock/add", String.class);
        System.out.println(forObject);
        return "Hello World," + forObject;
    }

}

stock

@RestController
@RequestMapping("/stock")
public class StockController {

    @RequestMapping("/add")
    public String add() {
        System.out.println("扣减库存");
        return "扣减库存";
    }

}

运行之后,访问 http://localhost:8012/order/add 之后,控制台输出结果如下。

下单成功
扣减库存

此时发现 stock 服务,调用成功了。

说实话,我倒是觉得微服务很像前后端分离,是因为提供一个接口,传递什么参数,然后返回什么内容。这里就很像是前后端的分离,现在发现,微服务其实也并不是什么很新鲜的东西。

上述的问题

上面有两个服务,order 调用 stock 调用成功了。两个服务还好说,要是有几百个服务,需要在每各服务中需要记录这些 ip 地址将是一件非常麻烦的事情。如果在这几百个服务中,有一个服务的 ip 地址改变了,假设这个服务被 40 个服务调用着,那就需要修改 40 个服务中记录的 ip 地址,这是非常浪费时间的。

hsmkfyn1415173.jpg

那么,我们需要将这些 ip 地址放到一个集中管理的地方。这样,一个地方发生变化,我们甚至都不需要更改 ip 地址就能直接访问到相对应的服务中了。

在 Spring Cloud 中 ,有许多衍生的微服务架构,其中 Spring Cloud Alibaba 就是一个非常之优秀的微服务架构,它里面有一个组件叫做 Nacos ,它是啥?

它是用于解决上述问题的。将每一个服务的访问地址添加 Nacos 中,我们就可以去非常方便的调用服务,当然还能够解决负载均衡,某个服务宕机之后停用这个服务都需要它来监控并操作。它的职责是服务注册与发现。

待续

后期在学习“服务注册与发现”之 Nacos 时,将会详细的写一篇日志来作为记录吧。