失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > eureka组件服务集群 feign远程调用 生产者服务集群 ribbon组件(负载均衡) hystrix

eureka组件服务集群 feign远程调用 生产者服务集群 ribbon组件(负载均衡) hystrix

时间:2021-03-20 21:10:15

相关推荐

eureka组件服务集群 feign远程调用 生产者服务集群 ribbon组件(负载均衡) hystrix

一、搭建Eureka服务集群

1、创建和一个父module(用于依赖管理)

a、 配置pom文件

<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.gec</groupId><artifactId>springcloudparent</artifactId><packaging>pom</packaging><version>1.0-SNAPSHOT</version><modules><module>eureka-server</module><module>provider-8801</module><module>provider-8802</module><module>provider-8803</module><module>consumer</module><module>consumer-feign</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.14.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><!--Springcloud的依赖库文件版本的锁定--><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement></project>

2、创建三个eureka server的module(此处仅详细列出一台服务的配置)

b、 配置pom文件

<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><parent><artifactId>eureka-parent</artifactId><groupId>com.gec</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>eureka-server</artifactId><dependencies><!--配置eureka依赖库组件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency></dependencies></project>

c、 配置全局配置文件application.yml

spring:application:name: eureka-serverserver:port: 7001eureka:instance:hostname: client:service-url:defaultZone: :7002/eureka/,:7003/eureka/#本身就是注册中心,不需要注册register-with-eureka: false#本身就是注册中心,不需要获取注册信息fetch-registry: false

d、 全局配置文件截图说明

e、 eureka-server集群后的另外两台配置yml截图,其余部分与第一台server的代码相同

第二台:

f、 第三台

g、 编写启动类

package com.gec;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.flix.eureka.server.EnableEurekaServer;@SpringBootApplication@EnableEurekaServerpublic class ServerApp7001 {public static void main(String[] args) {SpringApplication.run(ServerApp7001.class, args);}}

h、 验证集群是否配置成功,在浏览器中输入::7001或:7002或:7003验证是否成功

* 当eureka服务集群时,未全部启动所有参与集群的服务时,会报以下异常:com.sun.jersey.api.client.ClientHandlerException: org.apache.http.conn.ConnectTimeoutException: Connect to :7003 timed out……,当集群的全部服务都启动完后即可,也可增长服务连接超时时间,来消除此异常,异常截图如下:* ![在这里插入图片描述](https://img-/000455873.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjE4MzU2MQ==,size_16,color_FFFFFF,t_70)* 成功界面截图:![在这里插入图片描述](https://img-/000832570.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjE4MzU2MQ==,size_16,color_FFFFFF,t_70)

二、创建公共模块

1、创建公共模块(普通模块,通常就是创建bean,pom文件不用配置)

a、 编写一个user的pojo

package com.gec.user.pojo;import java.io.Serializable;public class UserBean implements Serializable {private String userName;private Integer age;public UserBean() {}public UserBean(String userName, Integer age) {this.userName = userName;this.age = age;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "UserBean{" +"userName='" + userName + '\'' +", age=" + age +'}';}}

三、生产者模块

1、生产者模块(一)

a、 配置pom文件

<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><parent><artifactId>eureka-parent</artifactId><groupId>com.gec</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>provider-8801</artifactId><dependencies><!--引入公共模块--><dependency><groupId>com.gec</groupId><artifactId>user-common</artifactId><version>1.0-SNAPSHOT</version></dependency><!--配置eureka的客户端--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--配置web的starter--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies></project>

b、 编写application.yml配置文件

spring:application:name: user-serviceserver:port: 8801#eureka的基本信息eureka:instance:hostname: 127.0.0.1client:service-url:defaultZone: :7001/eureka/,:7002/eureka/,:7003/eureka/#它本身是一个普通的服务,需要在eureka-server注册register-with-eureka: true#需要获取注册信息fetch-registry: true

c、 配置文件截图说明:

d、 编写controller

@RestControllerpublic class UserController {@RequestMapping("/getUser")public User getUser(){User user = new User("张三", "123");return user;}@RequestMapping("/addUser")public int addUser(@RequestBody User user){System.out.println("插入user成功:"+user);return 1;}@RequestMapping("/getUserById/{id}")public User alterUser(@PathVariable int id){if (id == 1){return new User("小泽", "12345");}else if (id == 2){return new User("小苍", "23456");}else if (id == 3){return new User("小野", "34567");}else {return new User("小罗", "45678");}}}

e、 编写启动类

package com.gec;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.flix.eureka.EnableEurekaClient;@SpringBootApplication@EnableEurekaClientpublic class ProviderApp8801 {public static void main(String[] args) {SpringApplication.run(ProviderApp8801.class, args);}}

2、生产者模块(二),直接复制生产者模块(一),并按照以下操作步骤进行

a、 导入复制好的模块,删除之前之前模块的idea配置文件和target文件夹,并将其设置为maven项目

b、 修改当前模块的pom文件

c、 修改父模块的pom文件

d、 修改配置文件application.yml;只需修改端口号不同即可,其余不改,服务名需相同,是服务集群的关键。

3、生产者其他模块操作步骤同上。

四、消费者模块

1、消费者Feign客户端,负载均衡

a、 pom文件

<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><parent><artifactId>eureka-parent</artifactId><groupId>com.gec</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>consumer-feign</artifactId><dependencies><!--引入自建公共模块--><dependency><groupId>com.gec</groupId><artifactId>user-common</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--支持feign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency></dependencies></project>

b、 编写配置文件application.yml

spring:application:name: user-feignserver:port: 9999eureka:client:service-url:defaultZone: :7001/eureka/,:7002/eureka/,:7003/eureka/#它本身是一个普通的服务,需要在eureka-server注册register-with-eureka: true#需要获取注册信息fetch-registry: true

c、 编写service接口(无需其实现类)

package com.gec.service;import com.gec.pojo.User;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;//value为指定微服务的应用访问名称(提供方)// 默认具备负载均衡功能(轮询)@FeignClient(value = "USER-SERVICE", fallback = UserServiceFallback.class)public interface UserService {//此接口无需实现,由框架帮实现,类似mybatis中的mapper//value为提供方的访问方式,method也需要和提供方保持一致@GetMapping("/getUser")User getUser();@RequestMapping("/addUser")int addUser(User user);@RequestMapping("/getUserById/{id}")User getUserById(@PathVariable int id);// 测试负载均衡方法@GetMapping("/getPort")String getPort();}

e、 编写控制器

package com.gec.controller;import com.gec.pojo.User;import com.gec.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class UserController {@AutowiredUserService userService;@RequestMapping("/getUser")public User getUser(){return userService.getUser();}@RequestMapping("/addUser")public String addUser(){User user = new User("lisi", "123");Integer isSuccess = userService.addUser(user);if (isSuccess == 1){return "添加user成功";}else {return "添加失败";}}@RequestMapping("/getUserById/{id}")public User getUserById(@PathVariable int id){User user = userService.getUserById(id);return user;}@GetMapping("/getPort")public String getPort(){return userService.getPort();}}

f、 编写配置负载均衡的类,可不配,则默认采用轮询负载均衡策略

package com.gec.config;import flix.loadbalancer.IRule;import flix.loadbalancer.RandomRule;import flix.loadbalancer.RoundRobinRule;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** 负载均衡配置类,包含七种策略:* 1.RoundRobinRule(默认) --轮询策略* 2.RandomRule --随机策略* 3.AvailabilityFilteringRule --根据并发数* 4.WeightedResponseTimeRule --根据响应时间* 5.RetryRule --重试效果* 6.BestAvailableRule* 7.ZoneAvoidanceRule*/@Configurationpublic class LoadBalanceConfig {/* @Beanpublic IRule setLoadBalancer(){//轮询策略return new RoundRobinRule();}*/@Beanpublic IRule setLoadBalancer(){//随机策略return new RandomRule();}}

g、 编写启动类

package com.gec;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.flix.eureka.EnableEurekaClient;import org.flix.hystrix.EnableHystrix;import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication@EnableEurekaClient@EnableFeignClients public class FeignClientApp {public static void main(String[] args) {SpringApplication.run(FeignClientApp.class, args);}}

2、启动完所有服务后,查看服务注册列表,并调用消费端的handler访问测试

a、 查看服务注册列表

b、访问测试

3、配置hystrix断路器

a、 断路器作用:由于网络原因或者自身服务的原因,导致服务可能会产生故障或者是不可用,如果此服务生产故障,就会导致请求此服务的线程阻塞,如果涉及大量的线程请求阻塞,就进一步导致容器产生瘫痪,也会导致其它服务不可用,就会产生“雪崩效应”。因此需要一种机制处理,此机制就是“断路器”。

a、为什么会有Hystrix组件

由于网络原因或者自身服务的原因,导致服务可能会产生故障或者是不可用,如果此服务生产故障,就会导致请求此服务的线程阻塞,如果涉及大量的线程请求阻塞,就进一步导致容器产生瘫痪,也会导致其它服务不可用,就会产生“雪崩效应”。因此需要一种机制处理,此机制就是“断路器”

2、Hystrix的特征

触发熔断条件 当请求服务失败的次数超过一定的比例(默认50%),熔断就会生效熔断默认持续时间5秒,5秒之后它就会从(开路状态—》半开路状态)处于半开路状态,判断下一次请求,是否成功,如果成功,则切回到闭路状态 降级服务 当熔断机制启动,此服务不可用,直接返回失败,它会有一个响应机制处理:调用降级服务的响应方法实现

3、如何实现熔断降级机制

a、原pom文件中新增依赖

<!--支持断路器--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>

b、application.yml文件中开启支持断路器

#开启支持熔断feign:hystrix:enabled: true

c、 编写回退类UserServiceFallback,用于访问服务出现异常时的降级处理

package com.gec.service;import com.gec.pojo.User;import org.ponent;@Componentpublic class UserServiceFallback implements UserService {@Overridepublic User getUser() {return new User("熔断啦", "111111111");}@Overridepublic int addUser(User user) {return 0;}@Overridepublic User getUserById(int id) {return new User("熔断啦", "888888888");}@Overridepublic String getPort() {return "发生了熔断";}}

c、 在原service接口中指定降级的处理类(回退类)

// fallback指定一个回退类(熔断机制),@FeignClient(value = "USER-SERVICE", fallback = UserServiceFallback.class)public interface UserService {……}

d、启动类中新增使能hystrix注解

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

4、依赖隔离

a、简介

可以根据服务划分出多个线程池处理,一般情况下,多个服务应用同一个线程池,如果一个服务不可用或者是阻塞,导致线程池的连接资源不足,这样子也会导致其它的服务不可用,因此可以使用依赖隔离解决此问题,根据服务划分多个线程池处理。举例:一个应用服务器中部署了服务A和服务B,默认情况下,此两服务共享同一容器中的线程池,当服务A出现了异常后,会导致出现线程阻塞,没有任何处理的情况下,阻塞线程会随着请求服务A的数量递增而递增,最终耗尽该容器的线程池中的线程,致使发送给正常的服务B也会无响应。

b、代码实现(给服务中,根据id查找用户的服务为例)

创建实现线程池的类

package com.gec.pool;import com.gec.pojo.User;import com.gec.service.UserService;import flix.hystrix.*;// HystrixCommand<User>此处的泛型类型与,自定义的UserService中根据id查找用户的返回值类型相同,因为此类的作用就是要给UserService中根据id查找用户的那个方法划分一个独立的线程池运行public class PoolCommandA extends HystrixCommand<User> {private UserService userService;private Integer id;public PoolCommandA(UserService userService) {super(Setter.withGroupKey(//服务分组HystrixCommandGroupKey.Factory.asKey("PoolCommandAGroup")).andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("PoolCommandAPool"))//线程池配置//withCoreSize:线程池大小为10//withKeepAliveTimeMinutes:线程存活时间15秒//withQueueSizeRejectionThreshold:队列等待的阈值为100,超过100执行拒绝策略.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(10).withKeepAliveTimeMinutes(3).withMaxQueueSize(10).withQueueSizeRejectionThreshold(10000))//线程池隔离.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)));this.userService=userService;}public void setUserService(UserService userService) {this.userService=userService;}public void setId(Integer id) {this.id = id;}/*线程池的任务方法执行*/@Overrideprotected User run() {System.out.println("PoolCommandAPool thread id="+Thread.currentThread().getId());//执行UserService中根据id查找用户的那个方法User user=this.userService.getUserById(id);return user;}}

创建一个service接口PoolCommandAUserService

package com.gec.service;import com.gec.pojo.User;public interface PoolCommandAUserService {//根据id查找用户,方法名不一定要与UserService中的方法名相同User getUserById(int id);}

创建一个类实现PoolCommandAUserService接口

package com.gec.service.impl;import com.gec.pojo.User;import com.gec.pool.PoolCommandA;import com.gec.service.PoolCommandAUserService;import com.gec.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.concurrent.ExecutionException;import java.util.concurrent.Future;/*** 此类用于体现hystrix依赖隔离*/@Servicepublic class PoolCommandAUserServiceImpl implements PoolCommandAUserService {@AutowiredUserService userService;@Overridepublic User getUserById(int id) {// 启动线程池PoolCommandA poolCommandA = new PoolCommandA(userService);poolCommandA.setId(id);// 执行线程池Future<User> future = poolCommandA.queue();try {User user=future.get();return user;} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}return null;}}

在原来的控制器中调用此方法

@RestControllerpublic class UserController {@AutowiredUserService userService;@AutowiredPoolCommandAUserService poolCommandAUserService;……@RequestMapping("/getUserByIdPool/{id}")public User getUserByIdPoolCommand(@PathVariable int id){User user = poolCommandAUserService.getUserById(id);return user;}}

重启消费者服务,并测试

五、Zuul网关模块

1、简介

在分布式系统系统中,有商品、订单、用户、广告、支付等等一大批的服务,前端怎么调用呢?和每个服务一个个打 交道?这显然是不可能的,这就需要有一个角色充当所有请求的入口,这个角色就是服务网关(API gateway)

2、优点

监控各个微服务统一认证处理减少客户端与各个微服务的交互次数

3、什么是ZUUL

它就是一个网关它其实就是微服务一道门 服务路由负载均衡权限控制 它是Netflix的组件

4、配置使用ZUUL

a、配置pom文件

<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><parent><artifactId>eureka-parent</artifactId><groupId>com.gec</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>zuul</artifactId><dependencies><!--配置eureka的客户端--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--支持zuui组件网关--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId></dependency></dependencies></project>

b、配置全局配置文件application.yml

spring:application:name: zuul-demoserver:port: 10000eureka:instance:hostname: 127.0.0.1client:service-url:defaultZone: :7001/eureka/,:7002/eureka/,:7003/eureka/register-with-eureka: truefetch-registry: true# 配置服务路由zuul:routes:api-user-provider: # 自定义的路由path: /api-user-provider/** # 自定义的路由的访问路径serviceId: user-service # 自定义的路由的访问路径所访问的真实服务api-user-consumer:path: /api-user-consumer/**serviceId: user-feign

c、编写启动类

package com.gec;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.flix.zuul.EnableZuulProxy;@SpringBootApplication@EnableZuulProxypublic class ZuulApp {public static void main(String[] args) {SpringApplication.run(ZuulApp.class, args);}}

d、启动服务测试

e、网关的过滤器类型

pre 可以在请求被路由之前调用。适用于身份认证的场景,认证通过后再继续执行下面的流程 route 在路由请求时被调用。适用于灰度发布场景,在将要路由的时候可以做一些自定义的逻辑。 post 在 route 和 error 过滤器之后被调用。这种过滤器将请求路由到达具体的服务之后执行。适用于需要添加响应头,记录响应日志等应用场景。 error 处理请求时发生错误时被调用。在执行过程中发送错误时会进入 error 过滤器,可以用来统一记录错误信息

f、网关的过滤器配置

创建一个过滤器类

package com.gec.filter;import flix.zuul.context.RequestContext;import flix.zuul.exception.ZuulException;import org.flix.zuul.filters.support.FilterConstants;import org.ponent;import javax.servlet.http.HttpServletRequest;@Componentpublic class ZuulFilter extends flix.zuul.ZuulFilter {/** 指明过滤器类型* 它是一个PRE过滤器* */@Overridepublic String filterType() {return FilterConstants.PRE_TYPE;}/** 同一个过滤器类型的执行顺序(例如可能会有两个前置过滤器)* */@Overridepublic int filterOrder() {return 1;}/** 是否作拦截处理* */@Overridepublic boolean shouldFilter() {return true;}/** 编写过滤器的业务逻辑处理* */@Overridepublic Object run() throws ZuulException {RequestContext context= RequestContext.getCurrentContext();//获取http的request对象HttpServletRequest request=context.getRequest();//获取请求参数:tokenString token=request.getParameter("token");System.out.println("zuul filter token="+token);//token如果有数据,并且等于1234,则允许访问,否则拦截处理if(token!=null && token.equals("1234")){return null;}else {//如何实现拦截处理RequestContext ctx = RequestContext.getCurrentContext();//设置为false:不再转发请求到目标服务ctx.setSendZuulResponse(false);ctx.set("sendForwardFilter.ran", true);ctx.setResponseBody("token error");return null;}}}

重启服务,并测试

eureka组件服务集群 feign远程调用 生产者服务集群 ribbon组件(负载均衡) hystrix组件(断路器) zuul(网关路由)

如果觉得《eureka组件服务集群 feign远程调用 生产者服务集群 ribbon组件(负载均衡) hystrix》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。