springcloud官方网站:spring.io/projects/sp…
什么是springcloud?它能干什么?
Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems (e.g. configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus).
大致意思是: springCloud是spring提供的一套可以快速搭建分布式系统中常见组件解决方案。使用springcloud可以快速搭建服务注册/发现,负载均衡,熔断限流,分布式配置中心,链路追踪等这些分布式系统中需要的服务模式。
先说说使用springcloud最应该注意的是使用的cloud版本和springboot版本,这点可以查看spring官网,会给出当前cloud版本对应的springboot版本是什么,我以最新的Hoxton.RELEASE版本为例,Hoxton对应的springboot版本是2.2.1.RELEASE

我们先从服务注册/发现聊起 服务注册发现我们不再使用Netflix中的Eureka,因为现在Eureka不在维护,同时spring官方也不建议再使用Eureka,现在市面上的服务治理组件zookeeper,consul,阿里的nacos。这里使用springcloud组件中的consul。
consul快速入门
1.consul-server搭建
整体的项目架构截图

<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
配置文件
spring.application.name=consul-client
server.port=8001
#consul的hostname
spring.cloud.consul.host=localhost
#consule注册地址端口
spring.cloud.consul.port=8500
#注册服务时是否使用ip进行注册
spring.cloud.consul.discovery.prefer-ip-address=true
启动类上加上@EnableDiscoveryClient注解启用springcloud的服务发现功能。
至此,我们服务注册功能雏形就已经基本完成了,启动项目,出现下面的日志,同时打开(http://localhhost:8500)能查看到我们的服务
日志(可以通过下图日志中的链接查看服务的状态,这个功能必须添加actuator依赖):

consul控制台:

congratulations!!! u build a server register by yourself.
下面让我们来实现服务发现以及实现服务调用功能
创建一个client2模块,让consul-client2调用consul-client的接口 我在client中创建了UserController,其中定义了两个方法,createUser和getUser,client2中同样创建了UserController,其中定义了两个方法,createUser和getUser,让client2的controller调用client的controller。 client的代码
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("/create_user")
public boolean addUser(@RequestBody UserVo vo){
System.out.println("这是client中的addUser方法");
return true;
}
@GetMapping("/get_user")
public UserVo getUser(Long id){
System.out.println("这是client中的getUser方法");
UserVo userVo = new UserVo();
userVo.setUserId(id);
userVo.setUserName("jim");
userVo.setAliasName("listener");
return userVo;
}
}
client2的代码
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private FeignConfig.UsereService usereService;
@PostMapping("/create_user")
public boolean addUser(@RequestBody UserVo vo){
System.out.println("这是client2中的addUser方法");
return usereService.addUser(vo);
}
@GetMapping("/get_user")
public UserVo getUser(Long id){
System.out.println("这是client2中的getUser方法");
return usereService.getUser(id);
}
}
下面需要使用RPC远程调用client的controller,一般情况下我们可以通过RestTemplate进行远程调用,但是RestTemplate每次调用都需要构建一个客户端去调用,分散在代码中不便于管理,这里使用Feign进行远程的服务调用,Feign在SpringBoot中有一个组件,然后SpringCloud又对其进行了封装(OpenFeign),这里直接使用cloud中的依赖,client2中的pom文件只是比client中的多了Feign的依赖
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
client2中的远程调用代码
@Component
public class FeignConfig {
@Value("${client1.url}")
private String clientUrl;
@Bean
public UsereService createUserService(){
return Feign.builder()
.logLevel(Logger.Level.FULL)
.encoder(new GsonEncoder())
.decoder(new GsonDecoder())
.target(UsereService.class,clientUrl);
}
public interface UsereService{
@RequestLine("POST /user/create_user")
@Headers("Content-Type:application/json")
boolean addUser(UserVo vo);
@RequestLine("GET /user/get_user?id={id}")
UserVo getUser(@Param("id") Long id);
}
}
这里需要注意,FeignConfig类需要注入到Spring中进行管理,同时在配置文件中配置下我们需要调用的服务的地址,这样其实没有通过consul服务中获取所有的服务列表。 Feign.builder().target(UsereService.class,clientUrl);会返回一个UsereService实例,中间的链式调用设置这个feignclient的一些配置,像日志级别,编码/解码等。 最后我们通过@Bean将这个UsereService注入到Spring中,其实简单点讲Feign.builder().target(UsereService.class,clientUrl)最后还是返回了一个UsereService的实现类对象,Feign主要是对这个UsereService的实现类对象做了点增强绑定,可以理解为将远程的url跟当前的UsereService接口进行绑定,当调用到UsereService中的方法时,会调用增强后的方法,就是调用远程的一个接口,Feign会构建一个远程请求,最后将结果返回。
最后,看一下运行结果。

控制台打印:

