@File
2019-10-29T07:07:06.000000Z
字数 7774
阅读 154
java
<!-- 配置服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!-- 配置客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- eureka 服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- eureka 客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- ribbon 负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!-- feign 负载均衡(依赖 ribbon) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Hystrix 断路器(依赖 feign) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- Hystrix 监控 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<!-- zuul 路由 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
eureka:
instance:
# eureka的服务机器名
hostname: localhost
client:
#表示是否从注册中心抓取服务
fetch-registry: false
# 是否将我这个服务注册到注册中心
register-with-eureka: false
# 表示注册中心的地址
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
spring:
application:
# 设置服务名(相同的服务,名称要一样)
name: ms-provider
eureka:
client:
#是否从注册中心抓取服务(消费方开启)
fetch-registry: false
# 是否注册到注册中心(服务方开启)
register-with-eureka: true
# 表示注册中心的地址
service-url:
# 地址为Eureka的地址,表示将我的服务注册到哪个注册中心
defaultZone: http://localhost:7961/eureka/
instance:
# 将服务的IP地址信息注册到 Eureka上
prefer-ip-address: true
入口文件开启服务
- 服务端:
@EnableEurekaServer
- 客户端:
@EnableEurekaClient
配置:
- 创建配置文件,通过
@LoadBalanced
启用负载均衡
@Configuration
public class BeanConfig {
@Bean
// @LoadBalanced 对接口使用 ribbon 负载均衡
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
调用:
- 调用 RestTemplate
@RestController
public class ConsumerController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/Lidaye")
public String lidaye() {
return restTemplate.getForObject("http://ms-provider/port", String.class);
}
}
配置:
- 在入口文件添加
@EnableFeignClients
- 创建一个service接口,用
@FeignClient
绑定一个服务名
// 绑定服务名
@FeignClient("ms-provider")
public interface TicketService {
// 绑定服务接口名
@GetMapping("/port")
String run();
}
调用:
- 调用自定义的 service
@RestController
public class ConsumerController {
@Resource
private TicketService ticketService;
@GetMapping("/Lidaye")
public String lidaye() {
return ticketService.run();
}
}
类名 | 描述 |
---|---|
RoundRobbinRule | 轮询(默认策略) |
RandomRule | 随机挑选 |
RetryRule | 按照轮询的方式去调用服务,如果其中某个服务不可用,但是还是会尝试几次,如果尝试过几次都没有成功,那么就不在调用该服务,会轮询调用其他的可用服务。 |
AvailabilityFilteringRule | 会先过滤掉因为多次访问不可达和并发超过阈值的服务,然后轮询调用其他的服务 |
WeightedResponseTimeRule | 根据平均响应时间计算权重,响应越快权重越大,越容易被选中。服务刚重启的时候,还未统计出权重会按照轮询的方式;当统计信息足够的时候,就会按照权重信息访问 |
ZoneAvoidanceRule | 判断server所在的区域性能和可用性选择服务器 |
BestAvailableRule | 会过滤掉多次访问都不可达的服务,然后选择并发量最小的服务进行调用,默认方式 |
@Configuration
public class BeanConfig {
@Bean
public IRule getRule() {
return new RandomRule();
}
}
AbstractLoadBalancerRule
类choose
方法
public class CustomizeRule extends AbstractLoadBalancerRule {
private int limit = 5;
/**
* 当前调用的服务
*/
private Server currentServer;
/**
* 调用次数
*/
private AtomicInteger num = new AtomicInteger(0);
@Override
public Server choose(Object key) {
ILoadBalancer loadBalancer = getLoadBalancer();
//获取可用服务
List<Server> serverList = loadBalancer.getReachableServers();
synchronized (this) {
if(null == currentServer && serverList != null && serverList.size() > 0) {
this.currentServer = serverList.get(0);
num.getAndIncrement();
return currentServer;
}
}
/**
* 1.当前服务是否服务是否满5次,如果是调用下一个。
* 2.如果没有下一个服务,再回到第一个服务。
*/
int size = serverList.size();
for(int i = 0; i < size; i++) {
Server server = serverList.get(i);
// 判断当前服务是否为正在循环的服务
if(server.getId().equals(currentServer.getId())) {
// 如果num为4
synchronized (this) {
if (num.get() >= limit) {
// 调用下一个服务,次数要置零, 重新开始计算
num.set(0);
// 表示当前服务为最后一个服务
if (i == (size - 1)) {
// 再从头开始调用
currentServer = serverList.get(0);
// 次数要 +1
num.getAndIncrement();
return currentServer;
} else {
// 走下一个服务
currentServer = serverList.get(i + 1);
num.getAndIncrement();
return currentServer;
}
} else{
num.getAndIncrement();
return currentServer;
}
}
}
}
return null;
}
// 初始化配置
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
}
@Bean
public IRule getRule() {
return new CustomizeRule();
}
feign:
hystrix:
#开启feign的熔断机制
enabled: true
@EnableCircuitBreaker
注解
// 实现 TicketService 接口
@Component
public class TicketServiceFallback implements TicketService {
@Override
public String run() {
// 熔断机制触发时执行的内容
return null;
}
}
@FeignClient
的参数 fallback
// 配置熔断机制
@FeignClient(value = "ms-provider", fallback = TicketServiceFallback.class)
public interface TicketService {
@GetMapping("/port")
String run();
}
@EnableHystrixDashboard
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
http://localhost:8080/hystrix
server:
port: 8086
spring:
application:
name: shop-zuul
eureka:
client:
#是否从注册中心抓取服务(消费方开启)
fetch-registry: true
# 是否注册到注册中心(服务方开启)
register-with-eureka: false
# 表示注册中心的地址
service-url:
# Eureka的地址
defaultZone: http://localhost:7961/eureka/
instance:
# 将服务的IP地址信息注册到 Eureka上
prefer-ip-address: true
zuul:
routes:
# 别名,无固定形式(一般使用服务名)
ms-consumer:
# 绑定服务
serviceId: ms-consumer
# 设置服务访问路径
path: /mc/**
# 前缀
prefix: /v1
# 忽略所有默认路径(只开放 path 指定的路径)
ignored-services: "*"
@EnableZuulProxy
@Component
public class MyZuulFilter extends ZuulFilter {
/**
* 过滤时机
* pre 要用在路由映射的阶段是寻找路由映射表的
* post routing,error运行完后才会调用该过滤器,是在最后阶段的
* error 一旦前面的过滤器出错了,会调用error过滤器。
* route 具体的请求转发的时候会调用
*/
@Override
public String filterType() {
return "pre";
}
/**
* 优先级
* @return 数值越小越优先级越大
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 是否执行过滤
* @return 是或否
*/
@Override
public boolean shouldFilter() {
// 检测前面是否有把 sendZuulResponse 设置为 false
return RequestContext.getCurrentContext().sendZuulResponse();
}
/**
* 核心逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
// 取 servlet 中的请求对象
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
// 获取头部 token 信息
String access_token = request.getHeader("access_token");
if(access_token == null || "".equals(access_token)){
// 是否要转发请求
requestContext.setSendZuulResponse(false);
// 状态码
requestContext.setResponseStatusCode(403);
// 返回内容
requestContext.setResponseBody("token is invalid");
}
return null;
}
}
打开 git 终端
输入命令上传文件
# 添加到暂存区
git add -A
# 提交到本地版本控制库
git commit -m 'config init'
# 上传到 github(要修改上边拿到的git地址)
git push <git地址> master
@EnableConfigServer
注解
server:
port: 7070
spring:
cloud:
config:
server:
git:
# git 地址
uri: https://github.com/theFiles/spring-cloud-config.git
spring:
cloud:
# 模拟请求:http://localhost:7070/application-dev.yml
config:
# 文件名
name: application
# 加载哪个文件
profile: dev
# config服务端的地址
uri: http://localhost:7070