Nacos初识项目实战:新手入门教程
本文介绍了Nacos初识项目实战,从Nacos的安装、配置中心和服务发现的功能入手,详细讲解了如何在微服务项目中集成Nacos进行配置管理和服务注册发现,并提供了实战案例和部署流程,帮助开发者快速上手和应用Nacos。
Nacos简介与安装 Nacos是什么Nacos是阿里巴巴开源的一款动态服务发现、配置管理和服务管理平台。它能够帮助进行微服务相关的配置管理、服务发现与服务管理。Nacos不仅为微服务提供了动态配置管理功能,还支持服务间的自动注册与发现,简化了服务之间的交互过程。
Nacos的主要功能Nacos提供了以下核心功能:
- 动态配置管理:支持配置的动态推送、覆盖更新、版本管理和配置回滚等功能。
- 服务发现与服务管理:支持服务注册、服务发现、健康检查、服务上下线通知等。
- 动态DNS服务:支持基于配置的DNS解析、动态域名解析,为服务提供动态DNS服务。
- 服务元数据及管理:对服务元数据进行管理,提供服务间依赖、调用关系的可视化展示。
- 多环境配置管理:支持不同环境下配置的管理,简化环境间的配置切换操作。
下载与解压
- 访问Nacos的GitHub项目页面,下载最新版本的Nacos压缩包。
- 解压下载的压缩包到本地目录,例如:
D:\nacos\nacos-server-\nacos
。
环境准备
- Java环境:确保安装了Java 8或更高版本,并将JAVA_HOME环境变量设置正确。
- 数据库支持:Nacos支持MySQL和PostgreSQL数据库,推荐使用MySQL。安装并配置好数据库,创建Nacos所需的数据库和用户。
启动Nacos
- 打开Nacos解压目录下的
conf
文件夹,找到application.properties
文件,根据自己的数据库配置修改数据库连接信息。 - 在解压目录运行启动脚本。例如,在Windows系统中,可以打开PowerShell或CMD,导航到Nacos解压目录,然后执行如下命令启动Nacos:
.\bin\startup.cmd -m standalone
-m standalone
参数表示以单机模式启动Nacos服务器。
检查Nacos是否启动成功
- 访问
http://localhost:8848/nacos
,如果能够看到Nacos的登录界面,则说明Nacos启动成功。 - 默认的登录用户名和密码都是
nacos
,可以在登录界面输入nacos
/nacos
登录。
配置中心是微服务架构中的重要模块,主要用于管理微服务相关的配置信息。配置中心能够实现配置的集中化管理、动态推送和版本控制,减少配置文件的维护成本,并且可以在不重启服务的前提下更新配置,提高系统的灵活性和可用性。
配置中心的典型应用场景包括:
- 配置信息的统一管理:将所有微服务的配置信息放到统一的配置中心,方便集中管理。
- 配置的动态更新:在不重启服务的前提下,可以动态更新配置信息,提升系统的灵活性。
- 配置的版本管理:能够记录配置的版本信息,方便回退到之前的配置版本。
- 配置的环境隔离:支持不同环境(开发、测试、生产等)的配置隔离和切换。
- 配置的监控与报警:能够监控配置的变化情况,并在配置发生变化时进行报警。
- 访问Nacos控制台:打开浏览器,访问
http://localhost:8848/nacos
,使用默认的用户名nacos
和密码nacos
登录。 - 创建配置:在左侧导航栏中选择
配置管理
,然后点击配置管理
。点击右上角的创建配置
按钮,输入配置名称、配置内容和其他可选信息,再点击确定
按钮即可创建配置。
{
"server.port": "8080",
ournals.active": "dev",
"database.url": "jdbc:mysql://localhost:3306/mydb"
}
配置的动态更新机制
当Nacos中的配置发生变更时,客户端会自动接收到更新信息,并且可以立即生效。具体步骤如下:
- 客户端订阅配置:客户端通过调用Nacos的API订阅配置,当配置发生变化时,Nacos会主动推送更新信息到客户端。
- 客户端处理更新:客户端接收到更新信息后,可以根据需要立即应用新的配置或者在适当的时候应用新配置。
- 配置推送机制:Nacos支持多种推送机制,包括HTTP长轮询、WebSocket、TCP等,确保配置变化能够及时推送到客户端。
示例代码
以下是一个简单的Java客户端代码,演示如何订阅和更新配置:
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.ConfigListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.ConfigInfo;
import com.alibaba.nacos.api.naming.pojo.Instance;
public class NacosConfigDemo {
public static void main(String[] args) throws NacosException {
// 创建NamingService实例
NamingService namingService = NamingFactory.createNamingService("localhost:8848");
// 设置配置信息监听器
namingService.subscribe("myapp", new ConfigListener() {
@Override
public void onEvent(NamingEvent namingEvent) {
// 获取配置信息
ConfigInfo configInfo = namingEvent.getConfigInfo();
System.out.println("Config updated: " + configInfo.getConfigInfo());
}
});
// 设置延迟,等待配置变化
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 卸载监听器
namingService.unsubscribe("myapp");
}
}
Nacos服务发现实战
服务发现的基础概念
服务发现是微服务架构中的关键机制,用于在运行时动态地发现和连接其他微服务。服务发现能够简化服务之间的交互,提高系统的可扩展性和灵活性。服务发现通常分为两种类型:
- 中心化服务发现:通过一个中心化的服务注册表来管理所有服务的注册与发现。服务注册表会保存服务的元数据信息,如IP、端口、健康状态等。
- 去中心化服务发现:通过分布式的方式实现服务发现,避免单点故障。例如,使用DNS解析来实现服务发现。
Nacos支持中心化的服务发现,服务注册表由Nacos服务器管理,所有服务实例都需要注册到Nacos,客户端通过Nacos获取服务的元数据信息。
服务注册与发现的过程
- 服务注册:服务提供者启动时,向Nacos注册自身信息,包括服务名称、IP地址、端口等。
- 服务发现:服务调用者通过Nacos获取服务提供者的元数据信息,例如IP地址和端口,实现服务调用。
- 服务心跳检测:服务提供者定期向Nacos发送心跳,保持自身的存活状态。服务调用者基于心跳信息判断服务提供者的健康状态。
- 服务实例变更通知:服务提供者或客户端的变更信息(如服务下线、实例增加等)会通过Nacos通知所有订阅者。
- 服务注册:在Nacos控制台中,选择
服务管理
,然后点击服务管理
。点击右上角的注册服务
按钮,输入服务名称、服务描述等信息,再点击确定
按钮即可注册服务。 - 服务发现:客户端通过调用Nacos的API来发现服务实例。以下是一个简单的Java客户端代码示例,演示如何通过Nacos发现服务实例:
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
public class ServiceDiscoveryDemo {
public static void main(String[] args) throws NacosException {
// 创建NamingService实例
NamingService namingService = NamingFactory.createNamingService("localhost:8848");
// 查询服务实例列表
Instance[] instances = namingService.getAllInstances("myapp");
for (Instance instance : instances) {
System.out.println("Instance: " + instance + ", IP: " + instance.getIp() + ", Port: " + instance.getPort());
}
}
}
如何配置服务的健康检查
Nacos支持对服务实例进行健康检查,确保服务实例的可用性。健康检查配置可以在Nacos控制台中进行设置。
- 访问Nacos控制台:打开浏览器,访问
http://localhost:8848/nacos
,使用默认的用户名nacos
和密码nacos
登录。 - 配置健康检查:在左侧导航栏中选择
服务管理
,然后点击服务管理
。选择需要配置健康检查的服务,点击健康检查
标签页,根据需要配置健康检查的策略,例如检查间隔、超时时间等。
示例代码
以下是一个简单的Java客户端代码示例,演示如何配置服务的健康检查:
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
public class ServiceHealthCheckDemo {
public static void main(String[] args) throws NacosException {
// 创建NamingService实例
NamingService namingService = NamingFactory.createNamingService("localhost:8848");
// 设置健康检查配置
namingService.setHealthCheckConfig("myapp", "true", "3000", "5000");
// 查询服务实例列表
Instance[] instances = namingService.getAllInstances("myapp");
for (Instance instance : instances) {
System.out.println("Instance: " + instance + ", Health Status: " + instance.getHealthy());
}
}
}
Nacos实战案例解析
使用Nacos管理微服务
在微服务架构中,Nacos可以用来管理服务的动态配置和注册发现。以下是一个具体的实战案例,演示如何使用Nacos来管理一个简单的微服务项目:
- 创建微服务项目:使用Spring Boot创建一个简单的微服务项目。
- 集成Nacos配置中心:在微服务项目中集成Nacos配置中心,实现配置的动态更新。
- 集成Nacos服务发现:在微服务项目中集成Nacos服务发现,实现服务实例的注册和发现。
- 配置健康检查:配置服务实例的健康检查,确保服务实例的可用性。
示例代码
创建微服务项目
- 新建Spring Boot项目:使用Spring Initializr创建一个Spring Boot项目,选择
web
和nacos
依赖。 - 配置文件:在项目的
src/main/resources
目录下创建application.properties
文件,引入Nacos配置:
spring.application.name=myapp
spring.cloud.nacos.config.server-addr=localhost:8848
集成Nacos配置中心
- 引入Nacos依赖:在
pom.xml
中引入Nacos配置中心的依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
- 配置监听器:在项目中添加配置监听器,监听配置变化:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.context.event.EventListener;
import org.springframework.context.event.ContextRefreshedEvent;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Configuration
public class ConfigListenerConfiguration {
@Bean
@Scope(scopeName = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public ConfigEventListener configEventListener() {
return new ConfigEventListener();
}
}
@Configuration
public class ConfigProperties {
@Bean
@RefreshScope
public MyProperties myProperties() {
return new MyProperties();
}
}
}
class ConfigEventListener {
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
// 配置变化处理
}
}
class MyProperties {
private String property;
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
}
集成Nacos服务发现
- 引入Nacos依赖:在
pom.xml
中引入Nacos服务发现的依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
- 配置服务注册:在项目的
application.properties
文件中配置服务注册信息:
spring.application.name=myapp
spring.cloud.nacos.discovery.server-addr=localhost:8848
- 注册服务实例:在服务启动时,注册服务实例到Nacos:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
配置健康检查
在Nacos控制台中,为微服务配置健康检查策略,确保服务实例的可用性。
实战项目部署流程- 准备项目代码:将微服务项目代码打包成JAR或WAR文件。
- 部署到服务器:将打包好的项目文件部署到服务器上,启动服务实例。
- 注册服务实例:启动服务实例后,服务实例会自动注册到Nacos,Nacos会记录服务实例的元数据信息。
- 配置管理:在Nacos中创建和管理配置信息,确保配置能够被服务实例动态加载。
在实战项目中,Nacos主要承担以下角色:
- 配置中心:集中管理微服务的配置信息,支持配置的动态更新和版本控制。
- 服务注册与发现:提供服务实例的注册、发现和管理功能,简化服务之间的交互。
- 健康检查:监控服务实例的健康状态,提供服务实例的健康检查和下线通知机制。
Nacos的作用包括:
- 简化服务管理:通过集中化管理服务实例和服务配置,简化微服务的管理流程。
- 提高系统灵活性:支持配置的动态更新和版本控制,提高系统的灵活性和响应速度。
- 提升系统可用性:通过健康检查和下线通知机制,确保服务实例的可用性和系统的稳定性。
Nacos提供了一系列的Java SDK,可以方便地在Java应用中集成Nacos。Nacos的Java SDK支持配置中心和注册中心的功能,包括配置的订阅和更新、服务的注册和发现等。
配置中心的使用
- 引入依赖:在项目的
pom.xml
文件中引入Nacos配置中心的依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
- 配置文件:在项目的
application.properties
文件中配置Nacos服务器地址和应用名称:
spring.cloud.nacos.config.server-addr=localhost:8848
spring.application.name=myapp
- 配置监听器:在项目中添加配置监听器,监听配置变化:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Configuration
public class ConfigListenerConfiguration {
@Bean
@RefreshScope
public MyProperties myProperties() {
return new MyProperties();
}
}
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
// 配置变化处理
}
public static class MyProperties {
private String property;
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
}
}
服务发现的使用
- 引入依赖:在项目的
pom.xml
文件中引入Nacos服务发现的依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
- 配置文件:在项目的
application.properties
文件中配置Nacos服务器地址和应用名称:
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.application.name=myapp
- 注册服务实例:在服务启动时,注册服务实例到Nacos:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
示例代码
以下是一个完整的示例代码,演示如何使用Nacos的Java SDK实现服务发现和配置中心的功能:
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.client.naming.NamingClient;
import com.alibaba.nacos.client.naming.pojo.Instance;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import java.util.Properties;
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) throws NacosException {
SpringApplication.run(Application.class, args);
// 配置中心示例
Properties properties = new Properties();
properties.put("serverAddr", "localhost:8848");
ConfigService configService = NacosFactory.createConfigService("myapp", properties, "default");
String config = configService.getConfig("myapp", "DEFAULT_GROUP", 5000);
System.out.println("Config: " + config);
// 服务发现示例
NamingClient namingClient = NacosFactory.createNamingClient("localhost:8848", properties);
Instance instance = new Instance();
instance.setIp("127.0.0.1");
instance.setPort(8080);
instance.setWeight(1.0);
instance.setHealthy(true);
namingClient.registerInstance("myapp", instance);
Instance[] instances = namingClient.getAllInstances("myapp");
for (Instance instance : instances) {
System.out.println("Instance: " + instance + ", IP: " + instance.getIp() + ", Port: " + instance.getPort());
}
}
@Configuration
public class ConfigListenerConfiguration {
@Bean
@RefreshScope
public MyProperties myProperties() {
return new MyProperties();
}
}
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
// 配置变化处理
}
public static class MyProperties {
private String property;
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
}
}
Nacos的API文档简介
Nacos提供了丰富的API文档,涵盖了配置中心和服务发现的所有操作。以下是Nacos API文档的简要介绍:
配置中心API
- 获取配置:通过
GET
请求获取配置信息。 - 发布配置:通过
POST
请求发布新的配置信息。 - 订阅配置:通过
GET
请求订阅配置信息,当配置发生变化时,会收到更新通知。
服务发现API
- 注册服务:通过
POST
请求注册服务实例。 - 发现服务:通过
GET
请求发现服务实例。 - 取消服务注册:通过
POST
请求取消服务实例的注册。
示例代码
以下是一些常用的Nacos API示例代码,演示如何使用Nacos的API实现配置中心和服务发现的功能:
获取配置
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.ConfigListener;
import com.alibaba.nacos.api.config.model.ConfigInfo;
public class NacosAPIDemo {
public static void main(String[] args) throws NacosException {
// 获取配置
ConfigService configService = NacosFactory.createConfigService("localhost:8848", "myapp");
String config = configService.getConfig("myapp", "DEFAULT_GROUP", 5000);
System.out.println("Config: " + config);
// 订阅配置
configService.addListener("myapp", "DEFAULT_GROUP", new ConfigListener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("Config updated: " + configInfo);
}
});
}
}
发布配置
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.ConfigListener;
import com.alibaba.nacos.api.config.model.ConfigInfo;
public class NacosAPIDemo {
public static void main(String[] args) throws NacosException {
// 发布配置
ConfigService configService = NacosFactory.createConfigService("localhost:8848", "myapp");
configService.publishConfig("myapp", "DEFAULT_GROUP", "new config content", 5000);
}
}
注册服务
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
public class NacosAPIDemo {
public static void main(String[] args) throws NacosException {
// 注册服务
NamingService namingService = NamingFactory.createNamingService("localhost:8848");
Instance instance = new Instance();
instance.setIp("127.0.0.1");
instance.setPort(8080);
instance.setWeight(1.0);
instance.setHealthy(true);
namingService.registerInstance("myapp", instance);
}
}
发现服务
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
public class NacosAPIDemo {
public static void main(String[] args) throws NacosException {
// 发现服务
NamingService namingService = NamingFactory.createNamingService("localhost:8848");
Instance[] instances = namingService.getAllInstances("myapp");
for (Instance instance : instances) {
System.out.println("Instance: " + instance + ", IP: " + instance.getIp() + ", Port: " + instance.getPort());
}
}
}
常见问题与解决方案
问题1:配置无法自动更新
问题描述:在Nacos配置中心订阅配置后,配置发生变化时,客户端没有接收到更新信息。
解决方案:确保配置订阅正确配置了监听器,并且Nacos服务端能够正常推送配置更新信息。检查网络连接和配置中心的推送策略。
问题2:服务注册失败
问题描述:服务实例注册到Nacos时,注册失败。
解决方案:检查服务实例的注册信息是否正确配置,包括服务名称、IP地址和端口。确保Nacos服务端能够正常接收注册请求。
问题3:服务发现失败
问题描述:服务实例发现失败,无法获取到服务实例的元数据信息。
解决方案:检查服务实例是否已经成功注册到Nacos,确保服务实例的注册信息正确配置。检查Nacos服务端是否能够正常提供服务实例的元数据信息。
Nacos项目实战总结 Nacos项目实战的回顾在Nacos项目实战中,我们通过以下步骤完成了项目的部署和管理:
- Nacos安装与配置:安装并配置Nacos服务器,确保Nacos能够正常提供服务。
- 集成Nacos配置中心:在微服务项目中集成Nacos配置中心,实现配置信息的集中管理和动态更新。
- 集成Nacos服务发现:在微服务项目中集成Nacos服务发现,实现服务实例的注册和发现。
- 配置健康检查:在Nacos中配置健康检查策略,确保服务实例的可用性。
通过Nacos的配置中心和服务发现功能,我们能够简化微服务的管理和维护工作,提高系统的灵活性和可用性。
Nacos与其他配置中心的对比Nacos与传统的配置中心(如Spring Cloud Config)相比,具有以下优势:
- 集中化管理:Nacos支持配置的集中化管理,简化了配置文件的维护工作。
- 动态更新:Nacos支持配置的动态更新,可以在不重启服务的情况下更新配置信息。
- 服务发现:Nacos不仅支持配置管理,还支持服务实例的注册和发现。
- 健康检查:Nacos提供服务实例的健康检查功能,确保服务实例的可用性。
Nacos与其他配置中心相比,具有更全面的功能和更强大的性能,能够更好地满足微服务架构的需求。
Nacos项目实战的心得体会通过Nacos项目实战,我们深刻体会到Nacos在微服务架构中的重要性和优势:
- 简化配置管理:Nacos的配置中心功能简化了配置文件的管理,减少了手动修改配置文件的工作量。
- 提高系统灵活性:Nacos支持配置的动态更新,使得系统更加灵活,能够快速响应业务需求的变化。
- 服务发现与服务管理:Nacos的服务发现功能简化了服务之间的交互,提高了系统的可扩展性和可用性。
- 健康检查:Nacos的健康检查功能确保服务实例的可用性,提高了系统的稳定性和可靠性。
在未来的项目中,我们将会继续使用并扩展Nacos的功能,充分利用其优势,提高项目的开发效率和维护成本。
共同学习,写下你的评论
评论加载中...
作者其他优质文章