SpringCloudAlibaba 项目
1. 简述
SpringCloudAlibaba 项目,采用的 SpringCloudAlibaba 相关组件:
Nacos:注册与发现、配置
Gateway:网关
Feign:远程调用
Sentinel:限流、熔断
Seata:分布式事务
2. 创建项目
2.1 通用配置
- 使用IDEA创建一个Empty Project,再创建4个module:common、producer、consumer、gateway;
- 拷贝一个pom.xml文件作为项目的总pom文件,起到聚合作用;
- 对4个模块添加通用配置:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.8.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
- common模块,添加基础依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--nacos注册中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
- 其他的三个模块,添加common模块依赖:
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
2.2 producer 生产者模块
- 修改启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Producer {
public static void main(String[] args) {
SpringApplication.run(Producer.class, args);
}
}
- 创建配置文件 application.yml
server:
port: 10000
spring:
application:
name: producer
cloud:
nacos:
discovery:
server-addr: 120.48.96.228:8848
management:
endpoints:
web:
exposure:
include: '*'
- 服务producer正常注册到Nacos中,服务正常启动;
2.3 consumer 消费者模块
- 修改启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class Consumer {
public static void main(String[] args) {
SpringApplication.run(Consumer.class, args);
}
}
- 创建配置文件:
server:
port: 11000
spring:
application:
name: consumer
cloud:
nacos:
discovery:
server-addr: 120.48.96.228:8848
- 服务consumer 正常注册到Nacos中,服务正常启动;
2.4 gateway 网关模块
- 修改依赖:
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
- 修改启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Gateway {
public static void main(String[] args) {
SpringApplication.run(Gateway.class, args);
}
}
- 创建配置文件:端口为8080
server:
port: 8080
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: 120.48.96.228:8848
gateway:
routes:
- id: producer_route
uri: lb://producer
predicates:
- Path=/api/producer/**
filters:
- RewritePath=/api/(?<segment>.*),/$\{segment}
- id: consumer_route
uri: lb://consumer
predicates:
- Path=/api/consumer/**
filters:
- RewritePath=/api/(?<segment>.*),/$\{segment}
- 服务gateway 正常注册到Nacos中,服务正常启动;
3. 创建接口,服务调用
3.1 创建接口
- producer 生产者模块
@RestController
@RequestMapping("/producer")
public class ProducerController {
//访问:http://localhost:10000/producer/add
@GetMapping(value = "/add")
public String add() {
System.out.println("producer success!");
return "producer add success!";
}
}
- consumer 消费者模块
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Value("${server.port}")
private String port;
//访问:http://localhost:11000/consumer/add
@RequestMapping("/add")
public String add() {
System.out.println("consumer add success!");
return "consumer add success!";
}
//访问:http://localhost:11000/consumer/sub
@RequestMapping("/sub")
public String sub() {
System.out.println("consumer sub success!");
return "consumer sub success! ------ port is " + port;
}
}
- 经过 gateway 网关进行访问:
http://localhost:8080/api/producer/add
http://localhost:8080/api/consumer/add
http://localhost:8080/api/consumer/sub
3.2 服务调用
以上是通过浏览器访问服务的接口,而服务间通常需要相互调用,如:producer去消费consumer;以下操作都是生产者producer上进行;
3.2.1 RestTemplate
- 创建一个配置类 RestTemplateConfig 支持负载均衡
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Configuration
@Component
public class RestTemplateConfig {
@Bean
@LoadBalanced //使RestTemplate请求支持负载均衡
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
- 修改类 ProducerController,添加接口:
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/add2")
public String add2() {
System.out.println("producer2 success!");
String apiReqResult = restTemplate.getForObject("http://consumer/consumer/add", String.class);
return "producer2 add success! return val is : " + apiReqResult;
}
3.2.2 Feign
Feign组件,声明式服务调用,可进行远程调用;
- 服务间会进行互相调用,所以在common模块中添加(已添加:openfeign);
- 生产者去调用消费者,所以在producer 模块中,创建目录feign,专用于远程调用;
- 创建一个接口类,与远程调用的类保持一致:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient("consumer") //要调用的服务名
public interface ConsumerService {
//要远程调用方法的完整签名
@RequestMapping("/consumer/add")
String add();
@RequestMapping("/consumer/sub")
String sub();
}
- 启动类处,添加注解:
@EnableFeignClients(basePackages = {"org.example.producer.feign"})
- 修改类 ProducerController,添加接口:
@Autowired
private ConsumerService consumerService;
@GetMapping(value = "/add3")
public String add3() {
String add = consumerService.add();
System.out.println("producer feign : " + add);
return "producer feign : " + add;
}
- 访问:http://localhost:8080/api/producer/add3 返回值正常;
4. 配置中心Nacos Server
Nacos的功能:注册中心、配置中心;
4.1 Nacos 配置功能
- 在common模块中,添加依赖:
<!--nacos配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 为3个模块添加配置文件:bootstrap.properties
spring.cloud.nacos.config.server-addr=120.48.96.228:8848
- 在含有变量的类上,添加注解:@RefreshScope ,开启动态刷新功能;(事实上,配置文件中添加变量,这种方式很少使用)
- 配置中心实现隔离、分组功能:命名空间、GROUP、抽离服务配置;
4.2 抽离服务配置
- 将配置文件application.yml 里面的内容进行分类,如(也可按服务分类):
datasource.yml
mybatisplus.yml
other.yml
nacos-discovery.yml
...
- 服务加载Nacos中的配置集信息
1. 即application.yml 配置文件不再写配置内容,配置内容在Nacos配置中心的多个yml文件中,而配置信息在bootstrap.properties文件中;
2. 即相同的配置内容,可重复使用;
- 在 bootstrap.properties 文件中加载配置信息
spring.application.name=consumer
spring.cloud.nacos.config.server-addr=120.48.96.228:8848
#指定配置文件的命名空间,默认 public
spring.cloud.nacos.config.namespace=public
#指定配置文件的分组,默认 DEFAULT_GROUP
spring.cloud.nacos.config.group=DEFAULT_GROUP
#数据源扩展配置的配置集id
spring.cloud.nacos.config.ext-config[0].data-id=nacos-discovery.yml
#加载dev分组的配置集
spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
#开启自动刷新
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.cloud.nacos.config.ext-config[1].data-id=port-11000.yml
spring.cloud.nacos.config.ext-config[1].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[1].refresh=true
- 说明:
1. 需要在Nacos中添加配置文件:nacos-discovery.yml、port-11000.yml
2. 文件内容就是之前的配置内容,使用配置扩展功能,启动时将配置信息读取出来;
3. 同上,将生产者、网关服务,配置信息配置到Nacos的配置中心去;
5. 熔断限流 Sentinel
高并发情况下,大量用户去访问服务,以及服务间的互相调用,所以需要对各个服务进行限流设置;
- 在common模块中添加公共依赖:
<!-- sentinel 启动器 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 在Nacos配置服务端,创建sentinel.yml 配置文件:
spring:
cloud:
sentinel:
eager: true #true表示取消Sentinel控制台懒加载,默认情况下 Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包
transport:
dashboard: 101.43.52.64:8858
# client-ip: #如果有多套网络,又无法正确获取本机IP,则需要使用下面的参数设置当前机器可被外部访问的IP地址,供admin控制台使用
- 在三个服务的配置文件bootstrap.properties 中添加配置:
spring.cloud.nacos.config.ext-config[3].data-id=sentinel.yml
spring.cloud.nacos.config.ext-config[3].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[3].refresh=true
- 启动三个服务,访问Sentinel控制台:会发现3个服务均注册到Sentinel中;
- 可以操作的有:
1. 实时监控,可用于查看接口访问情况
2. 簇点链路,可以对对应的资源流控降级
3. QPS流量控制、线程流量控制、关联限流、熔断降级
4. Sentinel支持多种保护规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则、热点参数规则
- 持久化规则,在Sentinel中的配置会因服务重启而消失,所以需要持久化,common模块中添加依赖:
<!--sentinel持久化存储-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
- 在Nacos中添加配置sentinel-durable 文件
[
{
"resource": "/producer/add",
"controlBehavior": 0,
"count": 2,
"grade": 1,
"limitApp": "default",
"strategy": 0
}
]
- 修改配置文件 sentinel.yml
spring:
cloud:
sentinel:
eager: true #true表示取消Sentinel控制台懒加载,默认情况下 Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包
transport:
dashboard: 101.43.52.64:8858
port: 8719 #默认为8719 ,假如被占用会自动从8719开始依次+1扫描,直到未被占用的端口,线上部署的ip -> ip必须打开8719的端口
# client-ip: #如果有多套网络,又无法正确获取本机IP,则需要使用下面的参数设置当前机器可被外部访问的IP地址,供admin控制台使用
datasource:
ds:
nacos:
serverAddr: 120.48.96.228:8848 #nacos的服务注册中心
dataId: sentinel-durable #Nacos配置中心的命名(不加.json)
dataType: json
groupId: DEFAULT_GROUP #nacos配置中心的组id
ruleType: flow #规则为限流
6. 事务 Seata
- Seata-Server端,注册和配置中心采用Nacos,数据库采用MySQL;
- common模块中引入依赖:
<!-- seata 分布式事务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
- 对各微服务对应的数据库中添加undo_log表
CREATE TABLE `undo_log`(
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
PRIMARY KEY(`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
- 对各个服务添加配置:
#配置seata的注册中心
seata.enabled=true
seata.application-id=${spring.application.name}
#配置事务分组
seata.tx-service-group=default_tx_group
seata.registry.type=nacos
seata.registry.nacos.server-addr=127.0.0.1:8848
seata.registry.nacos.application=seata-server
seata.registry.nacos.namespace=
seata.registry.nacos.username=nacos
seata.registry.nacos.password=nacos
seata.registry.nacos.group=SEATA_GROUP
#配置seata的配置中心
seata.config.type=nacos
seata.config.nacos.server-addr=127.0.0.1:8848
seata.config.nacos.namespace=
seata.config.nacos.username=nacos
seata.config.nacos.password=nacos
seata.config.nacos.group=SEATA_GROUP
- 在业务代码上添加注解:
@GlobalTransactional //分布式事务注解
public String addOrder(){
Order order = new Order("袜子");
int id = orderService.addOrder(order);
System.out.println("订单新增成功-id:" + id);
//调用库存扣减
String result = stockOpenFeignService.subStock(id);
return new Result(200,"订单服务-订单新增成功",result).toString();
}
标签:01,项目,spring,nacos,springframework,org,config,SpringCloudAlibaba,cloud
From: https://www.cnblogs.com/lailix/p/16661403.html