-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
515 lines (337 loc) · 51.9 KB
/
index.html
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
<link rel="mask-icon" href="/images/logo.svg" color="#222">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
<script id="hexo-configurations">
var NexT = window.NexT || {};
var CONFIG = {"hostname":"yoursite.com","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
</script>
<meta property="og:type" content="website">
<meta property="og:title" content="昊Site">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="昊Site">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="zyh">
<meta name="twitter:card" content="summary">
<link rel="canonical" href="http://yoursite.com/">
<script id="page-configurations">
// https://hexo.io/docs/variables.html
CONFIG.page = {
sidebar: "",
isHome : true,
isPost : false,
lang : 'zh-CN'
};
</script>
<title>昊Site</title>
<noscript>
<style>
.use-motion .brand,
.use-motion .menu-item,
.sidebar-inner,
.use-motion .post-block,
.use-motion .pagination,
.use-motion .comments,
.use-motion .post-header,
.use-motion .post-body,
.use-motion .collection-header { opacity: initial; }
.use-motion .site-title,
.use-motion .site-subtitle {
opacity: initial;
top: initial;
}
.use-motion .logo-line-before i { left: initial; }
.use-motion .logo-line-after i { right: initial; }
</style>
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<div class="container use-motion">
<div class="headband"></div>
<header class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-container">
<div class="site-nav-toggle">
<div class="toggle" aria-label="切换导航栏">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
</div>
<div class="site-meta">
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<h1 class="site-title">昊Site</h1>
<span class="logo-line-after"><i></i></span>
</a>
<p class="site-subtitle" itemprop="description">勿在浮沙筑高台</p>
</div>
<div class="site-nav-right">
<div class="toggle popup-trigger">
</div>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="main-menu menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>
</li>
<li class="menu-item menu-item-about">
<a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a>
</li>
<li class="menu-item menu-item-categories">
<a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>
</li>
</ul>
</nav>
</div>
</header>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
<span>0%</span>
</div>
<main class="main">
<div class="main-inner">
<div class="content-wrap">
<div class="content index posts-expand">
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2020/06/08/microservice02/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar2.jpg">
<meta itemprop="name" content="zyh">
<meta itemprop="description" content="">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="昊Site">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2020/06/08/microservice02/" class="post-title-link" itemprop="url">使用Netflix Eureka进行服务发现</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-06-08 16:09:18" itemprop="dateCreated datePublished" datetime="2020-06-08T16:09:18+08:00">2020-06-08</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar-check"></i>
</span>
<span class="post-meta-item-text">更新于</span>
<time title="修改时间:2020-07-12 22:59:01" itemprop="dateModified" datetime="2020-07-12T22:59:01+08:00">2020-07-12</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/Spring%E5%BE%AE%E6%9C%8D%E5%8A%A1/" itemprop="url" rel="index"><span itemprop="name">Spring微服务</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p> 在任何分布式架构中,都需要找到机器所在的物理地址。这个概念自分布式计算开始出现就已经存在,并且被正式称为服<br> 务发现。服务发现对于微服务和基于云的应用程序至关重要,主要有两个原因。首先,它为应用团队提供了一种能力,可<br> 以快速地对在环境中运行的服务实例数量进行水平伸缩。通过服务发现,服务消费者能够将服务的物理位置抽象出来。由<br> 于服务消费这不知道服务实例的物理位置,因此可以在不影响服务运行的情况下服务池中添加和移除服务实例。<br> 服务发现的第二个好处是,它有助于提高应用程序的弹性。当微服务实例变的不健康或者不可用时,大多数服务发现引擎<br> 将从内部移除该服务实例,并在路由时绕过不可用的服务,使不可用的服务造成的损害最小。</p>
<h3 id="服务发现架构"><a href="#服务发现架构" class="headerlink" title="服务发现架构"></a>服务发现架构</h3><p> 在讨论服务架构前,需要了解4个概念,这些在所有服务发现实现中都是共通的。<br> (1)服务注册——服务如何使用服务发现代理进行注册?<br> (2)服务地址的客户端查找——服务客户端查找服务信息的方法是什么?<br> (3)信息共享——如何跨节点共享服务信息?<br> (4)健康监控——服务发现代理如何监控其代理的服务的健康信息?</p>
<p> 下图为实现以上4个概念的架构:</p>
<p><img src="/image/eurekadiscovery01.png" alt="服务发现架构图1"></p>
<p> 服务在向服务发现进行注册之后,这个服务就可被需要使用这项服务功能的应用程序或其他服务使用。客户端可以使用不同模型来“发现”服务,在每次服务调用时客户端服务通过发现引擎来解析服务位置。但是,这种方法很脆弱,因为付客服端完全依赖于服务发现引擎来查找和调用服务。一种更健壮的方法是使用客户端负载均衡,使用Netflix的Ribbon库来实现客户端负载均衡,架构如下图:</p>
<p><img src="/image/eurekadiscovery02.png" alt="服务发现架构图2"></p>
<h3 id="使用Netflix-Eureka进行服务发现代理"><a href="#使用Netflix-Eureka进行服务发现代理" class="headerlink" title="使用Netflix Eureka进行服务发现代理"></a>使用Netflix Eureka进行服务发现代理</h3><p> 本文将使用Spring Cloud和Netflix Eureka实现服务发现代理,并通过Netflix的Ribbon库来实现客户端负载均衡。本次实践将创建两个客服端服务项目,许可证服务licensingservice和组织服务organizationservice。当许可证服务被调用时,他将调用组织服务以检索指定的组织信息。组织服务的位置的实际解析存储在服务发现注册列表中。本例将使用服务发现代理注册两个组织服务实例。<br>(1)随着服务启动,许可证服务和组织服务将通过Eureka服务进行注册,这个注册过程将告诉Eureka每个服务实例的物理位置和端口号,以及正在启动的服务的服务ID。<br>(2)当许可证服务调用组织服务时,许可证服务将使用Netflix Ribbon库来提供客户端负载均衡。Ribbon将联系Eureka服务去检索服务位置信息,然后在本地缓存。<br>(3)Netflix Ribbon 库将定期对Eureka服务进行ping操作,并刷新服务位置的本地缓存,任何新的组织服务实例都将对许可证服务可见,而任何不健康的实例都将从本地缓存移除。</p>
<h4 id="构建Spring-Eureka服务"><a href="#构建Spring-Eureka服务" class="headerlink" title="构建Spring Eureka服务"></a>构建Spring Eureka服务</h4><p>与Spring Cloud配置服务一样,我们将从构建新的Spring Boot项目开始,并运用注解来建立Spring Cloud Eureka服务。<br>代码清单1 pom.xml依赖配置</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><?xml version="1.0" encoding="UTF-8"?></span><br><span class="line"><project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"</span><br><span class="line"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"></span><br><span class="line"> <modelVersion>4.0.0</modelVersion></span><br><span class="line"></span><br><span class="line"> <groupId>com.thoughtmechanix</groupId></span><br><span class="line"> <artifactId>eurekasvr</artifactId></span><br><span class="line"> <version>0.0.1-SNAPSHOT</version></span><br><span class="line"> <packaging>jar</packaging></span><br><span class="line"></span><br><span class="line"> <name>Eureka Server</name></span><br><span class="line"> <description>Eureka Server demo project</description></span><br><span class="line"></span><br><span class="line"> <parent></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-starter-parent</artifactId></span><br><span class="line"> <version>1.4.4.RELEASE</version></span><br><span class="line"> </parent></span><br><span class="line"> <dependencyManagement></span><br><span class="line"> <dependencies></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-dependencies</artifactId></span><br><span class="line"> <version>Camden.SR5</version></span><br><span class="line"> <type>pom</type></span><br><span class="line"> <scope>import</scope></span><br><span class="line"> </dependency></span><br><span class="line"> </dependencies></span><br><span class="line"> </dependencyManagement></span><br><span class="line"></span><br><span class="line"> <dependencies></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-eureka-server</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-autoconfigure</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"> </dependencies></span><br><span class="line"></span><br><span class="line"> <properties></span><br><span class="line"> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></span><br><span class="line"> <start-class>com.thoughtmechanix.eurekasvr.EurekaServerApplication</start-class></span><br><span class="line"> <java.version>1.8</java.version></span><br><span class="line"> </properties></span><br><span class="line"></span><br><span class="line"> <build></span><br><span class="line"> <plugins></span><br><span class="line"> <plugin></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-maven-plugin</artifactId></span><br><span class="line"> </plugin></span><br><span class="line"> </plugins></span><br><span class="line"> </build></span><br><span class="line"></project></span><br></pre></td></tr></table></figure>
<p> 接着需要在resources目录下配置application.yml文件,在这里需要添加以独立模式运行的Eureka服务所需配置<br>代码清单2 在application.yml文件配置Eureka服务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">server:</span><br><span class="line"> port: 8761</span><br><span class="line">eureka:</span><br><span class="line"> instance:</span><br><span class="line"> hostname: localhost</span><br><span class="line"> client:</span><br><span class="line"> registerWithEureka: false</span><br><span class="line"> fetchRegistry: false</span><br><span class="line"> serviceUrl:</span><br><span class="line"> defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/</span><br><span class="line"> server:</span><br><span class="line"> waitTimeInMsWhenSyncEmpty: 0</span><br></pre></td></tr></table></figure>
<p>属性说明:<br>port: Eureka 服务将要监听的端口<br>hostname: 指定主机名,可以不用单独指定<br>registerWithEureka:是否将当前服务通过Eureka服务进行注册<br>fetchRegistry:注册时是否尝试在本地缓存注册表信息<br>defaultZone:指定Eureka服务注册地址<br>waitTimeInMsWhenSyncEmpty:Eureka服务启动后延迟多少分钟才通告已注册的服务列表,本地测试时最好注释掉或设为0,加快Eureka服务启动和服务发现过程。</p>
<p> 配置Eureka服务的最后一步是在启动类中加入开启Eureka服务的注解。在EurekaServerApplication中添加注解@EnableEurekaServer<br>代码清单3 添加Eureka服务启动注解</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@SpringBootApplication</span><br><span class="line">@EnableEurekaServer</span><br><span class="line">public class EurekaServerApplication {</span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> SpringApplication.run(EurekaServerApplication.class, args);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>此时,可以通过运行mvn spring-boot:run或运行docker-compose来启动服务。接着在浏览器访问: <a href="http://localhost:8761/,如下图所示:" target="_blank" rel="noopener">http://localhost:8761/,如下图所示:</a><br><img src="/image/eurekadiscovery03.png" alt="eureka服务注册web管理界面图"><br>上图圈中的区域是一个注册到该eureka服务实例的所有服务实例列表,因为此时尚未有任何服务注册,所以列表为空。</p>
<h4 id="通过Spring-Eureka-注册服务"><a href="#通过Spring-Eureka-注册服务" class="headerlink" title="通过Spring Eureka 注册服务"></a>通过Spring Eureka 注册服务</h4><p> 而接下来将构建组织服务,并通过这个Eureka服务来注册组织服务,首先要做的的是将Spring Eureka依赖项添加到组织服务的pom.xml文件中:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-eureka</artifactId></span><br><span class="line"></dependency></span><br></pre></td></tr></table></figure>
<p> 接下来要告诉Spring boot通过Eureka服务来注册组织服务,这个注册是通过组织服务的application.yml文件中的额外配置来完成的。<br>代码清单5 修改组织服务的application.yml配置以便与Eureka通信</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">spring:</span><br><span class="line"> application:</span><br><span class="line"> name: organizationservice</span><br><span class="line">eureka:</span><br><span class="line"> instance:</span><br><span class="line"> preferIpAddress: true #注册服务的IP而不是服务器名称</span><br><span class="line"> client:</span><br><span class="line"> registerWithEureka: true</span><br><span class="line"> fetchRegistry: true</span><br><span class="line"> serviceUrl:</span><br><span class="line"> defaultZone: http://localhost:8761/eureka/ #Eureka服务的位置</span><br><span class="line"> healthcheck:</span><br><span class="line"> enabled: true #开启心跳检测</span><br></pre></td></tr></table></figure>
<p> 每个通过Eureka注册的服务都会有两个与之相关的组件:应用程序ID和实例ID。应用程序ID用于表示一组服务实例。在Spring boot的微服务中,应用程序ID始终是由spring.application.name属性值指定。上述组织服务的服务ID为organizationservice,而实例ID是一个随机数,用于代表单个实例。<br>接下来在组织服务启动类添加Eureka客户端注解,告诉Spring boot以Eureka服务客户端模式启动服务<br>代码清单6 为组织服务添加Eureka服务客户端注解</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@SpringBootApplication</span><br><span class="line">@EnableEurekaClient</span><br><span class="line">public class OrganizationApplication {</span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> SpringApplication.run(OrganizationApplication.class, args);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p> 现在,可以启动组织服务,启动后组织服务将会通过Eureka服务进行注册,此时若再次访问<a href="http://localhost:8761/,可以看到类似如下图的界面:" target="_blank" rel="noopener">http://localhost:8761/,可以看到类似如下图的界面:</a><br><img src="/image/eurekadiscovery04.png" alt="eureka服务注册web管理界面图"><br>若出现的界面与上图类似,说明到此为止应用的搭建还算顺利。可以看到上图的注册到eureka服务的所有服务实例列表不为空,多出了一行,这一行列出的信息代表有一个application Id为”ORGANIZATIONSERVICE”,instance ID为”10.10.1.216:organizationservice:11000”的服务实例注册到eureka,”UP(1)”则代表该服务只有一个实例正在运行。</p>
<p> licenseservice服务的配置和启动注册和organizationservice服务的方式一样,这里就不在累赘,licenseservice注册成功后访问<a href="http://localhost:8761/结果如下图:" target="_blank" rel="noopener">http://localhost:8761/结果如下图:</a><br><img src="/image/eurekadiscovery05.png" alt="eureka服务注册web管理界面图"></p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://yoursite.com/2020/06/05/microservie01/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar2.jpg">
<meta itemprop="name" content="zyh">
<meta itemprop="description" content="">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="昊Site">
</span>
<header class="post-header">
<h2 class="post-title" itemprop="name headline">
<a href="/2020/06/05/microservie01/" class="post-title-link" itemprop="url">Spring Cloud配置管理服务搭建</a>
</h2>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-06-05 16:09:18" itemprop="dateCreated datePublished" datetime="2020-06-05T16:09:18+08:00">2020-06-05</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar-check"></i>
</span>
<span class="post-meta-item-text">更新于</span>
<time title="修改时间:2020-06-26 22:13:16" itemprop="dateModified" datetime="2020-06-26T22:13:16+08:00">2020-06-26</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/Spring%E5%BE%AE%E6%9C%8D%E5%8A%A1/" itemprop="url" rel="index"><span itemprop="name">Spring微服务</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<p> 对于在云中运行的微服务,管理应用程序配置是非常重要的,因为微服务实例需要以最少的人为干预快速启动。每当人们<br> 需要手动配置或接触服务以实现部署时,都有可能出现配置漂移、意外中断以及应用程序响应可伸缩性挑战出现延迟的情<br> 况。<br> 4条原则:<br> (1)分离——服务配置信息应该与服务的实际物理部署完全分开。<br> (2)抽象——将访问配置数据的功能抽象到一个服务接口中。<br> (3)集中——将应用程序配置集中在尽可能少的存储库中,因为基于云的应用程序可能有数百个服务。<br> (4)稳定——保证配置服务高可用和冗余。</p>
<h3 id="配置管理架构"><a href="#配置管理架构" class="headerlink" title="配置管理架构"></a>配置管理架构</h3><p><img src="/image/springcloudconfig01.png" alt="配置管理服务架构图"></p>
<h3 id="实施选择"><a href="#实施选择" class="headerlink" title="实施选择"></a>实施选择</h3><p> Etcd、Eureka、Consul、ZooKeeper、Spring cloud等开源项目都可实现配置服务的搭建,本文使用的是Spring cloud,<br> 主要出于以下几个原因:<br> (1)Spring cloud配置服务易于搭建和使用。<br> (2)Spring cloud配置与Spring boot紧密集成,可以使用简单注解来读取所有应用程序配置。<br> (3)Spring cloud配置服务器提供多个后端用于存储配置数据,如果你已经使用Eureka或Consul等工具,那可以直接插入<br> Spring cloud配置服务器中。<br> (4)Spring cloud配置服务可以直接与Git集成,同时实现配置存储和版本控制。</p>
<h3 id="构建Spring-Cloud配置管理服务"><a href="#构建Spring-Cloud配置管理服务" class="headerlink" title="构建Spring Cloud配置管理服务"></a>构建Spring Cloud配置管理服务</h3><p>代码清单1 Spring Cloud配置服务器maven配置 pom.xml</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><parent></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-starter-parent</artifactId></span><br><span class="line"> <version>1.4.4.RELEASE</version></span><br><span class="line"></parent></span><br><span class="line"><dependencyManagement></span><br><span class="line"> <dependencies></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-dependencies</artifactId></span><br><span class="line"> <version>Camden.SR5</version></span><br><span class="line"> <type>pom</type></span><br><span class="line"> <scope>import</scope></span><br><span class="line"> </dependency></span><br><span class="line"> </dependencies></span><br><span class="line"></dependencyManagement></span><br><span class="line"><dependencies></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-config-server</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-config</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"></dependencies></span><br><span class="line"><properties></span><br><span class="line"> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></span><br><span class="line"> <start-class>com.thoughtmechanix.confsvr.ConfigServerApplication</start-class></span><br><span class="line"> <java.version>1.8</java.version></span><br><span class="line"></properties></span><br><span class="line"></span><br><span class="line"><build></span><br><span class="line"> <plugins></span><br><span class="line"> <plugin></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-maven-plugin</artifactId></span><br><span class="line"> </plugin></span><br><span class="line"> </plugins></span><br><span class="line"></build></span><br></pre></td></tr></table></figure>
<p> 在本例中使用的是Spring Cloud的 Canmden.SR5版本。通过使用BOM定义,可以保证在Spring Cloud中使用子项目的兼容版本。这也意味着不必为子依赖项申明版本号。清单1中剩余部分声明了在服务中使用的特定Spring Cloud依赖项。一个是所有Spring Cloud项目使用的spring-cloud-starter-config。第二个是spring-cloud-config-server起步项目,它包含spring-cloud-config-server的核心库。</p>
<p>代码清单2 Spring Cloud配置服务启动配置<br>bootstrap.yml</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">spring:</span><br><span class="line"> application:</span><br><span class="line"> name: configserver</span><br></pre></td></tr></table></figure>
<p>application.yml</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">server:</span><br><span class="line"> port: 8888</span><br><span class="line">spring:</span><br><span class="line"> cloud:</span><br><span class="line"> config:</span><br><span class="line"> server:</span><br><span class="line"> git:</span><br><span class="line"> uri: github仓库地址</span><br><span class="line"> searchPaths: 配置文件存放路径目录,用‘,’分隔</span><br><span class="line"> username: xxxxx</span><br><span class="line"> password: xxxxx</span><br></pre></td></tr></table></figure>
<h3 id="创建Git仓库"><a href="#创建Git仓库" class="headerlink" title="创建Git仓库"></a>创建Git仓库</h3><p>创建用于存储服务配置的Git仓库,在仓库下建立服务配置目录并将需要管理的微服务配置提交到对应目录下,此目录名对应配置中的searchPaths字段本文会创建一个单独的名为lincensingServer的Spring boot服务,并将通过前面搭建的configserver配置管理服务来托管其服务配置,所以会在git仓库下创建一个名为licensingserver的目录,该目录下创建了三个配置文件分别对应服务的开发环境配置(licensingserver-dev.yml)、生产环境配置(licensingserver-prod.yml)、默认配置(licensingserver.yml),三个文件中都配置了example.property字段用于测试,值分别为“I AM A PROD PROPERTY DEV”,“I AM A PROD PROPERTY OVERRIDE”,“I AM IN THE DEFAULT”。<br>对应的git仓库目录如下:<br><img src="/image/springcloudconfig02.png" alt="git仓库配置存放目录"><br><img src="/image/springcloudconfig03.png" alt="服务配置文件列表"></p>
<h3 id="创建配置管理服务引导类"><a href="#创建配置管理服务引导类" class="headerlink" title="创建配置管理服务引导类"></a>创建配置管理服务引导类</h3><p>代码清单3</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@SpringBootApplication</span><br><span class="line">@EnableConfigServer //使服务成为Spring Cloud Config服务</span><br><span class="line">public class ConfigServerApplication {</span><br><span class="line"> public static void main(String[] args) {</span><br><span class="line"> SpringApplication.run(ConfigServerApplication.class, args);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h3 id="Spring-Cloud客户端服务配置"><a href="#Spring-Cloud客户端服务配置" class="headerlink" title="Spring Cloud客户端服务配置"></a>Spring Cloud客户端服务配置</h3><p>代码清单4 新建一个Spring boot项目licensingServer<br>pom.xml配置</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><parent></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-starter-parent</artifactId></span><br><span class="line"> <version>1.4.4.RELEASE</version></span><br><span class="line"></parent></span><br><span class="line"><dependencyManagement></span><br><span class="line"> <dependencies></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-dependencies</artifactId></span><br><span class="line"> <version>Camden.SR5</version></span><br><span class="line"> <type>pom</type></span><br><span class="line"> <scope>import</scope></span><br><span class="line"> </dependency></span><br><span class="line"> </dependencies></span><br><span class="line"></dependencyManagement></span><br><span class="line"></span><br><span class="line"><dependencies></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-starter-data-jpa</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-starter-web</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"> <!--启动spring cloud config客户端所需依赖--></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-starter-config</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"> <!--spring cloud config客户端核心类库--></span><br><span class="line"> <dependency></span><br><span class="line"> <groupId>org.springframework.cloud</groupId></span><br><span class="line"> <artifactId>spring-cloud-config-client</artifactId></span><br><span class="line"> </dependency></span><br><span class="line"></dependencies></span><br><span class="line"></span><br><span class="line"><properties></span><br><span class="line"> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></span><br><span class="line"> <java.version>1.8</java.version></span><br><span class="line"> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></span><br><span class="line"> <start-class>com.thoughtmechanix.licenses.LIcenseApplication</start-class></span><br><span class="line"></properties></span><br><span class="line"></span><br><span class="line"><build></span><br><span class="line"> <plugins></span><br><span class="line"> <plugin></span><br><span class="line"> <groupId>org.springframework.boot</groupId></span><br><span class="line"> <artifactId>spring-boot-maven-plugin</artifactId></span><br><span class="line"> </plugin></span><br><span class="line"> </plugins></span><br><span class="line"></build></span><br></pre></td></tr></table></figure>
<p>bootstrap.yml配置</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">server:</span><br><span class="line"> port: 8880</span><br><span class="line">spring:</span><br><span class="line"> application:</span><br><span class="line"> name: licensingservice # 配置文件名称,对应 git 仓库中配置文件前半部分</span><br><span class="line"> profiles:</span><br><span class="line"> active:</span><br><span class="line"> default # 指定环境,对应 git 仓库中配置文件的后缀名称,如dev,prod或者无</span><br><span class="line"> cloud:</span><br><span class="line"> config:</span><br><span class="line"> uri: http://localhost:8888 # config-server 服务端地址</span><br></pre></td></tr></table></figure>
<p>为了测试,我们在licensingserver项目下创建一个ServerConfig配置类和LicenseServiceController类,前者用于注入配置服务器管理下的配置文件信息,后者用于暴露请求接口,查询并返回配置信息<br>代码清单5</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">@Component</span><br><span class="line">public class ServiceConfig {</span><br><span class="line"></span><br><span class="line"> @Value("${example.property}")</span><br><span class="line"> private String exampleProperty;</span><br><span class="line"></span><br><span class="line"> public String getExampleProperty() {</span><br><span class="line"> return exampleProperty;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">@RestController</span><br><span class="line">@RequestMapping(value = "v1/license/")</span><br><span class="line">public class LicenseServiceController {</span><br><span class="line"></span><br><span class="line"> @Autowired</span><br><span class="line"> private ServiceConfig serviceConfig;</span><br><span class="line"></span><br><span class="line"> @RequestMapping(value = "/query", method = RequestMethod.GET)</span><br><span class="line"> public String getLicenses() {</span><br><span class="line"> return serviceConfig.getExampleProperty();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>至此,所有服务搭建相关配置已完成,分别启动配置服务 configserver 和 licensingserver 服务,调用 <a href="http://localhost:8880/v1/license/query" target="_blank" rel="noopener">http://localhost:8880/v1/license/query</a> 接口进行测试<br>测试结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ curl http://localhost:8880/v1/license/query</span><br><span class="line">$ I AM IN THE DEFAULT</span><br></pre></td></tr></table></figure>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
</div>
<script>
window.addEventListener('tabs:register', () => {
let { activeClass } = CONFIG.comments;
if (CONFIG.comments.storage) {
activeClass = localStorage.getItem('comments_active') || activeClass;
}
if (activeClass) {
let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
if (activeTab) {
activeTab.click();
}
}
});
if (CONFIG.comments.storage) {
window.addEventListener('tabs:click', event => {
if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
let commentClass = event.target.classList[1];
localStorage.setItem('comments_active', commentClass);
});
}
</script>
</div>
<div class="toggle sidebar-toggle">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
<aside class="sidebar">
<div class="sidebar-inner">
<ul class="sidebar-nav motion-element">
<li class="sidebar-nav-toc">
文章目录
</li>
<li class="sidebar-nav-overview">
站点概览
</li>
</ul>
<!--noindex-->
<div class="post-toc-wrap sidebar-panel">
</div>
<!--/noindex-->
<div class="site-overview-wrap sidebar-panel">
<div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image" alt="zyh"
src="/images/avatar2.jpg">
<p class="site-author-name" itemprop="name">zyh</p>
<div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
<nav class="site-state">
<div class="site-state-item site-state-posts">
<a href="/archives/">
<span class="site-state-item-count">2</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-categories">
<a href="/categories/">
<span class="site-state-item-count">1</span>
<span class="site-state-item-name">分类</span></a>
</div>
</nav>
</div>
</div>
</div>
</aside>
<div id="sidebar-dimmer"></div>
</div>
</main>
<footer class="footer">
<div class="footer-inner">
<div class="copyright">
©
<span itemprop="copyrightYear">2020</span>
<span class="with-love">
<i class="fa fa-heart"></i>
</span>
<span class="author" itemprop="copyrightHolder">zyh</span>
</div>
<div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a> 强力驱动
</div>
</div>
</footer>
</div>
<script src="/lib/anime.min.js"></script>
<script src="/lib/velocity/velocity.min.js"></script>
<script src="/lib/velocity/velocity.ui.min.js"></script>
<script src="/js/utils.js"></script>
<script src="/js/motion.js"></script>
<script src="/js/schemes/pisces.js"></script>
<script src="/js/next-boot.js"></script>
</body>
</html>