微服务注册中心
目录
1.微服务的注册中心
1.1 注册中⼼的主要作⽤
1.2 常⻅的注册中⼼
2.nacos简介
2.1 nacos实战⼊⻔
2.2.1 搭建nacos环境
2.2.2 将商品微服务注册到nacos
3.服务调⽤Ribbon⼊⻔
3.1 Ribbon概述
3.1.1 什么是Ribbon
3.1.2 Ribbon的主要作⽤
3.2.2 ⼯程改造
4.服务调⽤Ribbon⾼级
4.1 负载均衡概述
4.1.1 什么是负载均衡
4.2 基于Ribbon实现负载均衡
5.Nacos配置管理
5.1 统⼀配置管理
5.1.1 在nacos中添加配置⽂件
5.1.2 从微服务拉取配置
5.2 配置热更新
5.2.1.⽅式
5.3 配置共享
5.3.1 同服务内配置共享
5.3.2 不同微服务共享配置
1.微服务的注册中心
注册中心可以说是微服务架构中的”通讯录“ ,它记录了服务和服务地址的映射关系。在分布式架构中, 服务会注册到这⾥,当服务需要调⽤其它服务时,就这⾥找到服务的地址,进⾏调⽤。
1.1 注册中⼼的主要作⽤
服务注册中⼼(下称注册中⼼)是微服务架构⾮常重要的⼀个组件,在微服务架构⾥主要起到了协调者 的⼀个作⽤。注册中⼼⼀般包含如下⼏个功能:
-
服务发现: 服务注册/反注册:保存服务提供者和服务调⽤者的信息 服务订阅/取消订阅:服务调⽤者订阅服务提供者的信息,最好有实时推送的功能 服务路由(可选):具有筛选整合服务提供者的能⼒。
-
服务配置: 配置订阅:服务提供者和服务调⽤者订阅微服务相关的配置 配置下发:主动将配置推送给服务提供者和服务调⽤者
-
服务健康检测
检测服务提供者的健康情况
1.2 常⻅的注册中⼼
Zookeeper
zookeeper它是⼀个分布式服务框架,是Apache Hadoop 的⼀个⼦项⽬,它主要是⽤来解决分布式应 ⽤中经常遇到的⼀些数据管理问题,如:统⼀命名服务、状态同步服务、集群管理、分布式应⽤配置项 的管理等。简单来说zookeeper=⽂件系统+监听通知机制。
Eureka
Eureka是在Java语⾔上,基于Restful Api开发的服务注册与发现组件,Springcloud Netflix中的重要组 件 Consul Consul是由HashiCorp基于Go语⾔开发的⽀持多数据中⼼分布式⾼可⽤的服务发布和注册服务软件, 采 ⽤Raft算法保证服务的⼀致性,且⽀持健康检查。
Nacos
Nacos是⼀个更易于构建云原⽣应⽤的动态服务发现、配置管理和服务管理平台。简单来说 Nacos 就是 注册中⼼ + 配置中⼼的组合,提供简单易⽤的特性集,帮助我们解决微服务开发必会涉及到的服务注册 与发现,服务配置,服务管理等问题。 Nacos 还是 Spring Cloud Alibaba 组件之⼀,负责服务注册与 发现。
2.nacos简介
Nacos 致⼒于帮助您发现、配置和管理微服务。Nacos 提供了⼀组简单易⽤的特性集,帮助您快 速实现动态服务发现、服务配置、服务元数据及流量管理。 nacos的作⽤就是⼀个注册中⼼,⽤ 来管理注册上来的各个微服务
2.1 nacos实战⼊⻔
我们就在现有的环境中加⼊nacos,并将我们的两个微服务注册上去。
2.2.1 搭建nacos环境
第1步: 安装nacos
第2步: 启动nacos
#切换⽬录
cd nacos/bin
#命令启动
startup.cmd -m standalone
或者直接双击
startup.cmd
运⾏
第3步: 访问nacos Plain Text 打开浏览器输⼊http://localhost:8848/nacos,即可访问服务, 默认密码是nacos/nacos
2.2.2 将商品微服务注册到nacos
开始修改 shop-product 模块的代码, 将其注册到nacos服务上
1 在pom.xml中添加nacos的依赖
<!--nacos客户端--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
2 在主类上添加@EnableDiscoveryClient注解
3 在application.yml中添加nacos服务的地址
server:port: 8081
spring:application:name: service-productdatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_mybatis?serverTimezone=UTCusername: rootpassword: wwt15991178033#服务地址cloud:nacos:discovery:server-addr: 127.0.0.1:8848
4 启动服务, 观察nacos的控制⾯板中是否有注册上来的商品微服务
5.修改订单微服务controller
@RequestMapping("/order/prod/{pid}")public Order order(@PathVariable("pid") Integer pid){//从nacos中获取服务地址ServiceInstance serviceInstance = discoveryClient.getInstances("service-product").get(0);String url = serviceInstance.getHost() + ":" + serviceInstance.getPort();//调用商品微服务,查询商品信息Product product = restTemplate.getForObject("http://"+url+"/product/"+pid,Product.class);//下单(常见订单)Order order = new Order();order.setUid(1);order.setUsername("测试用户1");order.setPid(pid);order.setPname(product.getPname());order.setPprice(product.getPprice());order.setNumber(1);orderService.createOrder(order);return order;}
3.服务调⽤Ribbon⼊⻔
经过以上的学习,已经实现了服务的注册和服务发现。当启动某个服务的时候,可以通过HTTP的形式 将信息注册到注册中⼼,并且可以通过SpringCloud提供的⼯具获取注册中⼼的服务列表。但是服务之间的调⽤还存在很多的问题,如何更加⽅便的调⽤微服务,多个微服务的提供者如何选择,如何负载均衡等。
3.1 Ribbon概述
3.1.1 什么是Ribbon
是 Netflixfa 发布的⼀个负载均衡器,有助于控制 HTTP 和 TCP客户端⾏为。在 SpringCloud 中, Nacos⼀般配合Ribbon进⾏使⽤,Ribbon提供了客户端负载均衡的功能,Ribbon利⽤从Nacos中读取到 的服务信息,在调⽤服务节点提供的服务时,会合理的进⾏负载。 在SpringCloud中可以将注册中⼼和Ribbon配合使⽤,Ribbon⾃动的从注册中⼼中获取服务提供者的列 表信息,并基于内置的负载均衡算法,请求服务。
3.1.2 Ribbon的主要作⽤
( 1)服务调⽤ 基于Ribbon实现服务调⽤, 是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。借助 RestTemplate 最终进⾏调⽤
( 2)负载均衡 当有多个服务提供者时,Ribbon可以根据负载均衡的算法⾃动的选择需要调⽤的服务地址
3.2 基于Ribbon实现订单调⽤商品服务 3.2.1 坐标依赖 在springcloud提供的服务发现的jar中以及包含了Ribbon的依赖。所以这⾥不需要导⼊任何额外的坐标
3.2.2 ⼯程改造
( 1 )服务提供者 控制台打印查询商品的信息
( 2 )服务消费者 在创建RestTemplate⽅法 上添加 @LoadBalanced 注解
@EnableDiscoveryClient
@SpringBootApplication
public class ShopOrderApplication {public static void main(String[] args) {SpringApplication.run(ShopOrderApplication.class, args);}@Bean@LoadBalanced//负载均衡public RestTemplate restTemplate(){return new RestTemplate();}
}
通过服务名称消费使⽤
restTemplate .getForObject("http://商品服务名称/product/1" , Product.class);
@RestController
public class OrderController {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate IOrderService orderService;@RequestMapping("/order/prod/{pid}")public Order order(@PathVariable("pid") Integer pid){//通过restTemplate调用商品微服务String url = "service-product";Product product = restTemplate.getForObject("http://"+url+"/product/" + pid, Product.class);//下单(常见订单)Order order = new Order();order.setUid(1);order.setUsername("测试用户1");order.setPid(pid);order.setPname(product.getPname());order.setPprice(product.getPprice());order.setNumber(1);orderService.createOrder(order);return order;}
}
4.服务调⽤Ribbon⾼级
4.1 负载均衡概述
4.1.1 什么是负载均衡
在搭建⽹站时,如果单节点的 web服务性能和可靠性都⽆法达到要求;或者是在使⽤外⽹服务时,经常 担⼼被⼈攻破,⼀不⼩⼼就会有打开外⽹端⼝的情况,通常这个时候加⼊负载均衡就能有效解决服务问 题。
负载均衡是⼀种基础的⽹络服务,其原理是通过运⾏在前⾯的负载均衡服务,按照指定的负载均衡算 法,将流量分配到后端服务集群上,从⽽为系统提供并⾏扩展的能⼒。 负载均衡的应⽤场景包括流量包、转发规则以及后端服务,由于该服务有内外⽹个例、健康检查等功 能,能够有效提供系统的安全性和可⽤性。
4.2 基于Ribbon实现负载均衡
Ribbon内置了多种负载均衡策略,内部负责复杂均衡的顶级接⼝为 com.netflix.loadbalancer.IRule ,实现⽅式如下
-
com.netflix.loadbalancer.RoundRobinRule :以轮询的⽅式进⾏负载均衡
-
com.netflix.loadbalancer.RandomRule :随机策略
-
com.netflix.loadbalancer.RetryRule :重试策略
-
com.netflix.loadbalancer.WeightedResponseTimeRule :权重策略。会计算每个服务的权重,越⾼的被调⽤的可能性越⼤
-
com.netflix.loadbalancer.BestAvailableRule :最佳策略。遍历所有的服务实例,过滤掉故障实例,并返回请求数最⼩的实例返回
-
com.netflix.loadbalancer.AvailabilityFilteringRule :可⽤过滤策略。过滤掉故障和请 求数超过阈值的服务实例,再从剩下的实⼒中轮询调⽤
-
ZoneAvoidanceRule:以区域可⽤的服务器为基础进⾏服务器的选择。使⽤Zone对服务器进⾏分类,这个Zone可以理解为⼀个机房、⼀个机架等。⽽后再对Zone内的多个服务做轮询
⾃定义负载均衡策略
⽅式1:定义⼀个新的IRule:(全局设置)
@Beanpublic IRule randomRule(){return new RandomRule();}
⽅式2:在yml配置⽂件中配置:(局部设置)
#需要调⽤的微服务名称service-product:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
5.Nacos配置管理
5.1 统⼀配置管理
5.1.1 在nacos中添加配置⽂件
注意:项⽬的核⼼配置,需要热更新的配置才有放到nacos管理的必要。基本不会变更的⼀些配置还是保 存在微服务本地⽐较好。
5.1.2 从微服务拉取配置
bootstrap.yaml⽂件,会在application.yml之前被读取
配置实现步骤:
1)引⼊nacos-config依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2)添加bootstrap.yaml 不能使⽤原来的application.yml作为配置⽂件,⽽是新建⼀个bootstrap.yml作为配置⽂件
配置⽂件优先级(由⾼到低):
bootstrap.properties -> bootstrap.yml -> application.properties -> application.yml
spring:application:name: service-productcloud:nacos:config: YAMLserver-addr: 127.0.0.1:8848 #nacos中⼼地址file-extension: yaml # 配置⽂件格式profiles:active: dev #环境标识,开发环境
4) 在nacos中添加配置
5.2 配置热更新
我们最终的⽬的,是修改nacos中的配置后,微服务中⽆需重启即可让配置⽣效,也就是配置热更新。 要实现配置热更新,可以使⽤两种⽅式: 配置中⼼添加配置:
config:
appName: product
5.2.1.⽅式
在@Value注⼊的变量所在类上添加注解@RefreshScope:
@RestController@RefreshScope//
只需要在需要动态读取配置的类上添加此注解就可以
public class NacosConfigController {@Value("${config.appName}")private String appName; @GetMapping("/nacos-config-test1") public String nacosConfingTest1() {return appName;}
}
5.3 配置共享
当配置越来越多的时候,我们就发现有很多配置是重复的,这时候就考虑可不可以将公共配置⽂件 提取出来
5.3.1 同服务内配置共享
现步骤:
-
新建⼀个以 spring.application.name 命名的配置⽂件,然后将其所有环境的公共配置放在⾥ ⾯
2. 新建⼀个名为service-product-test.yaml配置存放测试环境的配置
3. 新建⼀个名为service-product-dev.yaml配置存放开发环境的配置
4. 在两个环境⽂件中配置独有信息
# 多配置⼀段
config:env: test
# 多配置⼀段
config:env: dev
5. 添加测试⽅法
@RestController
@RefreshScope//动态读取配置类
public class NocasConfigController {@Value("@{config.appName}")private String appName;@GetMapping("/nacos-config-test1")public String nacosStringTest1(){return appName;}
}
5.3.2 不同微服务共享配置
不同服务之间实现配置共享的原理类似于⽂件引⼊,就是定义⼀个公共配置,然后在当前配置中引 ⼊
-
在nacos中定义⼀个DataID为all-service.yaml的配置,⽤于所有微服务共享
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///shopserverTimezone=UTCusername: root password: root cloud:nacos: discovery: server-addr: 127.0.0.1:8848
2. 修改bootstrap.yaml
spring:application:name: service-productcloud:nacos:config:server-addr: 127.0.0.1:8848 #nacos中心地址file-extension: yaml #配置文件格式shared-dataids: datasource.yaml #配置要引入的配置refreshable-dataids: datasource.yaml #配置要实现动态配置刷新的配置profiles:active: dev
3. 启动商品微服务进⾏测试
配置共享的优先级
当nacos、服务本地同时出现相同属性时,优先级有⾼低之分:
服务名-profile.yaml > 服务名称.yaml > 本地配置(bootstrap > application)
相关文章:

微服务注册中心
目录 1.微服务的注册中心 1.1 注册中⼼的主要作⽤ 1.2 常⻅的注册中⼼ 2.nacos简介 2.1 nacos实战⼊⻔ 2.2.1 搭建nacos环境 2.2.2 将商品微服务注册到nacos 3.服务调⽤Ribbon⼊⻔ 3.1 Ribbon概述 3.1.1 什么是Ribbon 3.1.2 Ribbon的主要作⽤ 3.2.2 ⼯程改造 4.服务…...

HDU1032——The 3n + 1 problem,HDU1033——Edge,HDU1034——Candy Sharing Game
目录 HDU1032——The 3n 1 problem 题目描述 运行代码 代码思路 HDU1033——Edge 题目描述 运行代码 代码思路 HDU1034——Candy Sharing Game 题目描述 运行代码 代码思路 HDU1032——The 3n 1 problem 题目描述 Problem - 1032 运行代码 #include <iostr…...

内网对抗-隧道技术篇防火墙组策略HTTP反向SSH转发出网穿透CrossC2解决方案
知识点: 1、C2/C2上线-CrossC2插件-多系统平台支持 2、隧道技术篇-应用层-SSH协议-判断&封装&建立&穿透 3、隧道技术篇-应用层-HTTP协议-判断&封装&建立&穿透隧道技术主要解决网络通讯问题:遇到防火墙就用隧道技术,…...

实战案例:如何用ChatGPT生成适合不同领域的高质量文章
随着人工智能技术的快速进展,制作高质量文章已变得轻而易举。尤其是OpenAI推出的ChatGPT,极大地简化了写作任务。接下来,本文将通过具体案例,详解如何利用ChatGPT撰写不同领域的高品质文章。 背景:光辉AI交流-免费问答…...
多线程案例-单例模式
单例模式是设计模式之一,能保证某个类在程序中只存在唯一一份实例,而不会创建出多个实例 单例模式的具体实现方法有很多,最常见的是 “饿汉” 和 “懒汉” 两种。 饿汉模式 class Singlenton{private static Singlenton instance new Sin…...

P6 优化篇 - 数据折线图可视化步骤
增加新页面, 则需要在 page.json里面增加页面信息 2.添加目录, 和路径 同时也要添加目录了 , 新建目录LineChart , 添加文件LineChart.vue 4.LineChart.vue 直接复制黏贴 <template><view class"container"><!-- 图表显示区域 --><view cla…...

优选算法之二分查找(上)
目录 一、二分查找 1.题目链接:704. 二分查找 2.题目描述: 3.算法流程: 4.算法代码: 二、在排序数组中查找元素的第一个和最后一个位置 1.题目链接:34. 在排序数组中查找元素的第一个和最后一个位置 2.题目描述…...

JavaScript(16)——定时器-间歇函数
开启定时器 setInterval(函数,间隔时间) 作用:每隔一段时间调用这个函数,时间单位是毫秒 例如:每一秒打印一个hello setInterval(function () { document.write(hello ) }, 1000) 注:如果是具名函数的话不能加小括号…...
VUE中的重点*
1.MVC 和 MVVM的区别? MVC:M(model数据)、V(view视图),C(controlle控制器) 缺点是前后端无法独立开发,必须等后端接口做好了才可以往下走; 前端没…...

rabbitmq生产与消费
一、rabbitmq发送消息 一、简单模式 概述 一个生产者一个消费者模型 代码 //没有交换机,两个参数为routingKey和消息内容 rabbitTemplate.convertAndSend("test1_Queue","haha");二、工作队列模式 概述 一个生产者,多个消费者&a…...

spring-boot3.x整合Swagger 3 (OpenAPI 3) +knife4j
1.简介 OpenAPI阶段的Swagger也被称为Swagger 3.0。在Swagger 2.0后,Swagger规范正式更名为OpenAPI规范,并且根据OpenAPI规范的版本号进行了更新。因此,Swagger 3.0对应的就是OpenAPI 3.0版本,它是Swagger在OpenAPI阶段推出的一个…...

SM2隐式证书用户公私钥生成python代码实现
GMT0130-2023具体描述基于SM2算法的隐式证书公钥机制,这里尝试Python代码实现密钥生成部分功能,具体如下,椭圆曲线计算实现使用python第三方包gmssl。 #生成用户私钥Da和公钥Pa,其中Da(tAdA)mod N,Pa可以直…...

IEC104转MQTT网关快速实现了IEC104到MQTT的转换和数据交互
随着智能电网技术的不断进步,IEC 104(IEC 60870-5-104)协议作为电力系统中重要的远动通信标准,正逐步融入更广泛的物联网生态系统中。亚马逊AWS(Amazon Web Services),作为全球领先的云计算服务…...

【OpenCV C++20 学习笔记】调节图片对比度和亮度(像素变换)
调节图片对比度和亮度(像素变换) 原理像素变换亮度和对比度调整 代码实现更简便的方法结果展示 γ \gamma γ校正及其实操案例线性变换的缺点 γ \gamma γ校正低曝光图片矫正案例代码实现 原理 关于OpenCV的配置和基础用法,请参阅本专栏的其…...
web UI自动化测试 浏览器模式设置
自动化之浏览器模式设置 做selenium UI自动化测试时,每次都需要启动浏览器、用例运行结束后再关闭浏览器,浏览器启动相当地耗费时间,在本机运行用例的话还得放开双手,可以使用chrome的headless模式,让浏览器在后台运行…...

OpenCV图像滤波(1)双边滤波函数bilateralFilter的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 功能描述 bilateralFilter是图像处理和计算机视觉领域中的一种高级图像滤波技术,特别设计用于在去除噪声的同时保留图像的边缘和细节。相比于传…...
前端开发使用Big.js精算避免误差
1、下载 npm install big.js 全局引入还是局部引入可根据项目框架及个人需求 2、静态引入 < script src https://unpkg.com/big.js6.0.0/big.mjs > </ script > 或者 import Big from https://raw.githubusercontent.com/mikemcl/big.js/v6.0.0/big.mjs; i…...
在 Ubuntu 22.04/20.04 安装 CVAT 和 SAM 指南
1. 安装 Docker 和 Docker Compose sudo apt-get update sudo apt-get --no-install-recommends install -y \apt-transport-https \ca-certificates \curl \gnupg-agent \software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-ke…...

【SpringCloud】 微服务分布式环境下的事务问题,seata大合集
目录 微服务分布式环境下的事务问题 分布式事务 本地事务 BASE理论与强弱一致性 BASE理论 强弱一致性 常见分布式事务解决方案 - 2PC 常见分布式事务解决方案 - TCC 常见分布式事务解决方案 - 最大努力通知 常见分布式事务解决方案 - 最终一致性 Seata介绍与术语 Seata…...

vite5+vue3开发阅读APP实战笔记20240725
目前界面长成这样: 配置别名 修改vite.config.js import {defineConfig} from vite import vue from vitejs/plugin-vue import path from "path"// https://vitejs.dev/config/ export default defineConfig({server: {open: true,port: 8088,},plug…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...