Consul系列:让服务Running in anywhere

news2024/12/23 3:10:59

引言

随着微服务概念深入人心,越来越多的解决方案选择使用微服务架构,这类架构的共同点是服务数量多,因此种类繁多的服务之间如何互相访问就变成了一个很现实的问 题。目前比较流行的分布式存储比如:Consul, etcd, ZooKeeper,如何结合当前的业务场景,利用这些工具实现更加自动化的运维化方案、简化我们的流程呢?本文主要 给大家介绍在服务发现和配置管理方面的consul工具,同时也会为大家带来一些应用场景案例参考。

关于服务发现及Consul

将应用部署到集群时,服务IP或端口是动态分配的,用户访问时不知道后端的IP及端口,在访问这些服务时,使用一定的机制动态发现服务的IP及端口就是服务发现(ServiceDiscovery)。

Consul是一个服务发现和配置管理的工具,是具有分布式、高可用、高度可扩展的服务。

Consul的特性

  • 服务发现:Consul客户端可以提供其他服务的服务发现功能,使用dns和http,服务发现问题很容易被解决。
  • 监控检查:使用Consul可以提供任意数量的健康检查功能,无论是服务状态(web服务器返回 http 200)还是本地节点的信息(内存利用率超过90%),这些信息都可以 由我们进行自定义设置,并由服务发现组件将服务流量从不健康的组件中移开。
  • key/value存储:Consul的kv存储功能,通过http api可以很容易完成动态配置管理、协调服务、主选举、功能标记等服务。
  • 跨中心部署:Consul支持多数据中心感知,可以支撑任意数量的区域无需复杂配置。

节点

  • 节点类型
    • server服务发现、健康检查、数据一致性存储,leader选举机制,所以奇数部署。每个数据中心至少有一个 agent 运行在 server 模式,推荐为 3 个或 5个server节点 。
    • agent:运行在 consul 集群所有节点上的核心服务,其可运行在 client 或 server 模式,通过 consul agent命令来启动。由于所有节点必须运行 agent,指定节点运行于 client 或者 server 模式是很简单地,除非有其它的 agent 实例。 所有的 agent 都能运行 DNS 或者 HTTP 接口,并负责运行时检查和保持服务 同步
    • client:一个 client 是一个 转发所有 RPC 到 server的 agent 。这个 client 是相对无状态的。client 唯一执行的后台活动是加入 LAN gossip 池。这有一个 最低的资源开销并且仅消耗少量的网络带宽。
  • Consul节点退出
    • 正常退出(至关重要):节点通过信号正常关闭,接到信号的Consul会通知其他节点,正常离开后上面的服务和健康检查将被移除
    • 异常退出:没有通过信号正常关闭的节点,其他节点会由于没有接到信号,认为这个节点还是正常的,也不会移除其服务和健康检查。

架构

Consul vs. Other Software

Consul部署

可以参考Consul系列:Consul Server部署及用法介绍.

集群运行

Consul可以运行client和server 两种节点模式,每个数据中心必须有一个server节点,但如果高可用,需要部署3个以上。其它Consul全部运行在client模式。客户端连接 会有一个非常轻的注册过程,运行健康检查并发给server节点。

  • Consul server模板片段
#supervisor管理consul服务启动

[program:consul]

command=/usr/local/bin/consul agent -config-dir /home/项目用户/consul/conf -data-dir /home/项目用户/consul/data process_name=%(program_name)s

user=项目用户

numprocs=1

autostart=true

autorestart=true

startsecs=2

startretries=3

redirect_stderr=true

stdout_logfile_backups=10

stdout_logfile_maxbytes=300MB stdout_logfile=/home/项目用户/var/log/supervisor/s_%(program_name)s.log

#默认加载的config.json配置 {

"acl_token":"你的acl token", "bootstrap_expect":1, "client_addr":"0.0.0.0", "datacenter":"dc名称,一个数据中心统一使用一个", "enable_debug":false, "enable_syslog":false,

"log_level":"INFO", "node_name":"这里定义consul节点名称,通常建议hostname比较容易区分",, "raft_protocol":3,

"rejoin_after_leave":true,

"retry_interval":"3s", "retry_join":["server节点地址1","server节点地址2","....."], "server":true,

"ui":true

}
  • Consul client模板片段
#supervisor管理consul服务启动

[program:consul]

command=/usr/local/bin/consul agent -config-dir /home/项目用户/consul/conf -data-dir /home/项目用户/consul/data process_name=%(program_name)s

user=项目用户

numprocs=1

autostart=true

autorestart=true

startsecs=2

startretries=3

redirect_stderr=true

stdout_logfile_backups=10

stdout_logfile_maxbytes=300MB

stdout_logfile=/home/项目用户/var/log/supervisor/s_%(program_name)s.log

#默认加载的config.json配置 {

"acl_token":"你的acl token", "bootstrap_expect":0, "client_addr":"0.0.0.0", "datacenter":"dc名称,一个数据中心统一使用一个", "enable_debug":false, "enable_syslog":false,

"log_level":"INFO", "node_name":"这里定义consul节点名称,通常建议hostname比较容易区分",, "raft_protocol":3,

"rejoin_after_leave":true,

"retry_interval":"3s", "retry_join":["server节点地址1","server节点地址2","....."], "server":false,

"ui":false

} 

注册服务健康检查到Consul

Consul服务定义

Consul中的服务一种是可以在启动前就定义 ,提前写好定义服务的配置文件放置到 Consul配置的-config-dir指定目录中, 如果这种方式需要更新,需要使用重载命令 consul reload。另外一种是Consul api的方式来注册服务。注册服务的信息主要包含id, name, port, address, check每个服务可以由多个ip或者可以有多个端口的服务组 成。需要注意的是:每个服务可以有多个check,check可以是端口检查、http检查、脚本检查。其中检查脚本通常是自由做任何事情,以确定检查的状态。唯一的限制 是,该退出代码都必须遵守此约定:

  • Exit code 0 - 检查结果是 passing
  • Exit code 1 - 检查结果是 warning
  • 其它 Exit code - 检查结果是 failing

注册服务通常是通过agent来注册,因为服务的健康检查与所在Consul agent是绑定的,如果 Consul agent所在宿主机挂掉,就认为这台主机上的服务也是挂的。

注册服务及健康检查

  • 注消(deregister)agent 服务:-X PUT http://$IPADDR:8500/v1/agent/service/deregister/:service_id
  • 注销(deregister)检查:-X PUT http://$IPADDR:8500/v1/agent/check/deregister/:check_id
  • 注册服务:json文件注册方式。
{

"service": {

"name": "test",

"tags": ["test service"],

"port": 31030,

"address": "10.10.169.72",

"id": "test",

"check": {

"id": "api",

"http": "http://10.10.169.72:31030",

"interval": "3s"

        }

    }

}
  • 注册健康检查:json文件注册方式。
# cat http.json 

{

"service": {

"name": "web",

"tags": ["test web site"],

"port": 8099,

"check": {

"id": "web",

"name": "web on port 8099",

"tcp": "localhost:8099",

"interval": "10s",

"timeout": "1s"

        }

    }

}

注意:

  • 同一个服务 每个实例的id唯一
  • 同一个服务 每个检查项的id唯一

服务发现

Consul启动后,并且服务集群状态正常,就可以对外提供DNS或者HTTP API来查询服务了。

http api

  • 查询所有节点的服务列表信息:-X GET http://$IPADDR:8500/v1/catalog/services
  • 查询本节点注册的服务信息:-X GET http://$IPADDR:8500/v1/agent/services
  • 通过agent查询异常服务:X GET http://$IPADDR:8500/v1/health/state/critical

Consul dns服务发现

Consul自带一套dns 服务,所以可以处理简单的服务发现。通过dig命令查询Consul dns中的服务解析, critical的服务不会解析。

  • 使用DNSmasq转发Consul dnsConsul默认的dns服务端口是8600,常用的dns服务默认的端口为53,所以如果使用8600,不太方便。就算可以修改Consul dns端口,但又可能会跟其它的 dns服务冲突。
    • 可以使用puppet模块管理的服务DNSmasq来转发Consul dns和其它dns服务在/etc/dnsmasq.conf中添加 Consul dns地址

  • 配置NetworkManager在resolv.conf中添加search service.Consul和默认的dns server指定到本机,例如:

  • 这样即可直接在该节点使用dns访问到Consul中的服务了,而且可以使用短域名访问,例如:

案例分享

haproxy配合Consul dns实现服务发现

haproxy做为PaaS平台服务的负载均衡服务,对外服务;配置backend服务时,配置的是Consul中的服务域名。

这里有个坑,原来使用haproxy 1.5版本, 后端服务使用域名时,启动后只解析一次(和nginx类似),这时如果解析到的服务挂掉,访问haproxy页面时会503。查询官网得知haproxy 1.6支持了动态dns 域名解析的配置,后升级为haproxy 1.6。

下面是动态DNS解析相关的配置内容:

resolvers consuldns

nameserver dns1 127.0.0.1:53

resolve_retries 200 

timeout retry 1s

hold valid 10s

frontend uq

balance leastconn

cookie JSESSIONID prefix

bind 0.0.0.0:10000 accept-proxy

capture request header Host len 128 

option httplog

log-format %si:%sp\ %ci\ %ft\ %hrl\%r\ %ST\ %B\ %Tt



  # 自定义ACL(路由)策略

acl host_uq-xyteam hdr_dom(host) -i test.x.example.com

use_backend test if host_test



#自定义转发的realserver地址

backend test

server test test.service.consul:10000 resolvers mydns maxconn 50000 check inter 2000 rise 2 fall 100 

用户访问haproxy就会动态解析访问后端Consul中的服务。

基于Consul dns,实现推送服务的高可用切换

推送的unipush服务最初是基于常见的haproxy来做高可用的及入口的统一。为了减轻架构复杂度和更加的自动化,实现自动的阔缩容,通过将推送服务注册到Consul来做健康检查,并且去掉haproxy使用consul dns作为轻量级的代理。配置如下:

# cat service.json

{

"service": {

"name": "test_recv",

"port": 30121,

"check": {

"id": "up",

"name": "up on port 30121",

"tcp": "42.186.52.150:30121",

"interval": "60s",

"timeout": "30s"

        }

    }

}

正常情况该域名会解析到所有的test服务地址,如果一旦发生个别服务异常、节点故障等情况,dns会立即将故障服务节点踢出解析。

root@localhost:~$ dig @127.0.0.1 -p 53 test_recv.service.consul

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @127.0.0.1 -p 53 test_recv.service.consul ; (1 server found)

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16206

;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0



;; QUESTION SECTION:

;test_recv.service.consul. IN A



;; ANSWER SECTION:

test_recv.service.consul. 0 IN A 10.192.4.163

test_recv.service.consul. 0 IN A 10.192.4.150

test_recv.service.consul. 0 IN A 10.192.4.240



;; Query time: 3 msec

;; SERVER: 127.0.0.1#53(127.0.0.1) 

;; WHEN: Sat Nov 17 12:20:29 2018

;; MSG SIZE rcvd: 93

基于Consul template,实现服务配置文件动态渲染

日常运维中由于各种情况,我们少不了会对各类服务的配置文件进行变更。例如服务迁移、增加配置参数项等。利用consul,我们可以使用K/V、services等等集群内的数据信息渲染我们的配置文件内容。 实时监听unipush_recv这个service的变化,一旦出现变化,立即触发渲染,例如新增、故障等等。

实时监听unipush_recv这个service的变化,一旦出现变化,立即触发渲染,例如新增、故障等等。

{{range service "unipush_recv"}}   server {{.Node}} {{.Address}}:{{.Port}} maxconn 50000 check inter 2s addr {{.Address}} port {{.Port}}{{end}}

listen niepush_4

....

渲染后的内容,会将定义的变量用对应的service信息进行填充。

server test-up02 10.192.4.240:30121 maxconn 50000 check inter 2s addr 10.192.4.240 port 30121 

server test-up04 10.192.4.150:30121 maxconn 50000 check inter 2s addr 10.192.4.150 port 30121 

server test-up06 10.192.4.147:30121 maxconn 50000 check inter 2s addr 10.192.4.147 port 30121

......

最后在渲染后指定后续的处理逻辑:reload重载。

[program:consul-template]

command=/usr/local/bin/consul-template -consul-addr 127.0.0.1:8500 -template "/home/test/haproxy/conf/test_recv.ctmpl:/home/test/haproxy/conf/test_recv.conf:haproxy reload"

process_name=%(program_name)s

user=test

numprocs=1

autostart=true

autorestart=true

startsecs=2

startretries=3

redirect_stderr=true

stdout_logfile_backups=10

stdout_logfile_maxbytes=300MB

stdout_logfile=/home/test/var/log/supervisor/s_%(program_name)s.log stderr_logfile=/home/test/var/log/supervisor/s_%(program_name)s.log

同样不仅限于service,包括例如可以使用K/V的渲染,利用WEB UI界面可修改的K/V的特性,提供产品同学自助的文件变更&服务更新生效的功能。根据不同的场景、利用 consul的watch、template、check、service等功能组合出业务更加自动化的运维方案。

Consul监控

Consul开放了API可以直接获取Consul集群性能数据,可以脚本化拿到后进行渲染,效果如下:

Consul告警

Consul的服务相关问题都会有日志记录,所有重要的一点就是做日志监控,并且将日志中的error信息进行告警,效果如下:

访问安全控制

WEB UI

web ui一般采用apache+web ui的模式,从apache这里设置用户密码认证&ssl证书,再转发到一个web ui接口,这个web ui接口进行白名单限制。

API

采用防火墙限制端口(8300/8301/8302)处理.

Consul实践遇到的坑

调用deregistry接口删除Consul服务后,诡异的出现了

初期进行http api 调试测试时,注册了一些服务到Consul, 后来想删除就调用,ip:8500/v1/catalog/deregister 接口进行删除,调用该接口返回成功。但过一会儿去web ui查询, 发现刚才删除的服务还在,后来查询官方文档,原来server端catalog和 agent端都有deregister接口,我们的服务都是通过agent注册的,所以在catalog 删除不 生效,只能通过agent的 deregistry接口来删除。

总的来说目前已经尝试的有两种解决方案:

  • 在新的另外的节点注册一个相同的service,包括id相同进行覆盖。
  • 在注册该servive的agent上调用deregister删除。

清理Consul持久化数据异常

测试Consul server服务的高可用,先停止其中一台Consul server节点的容器,并清理Consul 的持久化数据,其它服务的Consul节点正常,达到预期结果,后来尝试恢复 这个Consul server,恢复后发现从Consul ui查发现 少了一些服务节点,查询过后,正好是清理数据的这台Consul server上的服务在 Consul 中消失了,因此又重新在这个 节点进行相应的服务注册才真正恢复正常。

健康检查状态码的坑

健康检查脚本中使用grep检查结果内容,如果匹配则正常,不匹配为异常,例如: echo result|grep ok,有一次,一个服务节点异常,grep也没有匹配,当时认为这样就不 会被解析了,后来发现这个服务ip还是会被解析,查询问题发现grep 不匹配的error code 为1 ,code 1 只是warning ,还是会被解析,所以修改检查脚本内容,如果不匹 配,手动返回error code 2,之后这个异常服务才不解析。

使用registrator自动注册的坑

推送服务这边通常注册时候,为了和cmdb信息统一,registrator 默认的注册规则是服务名注册为 Consul中的service id。service和check id如果是不同的端口服务,不 能一样,否则在Consul同一个节点上就有可能同一个服务被注册多次,实际上是同 个服务不同实例,影响例如服务未注册上,检查的是其它进程端口等。不同的节点上的 service id或check id可以相同,同一台节点上的service的id不能一样,统一check之间的id也不能一样。

同一个节点设置为相同的id:

同一个节点设置为不同的id:

Consul agent节点异常

部署客户环境时遇到一个诡异的问题,有两个节点总是异常,健康检查这两个节点时好时坏,大部分时间是坏的,少部分时间显示正常状态。

排查问题时,发现主机之间响应时间很快,Consul server 与Consul agnet 之间的Consul端口都是可以通的。查询Consul server日志,看到 server 日志中有error:

以为是有端口漏开放了,telnet 测试后,发现Consul server到agent都是通的,谷歌下这个错误,发现有可能是因为没有开通udp端口导致的,后来又使用nmap测试 Consul相关的udp端口是不是开放的,测试后发现udp 果然没有开通。于是就向客户申请开通相应的udp端口,开通后,再进行测试,发现问题还是存在。

这就不得不再想其它办法,后来又查询异常的Consul agent节点日志发现,发现Consul agent 也报类似的错误,乍一看跟server端的日志是一样的,但仔细研究发现关键问 题,异常节点的agent报了很多访问其它agent节点8301端口的 time out的日志:

才发现agent不仅访问server, 还需要访问同级的其它agent 8301端口进行健康检查,后来开放8301所有Consul节点的端口访问后才正常。

比起另外两个同样流行的分布式存储etcd和ZooKeeper, Consul从设计上就考虑到了很多服务发现的需求, 比如说健康检查, 服务注册, DNS等。所以基于Consul来实现服

务发现的功能还是有很多的想象空间的。更多思考

Q1:Consul, etcd, ZooKeeper能比较一下吗?为什么没有选用后两者呢?

A1:ZooKeeper 处理数据 不支持 resf api , 需要操作的时候比较繁琐,功能也比较单一,etcd 服务功能也相对单一,需要依赖其它 组件 配合使用Consul 本身自

Q2:就服务发现和zk相比,会有多大的延迟?

A2: 就服务发现来说,Consul 支持 api 和 dns 两个方式获取 服务, dns 解析基本无消耗。 api 操作的话,具体的数据我没有进行严格测试,但zk是java服务本身 需要的内存比较多,java gc 垃圾回收也会影响一些性能。Consul 是go 语言开发性能会有一些优势。

Q3: 这里问一个不是很相关的问题,怎么看待Docker和微服务更配这样的说法?

A3: 以前是所有功能集成到一个服务中,微服务本身需要拆分服务,需要部署、更新、维护的服务数量会几何增加,如果是传统的方式运维的话,操作起来就是个挑

战,Docker化之后,部署、迁移、交付都会变简单。Q4:Consul最大承受多大规模,有瓶颈吗?

A4: 我没有针对 Consul服务 做过压力测试,我们一般是会对服务进行压力测试,就现在我们部署的集群规模而言,支持几百来的Consul 节点是没有问题的。理论 上可以更多。

Q5:内部的web服务怎么注册?用后台脚本周期性地检测web服务正常后,再请求接口注册服务吗?失败取消

A5: 如果 使用了 registrator ,docker服务启动时,添加相应的环境变量,就会自动注册到Consul,也会自动删除,不过registrator偶尔异常情况会有不同步的现 象,我们在 registrator 启动时添加同步参数定时同步,如果没有使用 registrator ,就需要自己处理注册和删除的逻辑,例如我们使用marathon /mesos 做为调试 的核心基础组件,可以监听marathon 的事件获取 容器实例 启动在哪,删除了哪些,就可以相应对 Consul做操作Consul 也支持异常服务定时清理,在注册添加时 添加DeregisterCriticalServiceAfter 参数 就可以

Q6:“每个数据中心必须有一个server节点,但如果高可用,需要部署3个以上”为啥一定要三个以上

A6: Consul server 节点也分为 leader 和 follower 节点,leader 选举一般为基数选举,1个就不是高可用了,所以最少3个,遵循2N+1 原则,支持宕机 N 个节

点。Q7: Consul能够支撑多大的高并发系统?

A7: 这个问题跟上面的问题稍有些重合,其实高并发是指的业务,业务一般在 启动、停止、迁移 、或业务之间相互访问时 Consul 才会有些数据交互 ,Consul的健 康检查 和 访问都是分摊到每个宿主机上, Consul 的压力 对比业务来说可以忽略不计。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/543791.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【CSS】

目录 1. 什么是 CSS 2. CSS的引入方式 3. CSS 选择器 3.1 基础选择器 3.1.1 标签选择器 3.1.2 类选择器 3.1.3 id 选择器 3.1.4 通配符选择器 3.2 复合选择器 4. CSS 字体设置 5. CSS 文本属性 6. CSS 背景设置 7. CSS 的 display 属性 8. CSS 的盒子模型 9. CSS 的弹…

apple pencil二代平替笔哪个好用?ipad第三方电容笔了解下

近几年来&#xff0c;人们开始使用互联网的频率不断提高&#xff0c;网络教学也日益普及。再加上ipad在所有平板设备中都是数一数二的存在&#xff0c;所以很多人都将它当成了无纸化学习的首选。当然&#xff0c;如果要把 ipad变成一个可以用来学习的东西&#xff0c;那配件肯定…

软件工程实验:数据库设计

前言 本实验的主要内容是数据库设计&#xff0c;即如何根据需求分析&#xff0c;设计合理的数据模型&#xff0c;创建和管理数据库&#xff0c;以及实现数据的增删改查等操作。数据库设计是软件工程的重要组成部分&#xff0c;它涉及到数据的存储、组织、查询和处理等方面&…

JavaWeb-VUEElement综合案例

VUE&Element 今日目标&#xff1a; 能够使用VUE中常用指令和插值表达式能够使用VUE生命周期函数 mounted能够进行简单的 Element 页面修改能够完成查询所有功能能够完成添加功能 1&#xff0c;VUE 1.1 概述 接下来我们学习一款前端的框架&#xff0c;就是 VUE。 Vue 是…

晶圆切割机如何选用切割刀对崩边好

晶圆切割机在切割晶圆时&#xff0c;崩边是一种常见的切割缺陷&#xff0c;影响切割质量和生产效率。要选用合适的切割刀以减少崩边&#xff0c;可以考虑以下几点&#xff1a; 根据晶圆尺寸和切割要求&#xff0c;选择合适的金刚石颗粒尺寸和浓度的切割刀。金刚石颗粒越大&…

十大排序算法(下):计数排序,基数排序,桶排序

文章目录 5. 其他非基于比较的排序5.1 计数排序5.2 桶排序5.3 基数排序 5. 其他非基于比较的排序 5.1 计数排序 有n个数&#xff0c;取值范围是 0~n&#xff0c;写出一个排序算法&#xff0c;要求时间复杂度和空间复杂度都是O(n)的 我们知道&#xff0c;前面介绍的基于比较的排…

javaIO之字符流

目录 一、简介二、字符流入流1.1FileReader构造方法1.2FileReader读取字符数据 三、字符流出流3.1 FileWriter 构造方法3.2FileWriter写入数据3.3关闭close和刷新flush3.4FileWriter的续写和换行3.5文本文件复制 四、IO异常处理五、小结 一、简介 字符流 Reader 和 Writer 的故…

2023最全最细的Selenium+Pytest自动化测试框架实战

选前言# selenium自动化 pytest测试框架 本章你需要 一定的python基础——至少明白类与对象&#xff0c;封装继承 一定的selenium基础——本篇不讲selenium&#xff0c;不会的可以自己去看selenium中文翻译网 测试框架简介# 测试框架有什么优点呢&#xff1a; 代码复用率…

马斯克开造人形AI 变形金刚要成真?

当5个人形机器人迎面走来&#xff0c;你会下意识地期待它们具备怎样的能力。特斯拉最近公布的视频给出答案&#xff0c;它自研的机器人“擎天柱”&#xff08;Optimus&#xff09;能够探索环境&#xff0c;复刻人类动作&#xff0c;自主操纵物品。 特斯拉CEO埃隆马斯克对这些与…

chatgpt赋能Python-python3_4_4怎么打代码

Python3.4.4的入门指南&#xff1a;如何打出高效的Python代码&#xff1f; 作为一名有10年Python编程经验的工程师&#xff0c;我深深地了解到Python3.4.4的强大和灵活性。Python是一种易于学习和使用的编程语言&#xff0c;因此它已成为数据科学家&#xff0c;人工智能和机器…

700页!阿里120W架构师推荐学习的微服务架构解析,到底牛在哪里?

前言 当前&#xff0c;微服务架构在国内正处于蓬勃发展的阶段&#xff0c;无论是大型互联网公司还是传统的IT企业&#xff0c;纷纷采用微服务架构构建系统。 在过去几年里&#xff0c;DevOps、云原生、面向演进式架构等理念已经深入人心&#xff0c;围绕微服务生态也出现了大…

JavaEE(系列9) -- 多线程案列2(堵塞队列)

目录 1. 堵塞队列 2. 生产者消费者模型 2.1 解耦合 2.2 削峰填谷 2.3 代码实现生产者消费者模型 3. 构建堵塞队列 3.1 实现普通队列(循环队列) 3.2 普通队列加上线程安全 3.3 普通队列实现堵塞功能 3.4 堵塞队列最终代码 4. 使用生产者消费者模型测试自己构建的堵塞队列 1. …

IP协议的相关特性、数据链路层相关内容讲解

文章目录 IP协议相关特性地址管理NAT机制IP地址的组成特殊的IP地址 路由选择 数据链路层相关内容以太网MTU IP协议相关特性 首先我们来认识一下IP协议的报头&#xff1a; 4位版本号&#xff1a;指定IP协议的版本&#xff0c;对于IPv4就是4. 4位头部长度&#xff1a;IP头部的长…

每日一题158—— 图片平滑器

图像平滑器 是大小为 3 x 3 的过滤器&#xff0c;用于对图像的每个单元格平滑处理&#xff0c;平滑处理后单元格的值为该单元格的平均灰度。 每个单元格的 平均灰度 定义为&#xff1a;该单元格自身及其周围的 8 个单元格的平均值&#xff0c;结果需向下取整。&#xff08;即…

常用中外文献检索网站大盘点

一、常用中文文献检索权威网站&#xff1a; 1、知网&#xff1a;是全球最大的中文数据库。提供中国学术文献、外文文献、学位论文、报纸、会议、年鉴、工具书等各类资源&#xff0c;并提供在线阅读和下载服务。涵盖领域包括&#xff1a;基础科学、文史哲、工程科技、社会科学、…

世界博物馆日:一起来看看这些“不太正经”的文物!

今天是5月18日&#xff0c;世界博物馆日。 这两年喜欢逛博物馆的年轻人越来越多了。和爬山、露营一样&#xff0c;博物馆打卡已经是这一届年轻人最受欢迎的娱乐方式之一了。 今天我们要和大家分享的是&#xff1a;全国各地博物馆里收藏的那些萌的、凶的、神秘的、搞笑的…精品…

从零开始 Spring Boot 31:Spring 表达式语言

从零开始 Spring Boot 31&#xff1a;Spring 表达式语言 图源&#xff1a;简书 (jianshu.com) Spring表达式语言&#xff08;Spring Expression Language&#xff0c;简称 “SpEL”&#xff09;是一种强大的表达式语言&#xff0c;支持在运行时查询和操作对象图。该语言的语法…

2024王道数据结构考研丨第一章:绪论

2024王道数据结构考研笔记专栏将持续更新&#xff0c;欢迎 点此 收藏&#xff0c;共同交流学习… 文章目录 第一章&#xff1a;绪论1.1数据结构的基本概念1.2数据结构的三要素1.3算法的基本概念1.4算法的时间复杂度1.5算法的空间复杂度 第一章&#xff1a;绪论 1.1数据结构的基…

Vue - vxe-table 表格合并行应用

Vue - vxe-table 表格合并行应用 一. 将相同的列数据合并为一行实现效果实现方法 二. 拓展合并&#xff1a;根据某个字段合并后的数据 进行合并其他字段列实现效果实现方法 vxe-table 地址&#xff1a;https://vxetable.cn/v2/#/table/start/install 一. 将相同的列数据合并为一…

亚马逊云科技作为中国出海力量之一,为中国企业提供技术桥梁

这是一个真实的故事&#xff1a;一家出海企业的项目交付需要在非洲吉布提部署上云&#xff0c;企业负责人在地图上找了半天才找到吉布提&#xff0c;而亚马逊云科技仅用了3天的时间就为企业在当地的业务开展&#xff0c;交付了IT基础设施。对于出海企业来说&#xff0c;这种效率…