【SpringCloud】02-Nacos注册中心
1. 注册中心原理
2. Nacos安装
-
- custom.env 配置文件
PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql
MYSQL_SERVICE_HOST=localhost
MYSQL_SERVICE_DB_NAME=nacos
MYSQL_SERVICE_PORT=3306
MYSQL_SERVICE_USER=root
MYSQL_SERVICE_PASSWORD=***
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
-
- Docker安装Nacos
docker run -d \
--name nacos \
--env-file custom.env \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
--restart=always \
nacos/nacos-server:v2.1.0-slim
-
- Nacos登录
http://xxx:8848/nacos
-
- nacos依赖
<!--nacos 服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
-
- yaml配置服务器地址
spring:
application:
name: item-service # 服务名称
cloud:
nacos:
server-addr: 192.168.150.101:8848 # nacos地址
-
- 服务拉取
// 引入依赖
private final DiscoveryClient discoveryClient;
private final RestTemplate restTemplate;
private void handleCartItems(List<CartVO> vos) {
// TODO
Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
// 1. 获取实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("item-service");
if (CollUtil.isEmpty(instances)) {
return ;
}
// 2. 负载均衡
ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()));
// 3. 获取 Http 响应
ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
instance.getUri() + "/items?ids={ids}",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<ItemDTO>>() {
},
Map.of("ids", CollUtil.join(itemIds, ","))
);
// 4. 解析
if (!response.getStatusCode().is2xxSuccessful()) {
return;
}
List<ItemDTO> items = response.getBody();
if (CollUtils.isEmpty(items)) {
return;
}
// // 1.获取商品id
// Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
// // 2.查询商品
// List<ItemDTO> items = itemService.queryItemByIds(itemIds);
// if (CollUtils.isEmpty(items)) {
// return;
// }
// 3.转为 id 到 item的map
Map<Long, ItemDTO> itemMap = items.stream().collect(Collectors.toMap(ItemDTO::getId, Function.identity()));
// 4.写入vo
for (CartVO v : vos) {
ItemDTO item = itemMap.get(v.getItemId());
if (item == null) {
continue;
}
v.setNewPrice(item.getPrice());
v.setStatus(item.getStatus());
v.setStock(item.getStock());
}
}
3. OpenFegin
- 依赖
<!--openFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--负载均衡器 loadbalancer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
- 配置注释
@EnableFeignClients
@MapperScan("com.hmall.cart.mapper")
@SpringBootApplication
public class CartServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CartServiceApplication.class, args);
System.out.println("服务器启动成功");
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
- 配置Bean
@FeignClient("item-service")
public interface ItemClient {
@GetMapping("/items")
List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
}
private final ItemClient itemClient;
private void handleCartItems(List<CartVO> vos) {
// TODO
Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
List<ItemDTO> items = itemClient.queryItemByIds(itemIds);
if (CollUtils.isEmpty(items)) {
return;
}
// 3.转为 id 到 item的map
Map<Long, ItemDTO> itemMap = items.stream().collect(Collectors.toMap(ItemDTO::getId, Function.identity()));
// 4.写入vo
for (CartVO v : vos) {
ItemDTO item = itemMap.get(v.getItemId());
if (item == null) {
continue;
}
v.setNewPrice(item.getPrice());
v.setStatus(item.getStatus());
v.setStock(item.getStock());
}
}
3. OpenFegin整合连接池
<!--OK http 的依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
yaml配置
feign:
okhttp:
enabled: true # 开启OKHttp功能
4. 最佳实践
在需要调用的包下面引入依赖
<!--feign模块-->
<dependency>
<groupId>com.heima</groupId>
<artifactId>hm-api</artifactId>
<version>1.0.0</version>
</dependency>
在cart-service的启动类上添加声明,扫描到ItemClient。
// 方法一
@EnableFeignClients(basePackages = "com.hmall.api.client")
@MapperScan("com.hmall.cart.mapper")
@SpringBootApplication
public class CartServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CartServiceApplication.class, args);
System.out.println("服务器启动成功");
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
// 方法二
@EnableFeignClients(basePackageClasses = ItemClient.class)
@MapperScan("com.hmall.cart.mapper")
@SpringBootApplication
public class CartServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CartServiceApplication.class, args);
System.out.println("服务器启动成功");
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
5. 日志输出
logging:
level:
com.hmall: debug
pattern:
dateformat: HH:mm:ss:SSS
file:
path: "logs/${spring.application.name}"
配置类
import feign.Logger;
import org.springframework.context.annotation.Bean;
public class DefaultFeignConfig {
@Bean
public Logger.Level feignLogLevel() {
return Logger.Level.FULL;
}
}
全局配置
@EnableFeignClients(basePackageClasses = ItemClient.class, defaultConfiguration = DefaultFeignConfig.class)
@MapperScan("com.hmall.cart.mapper")
@SpringBootApplication
public class CartServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CartServiceApplication.class, args);
System.out.println("服务器启动成功");
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}