【springcloud系列】开篇:服务注册/发现--使用入门

507 阅读3分钟

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搭建

整体的项目架构截图

pom引入一下几个依赖,同时dependencyManagement将cloud的dependency作为pom import进来。

    <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会构建一个远程请求,最后将结果返回。

最后,看一下运行结果。

控制台打印:

到此为止,我们实现了服务的注册与调用,但是我们的服务调用并不是走的注册中心获取对应的服务地址去调用,而是直接配死的url,所以下面我们要做的就是通过注册中心进行服务调用,不需要字在配置文件中配置url地址