Zuul网关 hystix 配置中心

 目录

统一的调用接口

统一的权限校验

通过zuul的过滤器,判断用户权限,有权限,继续转发调用,反之,从网关直接返回结果

集成了ribbon   默认启用负载均衡 zuul不推荐启用重试

集成了hystrix    有容错限流功能

Hystrix限流熔断 

Hystrix 监控 对熔断降级进行监控

tubine服务

搭建配置中心

​​

 rabbitmq消息服务器(消息中间件broker)   (具有解耦,流量消峰)

(还有Activemq RocketMq kafka tubemq) spring集成了rabbitmq            

topic交换机(主题)

BUS--消息总线 链接消息服务器 收发刷新指令消息  在普通服务中执行配置刷新

服务配置刷新过程

用户服务的实现类上添加注解@RefreshScope

上下文对象Context


统一的调用接口

统一的权限校验

通过zuul的过滤器,判断用户权限,有权限,继续转发调用,反之,从网关直接返回结果

继承接口zuulfilter 添加@compnents

zuul的自动配置类,可以从spring容器自动发现过滤器实例,完成自动配置

@Component
public class AccessFilter extends ZuulFilter {
    // pre, routing, post, error
    @Override
    public String filterType() {
        //return "pre";
        return FilterConstants.PRE_TYPE;
    }

    // 过滤器的顺序号
    @Override
    public int filterOrder() {
        // 有5个默认的过滤器,自己的过滤器加到末尾
        // 在第5个过滤器中,向Context对象放入了 serviceId,
        // 后面组件中,才能访问这个数据
        return 6;
    }

    // 针对当前请求,判断是否要执行过滤代码
    // 如果调用 item-service,检查是否登录
    // 否则,不检查登录,直接访问
    @Override
    public boolean shouldFilter() {
        // 先获取当前请求的上下文对象
        RequestContext ctx = RequestContext.getCurrentContext();
        // 当前请求,调用的服务id
        String serviceId = (String)
                ctx.get(FilterConstants.SERVICE_ID_KEY);// "serviceId"
        // 调用的是否是 item-service
        return "item-service".equals(serviceId);
    }

    // 过滤代码
    @Override
    public Object run() throws ZuulException {
        // 获得上下文对象
        RequestContext ctx = RequestContext.getCurrentContext();
        // 获得 request 对象
        HttpServletRequest request = ctx.getRequest();
        // http://localhost:3001/item-service/u56y5g4?token=u6y54t
        // 接收 token 参数
        String token = request.getParameter("token");
        // 如果没有 token,阻止继续调用,直接返回响应
        // ""、null、"      "
        if (StringUtils.isBlank(token)) {
            // 阻止继续调用
            ctx.setSendZuulResponse(false);
            // 直接返回响应
            // JsonResult --- {code:1,msg:xxx,data:null}
            ctx.addZuulResponseHeader(
                "Content-Type","application/json;charset=UTF-8");
            ctx.setResponseBody(JsonResult
                    .err()
                    .code(400)
                    .msg("Not login! 未登录!")
                    .toString());
        }
        return null;// 当前 zuul 版本中,这个返回值没有使用
    }

集成了ribbon   默认启用负载均衡 zuul不推荐启用重试

zuul启用ribbon重试  添加spring-retry依赖 yml配置中添加zuul. retryable:true

集成了hystrix    有容错限流功能

zuul默认启用了Hystrix 可以直接写降级代码(容错) zuul会用自动配置类,对降级自动配置

         子类实现FallbackProvider接口

        添加@component

  

Hystrix限流熔断 

当流量过大,后台服务出现故障,可以断开后台服务的链路,等待后台服务器的恢复

断路器打开规则  m秒n次请求 ,z%失败执行降级代码  mnz是变量参数  mn为&的关系,当满足MN时才会继续检查失败率,当都满足时进行断流 (相当于if(m&n){z%})

半开状态  断路器打开一段时间后,进入半开状态 会尝试发送一次模拟客户端请求 ,成功则闭合断路,反之则继续断开.

Hystrix 监控 对熔断降级进行监控

Hystrix利用actuator暴露自己的监控日志数据

添加actuator依赖

 yml添加 

m.e.w.e.i="*" 暴露所有监控日志
m.e.w.e.i=health,bean,mappings 多种特殊指定日志
m.e.w.e.i=hhystrix.stream  用actuator暴露自己的监控日志

域名:端口号/actuator 查询监控日志 通过日志还能继续跳转查看

hystrix dashboard 监控表盘

新建项目

添加hystrix dashboard依赖

 yml配置 添加  服务器域名,服务名 

 启动类注解@enablehystrixdashboard   

访问http://localhost:4001/h'ystrix  输入框填写日志数据地址

先安装命令行apache压力测试工具          ab -n 2000 是请求数量  -c  50 并发请求数   服务路径 

tubine服务

新建spring模块:

添加eureka-client  turbine依赖   

yml配置 app-config:抓取的服务id的列表 为聚合后的数据命名 默认名为default   

 启动类注解@EnableTurbine

查询聚合

搭建配置中心

配置中心存储配置文件,可以存储不同环境的配置文件(服务名-xxx.yml),可以自定义,其中官方规定dev表示开发环境dev.yml   test表示测试环境test.yml  prod表示产品,生产环境prod.yml   服务名.yml是主配置文件 激活特定环境配置文件会和主配置合并加载

准备git仓库

创建配置中心文件config传入仓库

配置配置中心服务链接仓库

配置中心服务yml  git.uri=git远程仓库地址   search-paths=文件放在的文件夹路径

路径下可以设置分支default-label : master 这行和路径同缩进 分支默认为master 可以自己修改 

添加依赖 eureka-client config-sever    

启动类注解@EnableConfigServer

访问测试

链接配置中心获取配置

需要向配置中心获取配置的服务添加 bootstrap.yml  添加客户端依赖config-client

配置中心 通过消息服务rabbitmq向服务发送令牌,之后接收到令牌的服务从配置中心更新配置 

 rabbitmq消息服务器(消息中间件broker)   (具有解耦,流量消峰)

(还有Activemq RocketMq kafka tubemq) spring集成了rabbitmq 

rabbitmq可以创建virtual host 虚拟空间,用于隔离干扰 配置服务的配置中添加 virtual-host: 空间名

也可手动添加 rabbitmq控制台 admin->virtual hosts

用docker搭建rabbitmq消息服务器

工程中创建消息服务

添加maqp-client依赖

rabbitmq传入的消息不是永久存储,当消息被传出接收后,rabbitmq里的消息就会被删除,可以在消息发送时改变第三个属性由null变为MessageProperties.PERSISTENT_BASIC,这样消息就是永久了,但是需要队列是持久队列为根基,不然重启服务器,消息会随着队列一起消失

队列可以设置成持久队列和非持久队列如果设置成持久队列,队列的基本信息就会保存到磁盘,下次访问从磁盘中获取队列消息重新恢复队列,非持久储存在内存中,服务器重启就会消失.

消费方从队列获取的数据交给回调对象处理,通过以上回调对象的方法进行处理,其中数据被作为方法中的参数 传到message的位置,就是上面的方法中参数message就是接收的数据

消费方和队列为监听关系,监听队列,和监听消息 ,然后去接收消息

简单
package m1;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer {
    public static void main(String[] args) throws IOException, TimeoutException {
        //建立链接   接创建队列  创建回调对象  接收消息,收到的消息会传递到一个回调函数去处理
        ConnectionFactory f = new ConnectionFactory();
        f.setHost("192.168.64.140");
        f.setPort(5672);
        f.setUsername("admin");
        f.setPassword("admin");
        Connection con = f.newConnection();
        Channel c = con.createChannel();
        //创建队列hello-world 如果存在不会重复重建
        c.queueDeclare("hello-worldz",false,false,false,null);
        //创建回调对象
        DeliverCallback deliverCallback = new DeliverCallback() {

            public void handle(String consumerTag, Delivery message) throws IOException {
                byte[]a =message.getBody();
                String s =new String(a);
                System.out.println(s);
            }
        };
        CancelCallback cancelCallback = new CancelCallback() {

            public void handle(String consumerTag) throws IOException {

            }
        };
        //接收消息,收到的消息会传递到一个回调对象去处理
        //参数s:消息队列名称
        // b:autoAck-autoacknowledgment
        //     true自动确认 消息向消费者发送,服务器立即自动确认消息删除消息
        //     false手动确认 消息发出后,服务器会缓存消息,不删除,等待消费者发回一个确认消息(回执)才删除,
        //     如果消费者处理消息过程中崩溃或离线,服务器会回滚消息,等待重新发送 qos=1只在false的时候有效
        //deliverCallback这是自己创建的处理消息回调的对象
        //cancelCallback是自己创建的取消接收消息的回调对象
        c.basicConsume("hello-world",true,deliverCallback,cancelCallback);
    }
}
package m1;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import javax.xml.soap.SOAPConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory f = new ConnectionFactory();
        f.setHost("192.168.64.140");
        f.setPort(5672);
        f.setUsername("admin");
        f.setPassword("admin");
        Connection con = f.newConnection();//创建连接对象
        Channel c = con.createChannel();//创建连接通道
        //创建队列hello-world 如果存在不会重复重建
        //参数 s:队列名  b:是否是持久队列  b1:是否是排他队列,独占队列  b2:是否自动删除(没有消费者时)
        // map:其他参数属性(可以在这设置以键值对的方式存在的其他属性)
        // (s b b1 b2 map都是电脑自动生成的没有特定含义,只是代表相应位置,不必自己写)
        c.queueDeclare("hello-worldz",false,false,false,null);
        //发送消息
        //参数 s:交换机 ""是默认交换机 s1:消息队列名 basicProperties:消息的其他参数属性
        c.basicPublish("","hello-world",null,"Hello world".getBytes());
    }
}
工作
package m2;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer {
    public static void main(String[] args) throws IOException, TimeoutException {
        // 连接
        ConnectionFactory f = new ConnectionFactory();
        f.setHost("192.168.64.140"); // wht6.cn
        f.setPort(5672);
        f.setUsername("admin");
        f.setPassword("admin");
        Connection con = f.newConnection();
        final Channel c = con.createChannel();
        // 创建队列 hello-world,如果队列已经存在,不会重复创建
        c.queueDeclare("task_queue",true,false,false,null);

        // 创建回调对象
        DeliverCallback deliverCallback = new DeliverCallback() {
            public void handle(String consumerTag, Delivery message) throws IOException {
                byte[] a = message.getBody();
                String s = new Stri
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值