8

中秋佳节,来玩一波 SpringCloudAlibaba 之 Nacos 服务提供与消费实战

 3 years ago
source link: https://www.skypyb.com/2019/09/uncategorized/1065/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

中秋佳节,来玩一波 SpringCloudAlibaba 之 Nacos 服务提供与消费实战

中秋佳节当天,人在异乡,无法和家人团聚,既然如此 不如提升一波自己的姿势水平,免得浪费这假期大好光阴。

说道微服务,现在可不流行Netfilx那一套了, 现在都9102年9月了,Spring Cloud Aliabba都已经孵化完毕,再加上Netfilx将他旗下的项目通通打入冷宫,现在在不学习SpringCloudAlibaba体系就赶不上时代的潮流了。 Netfilx那套体系我都搭过demo 写过博客,各种配置啊注意点啊都挺详细的,感兴趣的可以翻我以前的文章。

https://github.com/alibaba/spring-cloud-alibaba 这是 SpringCloudAlibaba 的项目 git。

这篇文章主要是开个SpringCloudAliabba篇的头,正式开始SpringCloudAlibaba的学习。

废话不多说,进入正题。

今天就从微服务最重要的地方开始,当然,也只能从这个地方开始。

那就是服务治理。

在 Spring Cloud Netflix 使用的是Eureka,而SpringCloudAlibaba 给我们提供的就是Nacos。

而且,Nacos比Eureka 更加强大,他还可以用来当配置中心。

这里我就简单的先完成他基本的职责:服务注册与发现。

首先nacos和Eureka有点不同。

他这个应用。不是我们自己写的,Eureka这个东西他需要我们自己创建一个应用。然后在编写代码,然后再将项目打包,在启动。

Nacos这个东西他和Zipkin有点像,是那种直接下载下来运行就完事了的。

我这儿用Docker来运行一个单机的 Nacos 镜像添加到8848端口(默认端口),当然,集群是肯定可以集群的,我这先不玩。

对了,不知道为啥我用网易的docker镜像地址下载会卡住,之后换了alibaba的来下就没问题了。

docker pull nacos/nacos-server
docker run --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server

nacos登陆地址:http://ip:8848/nacos   默认账号密码是nacos/nacos

开启Nacos服务完毕后,就要开始写服务提供者和服务消费者了。

其实这俩都差不多,反正注册进服务治理中心了,A可以调用B的服务,自然B也可以调用A的服务,导入的配置也一样,我这就以服务消费者来举例子,避免贴两份基本相同的代码了。

我这使用的是最新的版本,要用就用最新的,不然没意思。我之前写的Netflix项目也是使用的最新的,当时用的是SpringCloud F版第三版

现在这个项目用的是SpringCloud G版第三版,SpringBoot 2.1.8.RELEASE

先创个依赖项目进行最基本的统一依赖管理

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
    </parent>
    <groupId>com.skypyb</groupId>
    <artifactId>sc-demo-alibaba-dependencies</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>sc-demo-alibaba-dependencies</name>
    <url>http://www.skypyb.com</url>
    <inceptionYear>2019-Now</inceptionYear>
    <properties>
        <!-- Environment Settings -->
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- Spring Settings -->
        <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
        <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
    </properties>
    <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>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <!-- Compiler 插件, 设定 JDK 版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>
            <!-- 打包 jar 文件时,配置 manifest 文件,加入 lib 包的 jar 依赖 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <configuration>
                            <archive>
                                <manifest>
                                    <!-- Add directory entries -->
                                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                                    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                                    <addClasspath>true</addClasspath>
                                </manifest>
                            </archive>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- resource -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
            </plugin>
            <!-- install -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-install-plugin</artifactId>
            </plugin>
            <!-- clean -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
            </plugin>
            <!-- ant -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
            </plugin>
            <!-- dependency -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <!-- Java Document Generate -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <executions>
                        <execution>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
        <!-- 资源文件配置 -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
    </build>
    <repositories>
        <repository>
            <id>aliyun-repos</id>
            <name>Aliyun Repository</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>sonatype-repos</id>
            <name>Sonatype Repository</name>
            <url>https://oss.sonatype.org/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>sonatype-repos-s</id>
            <name>Sonatype Repository</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>aliyun-repos</id>
            <name>Aliyun Repository</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>

这个项目集成了SpringBoot 然后导入了SpringCloud的依赖和SpringCloudAlibaba的依赖。

依赖项目写完之后就是正式开工编写服务。

这个服务就直接继承我刚刚写的依赖项目就可以了。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.skypyb</groupId>
        <artifactId>sc-demo-alibaba-dependencies</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../sc-demo-alibaba-dependencies/pom.xml</relativePath>
    </parent>
    <artifactId>sc-demo-alibaba-consumer</artifactId>
    <packaging>jar</packaging>
    <name>sc-demo-alibaba-consumer</name>
    <url>http://www.skypyb.com</url>
    <inceptionYear>2019-Now</inceptionYear>
    <dependencies>
        <!-- Spring Boot Begin -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot End -->
        <!-- Spring Cloud Begin -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Spring Cloud End -->
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.skypyb.provider.NacosConsumerApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

然后在其中,引入web、actuator、test几个SpringBoot依赖。当然还有必不可少的SpringCloudAlibaba Nacos 依赖。

package com.skypyb.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient//nacos使用spring cloud 原生注解
public class NacosConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosConsumerApplication.class, args);

这个启动类用了个 @EnableDiscoveryClient 这个注解,该注解是SpringCloud内置的,Nacos实现了这个注解,导入了Nacos的依赖的话就代表要注册进Nacos里边。

这样的好处就是以后要是换个新的服务治理中心,代码都不用改就可以轻易的更换,完美符合里式替换原则

既然能注册进去了,那接着还是老规矩,来个RestTemplate进行远程服务的调用,@LoadBalanced代表负载均衡,这些东西我以前的文章都有讲过啊,这儿就不详细说了。

package com.skypyb.provider.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestConfiguration {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();

这里就是编写一个控制层,来进行接口对外暴露,内部就是使用RestTemplate+LoadBalancerClient 来进行负载均衡的调用其他服务。

package com.skypyb.provider.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
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;
import org.springframework.web.client.RestTemplate;
@RequestMapping("/consumer")
@RestController
public class NacosConsumerController {
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping(value = "/hello/{msg}")
    public String hello(@PathVariable("msg") String msg) {
        //使用 LoadBalanceClient 和 RestTemplate 结合的方式来访问
        ServiceInstance serviceInstance = loadBalancerClient.choose("sc-demo-alibaba-provider");
        String url = String.format("http://%s:%s/echo/%s",
                serviceInstance.getHost(), serviceInstance.getPort(), msg);
        return restTemplate.getForObject(url, String.class);

当然,yml是肯定要写的。

spring:
  application:
    name: sc-demo-alibaba-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.14:8848 #注册进 nacos
server:
  port: 8081
management:
  endpoints:
      exposure:
        include: "*"

对了,这个management.endpoints 下边端点一定得打开。

因为 SpringCloudAlibaba 的 Nacos 在实现的时候提供了一个 EndPoint, EndPoint 的访问地址为 http://ip:port/actuator/nacos-discovery。

这玩意和服务注册发现息息相关,要是Nacos访问不了这个端点,那你就注册不了。

其实到这就差不多了,服务已经可以注册进Nacos里了,然后微服务之间的互相调用也是没有问题的,负载均衡也可以实现。

都没啥好说的,只要学会SpringCloud的思想,组件从一套换成另一套也就几十分钟的时间。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK