这个例子主要是将zuul和eureka结合起来使用,zuul作为反向代理,同时起到负载均衡的作用,同时网关后面的消费者也作为服务提供者,同时提供负载均衡。

一.API网关(摘自百度)

API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。
API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。

二. 整体架构

(1)http://localhost:40000/provider/hello?name=ljq3经过zuul网关之后,由于zuul对路径映射

zuul.routes.api-a.path=/provider/**
zuul.routes.api-a.serviceId=ribbon-consumer
(2)把provider映射到ribbon-cunsumer这个服务上,zuul利用负载均衡的方式选一个服务地址,然后将路径替换,得到
http://localhost:40001/hello?name=ljq3
(3)ribbon-consummer再利用ribbon负载均衡选择一个provider,但是因为我在代码中只把地址传递,而没有传递参数,所以得到的url是
http://localhost:20003/ (4)github地址:https://github.com/linjiaqin/scdemo

三. zuul代码结构

这里把zuul的服务作为一个服务提供者去注册到eureka中,要使用这个注解表名是一个服务提供者@EnableEurekaClient

1.引导类

package com.ljq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean; @EnableZuulProxy
@SpringBootApplication
@EnableEurekaClient
//把zuul作为服务提供者到eureka注册
public class GatewayApplication { private static final Logger LOGGER = LoggerFactory.getLogger(GatewayApplication.class);
GatewayApplication(){
LOGGER.info("app init");
}
public static void main(String[] args) {
LOGGER.info("app start");
SpringApplication.run(GatewayApplication.class, args);
} }

2.配置文件

这里把的路径匹配规则是当访问的符合provider这个路径时,自动映射到serviceId上,去eureka找到serviceID的所有可用地址,负载均衡选取一个后替换成这个地址

spring.application.name=gateway-service-zuul
server.port=
eureka.client.serviceUrl.defaultZone=http://mu01:8761/eureka,http://cu01:8762/eureka,http://cu02:8763/eureka
zuul.routes.api-a.path=/provider/**
zuul.routes.api-a.serviceId=eureka-client-service-provider

3. beanconfig

package com.ljq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service; @Service
public class MyBaenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(MyBaenConfig.class);
MyBaenConfig(){
LOGGER.info("service init");
}
@Bean
public MyFilter myFilter() {
LOGGER.info("bean init");
return new MyFilter();
}
}

4. zuul的核心filter类,用来过滤请求

package com.ljq;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest; public class MyFilter extends ZuulFilter { private final Logger LOGGER = LoggerFactory.getLogger(MyFilter.class); MyFilter(){
LOGGER.info("filter init");
}
@Override
public String filterType() {
return "pre"; // 可以在请求被路由之前调用
} @Override
public int filterOrder() {
return 0; // filter执行顺序,通过数字指定 ,优先级为0,数字越大,优先级越低
} @Override
public boolean shouldFilter() {
return true;// 是否执行该过滤器,此处为true,说明需要过滤
} @Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest(); LOGGER.info("--->>> MyFilter {},{}", request.getMethod(), request.getRequestURL().toString()); String token = request.getParameter("name");// 获取请求的参数 if (StringUtils.isNotBlank(token)) {
ctx.setSendZuulResponse(true); //对请求进行路由
ctx.setResponseStatusCode(200);
ctx.set("isSuccess", true);
return null;
} else {
ctx.setSendZuulResponse(false); //不对其进行路由
ctx.setResponseStatusCode(400);
ctx.setResponseBody("parameter name is empty");
ctx.set("isSuccess", false);
return null;
}
} }

5.mvn spring-boot:run起来之后,就可以看到网关服务在eureka上注册了

curl http://localhost:40000/provider  可以看到负载均衡的效果

6.网关的默认路由规则

但是如果后端服务多达十几个的时候,每一个都这样配置也挺麻烦的,spring cloud zuul已经帮我们做了默认配置。

默认情况下,Zuul会代理所有注册到Eureka Server的微服务,

并且Zuul的路由规则如下:http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的serviceId/**会被转发到serviceId对应的微服务。

二 .Ribbon Consumer

这里的consummer不仅是服务消费者去后面拿取provider的内容,同时也作为一个服务提供者对外提供服务

1.引导类

@SpringBootApplication
@EnableDiscoveryClient
@EnableEurekaClient
public class ConsumerApplication { public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
} }

2.beanconfig类

package com.ljq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate; @Configuration
public class ljqConfig {
private static final Logger logger = LoggerFactory.getLogger(ljqConfig.class);
ljqConfig(){
logger.info("config init");
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
logger.info("restTemplate function");
return new RestTemplate();
}
}

3.controller

package com.ljq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; @RestController
public class ljqController {
private static final Logger logger = LoggerFactory.getLogger(ljqController.class);
ljqController(){
logger.info("controller init");
}
@Autowired
private RestTemplate restTemplate; //这里不写eureka的注册中心,而是写服务提供者的应用名
@GetMapping(value = "/hello")
public String hello(HttpServletRequest request){
logger.info("hello function");
logger.info(request.getPathInfo());
logger.info("--->>> consumer contorller {},{}", request.getMethod(), request.getRequestURL().toString()); String token = request.getParameter("name");// 获取请求的参数
logger.info(token); return restTemplate.getForEntity("http://eureka-client-service-provider/", String.class).getBody();
}
}

配置与上篇文章一致

spring.application.name=ribbon-consumer
server.port=30001
eureka.client.serviceUrl.defaultZone=http://mu01:8761/eureka,http://cu01:8762/eureka,http://cu02:8763/eureka

springboot的执行顺序

注解

三. provider

代码与上篇文章基本一直

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; @RestController
public class ljqController {
private final Logger logger = LoggerFactory.getLogger(ljqController.class);
@Value("${server.port}")
String port; @RequestMapping("/")
public String home(HttpServletRequest request){
logger.info(request.getPathInfo());
logger.info("--->>> consumer contorller {},{}", request.getMethod(), request.getRequestURL().toString()); String token = request.getParameter("name");// 获取请求的参数
logger.info(token);
return "Hello world, port is:" + port;
}
}

一键启动脚本

#首先开启eureka,上篇文章中我们把eureka放在集群上,并单独写了一个脚本了,这里不在赘述
#然后开启zuul
cd /home/linjiaqin/log_stream_platform/source/scdemo/gateway;
nohup mvn spring-boot:run > /dev/null 2>&1 &
#开两个ribbon-consumer
cd /home/linjiaqin/log_stream_platform/source/scdemo/consumer
nohup mvn spring-boot:run -Dserver.port=30001 > /dev/null 2>&1 &
nohup mvn spring-boot:run -Dserver.port=30002 > /dev/null 2>&1 &
#开启三个provider
cd /home/linjiaqin/log_stream_platform/source/scdemo/provider
nohup mvn spring-boot:run -Dserver.port=20001 > /dev/null 2>&1 &
nohup mvn spring-boot:run -Dserver.port=20002 > /dev/null 2>&1 &
nohup mvn spring-boot:run -Dserver.port=20003 > /dev/null 2>&1 &

  

测试结果

linjiaqin@linjiaqin-computer:~$ curl http://localhost:40000/provider/hello?name=ljq2
Hello world, port is:20003
linjiaqin@linjiaqin-computer:~$ curl http://localhost:40000/provider/hello?name=ljq3
Hello world, port is:20003
linjiaqin@linjiaqin-computer:~$ curl http://localhost:40000/provider/hello?name=ljq4
Hello world, port is:20003
linjiaqin@linjiaqin-computer:~$ curl http://localhost:40000/provider/hello?name=ljq5
Hello world, port is:20002
linjiaqin@linjiaqin-computer:~$ curl http://localhost:40000/provider/hello?name=ljq6
Hello world, port is:20002

SpringCloud分布式微服务搭建(二)的更多相关文章

  1. SpringCloud分布式微服务搭建(一)

    本例子主要使用了eureka集群作为注册中心来保证高可用,客户端来做ribbon服务提供者的负载均衡. 负载均衡有两种,第一种是nginx,F5这种集中式的LB,对所有的访问按照某种策略分发. 第二种 ...

  2. SpringCloud分布式微服务搭建(三)

    本例子是一个springcloud的configserver,client例子 利用git存储各个服务的配置文件 server获取配置文件的仓库位置,并把server注册到eureka中,同时为了实现 ...

  3. eclipse上springCloud分布式微服务搭建-干货

    一.创建maven父工程(pom) pom.xml如下: eureka: client: registerWithEureka:false fetchRegistry:false serviceUrl ...

  4. Thrift搭建分布式微服务(二)

    第二篇 连接池  连接池配置,请前往Thrift搭建分布式微服务(一)  下面要介绍的其实不是单一的连接池,应该说是连接池集合.因为它要管理多个Tcp Socket连接节点,每个服务节点都有设置了自己 ...

  5. Thrift搭建分布式微服务1

    Thrift搭建分布式微服务 一.Thrift是什么? 关于Thrift的基本介绍,参看张善友的文章Thrift简介. 二.为什么使用微服务? 在公司的高速发展过程中,随着业务的增长,子系统越来越多. ...

  6. Surging 分布式微服务框架使用入门

    原文:Surging 分布式微服务框架使用入门 前言 本文非 Surging 官方教程,只是自己学习的总结.如有哪里不对,还望指正. 我对 surging 的看法 我目前所在的公司采用架构就是类似与S ...

  7. [转载]Surging 分布式微服务框架使用入门

    前言 本文非 Surging 官方教程,只是自己学习的总结.如有哪里不对,还望指正. 我对 surging 的看法 我目前所在的公司采用架构就是类似与Surging的RPC框架,在.NET 4.0框架 ...

  8. 我的分布式微服务框架:YC-Framework

    YC-Framework官方文档:http://framework.youcongtech.com/ YC-Framework源代码:https://github.com/developers-you ...

  9. 基于docker 如何部署surging分布式微服务引擎

    1.前言 转眼间surging 开源已经有1年了,经过1年的打磨,surging已从最初在window 部署的分布式微服务框架,到现在的可以在docker部署利用rancher 进行服务编排的分布式微 ...

随机推荐

  1. Android自动化框架介绍

    随着Android应用得越来越广,越来越多的公司推出了自己移动应用测试平台.例如,百度的MTC.东软易测云.Testin云测试平台…….由于自己所在项目组就是做终端测试工具的,故抽空了解了下几种常见的 ...

  2. Selenium2Lib库之界面元素交互常用关键字实战

    5.1 Select Radio Button单选按钮关键字 按F5 查看Select Radio Button关键字的说明,如下图: Select Radio Button [ group_name ...

  3. Selenium2Lib库之操作浏览器相关的关键字实战

    1.1  操作浏览器相关的关键字 Selenium2Lib提供了与浏览器交互的关键词 1.1.1 Open Browser关键字 按F5 查看Open Browser关键字的说明,如下图: Open ...

  4. Python学习 Part6:错误和异常

    Python学习 Part6:错误和异常 两种不同类型的错误:语法错误和异常 1. 语法错误 语法错误,也被称作解析错误: >>> while True print('Hello w ...

  5. Python《学习手册:第二章-习题》

    什么是Python解释器? Python解释器是运行Python程序的程序. 什么是源代码? 源代码是为程序所写的语句:它包括文本文件(通常以.py为文件名结尾)的文件. 什么是字节码? 字节码是Py ...

  6. Maven安装和使用

    一.安   装 1.解压好后,添加系统环境变量 变量名:MAVEN_HOME 属性值:D:\apache-maven-3.3.3  //也就是解压的路径 path中添加:%MAVEN_HOME%\bi ...

  7. C++程序内存布局

      代码区(code area) 程序内存空间 全局数据区(data area) 堆区(heap area) 栈区(stack area) 一个由C/C++编译的程序占用的内存分为以下几个部分, 1) ...

  8. 巩固java(七)-----java反射机制

    一般而言,开发者社群说到动态语言,大致认同的一个定义是:"程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言".从这个观点看,Perl,Python,Ruby是动态语言, ...

  9. [Python接口自动化]从零开始学习python自动化(1):环境搭建

    第一步:安装python编译环境 安装python编译环境之前,必须保证已安装jdk哈,如果为安装,请参考https://jingyan.baidu.com/article/6dad5075d1dc4 ...

  10. Python常用算法(二)

    1.快速排序 过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小 一般选取第一个数作为关键数据k,我们要把比k小的所有数据移到它的左面,从后往前找第一个比它 ...