微服務框架:如果不用 Spring Boot,還可以選擇誰?

来源:https://www.cnblogs.com/javastack/archive/2022/11/02/16851078.html
-Advertisement-
Play Games

前言 在 Java 和 Kotlin 中, 除了使用Spring Boot創建微服務外,還有很多其他的替代方案。 | 名稱 | 開發商 | | : : | : : | | Helidon SE | 甲骨文 | | Ktor | JetBrains | | Micronaut | Object Com ...


前言

在 Java 和 Kotlin 中, 除了使用Spring Boot創建微服務外,還有很多其他的替代方案。

名稱 開發商
Helidon SE 甲骨文
Ktor JetBrains
Micronaut Object Computing
Quarkus Red Hat
Spring Boot Pivotal

本文,基於這些微服務框架,創建了五個服務,並使用Consul的服務發現模式實現服務間的 相互通信。因此,它們形成了異構微服務架構(Heterogeneous Microservice Architecture, 以下簡稱 MSA):

本文簡要考慮了微服務在各個框架上的實現(更多細節請查看源代碼:https : //github.com/rkudryashov/heterogeneous-microservices)

  • 技術棧:
  • JDK 13
  • Kotlin
  • Gradle (Kotlin DSL)
  • JUnit 5
  • 功能介面(HTTP API):
  • GET /application-info{?request-to=some-service-name}
  • GET /application-info/logo
  • 實現方式:
  • 使用文本文件的配置方式
  • 使用依賴註入
  • HTTP API
  • MSA:
  • 使用服務發現模式(在Consul中註冊,通過客戶端負載均衡的名稱請求另一個微服務的HTTP API)
  • 構建一個 uber-JAR

先決條件

  • JDK 13
  • Consul

從頭開始創建應用程式

要基於其中一個框架上生成新項目,你可以使用web starter 或其他選項(例如,構建工具或 IDE):

名稱 支持的開發語言
Helidon Java,Kotlin
Ktor Kotlin
Micronaut Groovy、Java、Kotlin
Quarkus Java、Kotlin、Scala
Spring Boot Groovy、Java、Kotlin

Helidon服務

該框架是在 Oracle 中創建以供內部使用,隨後成為開源。Helidon 非常簡單和快捷,它提供了兩個版本:標準版(SE)和MicroProfile(MP)。在這兩種情況下,服務都是一個常規的 Java SE 程式。(在Helidon上瞭解更多信息)

Helidon MP 是 Eclipse MicroProfile的實現之一,這使得使用許多 API 成為可能,包括 Java EE 開發人員已知的(例如 JAX-RS、CDI等)和新的 API(健康檢查、指標、容錯等)。在 Helidon SE 模型中,開發人員遵循“沒有魔法”的原則,例如,創建應用程式所需的註解數量較少或完全沒有。

Helidon SE 被選中用於微服務的開發。因為Helidon SE 缺乏依賴註入的手段,因此為此使用了Koin。

以下代碼示例,是包含 main 方法的類。為了實現依賴註入,該類繼承自KoinComponent。

首先,Koin 啟動,然後初始化所需的依賴並調用startServer()方法—-其中創建了一個WebServer類型的對象,應用程式配置和路由設置傳遞到該對象;

啟動應用程式後在Consul註冊:

object HelidonServiceApplication : KoinComponent {
​
    @JvmStatic
    fun main(args: Array<String>) {
        val startTime = System.currentTimeMillis()
        startKoin {
            modules(koinModule)
        }
​
        val applicationInfoService: ApplicationInfoService by inject()
        val consulClient: Consul by inject()
        val applicationInfoProperties: ApplicationInfoProperties by inject()
        val serviceName = applicationInfoProperties.name
​
        startServer(applicationInfoService, consulClient, serviceName, startTime)
    }
}
​
fun startServer(
    applicationInfoService: ApplicationInfoService,
    consulClient: Consul,
    serviceName: String,
    startTime: Long
): WebServer {
    val serverConfig = ServerConfiguration.create(Config.create().get("webserver"))
​
    val server: WebServer = WebServer
        .builder(createRouting(applicationInfoService))
        .config(serverConfig)
        .build()
​
    server.start().thenAccept { ws ->
        val durationInMillis = System.currentTimeMillis() - startTime
        log.info("Startup completed in $durationInMillis ms. Service running at: http://localhost:" + ws.port())
        // register in Consul
        consulClient.agentClient().register(createConsulRegistration(serviceName, ws.port()))
    }
​
    return server
}

路由配置如下:

private fun createRouting(applicationInfoService: ApplicationInfoService) = Routing.builder()
    .register(JacksonSupport.create())
    .get("/application-info", Handler { req, res ->
        val requestTo: String? = req.queryParams()
            .first("request-to")
            .orElse(null)
​
        res
            .status(Http.ResponseStatus.create(200))
            .send(applicationInfoService.get(requestTo))
    })
    .get("/application-info/logo", Handler { req, res ->
        res.headers().contentType(MediaType.create("image", "png"))
        res
            .status(Http.ResponseStatus.create(200))
            .send(applicationInfoService.getLogo())
    })
    .error(Exception::class.java) { req, res, ex ->
        log.error("Exception:", ex)
        res.status(Http.Status.INTERNAL_SERVER_ERROR_500).send()
    }
    .build()

該應用程式使用HOCON格式的配置文件:

webserver {
  port: 8081
}
​
application-info {
  name: "helidon-service"
  framework {
    name: "Helidon SE"
    release-year: 2019
  }
}

還可以使用 JSON、YAML 和properties 格式的文件進行配置(在Helidon 配置文檔中瞭解更多信息)。

Ktor服務

該框架是為 Kotlin 編寫和設計的。和 Helidon SE 一樣,Ktor 沒有開箱即用的 DI,所以在啟動伺服器依賴項之前應該使用 Koin 註入:

val koinModule = module {
    single { ApplicationInfoService(get(), get()) }
    single { ApplicationInfoProperties() }
    single { ServiceClient(get()) }
    single { Consul.builder().withUrl("https://localhost:8500").build() }
}
​
fun main(args: Array<String>) {
    startKoin {
        modules(koinModule)
    }
    val server = embeddedServer(Netty, commandLineEnvironment(args))
    server.start(wait = true)
}

應用程式需要的模塊在配置文件中指定(HOCON格式;更多配置信息參考Ktor配置文檔 ),其內容如下:

ktor {
  deployment {
    host = localhost
    port = 8082
    environment = prod
    // for dev purpose
    autoreload = true
    watch = [io.heterogeneousmicroservices.ktorservice]
  }
  application {
    modules = [io.heterogeneousmicroservices.ktorservice.module.KtorServiceApplicationModuleKt.module]
  }
}
​
application-info {
  name: "ktor-service"
  framework {
    name: "Ktor"
    release-year: 2018
  }
}

在 Ktor 和 Koin 中,術語“模塊”具有不同的含義。

在 Koin 中,模塊類似於 Spring 框架中的應用程式上下文。Ktor的模塊是一個用戶定義的函數,它接受一個 Application類型的對象,可以配置流水線、註冊路由、處理請求等:

fun Application.module() {
    val applicationInfoService: ApplicationInfoService by inject()
​
    if (!isTest()) {
        val consulClient: Consul by inject()
        registerInConsul(applicationInfoService.get(null).name, consulClient)
    }
​
    install(DefaultHeaders)
    install(Compression)
    install(CallLogging)
    install(ContentNegotiation) {
        jackson {}
    }
​
    routing {
        route("application-info") {
            get {
                val requestTo: String? = call.parameters["request-to"]
                call.respond(applicationInfoService.get(requestTo))
            }
            static {
                resource("/logo", "logo.png")
            }
        }
    }
}

此代碼是配置請求的路由,特別是靜態資源logo.png。

下麵是基於Round-robin演算法結合客戶端負載均衡實現服務發現模式的代碼:

class ConsulFeature(private val consulClient: Consul) {
​
    class Config {
        lateinit var consulClient: Consul
    }
​
    companion object Feature : HttpClientFeature<Config, ConsulFeature> {
        var serviceInstanceIndex: Int = 0
​
        override val key = AttributeKey<ConsulFeature>("ConsulFeature")
​
        override fun prepare(block: Config.() -> Unit) = ConsulFeature(Config().apply(block).consulClient)
​
        override fun install(feature: ConsulFeature, scope: HttpClient) {
            scope.requestPipeline.intercept(HttpRequestPipeline.Render) {
                val serviceName = context.url.host
                val serviceInstances =
                    feature.consulClient.healthClient().getHealthyServiceInstances(serviceName).response
                val selectedInstance = serviceInstances[serviceInstanceIndex]
                context.url.apply {
                    host = selectedInstance.service.address
                    port = selectedInstance.service.port
                }
                serviceInstanceIndex = (serviceInstanceIndex + 1) % serviceInstances.size
            }
        }
    }
}

主要邏輯在install方法中:在Render請求階段(在Send階段之前執行)首先確定被調用服務的名稱,然後consulClient請求服務的實例列表,然後通過迴圈演算法定義一個實例正在調用。因此,以下調用成為可能:

fun getApplicationInfo(serviceName: String): ApplicationInfo = runBlocking {
    httpClient.get<ApplicationInfo>("http://$serviceName/application-info")
}

Micronaut 服務

Micronaut 由Grails框架的創建者開發,靈感來自使用 Spring、Spring Boot 和 Grails 構建服務的經驗。該框架目前支持 Java、Kotlin 和 Groovy 語言。依賴是在編譯時註入的,與 Spring Boot 相比,這會導致更少的記憶體消耗和更快的應用程式啟動。

主類如下所示:

object MicronautServiceApplication {
​
    @JvmStatic
    fun main(args: Array<String>) {
        Micronaut.build()
            .packages("io.heterogeneousmicroservices.micronautservice")
            .mainClass(MicronautServiceApplication.javaClass)
            .start()
    }
}

基於 Micronaut 的應用程式的某些組件與它們在 Spring Boot 應用程式中的對應組件類似,例如,以下是控制器代碼:

@Controller(
    value = "/application-info",
    consumes = [MediaType.APPLICATION_JSON],
    produces = [MediaType.APPLICATION_JSON]
)
class ApplicationInfoController(
    private val applicationInfoService: ApplicationInfoService
) {
​
    @Get
    fun get(requestTo: String?): ApplicationInfo = applicationInfoService.get(requestTo)
​
    @Get("/logo", produces = [MediaType.IMAGE_PNG])
    fun getLogo(): ByteArray = applicationInfoService.getLogo()
}

Micronaut 中對 Kotlin 的支持建立在kapt編譯器插件的基礎上(參考Micronaut Kotlin 指南瞭解更多詳細信息)。

構建腳本配置如下:

plugins {
    ...
    kotlin("kapt")
    ...
}
​
dependencies {
    kapt("io.micronaut:micronaut-inject-java:$micronautVersion")
    ...
    kaptTest("io.micronaut:micronaut-inject-java:$micronautVersion")
    ...
}

以下是配置文件的內容:

micronaut:
  application:
    name: micronaut-service
  server:
    port: 8083
​
consul:
  client:
    registration:
      enabled: true
​
application-info:
  name: ${micronaut.application.name}
  framework:
    name: Micronaut
    release-year: 2018

JSON、properties和 Groovy 文件格式也可用於配置(參考Micronaut 配置指南查看更多詳細信息)。

Quarkus服務

Quarkus是作為一種應對新部署環境和應用程式架構等挑戰的工具而引入的,在框架上編寫的應用程式將具有低記憶體消耗和更快的啟動時間。此外,對開發人員也很友好,例如,開箱即用的實時重新載入。

Quarkus 應用程式目前沒有 main 方法,但也許未來會出現(GitHub 上的問題)。

對於熟悉 Spring 或 Java EE 的人來說,Controller 看起來非常熟悉:

@Path("/application-info")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
class ApplicationInfoResource(
    @Inject private val applicationInfoService: ApplicationInfoService
) {
​
    @GET
    fun get(@QueryParam("request-to") requestTo: String?): Response =
        Response.ok(applicationInfoService.get(requestTo)).build()
​
    @GET
    @Path("/logo")
    @Produces("image/png")
    fun logo(): Response = Response.ok(applicationInfoService.getLogo()).build()
}

如你所見,bean 是通過@Inject註解註入的,對於註入的 bean,你可以指定一個範圍,例如:

@ApplicationScoped
class ApplicationInfoService(
    ...
) {
...
}

為其他服務創建 REST 介面,就像使用 JAX-RS 和 MicroProfile 創建介面一樣簡單:

@ApplicationScoped
@Path("/")
interface ExternalServiceClient {
    @GET
    @Path("/application-info")
    @Produces("application/json")
    fun getApplicationInfo(): ApplicationInfo
}
​
@RegisterRestClient(baseUri = "http://helidon-service")
interface HelidonServiceClient : ExternalServiceClient
​
@RegisterRestClient(baseUri = "http://ktor-service")
interface KtorServiceClient : ExternalServiceClient
​
@RegisterRestClient(baseUri = "http://micronaut-service")
interface MicronautServiceClient : ExternalServiceClient
​
@RegisterRestClient(baseUri = "http://quarkus-service")
interface QuarkusServiceClient : ExternalServiceClient
​
@RegisterRestClient(baseUri = "http://spring-boot-service")
interface SpringBootServiceClient : ExternalServiceClient

但是它現在缺乏對服務發現 ( Eureka和Consul ) 的內置支持,因為該框架主要針對雲環境。因此,在 Helidon 和 Ktor 服務中, 我使用了Java類庫方式的Consul 客戶端。

首先,需要註冊應用程式:

@ApplicationScoped
class ConsulRegistrationBean(
    @Inject private val consulClient: ConsulClient
) {
​
    fun onStart(@Observes event: StartupEvent) {
        consulClient.register()
    }
}

然後需要將服務的名稱解析到其特定位置;

解析是通過從 Consul 客戶端獲得的服務的位置替換 requestContext的URI 來實現的:

@Provider
@ApplicationScoped
class ConsulFilter(
    @Inject private val consulClient: ConsulClient
) : ClientRequestFilter {
​
    override fun filter(requestContext: ClientRequestContext) {
        val serviceName = requestContext.uri.host
        val serviceInstance = consulClient.getServiceInstance(serviceName)
        val newUri: URI = URIBuilder(URI.create(requestContext.uri.toString()))
            .setHost(serviceInstance.address)
            .setPort(serviceInstance.port)
            .build()
​
        requestContext.uri = newUri
    }
}

Quarkus也支持通過properties 或 YAML 文件進行配置(參考Quarkus 配置指南瞭解更多詳細信息)。

Spring Boot服務

創建該框架是為了使用 Spring Framework 生態系統,同時有利於簡化應用程式的開發。這是通過auto-configuration實現的。

Spring Boot 基礎就不介紹了,推薦下這個實戰教程:
https://github.com/javastacks/javastack

以下是控制器代碼:

@RestController
@RequestMapping(path = ["application-info"], produces = [MediaType.APPLICATION_JSON_VALUE])
class ApplicationInfoController(
    private val applicationInfoService: ApplicationInfoService
) {
​
    @GetMapping
    fun get(@RequestParam("request-to") requestTo: String?): ApplicationInfo = applicationInfoService.get(requestTo)
​
    @GetMapping(path = ["/logo"], produces = [MediaType.IMAGE_PNG_VALUE])
    fun getLogo(): ByteArray = applicationInfoService.getLogo()
}

微服務由 YAML 文件配置:

spring:
  application:
    name: spring-boot-service
​
server:
  port: 8085
​
application-info:
  name: ${spring.application.name}
  framework:
    name: Spring Boot
    release-year: 2014

也可以使用properties文件進行配置(更多信息參考Spring Boot 配置文檔)。

啟動微服務

在啟動微服務之前,你需要安裝Consul和 啟動代理-例如,像這樣:consul agent -dev。

你可以從以下位置啟動微服務:

IDE中啟動微服務IntelliJ IDEA 的用戶可能會看到如下內容:

要啟動 Quarkus 服務,你需要啟動quarkusDev的Gradle 任務。

console中啟動微服務在項目的根文件夾中執行:

java -jar helidon-service/build/libs/helidon-service-all.jar

java -jar ktor-service/build/libs/ktor-service-all.jar

java -jar micronaut-service/build/libs/micronaut-service-all.jar

java -jar quarkus-service/build/quarkus-service-1.0.0-runner.jar

java -jar spring-boot-service/build/libs/spring-boot-service.jar

啟動所有微服務後,訪問http://localhost:8500/ui/dc1/services,你將看到:

API測試

以Helidon服務的API測試結果為例:

GET http://localhost:8081/application-info

{
  "name": "helidon-service",
  "framework": {
    "name": "Helidon SE",
    "releaseYear": 2019
  },
  "requestedService": null
}

GET http://localhost:8081/application-info?request-to=ktor-service

{
  "name": "helidon-service",
  "framework": {
    "name": "Helidon SE",
    "releaseYear": 2019
  },
  "requestedService": {
    "name": "ktor-service",
    "framework": {
          "name": "Ktor",
          "releaseYear": 2018
    },
    "requestedService": null
  }
}

GET http://localhost:8081/application-info/logo返回logo信息

你可以使用Postman 、IntelliJ IDEA HTTP 客戶端 、瀏覽器或其他工具測試微服務的 API介面 。

不同微服務框架對比

不同微服務框架的新版本發佈後,下麵的結果可能會有變化;你可以使用此GitHub項目自行檢查最新的對比結果 。

程式大小

為了保證設置應用程式的簡單性,構建腳本中沒有排除傳遞依賴項,因此 Spring Boot 服務 uber-JAR 的大小大大超過了其他框架上的類似物的大小(因為使用 starters 不僅導入了必要的依賴項;如果需要,可以通過排除指定依賴來減小大小):

備註:什麼是 maven的uber-jar

在maven的一些文檔中我們會發現 “uber-jar”這個術語,許多人看到後感到困惑。其實在很多編程語言中會把super叫做uber (因為super可能是關鍵字), 這是上世紀80年代開始流行的,比如管superman叫uberman。所以uber-jar從字面上理解就是super-jar,這樣的jar不但包含自己代碼中的class ,也會包含一些第三方依賴的jar,也就是把自身的代碼和其依賴的jar全打包在一個jar裡面了,所以就很形象的稱其為super-jar ,uber-jar來歷就是這樣的。

微服務 程式大小(MB)
Helidon服務 17,3
Ktor服務 22,4
Micronaut 服務 17,1
Quarkus服務 24,4
Spring Boot服務 45,2

啟動時長

每個應用程式的啟動時長都是不固定的:

微服務 開始時間(秒)
Helidon服務 2,0
Ktor服務 1,5
Micronaut 服務 2,8
Quarkus服務 1,9
Spring Boot服務 10,7

值得註意的是,如果你將 Spring Boot 中不必要的依賴排除,並註意設置應用的啟動參數(例如,只掃描必要的包並使用 bean 的延遲初始化),那麼你可以顯著地減少啟動時間。

記憶體使用情況

對於每個微服務,確定了以下內容:

  • 通過-Xmx參數,指定微服務所需的堆記憶體大小
  • 通過負載測試服務健康的請求(能夠響應不同的請求)
  • 通過負載測試50 個用戶 * 1000 個的請求
  • 通過負載測試500 個用戶 * 1000 個的請求

堆記憶體只是為應用程式分配的總記憶體的一部分。例如,如果要測量總體記憶體使用情況,可以參考本指南。

對於負載測試,使用了Gatling和Scala腳本 。

1、負載生成器和被測試的服務在同一臺機器上運行(Windows 10、3.2 GHz 四核處理器、24 GB RAM、SSD)。

2、服務的埠在 Scala 腳本中指定。

3、通過負載測試意味著微服務已經響應了所有時間的所有請求。

微服務 堆記憶體大小(MB) 堆記憶體大小(MB) 堆記憶體大小(MB)
對於健康服務 對於 50 * 1000 的負載 對於 500 * 1000 的負載
Helidon服務 11 9 11
Ktor服務 13 11 15
Micronaut 服務 17 15 19
Quarkus服務 13 17 21
Spring Boot服務 18 19 23

需要註意的是,所有微服務都使用 Netty HTTP 伺服器。

結論

通過上文,我們所需的功能——一個帶有 HTTP API 的簡單服務和在 MSA 中運行的能力——在所有考慮的框架中都取得了成功。

是時候開始盤點並考慮他們的利弊了。

Helidon標準版

優點

創建的應用程式,只需要一個註釋(@JvmStatic)

缺點

開發所需的一些組件缺少開箱即用(例如,依賴註入和與服務發現伺服器的交互)

Helidon MicroProfile

微服務還沒有在這個框架上實現,所以這裡簡單說明一下。

優點

1、Eclipse MicroProfile 實現

2、本質上,MicroProfile 是針對 MSA 優化的 Java EE。因此,首先你可以訪問各種 Java EE API,包括專門為 MSA 開發的 API,其次,你可以將 MicroProfile 的實現更改為任何其他實現(例如:Open Liberty、WildFly Swarm 等)

Ktor

優點

1、輕量級的允許你僅添加執行任務直接需要的那些功能

2、應用參數所有參數的良好結果

缺點

1、依賴於Kotlin,即用其他語言開發可能是不可能的或不值得的

2、微框架:參考Helidon SE

3、目前最流行的兩種 Java 開發模型(Spring Boot/Micronaut)和 Java EE/MicroProfile)

4、中沒有包含該框架,這會導致:

  • 難以尋找專家

  • 由於需要顯式配置所需的功能,因此與 Spring Boot 相比,執行任務的時間有所增加

Micronaut

優點

1、AOT如前所述,與 Spring Boot 上的模擬相比,AOT 可以減少應用程式的啟動時間和記憶體消耗

2、類Spring開發模式有 Spring 框架經驗的程式員不會花太多時間來掌握這個框架

3、Micronaut for Spring可以改變現有的Spring Boot應用程式的執行環境到Micronaut中(有限制)

Quarkus

優點

1、Eclipse MicroProfile 的實現

2、該框架為多種 Spring 技術提供了相容層:DI、 Web、Security、Data JPA

Spring Boot

優點

1、平臺成熟度和生態系統對於大多數日常任務,Spring的編程範式已經有瞭解決方案,也是很多程式員習慣的方式。此外,starter和auto-configuration的概念簡化了開發

2、專家多,文檔詳細

我想很多人都會同意 Spring 在不久的將來仍將是 Java/Kotlin開發領域領先的框架。

缺點

  • 應用參數多且複雜但是,有些參數,如前所述,你可以自己優化。還有一個Spring Fu項目的存在,該項目正在積極開發中,使用它可以減少參數。

Helidon SE 和 Ktor 是 微框架,Spring Boot 和 Micronaut 是全棧框架,Quarkus 和 Helidon MP 是 MicroProfile 框架。微框架的功能有限,這會減慢開發速度。

我不敢判斷這個或那個框架會不會在近期“大更新”,所以在我看來,目前最好繼續觀察,使用熟悉的框架解決工作問題。

同時,如本文所示,新框架在應用程式參數設置方面贏得了 Spring Boot。如果這些參數中的任何一個對你的某個微服務至關重要,那麼也許值得關註。但是,我們不要忘記,Spring Boot 一是在不斷改進,二是它擁有龐大的生態系統,並且有相當多的 Java 程式員熟悉它。此外,還有未涉及的其他框架:Vert.x、Javalin 等,也值得關註。

譯文:https://www.kubernetes.org.cn/9526.html

原文:https://dzone.com/articles/not-only-spring-boot-a-review-of-alternatives

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發佈,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 2022-10-29 處理請求與響應的介面 一、HttpServletRequest (1)HttpServletRequest的含義:HttpServletRequest是一個介面,是ServletRequest介面的子介面,內部封裝了HTTP請求的相關信息。 (2)HttpServletRequ ...
  • 輪播圖組件 <template> <div id="banner"> <el-carousel height="400px"> <!-- 將banner_list迴圈--> <el-carousel-item v-for="item in banner_list" :key="item"> <!-- ...
  • 軟體技術基礎學習筆記(2)——獨立完成一個項目 | 這個作業屬於哪個課程 | <首頁 - 22軟體基礎 - 浙江理工大學 - 班級博客 - 博客園> | | | | | 這個作業的目標 | <在限定的期限內,完成一個滿足客戶要求的項目> | | 姓名-學號 | <曾翊>-<2020330301215 ...
  • 文章目錄 🦠一、前言 🦠二、軟體開發架構 🍀2.1、C/S架構 🍀2.2、B/S架構 🍀2.3、服務端與客戶端 🦠三、ip與埠號 🍀3.1、IP地址與埠號常識 🍀3.2、MAC和IP的概念與不同 🦠四、tcp協議和udp協議 🦠五、乙太網:區域網與交換機 🍀5.1、什麼是局 ...
  • 前言 環境使用 Python 3.8 Pycharm 模塊使用 requests jieba 結巴分詞 wordcloud 詞雲 數據來源分析 明確需求 <數據來源分析> 採集數據是什麼東西? 通過那個url地址得到想要數據的內容 抓包分析: 瀏覽器自帶工具 --> 開發者工具I. F12 或者 鼠 ...
  • 邏輯導航 1.當一訪問127.0.0.1:8000時,就會向某一地址發送請求 2.請求介面需要返迴首頁所需要的輪播圖片 3.前端vue輪播圖組件迴圈一下後端發送的圖片連接列表,依次展示輪播圖 輪播圖表設計 輪播圖中一些共有的欄位,我們可以創建一個公共的基礎表,以後需要該欄位直接基礎該表就行 基表,可 ...
  • 疫情尚未結束,我們需要做好自己,時刻防範,不給別人添麻煩。 今天我們來嘗試用Python抓取世界疫情,實現可視化地圖展示。 話不多說直接開搞! 採集數據 1、數據來源 數據來源於TX新聞,鏈接展示不了,就只貼圖了。 2、模塊 import requests import csv # Python學習 ...
  • 1. Seata Server 部署 Seata分TC、TM和RM三個角色,TC(Server端)為單獨服務端部署,TM和RM(Client端)由業務系統集成。 首先,下載最新的安裝包 也可以下載源碼,然後本地編譯。最新的版本是1.5.2 下載後的啟動包(或者源碼)中有個scripts目錄,裡面有各 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...