springcloud分布式简单模拟(客户端,注册中心,服务端)高可用简单实现

从我开始接触javaweb开发的时间来(很短),也接触了几个架构,有jsp+servlet+mysql这种最原始的架构,代码耦合度非常高,比如jdbc连接都得写好几次,后来开始用框架了,接触ssm,又接触了springboot,springcloud等等,下面就实现一个简单的分布式项目

分布式,就是要在客户和服务端间建立一个注册中心,这个注册中心可以用springcloud来实现,
有三个模块
在这里插入图片描述

首先建立一个服务端

在开发springboot的时候,遇到一个问题,就是,springboot的实现类,ServiceProvideApplication该类要与其他的包(controller包,mapper包…)在同一级目录,不然就不能成功访问
在这里插入图片描述
用springboot来创建该模块,因为要连接到数据库,所以记得勾选jdbc,mybatis,mysql,还有web的,没勾也没关系,直接到pom.xml中添加依赖


    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>service_provide</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>service_provide</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!-- 通用mapper,Mybatis使用mapper接口方式来实现,自己引入 -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </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>
        <!-- Eureka客户端,这是后面要用到的 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

    <!-- SpringCloud的依赖 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

这里省略了头尾,不要直接引用

server.port=8081

spring.datasource.url=jdbc:mysql:///springboot
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver 
#配置包扫描
mybatis.type-aliases-package=com.sb.pojo

#以下是在springcloud中心注册的配置,可以先关注上面的配置
eureka.client.service-url.defaultZone=http://127.0.0.1:10086/eureka
spring.application.name=service-provide
#如果有重名,开启覆盖
spring.main.allow-bean-definition-overriding=true

表的字段如下,大家可以自己建,或者用已有的数据库代替
在这里插入图片描述

要实现通过页面访问后,返回数据库中的数据,用json来返回数据,这样一个rest风格的接口,

@RestController
@RequestMapping("user")
public class UserController {
    @Autowired
    public UserService userService;

    @GetMapping("{id}")
    public User queryUserById(@PathVariable("id") long id){
        return this.userService.queryUserById(id);
    }
}

这个控制器,可以直接在http中输入id值来得到想要的数据,@PathVariable注解用来映射URL绑定的占位符,可以直接用url地址如localhost:8080/user/1来获取id为1的值,在以前学习ssm的时候,好像没有这样的方法,这应该也是springmvc的rest的风格的体现,

@Service
public class UserService {

    @Autowired
    public UserMapper userMapper;

    public User queryUserById(long id){
        User user = userMapper.selectByPrimaryKey(id);
        return user;
    }
}

上面有提到过,mybatis用接口的方式来实现数据库操作,但是这里的mapper类,只要继承tk.mybatis.mapper.common.Mapper;就可以实现了,

public interface UserMapper extends Mapper<User> {
}

直接映射到user实体类,可以实现selectByPrimaryKey(id);返回查询到的user数据了。这个依赖要自己引的,上面的pom.xml中已指出
但是现在的mapper和springboot项目还没有关联,要在ServiceProvideApplication中加入

@MapperScan("com.sb.mapper")
@EnableDiscoveryClient

扫描mapper包,下面的那个注解作用是使注册中心能够发现自己(当前的服务端)

这时候大家就可以启动服务器访问下数据了。

建客户端

在这里插入图片描述
看图就可以发现,客户端只管拿数据就行了,不用再做那些查数据库的操作,

@Controller
@RequestMapping("consumer/user")
public class UserController {

    @Autowired
    public RestTemplate restTemplate;

	
    @Autowired
    public DiscoveryClient discoveryClient;

    @GetMapping
    @ResponseBody
    public User queryUserById(@RequestParam("id")Long id){
        
        //	|
        //	\/
        //根据服务器名称,获取服务实例,有可能是集群,所以是service集合
        List<ServiceInstance> instances = discoveryClient.getInstances("service-provide");
        //因为只有一个service-provide所以获取第一个
        ServiceInstance instance = instances.get(0);
        String baseUrl = "http://"+instance.getHost()+":"+instance.getPort()+"/user/"+id;
        //	/\
        //	|
        
        User u = restTemplate.getForObject(baseUrl, User.class);
        return  u;
    } 
}

代码中的注释是和注册中心相关的,可以先不关注,baseUrl就是服务器的地址,这时的服务器是provide,注册中心还没做,直接连上provide,
RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

server.port=8082

#注册中心相关
eureka.client.service-url.defaultZone=http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
spring.application.name=service-consumer

配置也只要配个端口

启动服务器,然后再启动客户端,这是就可以通过localhost:8082/consumer/user/1来访问服务器,获取数据了。当然了,这时的服务器和客户端是放在同一个电脑上的,所以有些奇怪。

eureka服务器(注册中心)

在这里插入图片描述
在创建springboot项目时勾选eureka服务
在这里插入图片描述

 
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com</groupId>
    <artifactId>eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR3</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </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>
	<!-- SpringCloud的依赖 -->
    <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>
 

不要忘了加springcloud的统一依赖管理↑
配置信息↓

server.port=10086
#eureka服务的名字
spring.application.name=eureka-server
#默认的地址
eureka.client.service-url.defaultZone=http://127.0.0.1:10086/eureka

在springboot的启动器加上注解@EnableEurekaServer,开启eureka服务
启动服务,并访问:http://127.0.0.1:10086
在这里插入图片描述
这时候eureka服务就开启了,接下来就要将服务端和客户端加入这个服务器了
但是在现实生活中,只有一台服务器来处理请求就会有问题,一般都是多台服务器,这里就涉及到eureka的高可用,就是注册多台eureka服务器,这里注册两台,使用相互注册的方式,两台的端口号这里设置的是10086,10087
先将服务端和客户端的配置信息写好

service_provide的配置文件

spring.application.name=service-provide
#如果有重名,开启覆盖
spring.main.allow-bean-definition-overriding=true
#eureka客户端的配置,连接到注册中心的地址
eureka.client.service-url.defaultZone=http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka 

在启动服务端时,启动失败,

Description:The bean ‘dataSource’, defined in BeanDefinition defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration H i k a r i . c l a s s ] , c o u l d n o t b e r e g i s t e r e d . A b e a n w i t h t h a t n a m e h a s a l r e a d y b e e n d e f i n e d i n c l a s s p a t h r e s o u r c e [ o r g / s p r i n g f r a m e w o r k / b o o t / a u t o c o n f i g u r e / j d b c / D a t a S o u r c e C o n f i g u r a t i o n Hikari.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration Hikari.class],couldnotberegistered.Abeanwiththatnamehasalreadybeendefinedinclasspathresource[org/springframework/boot/autoconfigure/jdbc/DataSourceConfigurationHikari.class] and overriding is disabled.

应该是datasource定义了两次,找不到到底在哪定义了两次,直接在配置文件中配置覆盖,就能启动了。
客户端service_consumer也要加上

spring.application.name=service-consumer

eureka.client.service-url.defaultZone=http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
高可用

这里要先打开run dashboard窗口,便于操作
在你的项目中,D:…\myData.idea,我的项目名是myData,.idea中找workspace.xml文件,找到RunDashBoard字段,在component便签下添加

<option name="configurationTypes">  
    <set>  
        <option value="SpringBootApplicationConfigurationType" />  
    </set>  
</option> 

之后启动项目就会弹出dashboard窗口了,
右键EurekaApplication,点击复制配置,弹出编辑配置的窗口,直接点击确定,就会生成一个EurekaApplication2的复制项,
在这里插入图片描述

server.port=10087
spring.application.name=eureka-server
eureka.client.service-url.defaultZone=http://127.0.0.1:10086/eureka

把Eureka模块的配置文件的defaultZone的端口改为10087,因为相互注册,将10086注册给10087,启动原eureka的启动器,这时候会报错,但是dashboard中原eureka服务器后面已经跟着个10086的端口了,注册成功了,之后把配置文件(两个服务共用一个配置,但是加载完原项目后,把配置文件改了),

server.port=10086
spring.application.name=eureka-server
eureka.client.service-url.defaultZone=http://127.0.0.1:10087/eureka

把10087注册给10086,然后启动那个复制的eureka,在我启动时有时候会失败,但是照着上面的那个配置文件的修改顺序来,应该是没错的,
在这里插入图片描述
这时候,两个eureka就都启动了,在把服务端和客户端启动,可以访问http://127.0.0.1:10086来查看

在这里插入图片描述
这时候高可用就完成了在这里插入图片描述

这篇blog只是大体的论述下springcloud的使用,里面很多的细节并没有去细扣,也有许多的错误和不解。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值