前言

上两章节,介绍了下关于注册中心-Eureka的使用及高可用的配置示例,本章节开始,来介绍下服务和服务之间如何进行服务调用的,同时会讲解下几种不同方式的服务调用。

一点知识

SpringCloud体系中,我们知道服务之间的调用是通过http协议进行调用的。而注册中心的主要目的就是维护这些服务的服务列表。我们知道,在Spring中,提供了RestTemplateRestTemplateSpring提供的用于访问Rest服务的客户端。而在SpringCloud中也是使用此服务进行服务调用的。

同时在微服务中,一般上服务都不会进行单点部署的,都会至少部署2台及以上的。现在我们有了注册中心进行服务列表的维护,就需要一个客户端负载均衡来进行动态服务的调用。

所以开始示例前,我们先来大致了解下关于负载均衡RestTemplate的相关知识点。其实后面实例的RibbonFeign最后的调用都是基于RestTemplate的。使用比较简单~

何为负载均衡

负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一,它通常是指,将请求/数据【均匀】分摊到多个操作单元上执行,负载均衡的关键在于【均匀】。

实现的方式

实现负载均衡的方式有很多种,这里简单介绍下几种方式,并未过多深入。

注意:以下部分内容转至几种负载均衡技术的实现

1.HTTP重定向负载均衡

根据用户的http请求计算出一个真实的web服务器地址,并将该web服务器地址写入http重定向响应中返回给浏览器,由浏览器重新进行访问

优缺点:实现起来很简单,而缺点也显而易见了:请求两次才能完成一次访问;性能差;重定向服务器会成为瓶颈

2.DNS域名解析负载均衡

在DNS服务器上配置多个域名对应IP的记录。例如一个域名www.baidu.com对应一组web服务器IP地址,域名解析时经过DNS服务器的算法将一个域名请求分配到合适的真实服务器上。

优缺点:加快访问速度,改善性能。同时由于DNS解析是多级解析,每一级DNS都可能化缓存记录A,当某一服务器下线后,该服务器对应的DNS记录A可能仍然存在,导致分配到该服务器的用户访问失败,而且DNS负载均衡采用的是简单的轮询算法,不能区分服务器之间的差异,不能反映服务器当前运行状态。

3.反向代理负载均衡

反向代理处于web服务器这边,反向代理服务器提供负载均衡的功能,同时管理一组web服务器,它根据负载均衡算法将请求的浏览器访问转发到不同的web服务器处理,处理结果经过反向服务器返回给浏览器。

优缺点:实现简单,可利用反向代理缓存资源(这是最常用的了)及改善网站性能。同时因为是所有请求和响应的中转站,所以反向代理服务器可能成为瓶颈。


以上仅仅是部分实现方式,还有比如IP负载均衡数据链路层负载均衡等等,这些可能涉及到相关网络方面的知识点了,不是很了解,大家有兴趣可以自行搜索下吧。


客户端和服务端的负载均衡

实现负载均衡也又区分客户端和服务端之分,Ribbon就是基于客户端的负载均衡。

客户端负载均衡:

服务端负载均衡:

服务端实现负载均衡方式有很多,比如:硬件F5NginxHA Proxy等等,这些应该实施相关人员应该比较熟悉了,本人可能也就对Nginx了解下,⊙﹏⊙‖∣

RestTemplate简单介绍

RestTemplateSpring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

简单来说,RestTemplate采用了模版设计的设计模式,将过程中与特定实现相关的部分委托给接口,而这个接口的不同实现定义了接口的不同行为,所以可以很容易的使用不同的第三方http服务,如okHttphttpclient等。

RestTemplate定义了很多的与REST资源交互,这里简单介绍下一些常用的请求方式的使用。

exchange

在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity。其他的如GETPOST等方法底层都是基于此方法的。

如:

  • get请求
RequestEntity requestEntity = RequestEntity.get(new URI(uri)).build();
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
  • post请求
RequestEntity<User> requestEntity = RequestEntity.post(new URI(uri)).body(user);
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);

GET请求

get请求可以分为两类:getForEntity()getForObject().

// 1-getForObject()
User user1 = this.restTemplate.getForObject(uri, User.class); // 2-getForEntity()
ResponseEntity<User> responseEntity1 = this.restTemplate.getForEntity(uri, User.class);
HttpStatus statusCode = responseEntity1.getStatusCode();
HttpHeaders header = responseEntity1.getHeaders();
User user2 = responseEntity1.getBody();

其他的方法都大同小异了,可以根据实际的业务需求进行调用。

POST请求

简单示例:

// 1-postForObject()
User user1 = this.restTemplate.postForObject(uri, user, User.class); // 2-postForEntity()
ResponseEntity<User> responseEntity1 = this.restTemplate.postForEntity(uri, user, User.class);

关于postForLocation(),用的比较少,作用是返回新创建资源的URI,前面介绍的两者是返回资源本身,也就是结果集了。


关于其他的请求类型相关用法,这里就不详细阐述了,都是类似的。可以查看下此文章:详解 RestTemplate 操作,讲的蛮详细了。


特别说明:系列教程为了方便,github上分别创建了一个单体的Eureka注册中心和高可用的Eureka注册中心,无特殊说明,都是使用单体的Eureka注册中心进行服务注册与发现的,工程名为:spring-cloud-eureka-server,端口号为:1000。服务提供方工程名为:spring-cloud-eureka-client,应用名称为:eureka-client,端口号为:2000,提供了一个接口:http://127.0.0.1:2000/hello

spring-cloud-eureka-server示例:spring-cloud-eureka-server

spring-cloud-eureka-client示例:spring-cloud-eureka-client


LoadBalancerClient实例

此类是实现客户端负载均衡的关键。本身它是个接口类,位于spring-cloud-commons包下,此包包含了大量的服务治理相关的抽象接口,比如已经介绍过的DiscoveryClientServiceRegistry以及LoadBalancerClient实例等等。

首先,我们使用最原生的方式去获取调用服务接口。

创建个工程:spring-cloud-eureka-consumer

0.引入pom文件依赖。

<!-- 客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

1.配置文件添加相关注册中心等信息。

## 服务名称
spring.application.name=eureka-consumer
## 端口号
server.port=8008 #指定注册中心地址
eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
# 启用ip配置 这样在注册中心列表中看见的是以ip+端口呈现的
eureka.instance.prefer-ip-address=true
# 实例名称 最后呈现地址:ip:2000
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}

2.编写启动类,加入@EnableDiscoveryClient,申明为一个客户端应用,同时申明一个RestTemplate,最后是使用RestTemplate来完成rest服务调用的。

@SpringBootApplication
@EnableDiscoveryClient
@Slf4j
public class EurekaConsumerApplication { public static void main(String[] args) throws Exception {
SpringApplication.run(EurekaConsumerApplication.class, args);
log.info("spring-cloud-eureka-consumer启动!");
} @Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

3.编写一个调用类,调用spring-cloud-eureka-client服务提供者提供的服务。

/**
* 访问客户端示例
* @author oKong
*
*/
@RestController
@Slf4j
public class DemoController { @Autowired
LoadBalancerClient loadBalancerClient; @Autowired
RestTemplate restTemplate; @GetMapping("/hello")
public String hello(String name) {
ServiceInstance serviceInstance = loadBalancerClient.choose("eureka-client");
String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/hello?name=" + name;
log.info("url地址为:{}", url);
return restTemplate.getForObject(url, String.class);
}
}

4.启动应用,访问:http://127.0.0.1:8008/hell0?name=oKong ,可以看见控制台输出了利用LoadBalancerClientchoose方法,获取到了对应eureka-client服务ID的服务地址。

最后通过范围对应的http地址进行服务请求:

最后浏览器上可以看见,进行了正确的访问了:

此时,切换到服务提供者spring-cloud-eureka-client控制台,可以看见日志输出:

此时我们已经调用成功了,通过LoadBalancerClient获取到了服务提供者实际服务地址,最后进行调用。

大家可以创建多个的spring-cloud-eureka-client服务提供者,再去调用下,可以看见会调用不同的服务地址的。

客户端负载均衡Ribbon实例

Spring Cloud Ribbon是一个基于Http和TCP的客服端负载均衡工具,它是基于Netflix Ribbon实现的。与Eureka配合使用时,Ribbon可自动从Eureka Server (注册中心)获取服务提供者地址列表,并基于负载均衡算法,通过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均衡负载的作用。

上小节,简单的使用LoadBalancerClient进行了服务实例获取最后调用,也说了其实LoadBalancerClient是个接口类。而Ribbon实现了此接口,对应实现类为:RibbonLoadBalancerClient.

Ribbon实例

现在我们来看下,使用Ribbon的方式如何进行更加优雅的方式进行服务调用。

创建一个工程:spring-cloud-eureka-consumer-ribbon

(其实这个工程和spring-cloud-eureka-consumer是差不多的,只是有些许不同。)

0.加入pom依赖

<!-- 客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

1.配置文件修改,添加注册中心等相关信息。

spring.application.name=eureka-consumer-ribbon
server.port=8018 #指定注册中心地址
eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
# 启用ip配置 这样在注册中心列表中看见的是以ip+端口呈现的
eureka.instance.prefer-ip-address=true
# 实例名称 最后呈现地址:ip:2000
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}

2.编写启动类,加入@EnableDiscoveryClient,同时申明一个RestTemplate这里和原先不同,就在于加入了@LoadBalanced注解进行修饰RestTemplate类,稍后会大致讲解下是如何进行实现的。

@SpringBootApplication
@EnableDiscoveryClient
@Slf4j
public class EurekaConsumerRibbonApplication { public static void main(String[] args) throws Exception {
SpringApplication.run(EurekaConsumerRibbonApplication.class, args);
log.info("spring-cloud-eureka-consumer-ribbon启动!");
} //添加 @LoadBalanced 使其具备了使用LoadBalancerClient 进行负载均衡的能力
@Bean
@LoadBalanced
public RestTemplate restTemplage() {
return new RestTemplate();
}
}

3.编写测试类,进行服务调用。

/**
* ribbon访问客户端示例
* @author oKong
*
*/
@RestController
@Slf4j
public class DemoController { @Autowired
RestTemplate restTemplate; @GetMapping("/hello")
public String hello(String name) {
//直接使用服务名进行访问
log.info("请求参数name:{}", name);
return restTemplate.getForObject("http://eureka-client/hello?name=" + name, String.class);
}
}

可以看见,可以直接注入RestTemplate,通过服务名直接调用.

4.启动应用,访问:http://127.0.0.1:8018/hello?name=oKong ,可以看见调用成功:

控制台输出:

简单聊聊LoadBalanced注解

可以从以上示例中,可以看出,我们就加了一个@LoadBalanced注解修饰RestTemplatebean类,就实现了服务的调用。现在来简单看看具体是如何实现的。

首先,我们看看此注解的代码说明:

从注释可以看出,该注解用来给RestTemplate做标记,以使用负载均衡的客户端LoadBalancerClient

现在来看一眼相同包下的类的情况,可以看到有个LoadBalancerAutoConfiguration,字面意思可以知道这是一个自动配置类,此类就是我们要找的关键类了。

LoadBalancerAutoConfiguration,此类不长,一百来行,这里就不贴了。

简单说明下:

首先,此类生效的条件是

@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
  • RestTemplate类必须存在于当前工程的环境中。
  • 在Spring的Bean工程中有必须有LoadBalancerClient的实现Bean。

该自动化配置类中,主要做了几件事情:

  • 维护了一个被@LoadBalanced注解修饰的RestTemplate对象列表
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();

同时为其每个对象通过调用RestTemplateCustomizer添加了一个LoadBalancerInterceptorRetryLoadBalancerInterceptor拦截器(有生效条件),其为ClientHttpRequestInterceptor接口的实现类,ClientHttpRequestInterceptorRestTemplate的请求拦截器

RetryLoadBalancerInterceptor拦截器

LoadBalancerInterceptor拦截器

我们主要看下LoadBalancerInterceptor

可以看见,最后是实现了ClientHttpRequestInterceptor接口的实现类执行execute方法进行.

从继承关系里,此实现类就是RibbonLoadBalancerClient类了。

RibbonLoadBalancerClient类:

简单来说:最后还是通过loadBalancerClient.choose()获取到服务实例,最通过拼凑http地址来进行最后的服务调用。

总体来说,就是通过为加入@LoadBalanced注解的RestTemplate添加一个请求拦截器,在请求前通过拦截器获取真正的请求地址,最后进行服务调用。

里面的细节就不阐述了,毕竟源码分析不是很在行呀,大家可以跟踪进去一探究竟吧。


友情提醒:若被@LoadBalanced注解的RestTemplate访问正常的服务地址,如http://127.0.0.1:8080/hello时,是会提示无法找到此服务的。

具体原因:serverid必须是我们访问的服务名称 ,当我们直接输入ip的时候获取的servernull,就会抛出异常。

此时,若是需要调用非注册中心的服务,可以创建一个不被@LoadBalanced注解的RestTemplate,同时指定bean的名称,使用时,使用@Qualifier指定name注入此RestTemplate

    @Bean("normalRestTemplage")
public RestTemplate normalRestTemplage() {
return new RestTemplate();
} //使用
@Autowired
@Qualifier("normalRestTemplage")
RestTemplate normalRestTemplate; @GetMapping("/ip")
public String ip(String name) {
//直接使用服务名进行访问
log.info("使用ip请求,请求参数name:{}", name);
return normalRestTemplate.getForObject("http://127.0.0.1:2000/hello?name=" + name, String.class);
}

负载均衡器

目前还未进行过自定义负载均衡,这里就简单的举例下,上次整理ppt时有讲过一些,但未深入了解过⊙﹏⊙‖∣,

可以从继承关系看出,是通过继承IRule来实现的。

可继承ClientConfigEnabledRoundRobinRule,来实现自己负载均衡策略。

声明式服务Feign实例

从上一章节,我们知道,当我们要调用一个服务时,需要知道服务名和api地址,这样才能进行服务调用,服务少时,这样写觉得没有什么问题,但当服务一多,接口参数很多时,上面的写法就显得不够优雅了。所以,接下来,来说说一种更好更优雅的调用服务的方式:Feign

FeignNetflix开发的声明式、模块化的HTTP客户端。Feign可帮助我们更好更快的便捷、优雅地调用HTTP API

Spring Cloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解。Feign支持多种注释,例如Feign自带的注解或者JAX-RS注解等

Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和 Eureka,从而让Feign 的使用更加方便。只需要通过创建接口并用注解来配置它既可完成对Web服务接口的绑定。

Feign实例

创建个spring-cloud-eureka-consumer-ribbon工程项目。

0.加入feigin依赖

        <!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- eureka客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- rest api -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

1.配置文件

spring.application.name=eureka-consumer-feign
server.port=8028 #指定注册中心地址
eureka.client.service-url.defaultZone=http://127.0.0.1:1000/eureka
# 启用ip配置 这样在注册中心列表中看见的是以ip+端口呈现的
eureka.instance.prefer-ip-address=true
# 实例名称 最后呈现地址:ip:2000
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}

2.创建启动类,加入注解@EnableFeignClients,开启feign支持。

@SpringBootApplication
@EnableFeignClients
@Slf4j
public class EurekaConsumerFeignApplication { public static void main(String[] args) throws Exception {
SpringApplication.run(EurekaConsumerFeignApplication.class, args);
log.info("spring-cloud-eureka-consumer-feign启动");
} }

3.创建一个接口类IHelloClient,加入注解@FeignClient来指定这个接口所要调用的服务名称。

@FeignClient(name="eureka-client")
public interface IHelloClient { /**
* 定义接口
* @param name
* @return
*/
@RequestMapping(value="/hello", method=RequestMethod.GET)
public String hello(@RequestParam("name") String name);
}

4.创建一个demo控制层,引入此接口类。

/**
* feign 示例
* @author OKong
*
*/
@RestController
@Slf4j
public class DemoController { @Autowired
IHelloClient helloClient; @GetMapping("/hello")
public String hello(String name) {
log.info("使用feign调用服务,参数name:{}", name);
return helloClient.hello(name);
}
}

5.启动应用,访问:http://127.0.0.1:8028/hello?name=oKong-feign

是不是很简单,和调用本地服务是一样的了!

Feign继承特性

Feign支持继承,但不支持多继承。使用继承,可将一些公共操作分组到一些父类接口中,从而简化Feign的开发。

所以在实际开发中,调用服务接口时,可直接按接口类和实现类进行编写,调用方引入接口依赖,继承一个本地接口,这样接口方法默认都是定义好的,也少了很多编码量。用起来就更爽了,就是有点依赖性,对方服务修改后需要同步更新下,但这个团队内部约定下问题不大的

这里简单实例下,创建一个spring-cloud-eureka-client-api工程。

0.加入依赖,注意此依赖的作用范围:

    <!--api接口依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>

1.编写一个接口类IHellpApi

public interface IHelloApi {
//定义提供者服务名
public static final String SERVICE_NAME = "eureka-client"; /**
* 定义接口
* @param name
* @return
*/
@RequestMapping(value="/hello", method=RequestMethod.GET)
public String hello(@RequestParam("name") String name);
}

修改spring-cloud-eureka-client工程

0.引入api依赖

    <!-- 导入接口依赖 -->
<dependency>
<groupId>cn.lqdev.learning</groupId>
<artifactId>spring-cloud-eureka-client-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

1.创建一个HelloApiImpl类,实现IHelloApi:

/**
* 使用接口方式进行接口编写
* @author oKong
*
*/
@RestController
@Slf4j
public class HelloApiImpl implements IHelloApi { @Override
public String helloApi(@RequestParam("name") String name) {
log.info("[spring-cloud-eureka-client]服务[helloApi]被调用,参数name值为:{}", name);
return name + ",helloApi调用!";
}
}

此时,HelloApiImpl是个控制层也是个接口实现类了。

修改spring-cloud-eureka-consumer-feign工程。

0.引入api依赖

    <!-- 导入接口依赖 -->
<dependency>
<groupId>cn.lqdev.learning</groupId>
<artifactId>spring-cloud-eureka-client-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

1.同样创建一个接口,使其继承IHelloApi:

/**
* 直接继承接口
* @author Okong
*
*/
@FeignClient(name = IHelloApi.SERVICE_NAME)
public interface HelloApi extends IHelloApi{ }

小技巧:可以在IHelloApi定义一个服务名变量,如:SERVICE_NAME,这样让提供者进行变量的赋值,可以避免一些不必要的交流成本的,若有变化,服务调用方也无需关心的。一切都是约定编程!

2.修改下DemoController类,注入HelloApi

    @Autowired
HelloApi helloApi; @GetMapping("hello2")
public String hello2(String name) {
log.info("使用feign继承方式调用服务,参数name:{}", name);
return helloApi.helloApi(name);
}

3.分别启动各服务,访问:http://127.0.0.1:8028/hello2?name=oKong-api

使用起来没啥差别的,一样的调用,但对于调用方而言,可以无需去理会具体细节了,照着接口方法去传参就好了。

这种方式,和原来的dubbo调用的方式是类似的,简单方便。大家可以把接口和实体放入一个包中,调用者和提供者都进行依赖即可。

注意事项

在使用Feign时,会碰见一些问题,为了避免不必要的错误,以下这些需要额外注意下。

  • GET请求多个参数时,需要使用@RequestParam
  • GET请求参数为实体时,会自动转换成POST请求
  • POST请求使用@RequestBody注解参数
  • 不建议直接将@RequestMapping注解在类上,直接写在方法上

参考资料

  1. https://blog.csdn.net/mengdonghui123456/article/details/53981976

  2. https://cloud.spring.io/spring-cloud-static/Finchley.SR1/single/spring-cloud.html#_spring_cloud_openfeign

总结

本章节主要讲解了下服务消费者如何利用原生、ribbon、fegin三种方式进行服务调用的,其实每种调用方式都是使用ribbon来进行调用的,只是有些进行了增强,是的使用起来更简单高效而已。对于其原理的实现,本文未进行详细阐述,大家可以谷歌想相关知识,跟踪下源码了解下,本人也尚未深入研究过,还是停留在使用阶段,之后有时间了看一看,有啥心得再来分享吧。此时若服务上线下线,调用者调用可能会出现短暂的调用异常,最常见的就是找不到服务,此时服务容错保护就排上用场了,所以下一章节,就来说说关于服务容错保护相关知识点~

最后

目前互联网上大佬都有分享SpringCloud系列教程,内容可能会类似,望多多包涵了。原创不易,码字不易,还希望大家多多支持。若文中有错误之处,还望提出,谢谢。

老生常谈

  • 个人QQ:499452441
  • 微信公众号:lqdevOps

个人博客:http://blog.lqdev.cn

源码示例:https://github.com/xie19900123/spring-cloud-learning

原文地址:http://blog.lqdev.cn/2018/09/21/SpringCloud/chapter-four/

白话SpringCloud | 第四章:服务消费者(RestTemple+Ribbon+Feign)的更多相关文章

  1. 服务消费者(RestTemplate+Ribbon+feign)

    负载均衡 ​ spring cloud 体系中,我们知道服务之间的调用是通过http协议进行调用的.注册中心就是维护这些调用的服务的各个服务列表.在Spring中提供了RestTemplate,用于访 ...

  2. 白话SpringCloud | 第五章:服务容错保护(Hystrix)

    前言 前一章节,我们知道了如何利用RestTemplate+Ribbon和Feign的方式进行服务的调用.在微服务架构中,一个服务可能会调用很多的其他微服务应用,虽然做了多集群部署,但可能还会存在诸如 ...

  3. Spring Cloud学习笔记【二】Eureka 服务提供者/服务消费者(ribbon)

    Ribbon 是 Netflix 发布的开源项目,主要功能是为 REST 客户端实现负载均衡.它主要包括六个组件: ServerList,负载均衡使用的服务器列表.这个列表会缓存在负载均衡器中,并定期 ...

  4. 白话SpringCloud | 第三章:服务注册与发现(Eureka)-下

    前言 上一章节,讲解了在单机模式下的服务注册与发现的相关知识点及简单示例.而在实际生产或者在这种微服务架构的分布式环境中,需要考虑发生故障时,各组件的高可用.而其实高可用,我的简单粗俗理解就是,通过系 ...

  5. SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)

    在上一篇文章,讲了服务的注册和发现.在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的.Spring cloud有两种服务调用方式,一种是ribbon+r ...

  6. SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)(Finchley版本)

    在上一篇文章,讲了服务的注册和发现.在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的.Spring cloud有两种服务调用方式,一种是ribbon+r ...

  7. 史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)(Finchley版本)

    转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springcloud/2018/08/30/sc-f2-ribbon/ 本文出自方志朋的博客 在上一篇文章,讲了 ...

  8. 白话SpringCloud | 第零章:前言

    说在前面 大清早醒来,觉得睡不着了.还是起来,写写博客.但最后发现关于SpringBoot的安全相关的还是比较多内容的,也比较专业,怕是一个多小时完不成的,也罢,那就来写写关于SpringCloud前 ...

  9. springcloud干货之服务消费者(ribbon)

    本章介绍springcloud中的服务消费者 springcloud服务调用方式有两种实现方式: 1,restTemplate+ribbon, 2,feign 本来想一篇讲完,发现篇幅有点长,所以本章 ...

随机推荐

  1. SQL多行并一行统计例子之STUFF()函数+FOR XML PATH()函数应用

    SELECT * FROM tbiz_ProjectRelation 目标统计每个项目有几条申请记录 Step1 SELECT ProjectID , RelationIDs , , '') FROM ...

  2. SpringMVC+Hibernate 项目开发之一(Maven环境搭建)

    Maven环境搭建网上一大堆文章,直接引用leiOOlei同学的了:http://www.cnblogs.com/leiOOlei/p/3359561.html Maven版本:apache-mave ...

  3. Kylin存储和查询的分片问题

    本文来自网易云社区 作者:汪胜 相关概念介绍 为了了解Kylin存储和查询的分片问题,需要先介绍两个重要概念:segment和cuboid.相信大数据行业的相关同学都不陌生.Kylin每次提交一个新的 ...

  4. 跳转iPhone设置页面,绕过审核

    1.问题描述 跳转iPhone设置页面之前都是通过 App-Prefs:root=WIFI 来跳转,但是2018年6月废弃了这个函数,被认为是私有函数,审核会被拒绝. 有心人采用了字符串转码的方式来规 ...

  5. 生成HTML测试报告

    HTMLTestRunner是Python标准库unittest单元测试框架的一个扩展,可以生成易于使用的HTML测试报告,这个扩展很简单,只有一个HTMLTestRunner.py,下载地址:htt ...

  6. IDEA开发javaEE项目问题总结

    删了删了,不瞎折腾了,用Maven嘛事没有 注意在idea中,add framework后还需要在maven中添加相关依赖

  7. 【大数据系统架构师】0.1 Java编程基础

    1. 初识Java 2. Java语法 快速入门点我 2.1 数据类型和运算符 2.2 流程控制语句 2.3 数组 2.4 类和对象 2.5 OOP三大特性 2.6 集合框架与泛型 2.7 反射机制 ...

  8. EF进阶篇(一)——概述

    前言 以前在ITOO里面和图书馆项目开发的时候,采用的这个技术,但是总是对上下文那里不是特别清楚.上下文这个概念很是模糊,所以这次再次拿起这个技术点儿,然后复习了一遍,发现我以前想的好简单. 内容 E ...

  9. FastDFS分布式⽂文件系统

    FastDFS分布式⽂文件系统  1. 什么是FastDFS FastDFS 是⽤用 c 语⾔言编写的⼀一款开源的分布式⽂文件系统.FastDFS 为互联⽹网量量身定制, 充分考虑了了冗余备份.负载均 ...

  10. 编写可维护的Javascript纪要

    第一部分: 编程风格 在大型项目开发中,因为项目可读性规范性的需要(就像<编写可维护性的Javascript>一书作者Nicholas Zakas大神所说,他们团队所有成员写出的代码就像是 ...