目录
SpringCloud和SpringCloud Alibaba引入微服务治理方案
概述
SpringCloud Alibaba-Nacos
Nacos注册中心
Nacos配置中心
SpringCloud-Feign
Springcloud -Getway:API网关
跨域
elasticsearch
基本概念
初步检索
1._cat
3 .索引一个文档(保存)
4.查询请求文档
5.更新文档
6. 删除文档
7.bulk批量API
SpringCloud和SpringCloud Alibaba引入微服务治理方案 概述
SpringCloud的痛点
SpringCloud部分组件停止维护和更新,给开发带来不便
SpringCloud部分环境搭建复杂,没有完善的可视化界面,我们需要二次开发和定制。
SprigCloud配置复杂,部分配置差别难以区分和合理应用
SpringCloud Alibaba的优势
性能强悍,设计合理,开源,有可视化界面给运维开发带来极大的便利
结合SpringCloud Alibaba,我们最终的技术方案:
SpringCloud Alibaba-Nacos:注册中心(服务发现与注册)
SpringCloud Alibaba-Nacos:配置中心(动态配置管理)
SpringCloud-Ribbon:负载均衡
SpringCloud-Feign:调用远程服务
SpringCloud Alibaba -Sentinel:服务容错(限流,降级,熔断)
Springcloud -Getway:API网关(webflux编程模式)
SpringCloud-sleuth:调用链监控
SpringCloud-Alibaba-Seata:原fescar,分布式事务解决方案
SpringCloud与Springcloud alibaba与Springboot的对应关系
首先引入SpringCloud,SpringCloudAlibaba和Springboot的相关依赖(注意版本对应),因为后面要用SpringCloud,SpringCloudAlibaba的相关组件所以要引入我们SpringCloud,SpringCloudAlibaba的相关依赖。
SpringCloud Alibaba-Nacos Nacos注册中心首先下载nacos服务器
1.将Nacos Discovery的依赖引入,功能是将我们的微服务注册到我们的注册中心,包括发现其他微服务,对服务注册发现的功能,放在com文件下,那么其他的微服务也具有了服务发现注册的功能。
com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery
2.将 Nacos 服务器地址配置添加到 /src/main/resources/application.yml 文件中。那个微服务需要配置到注册中心就要在该服务中配置nacos服务器地址,那么该服务一旦上线就可以在nacos服务器中找到。 localhost:8848是注册中心地址,并且要为每个服务取一个应用的名字,不然nacos的客户端找不到该服务 Application:name。
cloud: nacos: discovery: server-addr: localhost:8848 application: name: ncpmall-coupon
3.使用@EnableDiscoveryClient注解开启服务注册与发现功能,运行该服务,nacos服务器就能发现该微服务。
@MapperScan("com.lizude.ncpmall.ncpmallcoupon.dao") @SpringBootApplication @EnableDiscoveryClient public class NcpmallCouponApplication { public static void main(String[] args) { SpringApplication.run(NcpmallCouponApplication.class, args); } }
4.启动该服务之前我们需要先打开Nacos服务器,然后启动该服务
Nacos配置中心1.引入配置中心的依赖,该服务在配置一些配置文件之后就能连接配置中心
com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config
2.将 Nacos config 元数据配置添加到文件 /src/main/resources/bootstrap.properties (这个文件会优先于application.properties加载)
spring.application.name=ncpmall-coupon spring.cloud.nacos.config.server-addr=localhost:8848
没有使用nacos之前如果要修改配置十分麻烦,需要在application里面修改,然后重新发布到服务器上,但是如果服务器一多就会十分麻烦,现在我们只需要在nacos修改一处,处处生效 。
3.在nacos的配置页面点加号
然后在运行的服务的console中找那个微服务配置文件的名字填到上面的配置图片中,我们是ncpmall-coupon.properties .
4.最后如果项目已经上线不方便重启,就使用@refreshScope,当配置信息改变,就不需要重启微服务
@Value("$(配置项名字)");获取到配置
如果配置中心和当前应用的配置文件都配置了相同的项,优先使用配置中心的配置
@RefreshScope//刷新配置信息 @RestController @RequestMapping("ncpmallcoupon/coupon") public class CouponController { @Autowired private CouponService couponService; @Value("${coupon.user.name}") private String name; @Value("${user.age}") private Integer age; @RequestMapping("/test") public R test(){ return R.ok().put("name",name).put("age",age); } @RequestMapping("/menber/list") public R menbercoupons(){ CouponEntity couponEntity = new CouponEntity(); couponEntity.setCouponName("满一百减10"); return R.ok().put("coupons",Arrays.asList(couponEntity)); } *.xml global-config: db-config: id-type: auto server: port: 8000
配置集ID:类似于配置文件名
配置分组:默认所有的配置集都属于:DEFAULT_GROUP
指定配置分组在bootstrap.properties文件中
spring.application.name=ncpmall-coupon spring.cloud.nacos.config.server-addr=localhost:8848 #或者dev,prop,test的名称空间 spring.cloud.nacos.config.namespace=47c04e7e-4096-4f5c-8e83-c04a5d252902 spring.cloud.nacos.config.group=11
配置分组区分环境 :每个微服务创建自己的命名空间,使用配置分组区分环境,dev,test,prop
3.同时加载多个配置集
在boottrap.properties中配置
spring.application.name=ncpmall-coupon spring.cloud.nacos.config.server-addr=localhost:8848 #或者dev,prop,test的名称空间 spring.cloud.nacos.config.namespace=a062449f-f8a6-409f-8d1d-b21eb28c1d00 #spring.cloud.nacos.config.group=11 spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml spring.cloud.nacos.config.ext-config[0].group=dev spring.cloud.nacos.config.ext-config[0].refresh=true spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml spring.cloud.nacos.config.ext-config[1].group=dev spring.cloud.nacos.config.ext-config[1].refresh=true spring.cloud.nacos.config.ext-config[2].data-id=other.yml spring.cloud.nacos.config.ext-config[2].group=dev spring.cloud.nacos.config.ext-config[3].refresh=trueSpringCloud-Feign
Feign是一个声明式的http客户端,它的目的就是让远程调用更加简单。feign提供了http请求的模板。引入了feign就具备了调用其他微服务的能力。
1.想要远程调用别的服务
(1):引入openFeigh
(2):编写一个接口,告诉Springcloud,这个接口需要调用远程服务
1.声明接口的每一个方法都是调用那个远程服务的那个请求(这个时候我们只需要把远程请求的方法黏贴到我们的openfeign中)
//告诉Springcloud这个接口是个远程客户端,注解要说明调用远程那个微服务 @FeignClient("ncpmall-coupon") //如果我们以后要调用这个接口的menbercoupons方法那么就会去注册中心中找ncpmall-coupon,然后再去调用这个请求ncpmallcoupon/coupon/menber/list对应的controller方法 public interface CouponFeignService { @RequestMapping("ncpmallcoupon/coupon/menber/list") public R menbercoupons(); }
(3)开启远程调用功能(用@EnableFeignClients注解开启),当服务启动就会自动扫描这个包下所有标了@Feignclinent注解的接口,每一个接口又说明了,他是调用那个接口的那个请求。
@MapperScan("com.lizude.ncpmall.ncpmallcoupon.dao") @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients("com.lizude.ncpmall.ncpmallcoupon.feign") public class NcpmallCouponApplication { public static void main(String[] args) { SpringApplication.run(NcpmallCouponApplication.class, args); } }Springcloud -Getway:API网关
简介:网关作为流量的入口,常用功能包括路由转发,权限校验,限流控制,Springcloud gateway作为SpringCloud官方推出的第二代网关框架,取代了zuul网关。
跨域定义:前后端分离就产生了跨域,指浏览器不能执行其他服务器的资源,它是由浏览器的同源策略造成的,是浏览器对Javascript施加的安全限制。
同源策略:协议,域名,端口号都要相同,其中有一个不同就是跨域
跨域流程:
跨域官方文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORSHTTP | MDN
解决跨域(一):使用nginx部署为同一域
解决跨域(二):发送预检请求,然后响应允许跨域,配置允许跨域的响应头
elasticsearch 基本概念应用场景:全文检索,ELK(elasticsearch,kibanna,logstack(收集日志)):日志储存,日志检索
elasticsearch是一个分布式的开源搜索和分析的引擎,可以快速存储,分析,检索海量数据。
1.index(索引)
动词相当于mysql中的insert等
名词相当于mysql中的database
2.Type(类型)
在elasticsearch的index中,可以定义一个或者多个类型type,类似于mysql中的table,每种数据类型的数据都放在一起。
数据就是json格式的文档,每一个文档都有它的属性,属性就相当于mysql中的列名。
在ealsearch6.6之后没有类型这个说法
3.Elasticsearch倒排索引机制
elasticsearch:存储检索数据 kibnana:可视化检索数据界面
初步检索 1._cat在get方法下,访问192.168.56.10:9200/_cat/nodes:查看所有节点
在get方法下,访问192.168.56.10:9200/_cat/health:查看所有elasticsearch的健康状况
在get方法下,访问192.168.56.10:9200/_cat/master:查看主节点
在get方法下,访问192.168.56.10:9200/_cat/indices:查看所有索引 相当于MySQL的show databases
2.索引创建,查询,删除
创建:192.168.56.10:9200/shopping put方法
查询:192.168.56.10:9200/shopping get方法
删除:192.168.56.10:9200/showpping delete方法
3 .索引一个文档(保存)保存一个数据,保存在那个索引的那个类型下,指定用哪个唯一标识
在put请求下,向elasticssearch 发送localhost:9200/customer/externer/1,在customer索引下的externer类型下保存一号数据,数据为{"name" : "lizude"},json数据
PUT和post都行:
post新增。如果不指定id,会自动生成id。指定id就会修改这个数据,并新增版本号
PUT可以新增可以修改。put必须指定id;由于put需要指定id,我们一般用来做修改,不指定id会报错,。
postman测试
_index,_type,_id,_version等这些带“_”,属于元数据
_index:索引
_type:类型
_id:刚刚的/1
_version:版本,如果postman再发送一个相同的请求,version就会是2
result:发送请求的结果,如果postman再发送一个相同的请求,result就会是update
_shards:分片(集群)
4.查询请求文档在get请求下,localhost:9200/customer/external/1
_seq_no,_primary_term是并发控制字段,用来做乐观锁(集群)
_found是否找到该数据
5.更新文档192.168.56.10:9200/customer/external/1/_update POST
{
"doc":{
"name": "John Doew"
}
}
POST customer/external/1
{
"name": "John Doe2"
}
PUT customer/external/1
{
"name": "John Doe"
}
不同:POST *** 作会对比源文档数据,如果相同不会有什么 *** 作,文档 version 不增加
PUT *** 作总会将数据重新保存并增加 version 版本;在创建索引时候只能用put不能post
带_update 对比元数据如果一样就不进行任何 *** 作。
看场景;
对于大并发更新,不带 update;
对于大并发查询偶尔更新,带 update;对比更新,重新计算分配规则
customer/external/1 DELETE方法 elasticsearch没有提供类型的删除 *** 作
7.bulk批量APIlocalhost:192.168.56.10/customer/external/_bulk post方法
{"index":{"_id":"1"}} 保存一个一号数据,index是索引,而是是post请求所以是保存
{"name": "John Doe" } 数据内容是"name": "John Doe"
两行为一个整体
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
批量 *** 作没有办法在postman中进行测试,到kibana测试:
POST customer/external/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":"My first blog post" }
{ "index":{ "_index": "website", "_type": "blog" }}
{ "title":"My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123"} }
{ "doc" : {"title" : "My updated blog post"} }
测试批量数据:es测试数据.json · 坐看云起时/common_content - Gitee.com
复杂检索官方文档:Start searching | Elasticsearch Guide [7.5] | Elastic
1.SearchAPI一个是通过使用 REST request URI发送搜索参数(uri+检索参数)
GET bank/_search?q=*&sort=account_number:asc
响应结果解释:
took - Elasticsearch 执行搜索的时间(毫秒)
time_out - 告诉我们搜索是否超时
_shards - 告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片
hits - 搜索结果
hits.total - 搜索结果
hits.hits - 实际的搜索结果数组(默认为前 10 的文档)
sort - 结果的排序 key(键)(没有则按 score 排序)
score 和 max_score –相关性得分和最高得分(全文检索用)
另一个是通过使用REST request body 来发送它们(uri+请求体)
GET bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"account_number": {
"order": "desc"
}
}
]
}
基本语法
一个查询语句 的典型结构
{
QUERY_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,
}
}
如果是针对某个字段,那么它的结构如下:
{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
GET bank/_search
{"query":{"match_all": {}},
"sort": [
{
"balance": {
"order": "desc"
}
}
]
}
可以简写为:
GET bank/_search
{"query":{"match_all": {}},
"sort": [
{
"balance": "desc"
}
]
}
GET bank/_search
{"query":{"match_all": {}},
"sort": [
{
"balance": "desc"
}
],
"from": 5,
"size": 5
}
返回部分字段
GET bank/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5,
"_source": ["age","balance"]
}
匹配查询
相当于mysql的条件匹配,也可以做模糊查询
匹配查询:
GET bank/_search
{
"query":{"match": {
"firstname": "Elinor"
}}
}
模糊查询
GET bank/_search
{
"query": {"match": {
"address": "mill lane"
}}
}
match_phrase短语匹配
包含了一个完整的mill lane,以前是匹配mill或者lane或者mill lane,根据一些规则进行打分。存储的数据维护一张倒排索引表 (也就是把存储的东西进行分词),然后将要配对短语的与我们存储的倒排索引表对比,得出scode。
GET bank/_search
{
"query": {
"match_phrase": {
"address": "mill road"
}
}
}
multi_match 多字段匹配
GET bank/_search
{
"query": {"multi_match": {
"query": "MILL",
"fields": ["address","city"]
}}
}
BOOL符合查询
GET bank/_search
{
"query":{
"bool": {
"must": [
{"match": {
"gender": "F"
}},
{
"match": {
"address": "mill"
}
}
],
"must_not": [
{"match": {
"age": "38"
}}
],
"should": [ //能匹配最好,不能匹配也行,满足得分高,不满足得分低。
{"match": {
"lastname": "Wallace"
}}
]
}
}
}
GET bank/_search
{
"query": {
"bool": {
"must": [
{"range": {
"age": {
"gte": 10,
"lte": 30
}
}},
{
"match": {
"address": "mill"
}
}
]
}
}
}
Filter
并不是所有的查询都需要产生分数,特别是那些仅用于 “filtering”(过滤)的文档。为了不
计算分数 Elasticsearch 会自动检查场景并且优化查询的执行
GET bank/_search
{
"query":{
"bool": {
"must": [
{"match": {
"gender": "F"
}},
{
"match": {
"address": "mill"
}
}
],
"must_not": [
{"match": {
"age": "38"
}}
],
"should": [
{"match": {
"lastname": "Wallace"
}}
],
"filter": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
}
}
term
和match都是用来匹配某个属性的值。全文检索字段用match,精确值检索用term
id推荐使用match,address推荐使用term,因为address会全文检索mill lane
aggregations
聚合提供了从数据中分组和提取数据的能力。最简单的聚合方法大致等于 SQL GROUP
BY 和 SQL 聚合函数。在 Elasticsearch 中,您有执行搜索返回 hits(命中结果),并且同时返
回聚合结果,把一个响应中的所有 hits(命中结果)分隔开的能力。这是非常强大且有效的,
您可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果,使用
一次简洁和简化的 API 来避免网络往返。
GET bank/_search
{
"query": {}, //查询的结果
"aggs": { //聚合
"NAME": { //此次聚合的名字
"AGG_TYPE": {} //此次聚合的类型
}
}
}
搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄,但不显示这些人的详情。
##根据匹配的address中含有mill的结果,然后进行聚合,有terms()聚合,有avg(平均),term有的类型下得age出现的次数
GET bank/_search
{
"query": {"match": {
"address": "mill"
}},
"aggs": {
"ageagg": {
"terms": {
"field": "age",
"size": 111
}
},
"ageavg":{"avg": {
"field": "age"
}},
"agebalance":{"avg": {
"field": "balance"
}}
}
}
按照年龄聚合,并且请求这些年龄段的这些人的平均薪资
##分清楚是基于在上一次聚合的基础上再聚合,还是在重新聚合(上面是重新聚合)
GET bank/_search
{"query": {"match_all": {}},
"aggs": {
"ageagg": {
"terms": {
"field": "age",
"size": 100
}
, "aggs": {
"ageavg": {
"avg": {
"field": "balance"
}
}
}
}
}
, "size": 0 //不显示搜索数据
}
查出所有年龄分布,并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄段的总体平均薪资。
GET bank/_search
{
"query": {"match_all": {}}
, "aggs": {
"aggage": {
"terms": {
"field": "age",
"size": 100
}
, "aggs": {
"allavgbalance": {
"avg": {
"field": "balance"
}
},
"aggsM":{
"terms": {
"field": "gender.keyword",
"size": 3
}
, "aggs": {
"avgM": {
"avg": {
"field": "balance"
}
}
}
},
"aggsF":{
"terms": {
"field": "gender.keyword",
"size": 3
}
, "aggs": {
"avgF": {
"avg": {
"field": "balance"
}
}
}
}
}
}
}
, "size":0
}
mapping
Mapping 是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和
索引的(相当于sql的字段设置类型)
1.创建一个mapping
##创建一个索引的mapping
GET bank/_mapping
PUT /myindex
{
"mappings": {
"properties": {
"age":{"type": "integer"},
"email":{"type": "keyword"},
"name":{"type": "text"},
}
}
}
2.如果在一个已存在的索引要添加一个没有一个字段,将不能直接添加到name的下面,,我们只能重新设置该字段的index属性设置为false,设置为false的意思是不能检索,只能充当于是沉余信息。
往myindex中添加一个新的字段id
PUT /myindex
{
"mappings": {"properties": {"id":{"type": "long","index": false}}}
}
GET myin/_mapping
3.对于已经存在的映射字段,我们不能更新。更新必须创建新的索引把旧数据进行数据迁移到新索引中。
把我们的原来索引中的bank数据,迁移到我们newbank中,修改我们之前想修改的age类型
然后进行数据迁移
POST _reindex { "source": { "index": "bank" ”type“:"account"//type其实可以省略,自从6.6之后type就被省略了 }, "dest": { "index": "newbank" } }
keyword精确匹配,text是全文检索
分词SpringCloud H版、SpringCloud Alibaba整合电商项目(谷粒商城2020)技术总结_m0_38140207的博客-CSDN博客
一个 tokenizer (分词器)接收一个字符流,将之分割为独立的 tokens (词元,通常是独立 的单词),然后输出 tokens 流。es默认设置的分词器都是支持英文的分词,所以我们要安装中文分词器。 standard分词器:POST _analyze { "tokenizer": "standard", "text": ["两只快速的棕狐跳过了懒狗的骨头。"] }
ik分词器:
POST _analyze { "analyzer": "ik_max_word", "text": ["超级喜欢彼岸舞"] }
POST _analyze { "analyzer": "ik_smart", "text": ["李祖德吃屎"] }
自定义词库
修改/usr/share/elasticsearch/plugins/ik/config/中的 IKAnalyzer.cfg.xml
nginx里面有三个文件夹
[root@localhost nginx]# ls conf html logs
conf是配置文件
html 是资源的存放处,相当于tomcat的web目录
logs是·日志信息
在nginx中我们事先放置了分词器的自定义词库
[root@localhost conf]# cd .. [root@localhost nginx]# cd html [root@localhost html]# ls es index.html [root@localhost html]# cd es [root@localhost es]# ls fci.txt [root@localhost es]#
我们只需要远程配置远程扩展地址,变为我们的nginx的分词库的地址,也就是
192.168.56.10:80/es/fci.txt
ik分词器的配置,nginx配置我们全部都挂载到了/mydata文件中的elasticsearch和nginx中,挂载就是把容器中的文件映射到其他文件下,如果我们删除容器,我们以前的配置却还在,更加方便。,修改容器配置也不用进入到容器中,我们只需要在映射文件中修改
Elasticsearch-Rest-Client 1 )、 9300 : TCP spring-data-elasticsearch:transport-api.jar ; springboot 版本不同, transport-api.jar 不同,不能适配 es 版本 7.x 已经不建议使用, 8 以后就要废弃 2 )、 9200 : HTTP JestClient :非官方,更新慢 RestTemplate :模拟发 HTTP 请求, ES 很多 *** 作需要自己封装,麻烦 HttpClient :同上 Elasticsearch-Rest-Client :官方 RestClient ,封装了 ES *** 作, API 层次分明,上手简单 最终选择 Elasticsearch-Rest-Client ( elasticsearch-rest-high-level-client ) https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html ealsticsearch可以有多种语言对其 *** 作为什么不使用Javascript *** 作es的呢?
1.ES集群属于后端,端口暴露在前端不安全
springboot整合es:
1.导入依赖 (相当于mysql的驱动)
org.elasticsearch.client elasticsearch-rest-high-level-client7.4.2
2.编写配置
根据官方文档的API,其实ealsticsearch很多 *** 作都被封装好了,我们直接通过引入的client的依赖,来使用其中的 *** 作在java端
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)