官网:https://spring.io/projects/spring-cloud-openfeign#learn
技能基础:Spring boot, Linux, Docker
##2、 微服务与单体架构
EureKa Server
EureKa Client
1、 Eureka Server 高可用
2、总结:EnbleEurekaServer EnbleEurekaClient
心跳检测、健康检查、负载均衡等功能
Eureka 的高可用,建议两台以上
3、服务发现的用处
桥梁:最重要的基础部分注册中心,代理
客户端发现: Eureka
服务端发现(含有代理):Nginx, Zookeeper, Kubernetes
微服务的特点: 异构
SpringCloud的服务调用方式: REST or RPC ?, Node.js 的enureka-js-client
起点:既有架构的形态
不适合的:系统访问压力不大, 业务稳定,包含很多强事物场景
终点:进化
因素:
原则:
康威定律:沟通的问题会影响系统设置。
服务拆分的方法论:
扩展立方模型:Scale Cube : X 轴 水平复制, Z轴 数据分区, Y轴 功能分区
(1) 单一职责、松耦合, 高内聚
(2) 关注点分离 : 按职责、 按通用性、 按粒度级别
(1) 先业务后数据
(2)无状态服
HTTP、 RPC 对应的 Dubbo、 Spring Cloud。
例如:
// @Autowired
//private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/getProductMsg")
public String getProductMsg(){
//1、第一种方式:(直接使用restTemplate, url 写死)
/*
RestTemplate restTemplate = new RestTemplate ( );
String response = restTemplate.getForObject ( "http://localhost:8080/msg", String.class );
log.info("response = {}", response);
*/
//2、第二种方式(利用loadBalancerClient通过应用名获取url)
/* ServiceInstance serviceInstance = loadBalancerClient.choose ( "PRODUCT");
String url = String.format ( "http://%s:%s",serviceInstance.getHost (), serviceInstance.getPort ()) + "/msg";
RestTemplate restTemplate = new RestTemplate ( );
String response = restTemplate.getForObject ( "http://localhost:8080/msg", String.class );*/
//3、第三种方式(利用注解@LoadBalanced,可在restTemplate里使用应用名字)
String response = restTemplate.getForObject ( "http://PRODUCT/msg", String.class );
log.info("response = {}", response);
return response;
}
客户端负载均衡器: Ribbon
(RestTemplate Feign Zuul)
Ribbon:
(1)过程: 服务发现、 服务选择规则、 服务监听
(2)包含组件:ServerList, IRule, ServerListFilter
Feign:
声明是REST客户端(伪RPC)
采用了基于接口的注解
模块命名:
XXX-server 所有业务逻辑
XXX-client 对外暴露的接口
XXX-common 公用的对象(可以被内外部使用)
消息中间件:
中间件的选择: RabbitMQ、 Kafa、 ActiveMQ
以往的缺陷:不方便维护、 配置内容安全与权限, 更新配置项目需要重启。
方式: 远端git ——config-server ——本地git
yml 文件命名规则:
/{name}-{profiles}.yml
/{label}/{name}-{profiles}.yml
其中: name 服务名 ,profiles 环境 label 分支
配置文件加载过程:
bootstrap.yml 先加载
application.yml后加载
SpringCloud Bus
/bus-refresh
远端git ————————》 Config-server : ——》product, order
本地git
消息队列: RabbitMQ
(1)加入 依赖
(2)改配置
(3)加注解 :
@RefreshScope
常见形态: 通知 、 请求/异步响应、 消息
MQ 应用场景: 异步处理、 流量削峰(如: 秒杀活动)、日志处理(卡夫卡)、应用解耦
RabbitMQ 的基本使用
自动创建对象
接收方(client)
package com.imooc.order.message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class MqReceiver {
// 1、@RabbitListener(queues = "myQueue")
// 2、自动创建
// @RabbitListener(queuesToDeclare = @Queue("myQueue"))
//3、 自动创建 exchange 和queue 绑定
@RabbitListener(bindings = @QueueBinding ( value = @Queue( "myQueue"), exchange = @Exchange("myExchange")))
public void process(String message){
log.info ("MqReceiver:{}", message);
}
/**
* 数码供应商
* @param message
*/
@RabbitListener(bindings = @QueueBinding ( exchange = @Exchange("myOrder"), key ="computer", value = @Queue( "computerOrder")))
public void processComputer(String message){
log.info ("computer MqReceiver:{}", message);
}
/**
* 水果供应商
* @param message
*/
@RabbitListener(bindings = @QueueBinding ( exchange = @Exchange("myOrder"), key ="fruit", value = @Queue( "fruitOrder")))
public void processFruit(String message){
log.info ("fruit MqReceiver:{}", message);
}
}
发送方(server)
package com.imooc.order;
import org.junit.Test;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MqSenderTest extends OrderApplicationTests {
@Autowired
private AmqpTemplate amqpTemplate;
@Test
public void send() {
amqpTemplate.convertAndSend("myQueue", "now " + new Date());
}
@Test
public void sendOrder() {
amqpTemplate.convertAndSend("myOrder", "computer", "now " + new Date());
}
}
单个实例
多个实例: 分组
rabbitMQ 查看消息堆积
服务网关的要素:稳定性、高可用、 安全性, 性能并发性, 扩展性
常见的网关方案:Ngnix+ Lua、 Kong、Tyk、SpringCloud Zuul
Zuul 四种过滤器API:前置(Pre)、 后置(Post)、 路由(Route)、 错误(Error)
1、 端口冲突,修改一下服务器端口号即可
2 、自定义路由:
把服务的路由定义为myProduct
查看路由规则
3、排除某些路由
Cookie 自动忽略,可以设置
动态路由配置
前置(pre): 限流 鉴权 参数校验
后置(Post): 统计 日志
Zuul 的高可用: 多个节点注册到Eureka Server, Nginx和 Zuul"混搭"
token 过滤
http头
cookie 里设置openid
可能出席因为版本不同导致客户端连接不上服务
解决:在pom文件添加如下:
org.springframework.boot
spring-boot-starter-web
优化
在前置过滤器中实现相关逻辑
分布式Session Vs OAuth2
@CrossOrigin(allowCredentials = "true")// 允许带cookie的跨域
雪崩效应: 牵一发而动全身
防雪崩利器:基于Netflix对应的Hystrix——> HyStrix
HyStrix:
(1)服务降级: 优先核心服务、 非核心服务不可用或弱可用,
通过HystrixCommand注解指定、 fallbackMethod(回退函数)中具体实现降级逻辑
(2) 服务熔断:
(3) 依赖隔离:
(4) 监控(HystrixDashboard):
降级应用场景:服务停止 、 内部抛异常
demo:
package com.imooc.order.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
@RestController
public class HystrixController {
@HystrixCommand(fallbackMethod = "fallback")
@GetMapping("/getProductInfoList")
public String getProductInfoList(){
RestTemplate restTemplate = new RestTemplate ();
return restTemplate.postForObject ("http://127.0.0.1:8001/product/listForOrder",
Arrays.asList ("157875196366160022"),
String.class);
//throw new RuntimeException ("发生异常了");
}
private String fallback(){
return "太拥挤了,请稍候再试~~";
}
}
@HystrixCommand(commandProperties = {@HystrixProperty (name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")}
完整示例如下:
package com.imooc.order.controller;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
@RestController
@DefaultProperties(defaultFallback = "defaulFallback")
public class HystrixController {
@HystrixCommand(commandProperties = {@HystrixProperty (name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")}) //超时时间设置
@GetMapping("/getProductInfoList")
public String getProductInfoList() {
RestTemplate restTemplate = new RestTemplate ();
return restTemplate.postForObject ("http://127.0.0.1:8001/product/listForOrder",
Arrays.asList ("157875196366160022"),
String.class);
//throw new RuntimeException ("发生异常了");
}
private String fallback() {
return "太拥挤了,请稍候再试~~";
}
private String defaulFallback() {
return "默认提示:太拥挤了,请稍候再试~~";
}
}
线程池隔离
Hystirx 自动实现了依赖隔离
@HystrixCommand(commandProperties = {
@HystrixProperty (name = "circuitBreaker.enabled", value = "true"), //服务熔断
@HystrixProperty (name="circuitBreaker.requestVolumeThreshold", value ="10" ),
@HystrixProperty (name="circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠时间窗
@HystrixProperty (name="circuitBreaker.errorThresholdPercentage", value = "60")})
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 1000
配置
feign:
hystrix:
enabled: true
通常做法:日志
链路监控:
Spring cloud sleuth 组件
链路追踪:zipkin工具, 配置
集成步骤:引入依赖、启动ZipKin Server 、 配置参数
分布式追踪系统:
(1)核心步骤:数据存储, 数据查询, 展示
(2)OpenTracing 标准:来自CNCF, ZIPKN等
(3)Annotation:事件类型, CS,CR,SS,SR
几个概念:traceId、 spanId, travelId
-(1) docker
供参考的学习课程:第一个docker 化的java应用
-(2) rancher
为了更方便地管理docker
rancher 服务端放置于Linux 服务器
rancher 客户端放置于另一台服务器
镜像加速器
GA:general availablility 面向大众的可用版本
M: milestone 里程碑版本
SNAPSHOT: 快照。代码可变
源码链接:github