目录
思考:服务A调用了服务B,服务B调用了服务C,那么服务B是什么角色
答:一个服务既可以是提供者也可以是消费者,提供者和消费者是相对的,一个服务可以同时服务提供者和服务消费者
(1)服务提供者会没个30秒向EurekServer发送心跳请求,报告健康状态
(2)eureka会更新记录服务列表信息,心跳不正常会被剔除
(2)编写启动类,添加@EnableEurkaServer注解
(3)添加application.yml文件,编写下面的配置
(1)服务拉取是基于服务名称获取服务列表,然后再对服务列表做负载均衡
(2)再order-service项目的启动类OrderApplication中的RestTemplate添加负载均衡
1、再cloud-demo父工程中添加spring-cloud-alilbaba的管理依赖
2、注释掉order-service和user-service中原有的eureka依赖
4、修改客户端中的application.yml文件,注释eurka地址,添加nacos地址
1、修改order-service中的application.yml,设置集群为HZ:
2、然后再order-service中设置负载均衡的IRule为NacosRule,这个规则优先会寻找与自己同集群的服务
2、再uservice的resoure目录添加一个bootstrap.yml文件,这个文件是引导文件,优先级高于application.yml
2、在order-service的启动类添加注解开启Feign的功能
主要是基于SpringMVC的注解来声明远程调用的信息,比如:
一、什么是微服务
单体架构
分布式架构
微服务结构
服务拆分注意事项
微服务远程调用
1、步骤一:注册RestTemplate
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
/**
* 创建RestTemplate并注入Spring容器
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2、步骤2:服务远程调用RestTemplat
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
//2.利用RestTemplate发起http请求,查询用户
//2.1url路劲
String url = "http://localhost:9101/user/"+order.getUserId();
//2.2 发起http请求,实现远程调用0
User user = restTemplate.getForObject(url, User.class);
//3 封装user到Order
order.setUser(user);
//4.返回
return order;
}
}
提供者和消费者
思考:服务A调用了服务B,服务B调用了服务C,那么服务B是什么角色
答:一个服务既可以是提供者也可以是消费者,提供者和消费者是相对的,一个服务可以同时服务提供者和服务消费者
Eureka注册中心
思考:1、消费者如何获取服务提供者具体信息
(1)服务者提供者启动时向eureka注册自己的信息
(2)eureka保存这些信息
(3)消费者提供服务名称向eureka拉去提供者信息
2、如果有多个服务提供者,消费者该如何选择?
服务消费者利用负载均衡算法,从服务列表中挑选一个
3、消费者如何感知服务提供者健康状态?
(1)服务提供者会没个30秒向EurekServer发送心跳请求,报告健康状态
(2)eureka会更新记录服务列表信息,心跳不正常会被剔除
(3)消费者 就可以拉去最新的信息
动手实践
1、搭建eureka注册中心
(1)创建项目引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
</dependencies>
(2)编写启动类,添加@EnableEurkaServer注解
(3)添加application.yml文件,编写下面的配置
server:
port: 10086 #服务端口
spring:
application:
name: eurekaserver #eurka的服务名称
eureka:
client:
service-url: #eurka的地址信息
defaultZone: http://127.0.0.1:10086/eureka/
2、服务注册
注册user-service
(1)导入依赖
<!-- eureka客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
(2)编写配置
server:
port: 9101
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
username: root
password: 20202024
driver-class-name: com.mysql.jdbc.Driver
application:
name: userservice #user的服务名称
mybatis:
type-aliases-package: cn.itcast.user.pojo
configuration:
map-underscore-to-camel-case: true
logging:
level:
cn.itcast: debug
pattern:
dateformat: MM-dd HH:mm:ss:SSS
eureka:
client:
service-url: #eurka的地址信息
defaultZone: http://127.0.0.1:10086/eureka/
实例部署
在Order-Service完成服务拉取
(1)服务拉取是基于服务名称获取服务列表,然后再对服务列表做负载均衡
String url = "http://userservice/user/"+order.getUserId();
(2)再order-service项目的启动类OrderApplication中的RestTemplate添加负载均衡
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
/**
* 创建RestTemplate并注入Spring容器
* @return
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
Ribbon负载均衡
负载均衡原理
负载均衡策略
懒加载
饥饿加载
Nacos
服务注册到Nacos
1、再cloud-demo父工程中添加spring-cloud-alilbaba的管理依赖
<!--nacos的管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
2、注释掉order-service和user-service中原有的eureka依赖
3、添加nacos的客户端依赖
<!-- nacos客户端依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
4、修改客户端中的application.yml文件,注释eurka地址,添加nacos地址
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
username: root
password: 20202024
driver-class-name: com.mysql.jdbc.Driver
application:
name: userservice #user的服务名称
cloud:
nacos:
server-addr: localhost:8848 #nacos服务地址
5、启动并测试
注意:必须启动nacos,账号密码都为nacos
Nacos服务分级存储模型
1、修改application.yml,添加如下内容
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
username: root
password: 20202024
driver-class-name: com.mysql.jdbc.Driver
application:
name: userservice #user的服务名称
cloud:
nacos:
server-addr: localhost:8848 #nacos服务地址
discovery:
cluster-name: HZ #集群名,这里HZ代指杭州
如何HZ改为SH再运行另外一个application
2、在Nacos控制台可以看到集群变化
根据集群负载均衡
1、修改order-service中的application.yml,设置集群为HZ:
datasource:
url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
username: root
password: 20202024
driver-class-name: com.mysql.jdbc.Driver
application:
name: orderservice #order的服务名称
cloud:
nacos:
server-addr: localhost:8848 #nacos服务地址
discovery:
cluster-name: HZ #集群名称
2、然后再order-service中设置负载均衡的IRule为NacosRule,这个规则优先会寻找与自己同集群的服务
userservice: #要做配置的微服务名称
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule #负载均衡规则
3、注意将user-service的权重都设置为1
根据权重负载均衡
环境隔离
nacos注册中心原理
Nacos配置隔离
统一配置管理
1、引入Nacos的配置管理依赖
<!-- nacos的配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2、再uservice的resoure目录添加一个bootstrap.yml文件,这个文件是引导文件,优先级高于application.yml
spring:
application:
name: userservice
profiles:
active: dev #环境
cloud:
nacos:
server-addr: localhost:8848 #nacos地址
config:
file-extension: yaml #文件后缀名
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Value("${pattern.dateformat}")
private String dateformat;
@GetMapping("now")
public String now(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
}
}
管理配置热更新(自动刷新)
@Data
@Component
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
private String dateformat;
}
@Slf4j
@RestController
@RequestMapping("/user")
//@RefreshScope
public class UserController {
@Autowired
private UserService userService;
@Autowired
private PatternProperties properties;
@GetMapping("now")
public String now(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(properties.getDateformat()));
}
}
多环境配置共享
Nacos集群搭建
Feign
使用Frign的步骤如下:
1、引入依赖:
<!-- feign客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、在order-service的启动类添加注解开启Feign的功能
3、编写Feign客户端
@FeignClient("userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private UserClient userClient;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
//2.用Feign远程调用
User user = userClient.findById(order.getUserId());
// 3 封装user到Order
order.setUser(user);
//4.返回
return order;
}
主要是基于SpringMVC的注解来声明远程调用的信息,比如:
服务名称:userservice
请求方式:GET
请求路径:/user/{id}
请求参数:Long id
返回值类型:User
自定义Fign配置
Feign性能优化
1、引入依赖
<!-- 引入HttpClient依赖 得加入版本才行-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>12.3</version>
</dependency>
2、配置连接池:
feign:
client:
config:
default: #default全局的配置
loggerLevel: BASIC #日志级别,BASIC就是基本的请求和响应信息
httpclient:
enabled: true #支持HttpClient的开关
max-connections: 200 #最大连接数
max-connections-per-route: 50 #单个路劲的最大连接数
注意:日志尽量使用BASIC
Frign的最佳实践
最佳实践 方式二:
1、创建新模板,命名为feign-api
创建模板后直接删除
feign-api引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
order-service引入依赖
<!-- 引入feign的统一api groupID自己创建项目的时候有的可以查看-->
<dependency>
<groupId>cn.itcast.demo</groupId>
<artifactId>feign-api</artifactId>
<version>1.0</version>
</dependency>
这样子才可以导入其他包
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients(clients = UserClient.class,defaultConfiguration = DefaultFeignConfiguration.class)
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
/**
* 创建RestTemplate并注入Spring容器
* @return
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}