SpringBoot: Eureka入门
1. IP列表
公司发展到一定的规模之后,应用拆分是无可避免的。假设我们有2个服务(服务A、服务B),如果服务A要调用服务B,我们能怎么做呢?最简单的方法是让服务A配置服务B的所有节点的IP,在服务A内部做负载均衡调用服务B的不同节点。
这种方式有3个明显的问题
- 服务B的节点变更,需要将服务B的IP列表更新进每个服务A,可以是通过配置文件、配置中心,甚至是数据库
- 服务A需要对服务B的节点做健康检测,避免将调用无效的节点
- 服务A要实现服务B调用的负载均衡策略
2. 反向代理
熟悉反向代理的人发现,反向代理不正是解决这个问题的办法吗?如果在服务A和服务B之间添加一个nginx,网络拓扑看起来就是这样的
我们需要将服务B的节点配置为upstream,定义nginx的server,服务A通过nginx调用服务B,我们看看下面的核心配置
- weight指定每个服务器的权重,值越大调用的次数越多
- max_fails指定失败多少次后标记为不可用,fail_timeout指过多长时间后将失败节点再次加入到服务列表中
- backup作为备用节点,其他节点不可用的时候,back节点会接受负载均衡
- down标记节点下线
- ip_hash指定负载均衡策略,通一个IP调度到同一个IP,默认是round-robin
- proxy_next_stream指定哪些条件认为是请求失败的(max_fails统计的条件)
upstream service_b { # 默认轮询策略round-robin,默认权重1server 192.168.100.11 weight=1; server 192.168.100.12 weight=2 max_fails=10 fail_timeout=30s ;server 192.168.100.13 backup; # 备用服务器,当其他服务器都不可用时才使用 server 192.168.100.14 down; # 标记为不可用,不参与负载均衡 ip_hash; # 负载均衡策略,基于客户端IP选择,默认round-robin
}server { listen 80; location / {proxy_pass http://service_b; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; }
}
通过这种方式基本解决1.1里提到的3个问题了,不过upstream的修改仍然是手动的,而且需要重启nginx。 nginx提供了一个模块ngx_http_dyups_module让我们可以通过HTTP调用动态的修改upstream,如果我们想要将service_b的节点改成下面2个节点,我们可以这么做:
curl 127.0.0.1:8000/upstream/service_b -d
"server 192.168.100.11:8080 max_fails=3 fail_timeout=5s weight=10;server 192.168.100.12:8080 max_fails=3 fail_timeout=5s weight=10;"
不过这个方案没有开始流行就已经没落了,最明显的问题是所有对服务B的调用都要经过中心节点(nginx),而且经过了一次转发,影响了调用性能。
3. 注册中心
大概在2010年开始国内的大中厂都开始走向服务化,但并没有一个成熟的中间件,dubbo、motan、hedwig都是这个时代产物。服务提供者在启动的时候会将自己注册到服务注册中心(zookeeper、consul等实现),服务消费者从注册中心拿到服务提供者的IP,在客户端做负载均衡,直接连接服务提供者的IP,相较于反向代理的方案好处是服务A和服务B是直接调用,避免了一次中间转发。
名称 | 语言 | 数据结构 | 存储 | |||
CP | Zab协议 | 服务发现、锁、选主、配置 | ||||
Eureka | Java | key-value | 内存 | |||
CP + AP | Raft | 服务发现、锁、选主、配置 | MySQL | |||
AP | Raft | 类似于Nacos |
- Zookeeper最早出现,常用于大数据系统的协调,比如Hadoop/Kafka等,生态成熟,但特性就比较老,出现在云原生之前,没有考虑云原生/微服务的支持
- Eureka专门为微服务设计,不支持一致性协议,适用gossip同步数据,选择AP,一致性较弱,功能单一,仅用于服务发现
- Nacos基于Raft算法,支持云原生,比如流量管理、灰度发布等功能
一般Java语言开发的新系统的注册中心是在Eureka和Nacos之间选择,Eureka天然和Spring Cloud集成,适用简单,当然功能也相当较弱。我们先来看看Eureka的使用。
4. Eureka入门
1. 创建应用
先创建Spring Boot应用,参见1. 手动创建应用,引入Spring Cloud的依赖管理
<project>...<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId> <!-- 创建为SpringBoot应用 --><version>3.2.7</version></parent>...<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-parent</artifactId> <!-- 使用Spring Cloud依赖 --><version>2023.0.0</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> <!-- 添加EurekaServer依赖 --></dependency></dependencies>
</project>
2. 启动类
添加启动类,除了正常的Spring Boot应用的注解,额外增加了@EnableEurekaServer注解
package org.keyniu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication
@EnableEurekaServer
public class StartEurekaServer {public static void main(String[] args) {SpringApplication.run(StartEurekaServer.class, args);}
}
3. 核心配置
创建配置文件 application.yml,包含的内容如下,我们我看看每个配置字段的含义
- Eureka服务端,一般register-with-eureka、fetch-registry都设置为false,不注册自己也从eureka拉取注册信息,信息的同步通过内部的gossip协议进行
- Eureka服务端,通过eureka.server.serviceUrl的配置感知其他peer节点,运行期间新增/删除节点通过修改配置文件实现,或配置中心配置
- Client周期性(lease-renewal-interval-in-seconds)向服务端续租,如果超过最大时间(lease-expiration-duration-in-seconds)没收到续租请求,这个节点被认为不可用
- Server周期性(eviction-interval-timer-in-ms)检查服务器节点,清理不可用的节点
- Client向Server注册后,Server之间通过gossip同步,同步后每个Server节点存储自己的注册表,evict线程(eviction-interval-timer-in-ms)统计本地注册表,查看阈值(renewal-percent-threshold)看是否进入保护模式,如果不是保护模式,清理过去的节点,节点的leaseInfo中保存了每个节点最后一次renewal的时间
server:port: 8080
spring:application:name: keyniu-eureka-server
eureka:instance:hostname: localhostlease-renewal-interval-in-seconds: 30lease-expiration-duration-in-seconds: 90client:register-with-eureka: falsefetch-registry: falseservice-url:defaultZone: http://127.0.0.1:${server.port}/eureka/server:wait-time-in-ms-when-sync-empty: 5enable-self-preservation: trueeviction-interval-timer-in-ms: 10000renewal-percent-threshold: 0.85
5. REST API
默认Eureka的接口返回的XML,可以通过提交请求时指定Accept HTTP头设置响应内容的格式为JSON,这一点对所有接口有效,后续不再赘述
curl -s -H 'Accept: application/json' http://192.168.31.52:8080/eureka/apps/${app}/${instanceId}
1. 获取所有实例
通过curl http://192.168.31.52:8080/eureka/apps能查看所有可用的节点列表,包括所有的应用(application),应用下所有的节点(instance),节点的元数据(metadata)、租约(leaseInfo)等等
2. 指定app的实例
通过如下命令读取数据,这里的KEYNIU-EUREKA-SERVER是app,需要替换成对应的值。
curl http://192.168.31.52:8080/eureka/apps/${app}
curl http://192.168.31.52:8080/eureka/apps/KEYNIU-EUREKA-SERVER
3. 指定app/instanceId的实例
通过如下命令读取数据,其中KEYNIU-EUREKA-SERVER是app,Randy:keyniu-eureka-server:8080是instanceId
curl http://192.168.31.52:8080/eureka/apps/${app}/${instanceId}
curl http://192.168.31.52:8080/eureka/apps/KEYNIU-EUREKA-SERVER/Randy:keyniu-eureka-server:8080
4. 服务上下线
通过修改instance的status字段,我们能控制服务的上下线,比如将节点状态改为OUT_OF_SERVICE
curl -v -XPUT http://192.168.31.52:8080/eureka/apps/${app}/${instanceId}/status?value=OUT_OF_SERVICE
curl -v -XPUT http://192.168.31.52:8080/eureka/apps/KEYNIU-EUREKA-SERVER/Randy:keyniu-eureka-server:8080/status?value=OUT_OF_SERVICE
curl -v -XDELETE http://192.168.31.52:8080/eureka/apps/${app}/${instanceId}/status?value=UP
curl -v -XDELETE http://192.168.31.52:8080/eureka/apps/KEYNIU-EUREKA-SERVER/Randy:keyniu-eureka-server:8080/status?value=UP
5. 更新元数据
比如我们要在元数据里添加一个admin字段,值是zhangsan,我们可以这么做
curl -v -XPUT http://192.168.31.52:8080/eureka/apps/${app}/${instanceId}/metadata?${key}=${value}
curl -v -XPUT http://192.168.31.52:8080/eureka/apps/KEYNIU-EUREKA-SERVER/Randy:keyniu-eureka-server:8080/metadata?admin=zhangsan
6. 新增instance
通过POST请求,请求体可以是JSON,格式按我们读取到的实例格式,假设我们要新增一个节点: Randy1:keyniu-eureka-server:8080, 命令看起来是这样的
curl -v -H 'Content-Type: application/json' -XPOST http://192.168.31.52:8080/eureka/apps/KEYNIU-EUREKA-SERVER -d '{"instance": {"instanceId": "Randy1:keyniu-eureka-server:8080","hostName": "192.168.31.53","app": "KEYNIU-EUREKA-SERVER","ipAddr": "192.168.31.53","status": "UP","overriddenStatus": "UNKNOWN","port": {"$": 8080,"@enabled": "true"},"securePort": {"$": 443,"@enabled": "false"},"countryId": 1,"dataCenterInfo": {"@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo","name": "MyOwn"},"leaseInfo": {"renewalIntervalInSecs": 30,"durationInSecs": 90,"registrationTimestamp": 1719660811233,"lastRenewalTimestamp": 1719661187133,"evictionTimestamp": 0,"serviceUpTimestamp": 1719655154360},"metadata": {"admin": "zhangsan","management.port": "8080","group": "secondKill"},"homePageUrl": "http://192.168.31.53:8080/","statusPageUrl": "http://192.168.31.53:8080/actuator/info","healthCheckUrl": "http://192.168.31.53:8080/actuator/health","vipAddress": "keyniu-eureka-server","secureVipAddress": "keyniu-eureka-server","isCoordinatingDiscoveryServer": "true","lastUpdatedTimestamp": "1719660811233","lastDirtyTimestamp": "1719655154170","actionType": "ADDED"}
}'
7. 删除instance
curl -XDELETE http://192.168.31.52:8080/eureka/${app}/${instanceId}
curl -XDELETE http://192.168.31.52:8080/eureka/KEYNIU-EUREKA-SERVER/Randy1:keyniu-eureka-server:8080
8. 发送心跳
curl -XPUT http://192.168.31.52:8080/eureka/apps/${app}/${instanceId}
curl -XPUT http://192.168.31.52:8080/eureka/apps/KEYNIU-EUREKA-SERVER/Randy1:keyniu-eureka-server:8080
6. 案例解析
现在我们反过来,从Eureka UI来看,显示的每个字段是从何而来,怎么配置
1. Eureka首页
下图是Eureka UI首页显示的内容,我们主要关系其中的6个显示字段,对应图上的数字,下面列表中是它的说明
- 环境,通过eureka.environment配置,默认test
- 数据中心,通过eureka.datacenter配置,默认MyOwn
- 是否删除过去租约,只要不处于自我保护模式,这个值就是true,不启动eureka.server.enable-self-preservation
- 进入自我保护模式的阈值,资料上计算公式: 客户端数量 * (60 / lease-renewal-interval-in-seconds ) * renewal-percent-threshold,实测下来有出入,待进一步研究
- 仅一个客户端,lease-renewal-interval-in-seconds = 20 , Renews threshod = 3,计算值= 1 * (60/20) * 0.85 = 2.55
2. 注册表信息
通过Eureka Server的REST接口,我们能读到注册表信息,下面这个连接能查看所有的APP信息,不过我们这里只有一个节点
http://127.0.0.1:8080/eureka/apps
下面是其中一个节点的内容,下面有序列表的数字对应图片里的数字
- dataCenterInfo表示数据中心,一般配置到Eureka Client,定义是个枚举DataCenterInfo.Name类,可选值有Netflix、Amazon、MyOwn,默认MyOwn
- 对应配置项eureka.instance.data-center-info
- eureka.datacenter也是数据中心的概念,一般配置到Eureka Server
- 暂时没看到这两个值如果不同的话有什么影响,但会让人觉得混乱,需要进一步研究
- metadata元数据信息,默认只有management.port,可以做自定义配置
- 基于元数据可以做服务分组,用MetadataAwarePredicate实现调用对应分组的节点
相关文章:
SpringBoot: Eureka入门
1. IP列表 公司发展到一定的规模之后,应用拆分是无可避免的。假设我们有2个服务(服务A、服务B),如果服务A要调用服务B,我们能怎么做呢?最简单的方法是让服务A配置服务B的所有节点的IP,在服务A内部做负载均衡调用服务B…...
Typescript 【实用教程】(2024最新版)含类型声明,类型断言,函数,接口,泛型等
简介 TypeScript 是 JavaScript 的超集,是 JavaScript(弱类型语言) 的强类型版本。 拥有类型机制文件后缀 .tsTypescript type ES6TypeScript 和 JavaScript 的关系类似 less 和 css 的关系TypeScript对 JavaScript 添加了一些扩展&#x…...
智慧校园-实训管理系统总体概述
智慧校园实训管理系统,专为满足高等教育与职业教育的特定需求而设计,它代表了实训课程管理领域的一次数字化飞跃。此系统旨在通过革新实训的组织结构、执行流程及评估标准,来增强学生的实践操作技能和教师的授课效率,为社会输送具…...
如何用GPT开发一个基于 GPT 的应用?
原文发自博客:GPT应用开发小记 如何开发一个基于 GPT 的应用?答案就在问题里,那就是用 GPT 来开发基于 GPT 的应用。本文以笔者的一个开源项目 myGPTReader 为例,分享我是如何基于 GPT 去开发这个系统的,这个系统的功能…...
大数据生态体系中各组件的区别面试题(更新)
一、MapReduce与Spark有什么区别? 1、处理方式: MapReduce基于磁盘处理数据,将中间结果保存到磁盘中,减少了内存占用,计算速度慢。 基于内存处理数据,将计算的中间结果保存到内存中,计算速度快。2、资源申请方式&…...
数字信号处理实验一(离散信号及离散系统的MATLAB编程实现)
实验要求: 离散信号及离散系统的MATLAB编程实现(2学时) 要求: 编写一程序,输出一定长度(点数),具有一定幅度、(角)频率和初始相位的实(或复&…...
数字图像处理专栏——introduction
Introduction: 数字图像处理技术是我在深入学习研究的方向之一。本科期间跟随导师做基于AndroidOpenCV的病虫识别app,因此入门,我也对该部分知识有进一步探索的欲望,但更多的是因该脚踏实地一步步记录,一步步成长。 本篇从数字图…...
Django 模版继承
1,设计母版页 Test/templates/6/base.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><!-- 修正了模板标签的全角字符问题 -->{% block title %}<title>这个是母版页</title>{…...
Apipost接口测试工具的原理及应用详解(一)
本系列文章简介: 随着软件行业的快速发展,API(应用程序编程接口)作为不同软件组件之间通信的桥梁,其重要性日益凸显。API的质量直接关系到软件系统的稳定性、性能和用户体验。因此,对API进行严格的测试成为…...
一款轻量级的通信协议---MQTT (内含Linux环境搭建)
目录 MQTT MQTT的关键特点: 应用场景 Linux环境搭建: 1. 安装mosquitto 2. Linux下客户端进行通信 3. PC端和Linux下进行通信 安装MQTT. fx 4. MQTT.fx的使用 1. 点击连接 编辑 2. 连接成功 3. 订阅主题或者给别的主题发送消息 遇到的问…...
记netty本地客户端断线无法自动重连 or 远程客户端自动重连本地服务端
记netty客户端断线无法自动完成重连 or 服务端无法让客户端断线重连 引场景案例bootstrap 引 netty既能开发socket服务端,也可开发客户端,实现连接的全双工通信。在客户端断线重启后,可自动重连服务端。 场景 本地代码既有socket客户端也有…...
UNIAPP_在js文件中使用i18n国际化
导入 import { initVueI18n } from dcloudio/uni-i18n import messages from /locale/index const { t } initVueI18n(messages) 使用 t(config.request.i001)....
第三节:如何理解Spring的两个特性IOC和AOP(自学Spring boot 3.x第一天)
大家好,我是网创有方,接下来教大家如何理解Spring的两个特性IOC和AOP。本节有点难,大家多理解。 IOC(控制反转) 定义与核心思想: IOC,全称Inversion of Control,即控制反转。 其核…...
【51单片机】串口通信(发送与接收)
文章目录 前言串口通信简介串口通信的原理串口通信的作用串口编程的一些概念仿真图如何使用串口初始化串口串口模式波特率配置 发送与接收发送接收 示例代码 总结 前言 在嵌入式系统的开发中,串口通信是一种常见且重要的通信方式。它以其简单、稳定的特性在各种应用…...
【AI研发工具包】sklearn教程(Scikit-learn)
目录 1. 引言 2. 安装sklearn 3. 导入sklearn 4. 加载数据集 5. 数据预处理 6. 训练模型 7. 评估模型 8. 保存和加载模型 9. 自定义数据 10. 深入sklearn 11. 注意事项 1. 引言 Scikit-learn(简称sklearn)是Python中一个非常流行的机器学习库…...
数位DP——AcWing 1081. 度的数量
数位DP 定义 数位DP是一种动态规划技巧,特别适用于处理与数字的位操作相关的问题,如数字序列的计数、数字的生成等问题。它通过将问题分解为对每一位数字的独立考虑,从而简化问题复杂度,实现高效求解。 数位DP的核心思想是将原…...
2024下半年必追国漫片单,谁将问鼎巅峰?
随着2024年上半年的落幕,国漫市场再度迎来了百花齐放的盛况。从经典续作到全新IP,从玄幻到科幻,每一部作品都以其独特的魅力吸引着观众的目光。本期为大家盘点下半年值得一看的国漫佳作,大胆预测,谁将成为这场神仙打架…...
信息发布小程序h5 uniapp thinkphp
纯手工uniapp thinkphp 全开源打造 信息发布小程序 一、概述 信息发布小程序是一种基于微信平台的小程序应用,旨在为用户提供便捷的信息发布与展示服务。用户可以通过该小程序快速发布各类信息,如招聘、寻物、公告等,同时也可以浏览和搜索…...
Windows定时任务执行脚本
场景:由于网络波动原因导致云数据库没连接上,从而导致某个流程引擎链接不上数据库从而导致该流程引擎服务挂了,网络恢复后 数据库链接正常,但是该引擎服务还是中止状态。 解决方案:在Windows中新建一个定时任务&#…...
优维“统一开放平台”:开放、开发、集成、客制化
基于丰富完善的产品体系,优维重磅推出了统一开放平台。这款由优维自主设计与研发,集数据开发、能力开放、能力集成、客制化为一体的统一开放平台,具备应用市场、应用开发、连接能力、采控平台、API集市、开发者工具等功能模块,可为…...
ChatGPT新纪元:揭秘GPT-4o的多模态能力
GPT-4o登场 探索ChatGPT的多模态创新 今日凌晨,OpenAI向全球宣布了AI发展的新篇章——GPT-4o,每次OpenAI发布重大更新时,尽管令人兴奋,但也不免使众多初创公司的梦想破灭。 GPT-4o的命名中的“o”象征着“omni”——全能的代表。…...
泰勒斯威夫特2022年纽约大学毕业典礼演讲:NYU‘s 2022 Commencement Speaker Taylor Swift
NYU’s 2022 Commencement Speaker Taylor Swift Link: https://www.youtube.com/watch?vOBG50aoUwlI Singer, songwriter, producer, and director Taylor Swift received a Doctor of Fine Arts, honoris causa, at the Commencement for the Class of 2022 and delivered …...
(四)SvelteKit教程:调用外部 API 获取数据
(四)SvelteKit教程:调用 API 我们先按照如下的方式来构建api服务: step 1:npm i json-serverstep 2:在根目录下新建 db.json 文件,内部写入如下内容:{"users": [{"id": 1,"name…...
数据结构-分析期末选择题考点(排序)
何似清歌倚桃李 一炉沈水醉红灯 契子 ✨ 上一期给大家提供了大概会考的题型给老铁们复习的大致思路 这一期还会是一样,我将整理一下排序的题型以及解题方法给你们 由于时间还很多,我就慢慢总结吧,一天一章的样子,明天总结串、后天…...
Python:探索高效、智能的指纹识别技术(简单易懂)
目录 概括 导入库 函数一 参数: 函数二 函数三 主函数 运行结果 src: model_base 7.bmp 编辑 总结 概括 指纹识别是一种基于人体生物特征的身份验证技术。它通过捕捉和分析手指上的独特纹路和细节特征,实现高准确度的身份识别。…...
『SD』AI绘画,不会写提示词怎么办?
提示词 有没有想过,为什么你用 SD 生成的猫是长这样的。 而其他人可以生成这样的猫。 虽然生成的都是猫,但猫与猫之间还是有差距的。 如果你的提示词只是“cat”,那大概率就会出现本文第一张图的那个效果。而如果你加上一些形容词ÿ…...
搭建大型分布式服务(四十二)SpringBoot 无代码侵入实现多Kafka数据源整合插件发布
系列文章目录 文章目录 系列文章目录前言MultiKafkaStarter [V2.2]一、功能特性二、快速开始(生产端)三、快速开始(消费端)四、其它特性五、变更记录六、参考文章 前言 在分布式服务的架构演进中,消息队列作为核心组件…...
Python 学习路线及技巧
一、学习路线 1. 基础阶段 ● 学习 Python 的语法基础,如变量、数据类型、运算符、控制流等。 ● 掌握常用的 Python 标准库,如 os、sys、re、datetime 等。 ● 通过编写简单的程序来巩固基础,如计算器、字符串处理等。 2. 进阶阶段 ● 深入…...
计算机网络知识整理笔记
目录 1.对网络协议的分层? 2.TCP/IP和UDP之间的区别? 3.建立TCP连接的三次握手? 4.断开TCP连接的四次挥手? 5.TCP协议如何保证可靠性传输? 6.什么是TCP的拥塞控制? 7.什么是HTTP协议? 8…...
练习 String翻转 注册处理 字符串统计
p493 将字符串中指定部分进行翻转 package chapter;public class reverse {public static void main(String[] args) {String str "abcdef";str reverseMethod(str,0,3);System.out.println(str);}public static String reverseMethod(String str, int start, in…...
wordpress小程序详解/怎么做电商卖东西
创建一个新的Jakarta Persistence项目 首先,我们将在IntelliJ IDEA Ultimate中创建一个新项目,方法是单击“welcome”屏幕中的“New Project”按钮。我们将从左侧菜单中选择Java Enterprise,这使我们能够利用IntelliJ IDEA Ultimate中提供的…...
android毕业设计代做网站/如何建立网站
基因沉默(gene silencing)是指生物体中特定基因由于种种原因不表达或者是表达减少的现象。基因沉默现象首先在转基因植物中发现,接着在线虫、真菌、水螅、果蝇以及哺乳动物中陆续发现。 基因沉默机制: 外源基因进入细胞核后&…...
套模版做网站/站长之家素材
学校C语言课设 文章目录Calculate.hCalculate.cppCalculate.h #pragma once#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct node* LIST;struct Date//每个数字的系数和指数 {int c;//系数i…...
企业网站空间多大合适/百度查询入口
首先介绍几个相关概念。 临界资源:在同一时刻,只能被一个进程/线程所使用的资源。 临界区:访问临界资源的代码段。因此同一时刻只能有一个进程/线程进入临 界区。 进入区:进入临界区之前的代码段,一般用来做加锁操作。…...
wordpress安装/关键词推广软件排名
Table of Contents 一、原子操作介绍 二、什么情况下选择使用原子操作? 三、原子操作编程步骤 1、定义并初始化原子变量 atomic_t 2、对原子变量进行原子操作(计数) 1)、原子变量自增/自减 2)、原子变量加/减 …...
飞色网站商城怎么做/西安百度推广运营公司
题目链接 https://www.luogu.org/problemnew/show/P2802 题目描述 小H在一个划分成了n*m个方格的长方形封锁线上。 每次他能向上下左右四个方向移动一格(当然小H不可以静止不动), 但不能离开封锁线,否则就被打死了。 刚开始时他有…...