• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

从零学习微服务

武飞扬头像
鸡蛋灌饼侠
帮助1

更新中,关注不断更…
如果觉得需要补充哪些内容,可以在评论区留言或者私信我哦


🌟引入

这里讲的是基于springboot和springboot alibaba的微服务,Spring Boot和Spring Boot Alibaba都是基于Spring框架的开源框架,用于简化应用程序的开发和部署。

这篇文章里会介绍微服务的整体概念,目前国内常用的组件,以及国内使用非常广泛的Snowy框架。

学新通

首先说一下微服务的概念,相信很多小伙伴已经对单体架构和SOA架构有所了解,当然如果没有了解过也不用着急,这里大致讲一下:

单体架构:将系统所有功能,包括前端界面、后端服务全部在同一个工程上开发,最终将所有模块、所有功能打包在一起放在一个进程上运行。

SOA架构:粗颗粒度的、松耦合的、面向服务的架构,在架构中使用一个标准 的通信协议,通过网络提供应用程序的业务功能服务,且所有服务都是完全独立部署和维护的,并且可以组合使用。

学新通

SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud

SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。

学新通

所以刚入手SpringCloud的家人们可以简单理解成一个SpringCloud项目是把一个整体的SpringBoot项目拆成很多小的SpringBoot项目并且集成上优秀组件。

本文中会介绍feignribbonnacosgatewayrabbitMQredisSentinelSeata,以及docker部署工具。

下面这个是一个典型的微服务架构,整个项目拆分成四个模块。
这里说一下微服务架构的几个原则

  • 不同微服务,不要重复开发相同业务
  • 微服务数据相互独立,不要访问其他服务的数据库
  • 微服务可以将自己的业务暴露为接口,供其他的微服务调用

学新通

看到上面的图,有些小伙伴就会想到一个问题,不同的微服务会部署到不同的服务器上,这样就会涉及到一个远程调用的问题,那么这里就开始介绍SpringCloud的第一个组件——feign


🎶Feign

Feign是一个声明式的http客户端,官方地址:https://github.com/OpenFeign/feign
其作用就是帮助我们优雅的实现http请求的发送,解决远程调用的问题。

远程调用简称RPC(Remote Procedure Call),简单来说就是调用方和被调用方不在同一个机器上,可以对比着“本地过程调用”理解这一概念。

这里我们先看一下官方文档:

学新通

这段话总结一下就是Feign是以添加注释的形式使用的。

Feign的具体使用方法如下:

  1. 引入依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 添加注解

在启动类上加上 @EnableFeignClients 注解

@EnableFeignClients
@SpringBootApplication
public class OrderApplication{
	public static void main(String[] args){
		SpringApplication.run(OrderApplication.class,args);
	}
}
  1. 编写Feign客户端
import org.springframework.cloud.openfeign.Feignclient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.Pathvariable;

//指定绑定服务为userservice
@FeignClient("userservice")
public interface UserClient{
	@GetMappring("/user/{id}")
	User findById(@PathVariable("id") Long id);
}

这个客户端主要是基于SpringMVC的注解来声明远程调用的信息

  1. 测试
@Autowired
private UserClient userClient;

public Order queryOrderById(Long orderId){
	//1.查询订单(假设这里已经定义好了order实体类)
	Order order = orderMapper.findById(orderId);
	//2.利用Feign发起http请求,查询用户
	User user = userClient.findById(order.getUserId());
	//3.封装user到order
	order.SetUser(user);
	//4.返回
	return order;
}

要是有用过RestTemplate的小伙伴就会发现Feign要整洁很多,可读性也更高。

Feign还可以支持很多的自定义配置,如下表所示:

类型 作用 说明
feign.Logger.Level 修改日志级别 包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder 响应结果的解析器 http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送
feign.Contract 支持的注解格式 默认是SpringMVC的注解
feign.Retryer 失败重试机制 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可。

基于配置文件修改feign的日志级别可以针对单个服务:

feign:  
  client:
    config: 
      userservice: # 针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

也可以针对所有服务:

feign:  
  client:
    config: 
      default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

NONE:不输出日志信息。
BASIC:仅输出请求方法、URL、响应状态码和执行时间四个基本信息。
HEADERS:输出BASIC级别的信息,并且输出请求和响应的头信息。
FULL:输出完整的请求和响应的详细信息,包括请求和响应的正文。

基于Java代码来修改日志级别:先声明一个类,然后声明一个Logger.Level的对象:

public class DefaultFeignConfiguration  {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class) 

如果是局部生效,则把它放到对应的@FeignClient这个注解中:

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration.class) 

我们在使用中还会遇到Feign性能优化的问题,这里主要使用的就是用连接池替换Feign默认的URLConnection

使用连接池可以有效地提高Feign的性能和可靠性。连接池可以缓存已经建立的HTTP连接,避免每次发送HTTP请求都需要建立新的连接,从而提高请求的响应速度。同时,连接池还可以限制并发连接的数量,防止由于并发连接数过高而导致的服务器负载过高的问题。

完成改操作需要引入依赖并在在yaml文件中加入如下配置

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-jackson</artifactId>
    <version>11.5</version>
</dependency>
feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

当然具体的配置都是按照项目的需求来的。

Feign的性能优化还有超时设置,重试机制,这里就不详细介绍了,感兴趣的小伙伴可以去自己了解。


😺Ribbon

接下来介绍的是Ribbon,这是SpringCloud底层使用的实现负载均衡的组件。

关于负载均衡这个概念很多小伙伴都已经在学习网络的时候了解了,这里就只放一张图去描述,Ribbon就是实现了蓝色的功能。

学新通

Ribbon使用起来很方便,首先加入依赖:

<dependency>
    <groupId>com.netflix.ribbon</groupId>
    <artifactId>ribbon</artifactId>
    <version>2.2.2</version>
</dependency>

第二步是在启动类加上 @LoadBalance 注解

@LoadBalanced
@SpringBootApplication
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

也会在创建RestTemplate并注入Spring容器时用到:

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

下面说一下修改负载均衡的方法:

负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类:

学新通

修改负载均衡规则有两种方式:

  1. 代码方式:在Application类中,定义一个新的IRule
@Bean
public IRule randomRule(){
    return new RandomRule();
}
  1. 配置文件方式:在application.yml文件中,添加新的配置也可以修改规则:
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 

说一下Ribbon加载的问题:

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长,而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:
  eager-load:
    enabled: true
    clients: userservice

🐎Naocs

说完了Ribbon就该讲Nacos了,Nacos是一个注册中心组件,同样是注册中心组件的还有Eureka,但现在国内更推崇Alibaba的Nacos,所以这里就仅介绍Nacos。

Nacos可以在本机上安装,官网链接在这里:https://nacos.io/zh-cn/docs/quick-start.html ,安装好的效果如下:

学新通

我现在在本机上跑的是小诺开源项目,这是服务已经注册到我的Nacos上的效果。

如果是自己的新项目要使用的时候,先找到你nacos的安装目录,点开bin目录,在命令行运行这行命令:

.\startup.cmd -m standalone

保证你的nacos正常运行,这时候对你们项目进行下面的操作:

  1. 引入依赖
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.2.6.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

这里不要忘记如果有Eureka的依赖一定要注释掉

  1. 配置nacos地址

在你需要的服务的application.yml文件中添加nacos地址:

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
  1. 重启

重启微服务后,登录nacos管理页面,可以看到微服务信息啦

有的小伙伴可能不知道去哪看,这个时候你可以试试在浏览器输入localhost:8848,
或者直接点运行起来的项目中的蓝色的8848

学新通

你改了端口号的话就输入自己的nacos服务用到的端口号就行

下面是一些nacos的其他配置:

  1. 配置集群

修改application.yml文件,添加集群配置:

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ # 集群名称

重启后,我们就可以在nacos控制台看到类似下面的结果:

学新通

如果要实现同集群优先,可以将所需服务的yml文件进行如下修改:

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 

我们在实际部署的时候还会遇到配置权重的问题,这个需要在nacos控制台中找到服务列表,点击详情进行编辑:

学新通

权重从1到0,权重越小被访问几率越小,如果权重修改为0,则该实例永远不会被访问。

Nacos中还有一个命名空间的可选配置,不同namespace之间相互隔离,不同namespace的服务互相不可见。

学新通

如果要修改命名空间,则加上自己的命名空间的ID:

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ
        namespace: 492a7d5d-237b-46a1-a99a-fa8e98e4b0f9 # 命名空间,填ID

学新通

如果要新建命名空间则直接点击即可,ID为了防止重复,用自动生成的比较好

学新通


🍨Gateway

Gateway(网关)是微服务架构中的守住门口神,为所有微服务提供统一的入口。它充当了客户端请求与服务端应用之间的门户,将请求通过定义的路由和断言进行转发,路由表示需要转发请求的地址,断言则代表请求这些地址时所需满足的条件。只有同时符合路由和断言,Gateway才会转发请求。

学新通

网关有三个大的功能

  • 权限控制:网关作为微服务入口,需要校验用户是是否有请求资格,如果没有则进行拦截。

  • 路由和负载均衡:一切请求都必须先经过gateway,但网关不处理业务,而是根据某种规则,把请求转发到某个微服务,这个过程叫做路由。当然路由的目标服务有多个时,还需要做负载均衡。

  • 限流:当请求流量过高时,在网关中按照下流的微服务能够接受的速度来放行请求,避免服务压力过大。

网关常用的有gateway和zuul,zuul是阻塞式的,性能远远不如gateway,我们这里就只对gateway进行介绍。

阻塞式(Blocking)通常用来描述一种同步的操作方式。当一个线程或进程执行一个阻塞式的操作时,它会一直等待,直到操作完成并且返回结果。在此期间,线程或进程会被挂起,无法执行其他任务。

下面说一下怎么在项目中使用gateway

  1. 引入依赖
<!--网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
  1. 编写启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayApplication {

	public static void main(String[] args) {
		SpringApplication.run(GatewayApplication.class, args);
	}
}
  1. 编写基础配置和路由规则

创建application.yml文件,内容包括服务基本信息、nacos地址、路由:

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求

将符合Path 规则的一切请求,都代理到 uri参数指定的地址。

这里将 /user/**开头的请求,代理到lb://userservice,lb是负载均衡,根据服务名拉取服务列表,实现负载均衡。

学新通

上面yml中的路由配置包括两个很重要的配置——断言和过滤器,这里只列出种类,需要使用的话可以去深入了解

断言工厂

名称 说明 示例
After 是某个时间点后的请求 - After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before 是某个时间点之前的请求 - Before=2031-04-13T15:14:47.433 08:00[Asia/Shanghai]
Between 是某两个时间点之前的请求 - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie 请求必须包含某些cookie - Cookie=chocolate, ch.p
Header 请求必须包含某些header - Header=X-Request-Id, \d
Host 请求必须是访问某个host(域名) - Host=.somehost.org,.anotherhost.org
Method 请求方式必须是指定方式 - Method=GET,POST
Path 请求路径必须符合指定规则 - Path=/red/{segment},/blue/**
Query 请求参数必须包含指定参数 - Query=name, Jack或者- Query=name
RemoteAddr 请求者的ip必须是指定范围 - RemoteAddr=192.168.1.1/24
Weight 权重处理  

过滤器工厂

名称 说明
AddRequestHeader 给当前请求添加一个请求头
RemoveRequestHeader 移除请求中的一个请求头
AddResponseHeader 给响应结果中添加一个响应头
RemoveResponseHeader 从响应结果中移除有一个响应头
RequestRateLimiter 限制请求的流量

这里举一个小栗子🌰:

如果需要给所有进入userservice的请求添加一个请求头:Truth=give an example

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/** 
        filters: # 过滤器
        - AddRequestHeader=give an example # 添加请求头

这个时候因为当前过滤器写在userservice路由下,因此仅仅对访问userservice的请求有效。

如果要对所有的路由都生效,则可以将过滤器工厂写到default下。格式如下:

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/**
      default-filters: # 默认过滤项
      - AddRequestHeader=give an example 

有的时候可能会遇到跨域问题,解决方法如下:

在yml文件进行按照下面进行修改:

spring:
  cloud:
    gateway:
      # 。。。
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求 
              - "http://localhost:8090"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期
学新通

只允许8090端口发5种请求访问10010端口。


🍬Docker

Docker是一款流行的开源容器化平台,可以帮助开发人员和系统管理员更轻松地打包、发布和运行应用程序。Docker的主要目标是提供一种轻量级的、可移植的容器化解决方案,使应用程序可以在任何环境中运行,而不需要担心底层操作系统或基础设施的变化。

Docker基于容器技术,允许用户将应用程序及其所有依赖项打包成一个独立的容器,从而简化了应用程序的部署和管理。Docker容器可以在任何支持Docker的操作系统上运行,包括Linux、Windows和macOS等。

学新通

简单来说,Docker解决了操作系统环境差异,依赖版本差异的问题。

要是看到这里还不懂的可以去网站看一下这篇:https://www.runoob.com/docker/docker-tutorial.html?source=1

说一下怎么使用docker,在使用之前,要准备的是一个CentOS7的云服务器或者虚拟机,还没有的小伙伴建议先暂停一下,准备好环境再来学习。

  1. 安装docker

如果是之前有下过的话这里有删除命令:

yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine \
                  docker-ce

下载docker需要yum工具,这里先安装:

yum install -y yum-utils \
           device-mapper-persistent-data \
           lvm2 --skip-broken

更新本地镜像:

# 设置docker镜像源
yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo

yum makecache fast

然后输入命令:

yum install -y docker-ce

docker-ce为社区免费版本。稍等片刻,docker即可安装成功。

商业版docker-ee有需要的小伙伴可以安装

  1. 启动docker

这里网上有说要直接关防火墙的,但我不太建议,需要哪个端口的时候开放指定端口即可

通过命令启动docker:

systemctl start docker  # 启动docker服务

systemctl stop docker  # 停止docker服务

systemctl restart docker  # 重启docker服务

然后输入命令,可以查看docker版本:

docker -v

学新通

这里写一个使用docker创建nginx容器的栗子:

我们这里会用到,用下面的命令把8080端口上的进程杀掉

学新通

下一步是安装镜像

docker pull nginx

需要安装什么镜像可以自己去dockerhub上去找

学新通

当然,如果你觉得服务器的网速太慢,你也可以选择用本机传输的方式,这里就不详细讲了

下面这个就是创建的命令:

学新通

docker run --name myn -d -p 8080:80 nginx

解释一下每个参数是什么意思:

  • “–name” => 容器名称

容器名称一定一定不要随便起一个,不然到时候你自己都不知道这个容器是做什么的

  • “-d” => 以后台模式进行运行
  • “-p” => 指定映射端口,我这里是让新建的docker容器上的80端口映射到服务器上的8080端口
  • 最后是这个容器上需要什么服务,因为这里演示我们创建的是nginx,所以直接写nginx就好

创建完成之后,你在浏览器输入 你服务器的ip :端口号 就可以进行访问

学新通

加点拓展知识,如果你点开这个想看到的不是这个页面该怎么办呢

这个就需要找到存nginx的html页面的文件夹

cd /usr/share/nginx/html

学新通

这里可以看到index.html这个文件,将这个文件用本机编译器打开

学新通

选择系统关联,然后打开进行编辑就可以了

docker还有一些高级应用我会专门写一篇文章,写完了链接会放到这里,现在先带过了

🚢MQ

RabbitMQ是一个使微服务项目支持异步通信的中间件,这里就要说一下什么是同步通信什么是异步通信了。前面介绍的Feign就属于同步通信的组件,而异步通信指发送数据时不要求接收端时钟和发送端时钟同步,这样最大的好处就是传输信息灵活。

这里是RabbitMQ的原理图,消息首先由生产者发送到一个统一的交换中心,交换中心根据一定的转发规则将消息转发到对应的队列中,然后通过消息队列最终将消息传递给消费者。

学新通

关于RabbitMQ远程调用这块就不做解释了,因为不常用

使用起来也比较容易,还是前面说的用docker的方法(真不建议在Windows系统上部署),用下面的命令拉取:

docker pull rabbitmq

在项目中使用的时候用到的会是SpringAMQP,SpringAMQP是基于RabbitMQ封装的一套模板,并且还利用SpringBoot对其实现了自动装配,使用起来非常方便。

SpringAmqp的官网:https://spring.io/projects/spring-amqp

我们也可以看到SpringAmqp也是Spring全家桶中的一员

学新通

SpringAMQP提供了三个功能:

  • 自动声明队列、交换机及其绑定关系
  • 基于注解的监听器模式,异步接收消息
  • 封装了RabbitTemplate工具,用于发送消息

使用时记得加上依赖:

<!--AMQP依赖,包含RabbitMQ-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

这里内容有点多,建议去看一下官方给的示例:https://github.com/spring-projects/spring-amqp-samples

🏄🏻sentinel

下面的内容等更新…

seata

下面的内容等更新…

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfckbjb
系列文章
更多 icon
同类精品
更多 icon
继续加载