• 容器化nacos部署并实现服务发现(gradle)


    1.如何容器化部署mysql
    2. 如何容器化部署nacos

    为不暴露我的服务器地址,本文全部使用localhost来代替服务器地址,所有的localhost都应该调整为你自己的服务器地址。
    为不暴露我的服务器地址,本文全部使用localhost来代替服务器地址,所有的localhost都应该调整为你自己的服务器地址。

    容器化nacos并实现服务发现

    • 本文使用技术:springclod、springcloudAlibaba、kotlin、jpa、gradle
    创建项目
    • 创建empty project
      在这里插入图片描述

    • 选择jdk17、语言等级17

    新建provider模块

    • 新建模块(命名为provider) 选择spring 3.0.2
    • 依赖添加spring data jpa、spring web、lombok
    • 添加mysql连接池依赖
    dependencies {  
    // other denpendencies
    	implementation 'mysql:mysql-connector-java:8.0.26'  
    	implementation("com.alibaba:druid:1.2.20")
    // other denpendencies
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • mvn官网查询springcloud的导入方式,springcloud的github页面查询版本对应关系
    • mvn官网查询springcloudalibaba,引入springcloudalibaba对应版本
    • 引入spring-cloud-alibaba-nacos-discovery
    ext {
        set('springCloudVersion', "2022.0.0")
        set('springCloudAlibabaVersion', "2022.0.0.0") // 设置Spring Cloud Alibaba的版本号
    }
    
    repositories {
        //阿里源
        maven { url 'https://maven.aliyun.com/repository/public' }
        mavenCentral()
    }
    
    dependencies {
    ...
    	implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2022.0.0.0'
    ...
    }
    
    dependencyManagement {
        imports {
            mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
            mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:${springCloudAlibabaVersion}" // 导入Spring Cloud Alibaba BOM
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 开放服务器8848、9848端口

    • 配置application(更改数据库地址和账户密码即可)

    spring:
      cloud:
        nacos:
          discovery:
            # nacos注册中心地址
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
      # 微服务名称
      application:
        name: depart-provider
      jpa:
        # 指定是否在spring容器启动时创建表,默认false
        generate-ddl: true
        show-sql: true
        hibernate:
          # 指定应用重启时不重新更新表
          ddl-auto: none
        # 关闭前端访问的懒加载机制
        open-in-view: false
    
      # 配置数据源
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1/rdtcloud?serverTimezone=Asia/Shanghai&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
        username: root
        password: 'your_password'
        druid:
          # 初始连接数
          initialSize: 5
          # 最小连接池数量
          minIdle: 10
          # 最大连接池数量
          maxActive: 20
          # 配置获取连接等待超时的时间
          maxWait: 60000
          # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
          timeBetweenEvictionRunsMillis: 60000
          # 配置一个连接在池中最小生存的时间,单位是毫秒
          minEvictableIdleTimeMillis: 300000
          # 配置一个连接在池中最大生存的时间,单位是毫秒
          maxEvictableIdleTimeMillis: 900000
          # 配置检测连接是否有效
          validationQuery: SELECT 1 FROM DUAL
          testWhileIdle: true
          testOnBorrow: false
          testOnReturn: false
    
    # 日志
    logging:
      # 控制台日志输出格式
      pattern:
        console: level-%level %msg%n
      level:
        # 控制springboot 启动时显示的日志级别
        root: info
        # hibernate相关的日志级别
        org.hibernate: info
        # 控制自己写的代码运行时显示的日志级别
        com.rdt: debug
        #  show-sql: true 的前提下显示sql中的动态参数值
        org.hibernate.type.descriptor.sql.BasicBinder: trace
        #  show-sql: true 的前提下显示sql的查询结果
        org.hibernate.type.descriptor.sql.BasicExtractor: trace
    
    server:
      port: 8081
      servlet:
        encoding:
          charset: utf-8
          # 确保字符集总是被应用
          force: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    新建consumer模块

    • 新建模块(命名为provider) 选择spring 3.0.2
    • 依赖添加spring web、lombok
    • 引入provider0引入的微服务依赖内容(spring、springcloudalibaba、nacos-discovery)
    ext {
        set('springCloudVersion', "2022.0.0")
        set('springCloudAlibabaVersion', "2022.0.0.0") // 设置Spring Cloud Alibaba的版本号
    }
    
    repositories {
        //阿里源
        maven { url 'https://maven.aliyun.com/repository/public' }
        mavenCentral()
    }
    
    dependencies {
    ...
    	implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2022.0.0.0'
    ...
    }
    
    dependencyManagement {
        imports {
            mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
            mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:${springCloudAlibabaVersion}" // 导入Spring Cloud Alibaba BOM
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 配置consumer的yml
    spring:
      cloud:
        nacos:
          discovery:
            # nacos注册中心地址
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
      # 微服务名称
      application:
        name: depart-consumer
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 以上配置完成,启动provider和consumer,可以在注册中nacos中找到这两个服务
    • 如何容器化配置并启动nacos在文章开头的链接中
      在这里插入图片描述

    consumer和provider通信

    provider代码测试

    使用传统的三层架构就可以

    • 实体类
    package com.rdt.provider8081.bean
    
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties
    import jakarta.persistence.Entity
    import jakarta.persistence.GeneratedValue
    import jakarta.persistence.GenerationType
    import jakarta.persistence.Id
    
    @Entity
    @JsonIgnoreProperties(value = ["hibernateLazyInitializer", "handler", "fieldHandler"])
    class Depart {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        val id: Int? = null
        var name: String? = null
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 服务层
    package com.rdt.provider8081.service
    
    import com.rdt.provider8081.bean.Depart
    import com.rdt.provider8081.repository.DepartRepository
    import lombok.RequiredArgsConstructor
    import org.springframework.stereotype.Service
    
    @Service
    @RequiredArgsConstructor
    class DepartService(private val departRepository: DepartRepository) {
        fun saveDepart(depart: Depart) = departRepository.save(depart)
        fun removeDepart(id: Int) {
            if (departRepository.existsById(id) != null)
                departRepository.deleteById(id)
        }
    
        fun getDepartById(id: Int): Depart {
            if (departRepository.existsById(id)) {
                return departRepository.getReferenceById(id)
            } else {
                return Depart()
            }
    
        }
    
        fun modifyDepart(depart: Depart): Depart {
            if (departRepository.existsById(depart.id!!)) {
                return departRepository.save(depart)
            }
            return Depart()
        }
    
        fun findAllDeparts() = departRepository.findAll()
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 持久层
    package com.rdt.provider8081.repository  
      
    import com.rdt.provider8081.bean.Depart  
    import org.springframework.data.jpa.repository.JpaRepository  
      
    interface DepartRepository :JpaRepository<Depart,Int>{  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 视图层
    package com.rdt.provider8081.controller
    
    import com.rdt.provider8081.bean.Depart
    import com.rdt.provider8081.service.DepartService
    import lombok.RequiredArgsConstructor
    import org.springframework.cloud.client.discovery.DiscoveryClient
    import org.springframework.web.bind.annotation.*
    
    @RestController
    @RequiredArgsConstructor
    @RequestMapping("/provider/depart")
    class DepartController(
        private val departService: DepartService, private val discoveryClient: DiscoveryClient
    ) {
    
        @PostMapping("/")
        fun saveHandle(@RequestBody depart: Depart) {
            println(depart.name)
            departService.saveDepart(depart)
    
        }
    
        @DeleteMapping("/{id}")
        fun deleteHandle(@PathVariable("id") id: Int) {
            return departService.removeDepart(id)
        }
    
        @PutMapping("/")
        fun updateHandle(@RequestBody depart: Depart) = departService
    
        @GetMapping("/get/{id}")
        fun getHandle(@PathVariable id: Int) = departService.getDepartById(id)
    
        @GetMapping("/list")
        fun listHandle() = departService.findAllDeparts()
    
        @GetMapping("/discovery")
        fun discoveryHandle(): List<String> {
            //获取所有的服务名称
            val services: List<String> = discoveryClient.services
            for (service in services) {
                // 获取指定微服务名称的所有微服务实例
                var instances = discoveryClient.getInstances(service)
                for (instance in instances) {
    //                val map = HashMap()
                    val map = mutableMapOf<String, Any>()
                    map["serviceName"] = service
                    map["serviceId"] = instance.serviceId
                    map["serviceHost"] = instance.host
                    map["servicePort"] = instance.port
                    map["uri"] = instance.uri
                    println(map)
                }
    
            }
            return services
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    Consumer代码测试

    • 注意,目前新版的springcloudAlibaba已经弃用了ribbon,所以负载均衡需要引入依赖
    • consumer不需要持久层,consumer是调用provider的,它不与数据库交互
    dependencies{
        //nacos-discover引入
        implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer:4.0.4'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 实体层
    package com.rdt.consumer8080.bean
    
    class Depart {
         var id:Int?=null
         var name:String?=null
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 配置类
    • consumer需要配置类,在视图层需要使用
    package com.rdt.consumer8080.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  
    class DepartConfig {  
      
    @LoadBalanced //以负载均衡的方式调用  
    @Bean  
    public fun restTemplate():RestTemplate{  
    return RestTemplate()  
    }  
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 视图层
    package com.rdt.consumer8080.controller
    
    import com.google.gson.GsonBuilder
    import com.rdt.consumer8080.bean.Depart
    import com.rdt.consumer8080.consts.ConstTime
    import lombok.RequiredArgsConstructor
    import org.springframework.core.ParameterizedTypeReference
    import org.springframework.web.bind.annotation.DeleteMapping
    import org.springframework.web.bind.annotation.GetMapping
    import org.springframework.web.bind.annotation.PathVariable
    import org.springframework.web.bind.annotation.PostMapping
    import org.springframework.web.bind.annotation.PutMapping
    import org.springframework.web.bind.annotation.RequestBody
    import org.springframework.web.bind.annotation.RequestMapping
    import org.springframework.web.bind.annotation.RestController
    import org.springframework.web.client.RestTemplate
    import org.springframework.web.client.getForObject
    
    @RestController
    @RequestMapping("/consumer/depart")
    @RequiredArgsConstructor
    class DepartController(private val template:RestTemplate) {
        //直连方式
    //    final val SERVICE_PROVIDER_DEPART="http://localhost:8081/provider/depart/"
    
        //微服务方式
        final val SERVICE_PROVIDER_DEPART="http://depart-provider/provider/depart/"
        //增
        @PostMapping("/")
        fun saveHandle(@RequestBody depart:Depart):Boolean?{
            return template.postForObject(SERVICE_PROVIDER_DEPART, depart, Boolean::class.java)
        }
    
        //删
        @DeleteMapping("/del/{id}")
        fun deleteHandle(@PathVariable("id") id:Int){
            val url=SERVICE_PROVIDER_DEPART+"del"
            template.delete(url+id)
        }
    
        //改
        @PutMapping("/")
        public fun updateHandle(@RequestBody depart: Depart){
            template.put(SERVICE_PROVIDER_DEPART,depart)
        }
    
        //查单个
        @GetMapping("/get/{id}")
        fun getHandle(@PathVariable("id") id:Int):Depart?{
            val url:String= "$SERVICE_PROVIDER_DEPART/get/$id"
            return  template.getForObject(url,Depart::class.java)
        }
    
        //查全部
        @GetMapping("/list")
        fun listHandle():List<Depart>?{
            val url="$SERVICE_PROVIDER_DEPART/list"
            return template.getForObject(url,Array<Depart>::class.java)?.toList()
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    这些都完成之后就可以启动两个服务进行测试了。
    有任何问题欢迎私信我,或者添加我的联系方式,我会很乐于交流!

  • 相关阅读:
    森林消防隔膜泵的应用与前景——恒峰智慧科技
    网站部署:使用Nginx部署vue项目到阿里云服务器
    爆肝!阿里最新版的Spring Security源码手册,强行霸占GitHub榜首
    《代码整洁之道》读书笔记(二)
    Redis数据类型-Hash-存储结构之ziplist
    Ansible简介-安装
    工程压缩与解压缩
    Sqoop数据导出 第3关:Hive数据导出至MySQL中
    【网站架构】服务器弹性伸缩不能全自动,实际如何追加服务器
    循环神经网络介绍(RNN)
  • 原文地址:https://blog.csdn.net/qq_44095715/article/details/134396240