容器化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连接池依赖
groovy 复制代码
dependencies {  
// other denpendencies
	implementation 'mysql:mysql-connector-java:8.0.26'  
	implementation("com.alibaba:druid:1.2.20")
// other denpendencies
}
  • mvn官网查询springcloud的导入方式,springcloud的github页面查询版本对应关系
  • mvn官网查询springcloudalibaba,引入springcloudalibaba对应版本
  • 引入spring-cloud-alibaba-nacos-discovery
groovy 复制代码
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
    }
}
  • 开放服务器8848、9848端口

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

yaml 复制代码
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

新建consumer模块

  • 新建模块(命名为provider) 选择spring 3.0.2
  • 依赖添加spring web、lombok
  • 引入provider0引入的微服务依赖内容(spring、springcloudalibaba、nacos-discovery)
groovy 复制代码
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
    }
}
  • 配置consumer的yml
yml 复制代码
spring:
  cloud:
    nacos:
      discovery:
        # nacos注册中心地址
        server-addr: 127.0.0.1:8848
        username: nacos
        password: nacos
  # 微服务名称
  application:
    name: depart-consumer
  • 以上配置完成,启动provider和consumer,可以在注册中nacos中找到这两个服务
  • 如何容器化配置并启动nacos在文章开头的链接中

consumer和provider通信

provider代码测试

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

  • 实体类
kotlin 复制代码
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

}
  • 服务层
kotlin 复制代码
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()

}
  • 持久层
kotlin 复制代码
package com.rdt.provider8081.repository  
  
import com.rdt.provider8081.bean.Depart  
import org.springframework.data.jpa.repository.JpaRepository  
  
interface DepartRepository :JpaRepository<Depart,Int>{  
}
  • 视图层
kotlin 复制代码
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<String, Any>()
                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
    }

}

Consumer代码测试

  • 注意,目前新版的springcloudAlibaba已经弃用了ribbon,所以负载均衡需要引入依赖
  • consumer不需要持久层,consumer是调用provider的,它不与数据库交互
groovy 复制代码
dependencies{
    //nacos-discover引入
    implementation 'org.springframework.cloud:spring-cloud-starter-loadbalancer:4.0.4'
}
  • 实体层
kotlin 复制代码
package com.rdt.consumer8080.bean

class Depart {
     var id:Int?=null
     var name:String?=null
}
  • 配置类
  • consumer需要配置类,在视图层需要使用
kotlin 复制代码
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()  
}  
  
}
  • 视图层
kotlin 复制代码
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()
    }

}

这些都完成之后就可以启动两个服务进行测试了。

有任何问题欢迎私信我,或者添加我的联系方式,我会很乐于交流!

相关推荐
丘山子39 分钟前
一些鲜为人知的 IP 地址怪异写法
前端·后端·tcp/ip
投笔丶从戎1 小时前
Kotlin Multiplatform--01:项目结构基础
android·开发语言·kotlin
CopyLower1 小时前
在 Spring Boot 中实现 WebSockets
spring boot·后端·iphone
IT小辉同学1 小时前
Docker如何更换镜像源提高拉取速度
spring cloud·docker·eureka
.生产的驴2 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
景天科技苑2 小时前
【Rust】Rust中的枚举与模式匹配,原理解析与应用实战
开发语言·后端·rust·match·enum·枚举与模式匹配·rust枚举与模式匹配
追逐时光者3 小时前
MongoDB从入门到实战之Docker快速安装MongoDB
后端·mongodb
方圆想当图灵3 小时前
深入理解 AOP:使用 AspectJ 实现对 Maven 依赖中 Jar 包类的织入
后端·maven
豌豆花下猫3 小时前
Python 潮流周刊#99:如何在生产环境中运行 Python?(摘要)
后端·python·ai
嘻嘻嘻嘻嘻嘻ys3 小时前
《Spring Boot 3 + Java 17:响应式云原生架构深度实践与范式革新》
前端·后端