微服务框架(一):服务拆分和服务注册、远程调用

微服务

微服务是一种软件架构风格,它是以专注于单一职责的很多小型项目为基础,组合出复杂的大型应用。

微服务框架(一):服务拆分和服务注册、远程调用

微服务拆分

什么时候拆分?

  • • 创业型项目:先采用单体架构,快速开发,快速试错。随着规模扩大,逐渐拆分。

  • • 确定的大型项目:资金充足,目标明确,可以直接选择微服务架构,避免后续拆分的麻烦。

怎么拆分?

从拆分目标来说,要做到:

  • • 高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高。

  • • 低耦合:每个微服务的功能要相对独立,尽量减少对其它微服务的依赖。

从拆分方式来说,一般包含两种方式:

  • • 纵向拆分:按照业务模块来拆分

  • • 横向拆分:抽取公共服务,提高复用性

黑马商城

以黑马商城为例,原来所有业务都在一个单体项目里,现在我们可以把他拆分为以下五个微服务

  • • 用户服务

  • • 商品服务

  • • 订单服务

  • • 购物车服务

  • • 支付服务

下面是拆分完毕的项目结构,这里因为测试了负载均衡,所以启动了两个商品微服务实例

微服务框架(一):服务拆分和服务注册、远程调用

微服务框架(一):服务拆分和服务注册、远程调用

注册中心

在微服务远程调用的过程中,包括两个角色:

  • • 服务提供者:提供接口供其它微服务访问,比如item-service

  • • 服务消费者:调用其它微服务提供的接口,比如cart-service

在大型微服务项目中,服务提供者的数量会非常多,为了管理这些服务就引入了注册中心的概念

我们这里就采用了Nacos(Alibaba公司出品,目前被集成在SpringCloudAlibaba中)

导入数据库

首先需要将nacos所需要的sql文件导入数据库(这里以mysql为例)

微服务框架(一):服务拆分和服务注册、远程调用

配置数据库

然后创建一个配置文件在/root/nacos/custom.env

注意这里其实就是在配置nacos的数据库

PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql
MYSQL_SERVICE_HOST=192.168.88.188
MYSQL_SERVICE_DB_NAME=nacos
MYSQL_SERVICE_PORT=3306
MYSQL_SERVICE_USER=root
MYSQL_SERVICE_PASSWORD=123
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai

创建Nacos容器

使用docker创建nacos容器

docker run -
--name nacos 
--env-file ./nacos/custom.env 
-8848:8848 
-9848:9848 
-9849:9849 
--restart=always 
nacos/nacos-server:v2.1.0-slim

启动完成后就可以访问nacos登录页:http://IP:8848/nacos/,账号密码都是nacos

服务注册

application.yml里添加nacos配置

spring:
  application:
    name: item-service # 服务名称
  cloud:
    nacos:
      server-addr: 192.168.88.188:8848 # nacos地址

访问控制台即可发现服务注册成功,可以看到服务实例信息

服务发现

在pom.xml里引入依赖,并在在application.yml里添加nacos配置

<!--nacos 服务注册发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

之后,服务调用者就可以利用负载均衡的算法,从多个实例中挑选一个去访问订阅服务。

常见的负载均衡算法有:

  • • 随机

  • • 轮询

  • • IP的hash

  • • 最近最少访问

  • • …

这里我们可以选择最简单的随机负载均衡。

OpenFeign远程调用

引入依赖

OpenFeign可以让远程调用像本地方法调用一样简单

首先引入OpenFeign的依赖和负载均衡的依赖

  <!--openFeign-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
  </dependency>
  <!--负载均衡器-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-loadbalancer</artifactId>
  </dependency>

还有连接池的依赖,这里选用okhttp

<!--OK http 的依赖 -->
<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-okhttp</artifactId>
</dependency>

application.yml里配置连接池生效

feign:
  okhttp:
    enabled: true # 开启OKHttp功能

启用组件

接下来,我们在项目启动类上添加注解,启动OpenFeign功能:

@EnableFeignClients(basePackages = "top.zhengru.hmall.api.client", defaultConfiguration = DefaultFeignConfig.class)
@MapperScan("top.zhengru.hmall.pay.mapper")
@SpringBootApplication
public class PayApplication {
    public static void main(String[] args) {
        SpringApplication.run(PayApplication.class, args);
    }
}

使用方法

一般来说,为了避免重复编写Client接口(后面会提到),会采取两种方法来抽取代码(如图)

  • • 思路1:抽取到微服务之外的公共module

  • • 思路2:每个微服务自己抽取一个module

方案1抽取更加简单,工程结构也比较清晰,但缺点是整个项目耦合度偏高。

方案2抽取相对麻烦,工程结构相对更复杂,但服务之间耦合度降低。

微服务框架(一):服务拆分和服务注册、远程调用

我们这里采用了第二种方法,所以其他的服务可以通过依赖引入的方法来使用Client

  <dependency>
      <groupId>top.zhengru.hmall</groupId>
      <artifactId>hm-api</artifactId>
      <version>1.0.0</version>
  </dependency>

接着可以看一下Client的写法

@FeignClient("item-service")
public interface ItemClient {

    @GetMapping("/items")
    List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);

    @PutMapping("/stock/deduct")
    void deductStock(@RequestBody List<OrderDetailDTO> items);
}

微服务框架(一):服务拆分和服务注册、远程调用

在对应的service里,通过Client来远程调用

//    private final IItemService itemService;
    private final ItemClient itemClient;
//        List<ItemDTO> items = itemService.queryItemByIds(itemIds);
        List<ItemDTO> items = itemClient.queryItemByIds(itemIds);

配置日志级别

需要在开头启动类的注解@EnableFeignClients里配置全局生效,想要局部生效也可以在某个Client里配置

public class DefaultFeignConfig {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.FULL;
    }
}

如果你觉得这篇文章对你有所帮助,记得走之前点个「赞」「在看」

欢迎点击左下角「阅读原文」访问博客


原文始发于微信公众号(正如的集装箱):微服务框架(一):服务拆分和服务注册、远程调用

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/241858.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!