文章仅作为本人学习笔记,有个人理解,也有参考及摘录各路大神的文章或者视频
。
为什么会有服务注册中心这个东西出现,下面就来说一下。
原本的项目之间的调用如下:
看着没什么要紧的,如果随着业务量的增加,系统也在增加,系统之间的调用可能就是下面酱紫的:
看着还凑合吧,如果系统有十几个甚至二三十个呢,全都是调用关系的连线,任何一个项目的修改都会导致其他相关联的好几个项目都跟着重启,很麻烦,而且容易出错。通过服务中心来获取服务你不需要关注你调用的项目IP地址,由几台服务器组成,每次直接去服务中心获取可以使用的服务去调用既可。
如果使用服务注册中心的话,拿项目A调用项目B,项目B调用项目C来说,如下图:
项目之间没有了直接调用。其实有点像企业服务总线的功能。公司内部可以使用服务注册中心,但是与外公司系统对接时,还是需要一个类似于服务注册中心的系统存在的,也就是企业服务总线。
Spring Cloud封装了Netflix公司开发的Eureka模块来是实现服务注册与发现。Eureka Server作为服务注册功能的服务器,是服务注册中心,而其他的微服务则使用Eureka的客户端连接到Eureka Server,并维持心跳连接。这样的话维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。
Eureka由两个组件组成:Eureka服务器和Eureka客户端
。Eureka服务器用作服务注册中心,Eureka客户端是一个java客户端。如下图:
上图描述了Eureka的基本架构,由3个角色构成,跟zookeeper是一样的。
1).Eureka Server
2).Service Provider
3).Service Consumer
服务启动后向Eureka Server注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址(即:服务应用名,yaml配置文件中spring.application.name的值),然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。
当服务注册中心Eureka Server检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为DOWN状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。
服务提供者在启动后,周期性(默认30秒)向Eureka Server发送心跳,以证明当前服务是可用状态。Eureka Server在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例。
项目父工程统一管理版本添加如下依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Finchley.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
启动类添加@EnableEurekaServer
注解
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/*
* @Author 友野浩二
* @Description // eureka服务注册中心(Finchley版本), eureka-server
* 启动项目后,在浏览器地址栏输入application.properties中配置的eureka.client.service-url地址,就可以查看eureka注册中心
**/
@SpringBootApplication
@EnableEurekaServer
@Slf4j
public class JeresServerApplication {
public static void main(String[] args) {
SpringApplication.run(JeresServerApplication.class, args);
log.info("<<<<======== Tong Stand-Lone Eureka Server Started ========>>>>");
}
}
1).bootstrap.properties
# bootstrap.yml(bootstrap.properties):用来程序引导时执行,应用于更加早期配置信息读取,如可以使用来配置application.yml中使用到参数等
# bootstrap.yml 先于 application.yml 加载
# 应用名
spring.application.name=tong-jeres-server
2).application.properties
# application.yml(application.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=8000
# 实例主机名称
eureka.instance.hostname=127.0.0.1
# ==================================================
# 在默认情况下erureka server也是一个eureka client ,必须要指定一个 server。
# 通过eureka.client.registerWithEureka:false和fetchRegistry:false来表明自己是一个eureka server.
# 表示是否将自己注册到Eureka Server
eureka.client.register-with-eureka=false
# 表示是否从Eureka Server获取注册信息
eureka.client.fetch-registry=false
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 指定单台机器(集群多个地址可使用 , 分隔)
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
启动成功后,在浏览器地址栏输入http://127.0.0.1:8000可以看到如下图:
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
启动类中添加@EnableDiscoveryClient
或@EnableDiscoveryClient
(两者的区别见启动类的注释)
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @Author 友野浩二
* @Description eureka服务提供者
*
*
* 服务发现@EnableDiscoveryClient 和 @EnableEurekaClient的区别: 用法基本一致。
* spring cloud中discovery service有许多种实现(eureka、consul、zookeeper等)。
* @EnableDiscoveryClient 基于spring-cloud-commons;@EnableEurekaClient基于spring-cloud-netfix。
* 简单说,如果选用的服务注册中心是eureka,那么就推荐@EnableEurekaClient,如果是其他注册中心,那么推荐使用@EnableDiscoveryClient。
* @EnableEurekaClient 的使用场景较为单一。
*
*/
@SpringBootApplication
// 服务提供者启动类中添加@EnableDiscoveryClient或者@EnableEurekaClient注解,使用注解后,项目就具有了服务注册的功能。
//@EnableDiscoveryClient
@EnableEurekaClient
@Slf4j
public class JeresProviderApplication {
public static void main(String[] args) {
SpringApplication.run(JeresProviderApplication.class, args);
log.info("<<<<======== Tong Stand-Lone Eureka Provider Started ========>>>>");
}
}
1).bootstrap.properties
# bootstrap.yml(bootstrap.properties):用来程序引导时执行,应用于更加早期配置信息读取,如可以使用来配置application.yml中使用到参数等
# bootstrap.yml 先于 application.yml 加载
# 应用名: 指定微服务的应用名,后续在调用的时候只需要使用该名称就可以进行服务的访问.
spring.application.name=tong-jeres-provider
2).application.properties
# application.yml(application.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=8001
# 实例主机名称
eureka.instance.hostname=127.0.0.1
# ==================================================
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 多个地址可使用 , 分隔
# 对应服务注册中心的配置内容,指定服务注册中心的位置。即eureka-server的配置内容。
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:8000/eureka/
提供loveranswer服务
package cn.buddha.jeres.provider.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author 友野浩二
* @Description 服务提供者测试
*/
@RestController
@Slf4j
public class TongController {
// http://127.0.0.1:8001/loveanswer?requestName=shihao
@RequestMapping(method = RequestMethod.GET, value = "/loveanswer")
public String loveAnswer(@RequestParam(value = "requestName") String requestName) {
log.info("Do you love me ?");
if ("shihao".equals(requestName)) {
return "YES! I LOVE YOU!!!";
}
return "NO!";
}
}
1). 成功启动后,可以在服务注册中心类的日志中看到如下log日志
INFO 8672 --- [nio-8000-exec-3] c.n.e.registry.AbstractInstanceRegistry : Registered instance TONG-JERES-PROVIDER/shihao:tong-jeres-provider:8001 with status UP (replication=false)
2). 在注册中心的页面也可以看到TONG-JERES-PROVIDER服务。
3). 为了验证loveranswer这个restful服务是否好着呢,地址栏输入http://127.0.0.1:8001/loveranswer?requestName=shihao
可以看到服务时好着的,防止后面服务消费者使用报错的时候太麻烦找错。
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @Author 友野浩二
* @Description 服务消费者
*
* @EnableFeignClients : 启用feign进行远程调用
* Feign是一个声明式Web Service客户端,使用Feign能让编写Web Service客户端更加简单。
* 使用方法: 定义一个接口,然后在上面添加注解。同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。
* Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。
*
*/
@SpringBootApplication
@EnableFeignClients
@Slf4j
public class JeresConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(JeresConsumerApplication.class, args);
log.info("<<<<======== Tong Stand-Lone Eureka Consumer Started ========>>>>");
}
}
1).bootstrap.properties
# bootstrap.yml(bootstrap.properties):用来程序引导时执行,应用于更加早期配置信息读取,如可以使用来配置application.yml中使用到参数等
# bootstrap.yml 先于 application.yml 加载
# 应用名
spring.application.name=tong-jeres-consumer
2).application.properties
# application.yml(application.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=8002
# 实例主机名称
eureka.instance.hostname=127.0.0.1
# ==================================================
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 多个地址可使用 , 分隔
# 对应服务注册中心的配置内容,指定服务注册中心的位置。即eureka-server的配置内容。
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:8000/eureka/
@FeignClient
注解的 name属性:绑定的远程服务名(即服务提供者bootstrap.properties中配置的spring.application.name)
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @Author 友野浩二
* @Description // feign调用实现
*
* 使用@FeignClient注解来指定这个接口所要调用的服务名称,接口中定义的各个函数使用 Spring MVC 的注解就可以来绑定服务提供方的 REST 接口。
* 【注意】: 此类中的方法和远程服务中contoller中的方法名和参数需保持一致。
*
*/
@FeignClient(name = "tong-jeres-provider")
public interface TongFeign {
/*
* 将远程服务http://tong-eureka-provider/loveanswer映射为一个本地Java方法调用。
**/
@RequestMapping(method = RequestMethod.GET, value = "/loveanswer")
public String loveAnswer(@RequestParam(value = "requestName") String requestName);
}
import cn.buddha.jeres.consumer.feign.TongFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author 友野浩二
* @Description 服务消费者controller测试类
*/
@RestController
@Slf4j
public class ConsumerController {
// 通过注解@Autowired使用定义feign的客户端
@Autowired
private TongFeign tongFeign;
@RequestMapping(method = RequestMethod.GET, value = "/client")
public String consumerHello(@RequestParam(name = "lover") String lover) {
log.info("ConsumerController.consumerHello starting...");
// 这里的使用本地Java API的方式调用远程的Restful接口
String tongProvider = this.tongFeign.loveAnswer(lover);
return "通过feign调用远程服务tong-eureka-provider的restful接口/loveanswer的结果: ".concat(tongProvider);
}
}
浏览器地址栏输入http://127.0.0.1:8002/client?lover=shihao
可以看到响应结果,依然成功了。
原因:
服务消费者本地缓存了服务提供者的地址
,即使Eureka Server宕机,也不会影响服务之间的调用,但是一旦新服务上线,已经在缓存在本地的服务提供者不可用了,服务消费者也无法知道,所以保证Eureka Server的高可用还是很有必要的。
在分布式系统中,任何的地方存在单点,整个体系就不是高可用的,Eureka 也一样,也要以集群的方式对外提供服务。【此处可以看一下zookeeper注册中心的paxos算法】
同 3.1.1
同 3.1.2
1).bootstrap.properties
spring.application.name=tong-jerec-server
2).application.properties
在Eureka Server集群时,需要部署多个节点,则需要同一个项目使用不同的配置。so,在本案例中使用JerecServerApplication一个项目通过不同的启动参数来启动占用不同端口的3个Server服务,来模拟Eureka集群。
包含以下3个文件:
A. application-server1.properties
# application.yml(application-server1.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=9001
# 2- eureka配置
# 实例主机名称
eureka.instance.hostname=eurekaServer1
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 指定集群机器(多个地址可使用 , 分隔),配置对方的地址作为Eureka Client进行相互注册
eureka.client.service-url.defaultZone=http://eurekaServer2:9002/eureka/,http://eurekaServer3:9003/eureka/
# 关闭自我保护机制
eureka.server.enable-self-preservation=false
B. application-server2.properties
# application.yml(application-server2.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=9002
# 2- eureka配置
# 实例主机名称
eureka.instance.hostname=eurekaServer2
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 指定集群机器(多个地址可使用 , 分隔),配置对方的地址作为Eureka Client进行相互注册
eureka.client.service-url.defaultZone=http://eurekaServer1:9001/eureka/,http://eurekaServer3:9003/eureka/
# 关闭自我保护机制
eureka.server.enable-self-preservation=false
C. application-server3.properties
# application.yml(application-server3.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=9003
# 2- eureka配置
# 实例主机名称
eureka.instance.hostname=eurekaServer3
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 指定集群机器(多个地址可使用 , 分隔),配置对方的地址作为Eureka Client进行相互注册
eureka.client.service-url.defaultZone=http://eurekaServer1:9001/eureka/,http://eurekaServer2:9002/eureka/
# 关闭自我保护机制
eureka.server.enable-self-preservation=false
可以看到server1、server2、server3三个文件中配置的端口号不同,hostname也不同(hostname需要在hosts文件中进行配置。Windows在C:\Windows\System32\drivers\etc\hosts,修改完后打开cmd输入ipconfig /flushdns才可以是其生效;Linux在/etc/hosts[需要root权限])。
com.sun.jersey.api.client.ClientHandlerException: org.apache.http.conn.ConnectTimeoutException: Connect to eurekaServer3:9003 timed out
正常启动后的日志如下:
Registered instance TONG-JEREC-SERVER/shihao:tong-jerec-server:9001 with status UP (replication=true)
Registered instance TONG-JEREC-SERVER/shihao:tong-jerec-server:9002 with status UP (replication=true)
Registered instance TONG-JEREC-SERVER/shihao:tong-jerec-server:9003 with status UP (replication=true)
可以看到注册成功了,我们再打开浏览器看一下 http://127.0.0.1:9001
根据图可以看出server1的注册中心DS Replicas已经有了server2、server3的相关配置信息,并且出现在available-replicas中。
高可用性验证:
我们手动停止server3,过几分钟来观察,发现server3就会移动到unavailable-replicas一栏中,而且eureka上注册的实例已经没有了server3,表示server3不可用。
同3.2.1
桶3.2.2
1).bootstrap.properties
# 应用名: 指定微服务的应用名,后续在调用的时候只需要使用该名称就可以进行服务的访问.
spring.application.name=tong-jerec-provider
2).application.properties
包含以下3个文件:
A. application-provider1.properties
# application.yml(application-provider1.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=9011
# 实例主机名称
eureka.instance.hostname=127.0.0.1
# ==================================================
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 多个地址可使用 , 分隔
# 对应服务注册中心的配置内容,指定服务注册中心的位置。即eureka-server的配置内容。
eureka.client.service-url.defaultZone=http://eurekaServer1:9001/eureka/,http://eurekaServer2:9002/eureka/,http://eurekaServer3:9003/eureka/
B. application-provider2.properties
# application.yml(application-provider1.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=9012
# 实例主机名称
eureka.instance.hostname=127.0.0.1
# ==================================================
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 多个地址可使用 , 分隔
# 对应服务注册中心的配置内容,指定服务注册中心的位置。即eureka-server的配置内容。
eureka.client.service-url.defaultZone=http://eurekaServer1:9001/eureka/,http://eurekaServer2:9002/eureka/,http://eurekaServer3:9003/eureka/
C. application-provider3.properties
# application.yml(application-provider1.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=9013
# 实例主机名称
eureka.instance.hostname=127.0.0.1
# ==================================================
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 多个地址可使用 , 分隔
# 对应服务注册中心的配置内容,指定服务注册中心的位置。即eureka-server的配置内容。
eureka.client.service-url.defaultZone=http://eurekaServer1:9001/eureka/,http://eurekaServer2:9002/eureka/,http://eurekaServer3:9003/eureka/
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* @Description 服务提供者测试
*/
@RestController
@Slf4j
public class ProviderController {
// http://127.0.0.1:端口/loveanswer?requestName=shihao
@RequestMapping(method = RequestMethod.GET, value = "/loveanswer")
public String loveAnswer(@RequestParam(value = "requestName") String requestName, HttpServletRequest httpServletRequest) {
log.info("I am a provider.");
log.info("Do you love me ?");
StringBuilder resultMsg = new StringBuilder(httpServletRequest.getRequestURL().toString());
if ("shihao".equals(requestName)) {
resultMsg.append(", YES! I LOVE YOU!!!");
} else {
resultMsg.append(", NO!");
}
return resultMsg.toString();
}
}
1). 成功启动后,可以在服务注册中心类的日志中看到如下log日志
Registered instance TONG-JEREC-PROVIDER/shihaod.digitalchina.com:tong-jerec-provider:9011 with status UP (replication=false)
Registered instance TONG-JEREC-PROVIDER/shihaod.digitalchina.com:tong-jerec-provider:9012 with status UP (replication=false)
Registered instance TONG-JEREC-PROVIDER/shihaod.digitalchina.com:tong-jerec-provider:9013 with status UP (replication=false)
2). 在注册中心的页面也可以看到TONG-JEREC-PROVIDER服务。
3).为了验证loveranswer这个restful服务是否好着呢,地址栏输入http://127.0.0.1:9011/loveanswer?requestName=shihao
在3.3.1的基础上添加如下依赖
由于项目依赖的spring-boot-starter-parent的父工程是spring-boot-dependencies,在这个pom里面已经声明了httpclient的版本,所以在正式使用的时候不需要再写版本号
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>${httpclient.version}version>
<exclusions>
<exclusion>
<artifactId>commons-loggingartifactId>
<groupId>commons-logginggroupId>
exclusion>
exclusions>
dependency>
同3.3.2
1).bootstrap.properties
spring.application.name=tong-jerec-consumer
2).application.properties
# application.yml(application.properties) 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
# 1- 端口号
server.port=9021
# 实例主机名称
eureka.instance.hostname=127.0.0.1
# ==================================================
# 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
# 默认地址org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中有配置http://localhost:8761/eureka/
# 多个地址可使用 , 分隔
# 对应服务注册中心的配置内容,指定服务注册中心的位置。即eureka-server的配置内容。
eureka.client.service-url.defaultZone=http://eurekaServer1:9001/eureka/,http://eurekaServer2:9002/eureka/,http://eurekaServer3:9003/eureka/
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @Author 友野浩二
* @Description // feign调用实现
*
*
* 使用@FeignClient注解来指定这个接口所要调用的服务名称,接口中定义的各个函数使用 Spring MVC 的注解就可以来绑定服务提供方的 REST 接口
* name: 绑定的远程服务名(即,bootstrap.properties中配置的spring.application.name)
* 【注意】: 此类中的方法和远程服务中contoller中的方法名和参数需保持一致。
*
**/
@FeignClient(name = FeignConstant.TONG_JERES_PROVIDER)
public interface JerecProviderFeign {
/*
* @Description // 将远程服务http://tong-eureka-provider/loveanswer映射为一个本地Java方法调用。
**/
@RequestMapping(method = RequestMethod.GET, value = "/loveanswer")
public String loveAnswer(@RequestParam(value = "requestName") String requestName);
}
import cn.buddha.jerec.consumer.feign.JerecProviderFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* @Description 服务消费者controller测试类
*/
@RestController
@Slf4j
public class ConsumerController {
@Autowired
private JerecProviderFeign jerecProviderFeign;
@RequestMapping(method = RequestMethod.GET, value = "/client")
public String consumerHello() {
log.info("ConsumerController.consumerHello starting...");
// 这里的使用本地Java API的方式调用远程的Restful接口
String tongProvider = this.jerecProviderFeign.loveAnswer("shihao");
return "通过feign调用远程服务tong-eureka-provider的restful接口/loveanswer的结果: ".concat(tongProvider);
}
}
eureka复制注册中心页面刷新一下,可以看到consumer也注册到注册中心了。
浏览器输入http://127.0.0.1:9021/client,显示
可以看出消费者调用到提供者集群的9013上了。
下面我们模拟发6次请求,看一下都发到服务提供者集群的那台机器了。
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
/**
* @Description http测试模拟请求
*/
@Slf4j
public class TestHttpClient {
public static void main(String[] args) throws IOException {
// 创建默认的httpclient
CloseableHttpClient httpClient = HttpClients.createDefault();
// 调用6次服务并输出结果
for (int i = 0; i < 6; i++) {
// 调用 GET 方法请求服务
HttpGet httpget = new HttpGet("http://localhost:9021/client");
// 获取响应
HttpResponse response = httpClient.execute(httpget);
// 根据 响应解析出字符串
log.info(EntityUtils.toString(response.getEntity()));
}
}
}
运行日志如下:
INFO cn.buddha.jerec.consumer.TestHttpClient - 通过feign调用远程服务tong-eureka-provider的restful接口/loveanswer的结果: http://127.0.0.1:9012/loveanswer, YES! I LOVE YOU!!!
INFO cn.buddha.jerec.consumer.TestHttpClient - 通过feign调用远程服务tong-eureka-provider的restful接口/loveanswer的结果: http://127.0.0.1:9013/loveanswer, YES! I LOVE YOU!!!
INFO cn.buddha.jerec.consumer.TestHttpClient - 通过feign调用远程服务tong-eureka-provider的restful接口/loveanswer的结果: http://127.0.0.1:9011/loveanswer, YES! I LOVE YOU!!!
INFO cn.buddha.jerec.consumer.TestHttpClient - 通过feign调用远程服务tong-eureka-provider的restful接口/loveanswer的结果: http://127.0.0.1:9012/loveanswer, YES! I LOVE YOU!!!
INFO cn.buddha.jerec.consumer.TestHttpClient - 通过feign调用远程服务tong-eureka-provider的restful接口/loveanswer的结果: http://127.0.0.1:9013/loveanswer, YES! I LOVE YOU!!!
INFO cn.buddha.jerec.consumer.TestHttpClient - 通过feign调用远程服务tong-eureka-provider的restful接口/loveanswer的结果: http://127.0.0.1:9011/loveanswer, YES! I LOVE YOU!!!
可以看出eureka server随机将请求发送给服务提供者了,这里可以看出eureka server起到了负载均衡的作用。
还没写完,太晚了,该睡觉了……