优点:
易于开发调试,也易于部署,通过负载均衡后端运行多个拷贝也使其易于扩展
缺点:
复杂性高:模块边界模糊,修改bug可能会带来隐含缺陷
技术负债:随着时间推移,“不坏不修”的技术负载越积愈多
部署频率低:每次功能变更都会导致重新部署整个应用,全量部署耗时长,影响范围大,风险高
可靠性差:某个功能出现问题可能会出现连环效应,造成OOM,或整个应用的雪崩
扩展能力受限:不同类型的功能模块不能按需扩展
阻碍技术创新:单体应用使用统一的技术方案解决所有问题,引入新框架相当于重写代码
SpringCloud是一个基于Spring Boot实现的微服务架构开发工具。
商品模块——>调用商品模块
okhttp封装了http,是比HttpClient友好易用的工具
# 添加okhttp依赖
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.9.0</version>
</dependency>
注入RequestTemplate对象进行方法调用
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
# 订单模块
@Service
public class ItemService {
// Spring框架对RESTful方式的http请求做了封装,来简化操作
@Autowired
private RestTemplate restTemplate;
@Value("${myspcloud.item.url}")
private String itemUrl;
public Item queryItemById(Long id) {
return this.restTemplate.getForObject(itemUrl, Item.class);
}
}
问题:1. 如果有多个商品服务,订单该怎么调用呢
2. 商品服务ip地址变更,订单服务配置文件也要跟着修改
Eureka2.0已经闭源了。
a) 服务提供者注册到注册中心
b) 服务消费者从注册中心拉取服务列表,并缓存到本地缓存
c) 消费者根据服务列表调用相应提供者的服务 提供了服务提供者 和 ip地址的映射
d) 客户端通过发送心跳和注册中心保持连接,一旦地址发生变更,注册中心会通知消费者,一旦服务提供者下线,注册中心会将其从服务列表移除
Eureka通过复制机制,心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。客户端缓存机制,即使Eureka挂掉,客户端依然正常运行;应用启动后,会向Eureka Server发送心跳,若超过超时时间,则将其从服务列表移除,
Ribbon是Netflix发步的负载均衡器,当Ribbon收到服务提供者地址列表后,Ribbon就可以基于某种负载均衡算法,为服务消费者选择某个地址去进行请求。例如轮询,随机和自定义算法。
Ribbon会根据Eureka提供的服务列表选择一个ip发起请求
# 注入Template
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
# http://+ url +/item/
public Item queryItemById(Long id) {
String serviceId = "app-item";
List<ServiceInstance> instances = this.discoveryClient.getInstances(serviceId);
if(instances.isEmpty()){
return null;
}
ServiceInstance serviceInstance = instances.get(0);
String url = serviceInstance.getHost() + ":" + serviceInstance.getPort();
return this.restTemplate.getForObject("http://" + url + "/item/" + id, Item.class);
}
# http://+ servicename +/item/,Ribbon会根据Eureka提供的服务列表选择一个ip发起请求
public Item queryItemById(Long id) {
// 该方法走eureka注册中心调用(这种方式必须先开启负载均衡@LoadBalanced)
String itemUrl = "http://app-item/item/{id}";
Item result = restTemplate.getForObject(itemUrl, Item.class, id);
System.out.println("订单系统调用商品服务,result:" + result);
return result;
}
# 配置负载均衡策略
app-item:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
Feign是Netflix开发的Http客户端,整合了Ribbon和Eureka,支持Spring MVC注解或者JAX-RS注解,从而在服务间实现了服务消费 和 负载均衡。
流程分析
# 定义Ribbon的Restmelate对象,启动负载均衡
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
## 申明这是一个Feign客户端,并且指明服务id
@FeignClient(value = "app-item")
public interface ItemFeignClient {
@RequestMapping(value = "/item/{id}", method = RequestMethod.GET)
Item queryItemById(@PathVariable("id") Long id);
}
# 使用Hystrix实现断路器
@Autowired
private ItemFeignClient itemFeignClient;
@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
public Item queryItemById3(Long id) {
String itemUrl = "http://+ servicename +/item/{id}";
//Item result = restTemplate.getForObject(itemUrl, Item.class, id);
Item result = itemFeignClient.queryItemById(id);
return result;
}
服务网关统一向外提供Rest API,具有服务路由,负载均衡,权限控制,日志收集等功能,将公用的业务逻辑迁移到服务器路由层面,维护了服务功能的单一性,使其具备更高的可复用性和可测试性。除此之外,它简化了客户端访问微服务的方式,客户端只需要访问网关一个服务就可以访问到后面所有服务
Zuul是Nerflix开源的微服务网关,可以和Eureka,Ribbon,Hystrix等组件配置使用
通过Nginx搭建网关集群
http {
upstream myhttpServer{
#配置多个zuul地址
server localhost:8087;
server localhost:8086;
}
server {
listen 80;
server_name www.zpc.com;
location / {
proxy_pass http://myhttpServer;
index index.html index.htm;
}
}
}
当应用数量庞大,需要修改配置文件时间,都需要一一修改,然后进行重启。
Config Server是一个可横向扩展,集中式的配置服务器,可集中管理应用各个环境下的配置,可使用Git,Svn,本地文件进行存储。 bootstrap.yml配置
使用actuator监控中心完成刷新功能
POST请求监控中心 http://localhost:8080/actuator/refresh
配合Spring Cloud Config实现微服务应用配置的动态更新。
Spring Cloud Bus是通过使用轻量级消息代理来构件一个公用的消息主题,然后所有微服务实例都订阅该主题。在该主题上可以方便的广播一些配置信息变更消息,或者其他一些管理操作。
Hystrix是Netfix开源的一个延迟和容错库,用户隔离访问远程服务,防止级联错误的发生,从而提升系统的可用性和容错性
参考博客
springcloud通过bootstrap.yml负责从外部资源加载配置属性
spring.application.name:config 配置EurekaClient的应用名称
eureka.instance.non-secure-port:${server.port:8888} 若环境变量有server.port有值则使用 环境变量的值,否则使用8888
eureka.instance.metadata-map.instanceId: ${spring.application.name}:${random.value} 配置实例ID
eureka.service-url.defaultZone:http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ 配置Eureka Server的地址
## 其他应用配置都集中配置在 类路径的config目录下
Feign的中文名称翻译过来是伪装,通过调用RPC服务提供者的功能伪装成服务提供者。。。。
Ribbon添加maven依赖 spring-starter-ribbon 使用@RibbonClient(value=“服务名称”) 使用RestTemplate调用远程服务对应的方法
Feign添加maven依赖 spring-starter-feign 服务提供方提供对外接口 调用方使用 在接口上使用@FeignClient(“指定服务名”)