热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringCloud实现Zuul集群(负载均衡)

前言:

  1. 在微服务架构中,有一个组件可以说是必不可少的,那就是微服务网关,微服务网关处理了负载均衡,缓存,路由,访问控制,服务代理,监控,日志等。API网关在微服务架构中正是以微服务网关的身份存在。
  2. 一般在微服务架构中,网关都是部署多个服务的,以实现负载均衡和保证高可用。

一、使用 Nginx+Zuul 实现网关集群

1.互联网公司中网关都是集群         搭建集群: Nginx+Zuul 一主一备,或者轮询多个。
2.在微服务中,所有服务请求都会统一请求到Zuul网关上。

图示:
SpringCloud实现Zuul集群(负载均衡)
过程:客户端发送请求统一到Nginx上,在使用Nginx实现反向代理和负载均衡,采用轮询算法转发到网关上。

1.创建Eurek注册中心、会员服务、订单服务 (略)

搭建Zull集群前,应该对Eureka注册中心,以及创建SpringBoot项目应该有了解,这里就不一 一赘述了。
实际上创建会员服务、订单服务这一步可以省略,因为我们仅仅是为了演示Zuul网关的负载均衡效果。

会员服务配置:

#会员服务
server:
  port: 8082
spring:
  application:
    name: member-service    #服务名

#Eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/     #注册中心的地址

订单服务:

#订单服务
server:
  port: 8081
spring:
  application:
    name: order-service   #服务名

#Eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/      #注册中心地址

2. 创建Zuul服务

application.yml文件中配置 (Zull的配置生产时一般是放到配置中心中)

#配置Zuul端口
server:
  port: 81
spring:
  application:
    name: zull-gateway-service    #服务名
#Eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/    #注册中心地址
      
# 配置网关反向代理,例如访问/api-member/** 直接重定向到member-service服务,实现路由转发,隐藏服务的真实ip(服务都实在内网中)
#zull根据服务名,去Eureka获取服务真实地址,并通过本地转发,而且默认开启Ribbon实现负载均衡
#默认读取Eureka注册列表 默认30秒间隔  
zuul:
 routes:
   api-a: #会员服务网关配置
     path: /api-member/**   #访问只要是/api-member/ 开头的直接转发到member-service服务
     #服务名
     serviceId: member-service
   api-b: #订单服务网关配置
     path: /api-order/**
     serviceId: order-service

创建TokenFilet类继承ZuulFilter,在run方法中输入网关的端口,调用服务时方便查看Nginx转发到哪个网关

package com.example.zuul.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class TokenFilter extends ZuulFilter {
	//统计当前Zuul调用次数
    int count = 0;
    
	//获取Zuul服务端口号
    @Value("${server.port}")
    private String prot;
    
    /**
     * 指定该Filter的类型
     * ERROR_TYPE = "error";
     * POST_TYPE = "post";
     * PRE_TYPE = "pre";
     * ROUTE_TYPE = "route";
     */
    @Override
    public String filterType() {
        System.out.println("filterType()...");
        return "pre";
    }


    /**
     * 指定该Filter执行的顺序(Filter从小到大执行)
     * DEBUG_FILTER_ORDER = 1;
     * FORM_BODY_WRAPPER_FILTER_ORDER = -1;
     * PRE_DECORATION_FILTER_ORDER = 5;
     * RIBBON_ROUTING_FILTER_ORDER = 10;
     * SEND_ERROR_FILTER_ORDER = 0;
     * SEND_FORWARD_FILTER_ORDER = 500;
     * SEND_RESPONSE_FILTER_ORDER = 1000;
     * SIMPLE_HOST_ROUTING_FILTER_ORDER = 100;
     * SERVLET_30_WRAPPER_FILTER_ORDER = -2;
     * SERVLET_DETECTION_FILTER_ORDER = -3;
     */
    @Override
    public int filterOrder() {
        System.out.println("filterOrder()...");
        return 0;
    }

    /**
     * 指定需要执行该Filter的规则
     * 返回true则执行run()
     * 返回false则不执行run()
     */
    @Override
    public boolean shouldFilter() {
        System.out.println("shouldFilter()...");
        return true;
    }

    /**
     * 该Filter具体的执行活动
     */
    @Override
    public Object run() throws ZuulException {
        // 获取上下文
        //RequestContext currentCOntext= RequestContext.getCurrentContext();
        //HttpServletRequest request = currentContext.getRequest();
        //获取userToken
       // String userToken = request.getParameter("userToken");
        //System.out.println("userToken: "+userToken);
        //if (StringUtils.isEmpty(userToken)) {
            //不会继续执行调用服务接口,网关直接响应给客户端
            //currentContext.setSendZuulResponse(false);
            //currentContext.setResponseStatusCode(401);
           // currentContext.setResponseBody("userToken is Null");
           // return null;
       // }else if(!userToken.equals("10010")){
           // currentContext.setSendZuulResponse(false);
            //currentContext.setResponseStatusCode(401);
            //currentContext.setResponseBody("userToken is Error");
            //return null;
        //}
        // 否则正常执行业务逻辑,调用服务.....
        System.out.println("访问Zuul网关端口为:"+prot +"(total:"+ ( count++) +")");
        return null;

    }
}

启动两个Zuul服务,端口号分别为81和82

3. 下载Nginx服务器

这里演示使用Windows版本,Linux安装也很简单,后面操作都一样。
windows版下载地址:http://nginx.org/en/download.html
SpringCloud实现Zuul集群(负载均衡)
下载好后解压,进入conf目录找到nginx.conf文件打开,配置如下:

#配置上游服务器 集群,默认轮询机制
	upstream backServer{
		server 127.0.0.1:81;
		server 127.0.0.1:82;
	}
    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            ##root   html;
			#指定上游负载均衡服务器
			proxy_pass http://backServer/;
            index  index.html index.htm;
        }
    }

双击nginx.exe启动Nginx服务器

二、 测试

浏览器访问http://localhost/api-member
我们可以看到两个网关分别输出了日志,实现了负载均衡

SpringCloud实现Zuul集群(负载均衡)SpringCloud实现Zuul集群(负载均衡)
我们看到访问的次数不一样,这其实和使用Google浏览器有关,可以换其他浏览器试试。

三、补充

Nginx和网关的区别在什么地方?

  1. 都可以实现反向代理。
  2. 都可以实现负载均衡,Nginx是服务端负载均衡,Zuul是本地负载均衡。

Nginx也可以实现网关,为什么不用Nginx实现网关呢?
        因为微服务网关是针对整个微服务实现统一的请求拦截,网关基本上都是采用自己熟悉的语言开发的,目的方便易学。

网关的作用:

  1. 网关对所有服务会话进行拦截
  2. 网关安全控制、统一异常处理、xxs、sql注入
  3. 权限控制、黑名单和白名单、性能监控、日志打印等

推荐阅读
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 2018深入java目标计划及学习内容
    本文介绍了作者在2018年的深入java目标计划,包括学习计划和工作中要用到的内容。作者计划学习的内容包括kafka、zookeeper、hbase、hdoop、spark、elasticsearch、solr、spring cloud、mysql、mybatis等。其中,作者对jvm的学习有一定了解,并计划通读《jvm》一书。此外,作者还提到了《HotSpot实战》和《高性能MySQL》等书籍。 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 熟练掌握Spring Cloud,终于成为Java工程师的面试门槛 ... [详细]
  • 1.脚本功能1)自动替换jar包中的配置文件。2)自动备份老版本的Jar包3)自动判断是初次启动还是更新服务2.脚本准备进入ho ... [详细]
  • [翻译]微服务设计模式5. 服务发现服务端服务发现
    服务之间需要互相调用,在单体架构中,服务之间的互相调用直接通过编程语言层面的方法调用就搞定了。在传统的分布式应用的部署中,服务地 ... [详细]
author-avatar
Pissa_lo
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有