SpringCloud分布式微服务搭建(二)

这个例子主要是将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=40000
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  &

  

测试结果

[email protected]:~$ curl http://localhost:40000/provider/hello?name=ljq2
Hello world, port is:20003[email protected]:~$ curl http://localhost:40000/provider/hello?name=ljq3
Hello world, port is:20003[email protected]:~$ curl http://localhost:40000/provider/hello?name=ljq4
Hello world, port is:20003[email protected]:~$ curl http://localhost:40000/provider/hello?name=ljq5
Hello world, port is:20002[email protected]:~$ curl http://localhost:40000/provider/hello?name=ljq6
Hello world, port is:20002

原文地址:https://www.cnblogs.com/linjiaqin/p/10776395.html

时间: 2024-08-01 13:03:04

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

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

本例子主要使用了eureka集群作为注册中心来保证高可用,客户端来做ribbon服务提供者的负载均衡. 负载均衡有两种,第一种是nginx,F5这种集中式的LB,对所有的访问按照某种策略分发. 第二种是客户端知道所有的服务的地址,在客户端做负载均衡,客户端自己去发送. github地址:https://github.com/linjiaqin/scdemo 一. eureka注册中心的搭建 1.为了实现HA(高可用性),采用集群方式搭建,由mu01(192.168.0.100),cu01(192

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

本例子是一个springcloud的configserver,client例子 利用git存储各个服务的配置文件 server获取配置文件的仓库位置,并把server注册到eureka中,同时为了实现HA,多开几个server client通过server获得git的地址,运行时利用获得的git配置文件来配置服务自身. 这样子服务的配置修改更加方便 git上的配置文件仓库地址:https://github.com/linjiaqin/springcloud-config-repo 本例子代码:h

SpringCloud分布式微服务云架构 第五篇: 路由网关(zuul)(Finchley版本)

SpringCloud分布式微服务云架构 第五篇: 路由网关(zuul)(Finchley版本)在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,了解springcloud架构可以加求求:三五三六二四七二五九,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: 注意:A服务和B服务是可以相互调用的,并且配置服务也是注册到服务注册中心的. 在Spring Cloud微服务系统中,一种常见的负载均衡方

Springcloud分布式微服务多用户商城系统b2b2c-Spring Cloud常见问题

在使用Spring Cloud的过程中,难免会遇到一些问题.所以对Spring Cloud的常用问题做一些总结.需要JAVA Spring Cloud大型企业分布式微服务云构建的B2B2C电子商务平台源码:三五三六二四七二五九 一.Eureka常见问题 Eureka 注册服务慢 默认情况下,服务注册到Eureka Server的过程较慢.在开发或测试时,常常希望能够加速这一过程,从而提升工作效率. 该问题的原因及解决方案: 服务的注册涉及周期性心跳,默认30秒一次(通过客户端配置的service

SpringCloud分布式微服务b2b2c电子商务(二)Eureka(服务注册和服务发现基础篇)

一:Eureka简介 Eureka是Spring Cloud Netflix的一个子模块,也是核心模块之一.用于云端服务发现,一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移.了解springcloud架构可以加求求:三五三六二四七二五九,服务注册与发现对于微服务系统来说非常重要.有了服务发现与注册,你就不需要整天改服务调用的配置文件了,你只需要使用服务的标识符,就可以访问到服务.他的功能类似于dubbo的注册中心(register).服务发现:服务发现是微服务基础架构的

java版b2b2c社交电商spring cloud分布式微服务(二)Eureka(服务注册和服务发现基础篇)

一:Eureka简介 电子商务社交平台源码请加企鹅求求:叁五叁六贰四柒贰五九.   Eureka是Spring Cloud Netflix的一个子模块,也是核心模块之一.用于云端服务发现,一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移. 服务注册与发现对于微服务系统来说非常重要.有了服务发现与注册,你就不需要整天改服务调用的配置文件了,你只需要使用服务的标识符,就可以访问到服务.他的功能类似于dubbo的注册中心(register). 服务发现:服务发现是微服务基础架构

SpringCloud分布式微服务云架构 第一篇: 服务的注册与发现Eureka(Finchley版

一.spring cloud简介鉴于<史上最简单的Spring Cloud教程>很受读者欢迎再次我特意升级了一下版本目前支持的版本为Spring Boot版本2.0.3.RELEASE,Spring Cloud版本为Finchley.RELEASE. Finchley版本的官方文档如下http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html spring cloud 为开发人员提供了

SpringCloud分布式微服务云架构 第四篇:断路器(Hystrix)(Finchley版本)

在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用.为了保证其高可用,单个服务通常会集群部署.由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪.服务与服务之间的依赖性,故障会传播,了解springcloud架构可以加求求:三五三六二四七二五

SpringCloud分布式微服务b2b2c电子商务(一)构建第一个SpringBoot工程

spring boot 它的设计目的就是为例简化开发,开启了各种自动装配,你不想写各种配置文件,引入相关的依赖就能迅速搭建起一个web工程.它采用的是建立生产就绪的应用程序观点,优先于配置的惯例. 可能你有很多理由不放弃SSM,SSH,但是当你一旦使用了springboot ,你会觉得一切变得简单了,配置变的简单了.编码变的简单了,部署变的简单了,感觉自己健步如飞,开发速度大大提高了.了解springcloud架构可以加求求:三五三六二四七二五九,就好比,当你用了IDEA,你会觉得再也回不到Ec