分类目录微服务

socket.io for java

Server

<dependency>
      <groupId>com.corundumstudio.socketio</groupId>
      <artifactId>netty-socketio</artifactId>
      <version>1.7.16</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-nop</artifactId>
      <version>1.7.2</version>
    </dependency>

public class ServerStart {

    public static void main(String [] args){
        Configuration config = new Configuration();
        config.setHostname("localhost");
        config.setPort(9999);
        SocketIOServer server = new SocketIOServer(config);
        server.addConnectListener(new ConnectListener() {
            // 添加客户端连接监听器
            public void onConnect(SocketIOClient client) {
                //logger.info(client.getRemoteAddress() + " web客户端接入");
                //不知道如何与客户端对应,好的办法是自己去写对应的函数
                client.sendEvent("connected", "hello");
            }
        });

        //监听客户端事件,client_info为事件名称,-自定义事件
         server.addEventListener("client_info", String.class, new DataListener<String>(){
            public void onData(SocketIOClient client, String data, AckRequest ackRequest) throws ClassNotFoundException {
                //客户端推送advert_info事件时,onData接受数据,这里是string类型的json数据,还可以为Byte[],object其他类型
                String sa = client.getRemoteAddress().toString();
                String clientIp = sa.substring(1,sa.indexOf(":"));//获取客户端连接的ip
                Map params = client.getHandshakeData().getUrlParams();//获取客户端url参数
                System.out.println(clientIp+":客户端:************"+data);
            }
         });

        //添加客户端断开连接事件
        server.addDisconnectListener(new DisconnectListener(){
            public void onDisconnect(SocketIOClient client) {
                String sa = client.getRemoteAddress().toString();
                String clientIp = sa.substring(1,sa.indexOf(":"));//获取设备ip
                System.out.println(clientIp+"-------------------------"+"客户端已断开连接");
                //给客户端发送消息
                client.sendEvent("advert_info",clientIp+"客户端你好,我是服务端,期待下次和你见面");
            }
        });
        server.start();

        while (true){
            try {
                Thread.sleep(1500);
                //广播消息
                server.getBroadcastOperations().sendEvent("borcast","are you live?");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Client

        <dependency>
            <groupId>io.socket</groupId>
            <artifactId>socket.io-client</artifactId>
            <version>1.0.0</version>
        </dependency>

public class AppStart {

    public static void main(String [] args){
        String url ="http://localhost:9999";
        try{
            IO.Options options = new IO.Options();
            options.transports = new String[]{"websocket"};
            options.reconnectionAttempts = 2;
            options.reconnectionDelay = 1000;//失败重连的时间间隔
            options.timeout = 500;//连接超时时间(ms)
            //par1 是任意参数
            final Socket socket = IO.socket(url+"?par1=1234", options);

            socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {

                public void call(Object... args) {
                    socket.send("hello");
                }
            });

            //自定义事件
            socket.on("borcast", new Emitter.Listener() {
                public void call(Object... objects) {
                    System.out.println("receive borcast data:" + objects[0].toString());
                }
            });

            socket.on("connected", new Emitter.Listener() {
                public void call(Object... objects) {
                    System.out.println("receive connected data:" + objects[0].toString());
                }
            });

            socket.connect();
            //循环发送数据
            while (true){
                socket.emit("client_info"," 客户端在发送数据");
                Thread.sleep(2000);
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }
}

VUE
https://www.npmjs.com/package/vue-socket.io

import VueSocketIO from 'vue-socket.io'
import SocketIO from 'socket.io-client'

Vue.use(new VueSocketIO({
  debug: true,
  connection: SocketIO('http://192.168.88.108:443', {
    path: '', // path千万不要写“/”
    transports: ['websocket', 'xhr-polling', 'jsonp-polling']
  }) // options object is Optional
}))

Other https://github.com/probil/vue-socket.io-extended

import Vue from 'vue'
import VueSocketIOExt from 'vue-socket.io-extended'
import SocketIO from 'socket.io-client';

const socket = SocketIO('https://localhost');
export default ({ store }) => {
  Vue.use(VueSocketIOExt, socket, { store });
}

sockets: {
      // 创建连接
      connect() {
        console.log('连接成功啦')
      },
      // 监听断开连接,函数
      disconnect() {
        console.log('断开服务器连接');
        this.connectdisabled = false;
        this.leavedisabled = true;
        this.senddisabled = true;
        this.inputdisabled = true;
      },
      reconnect() {
        console.log("重新链接");
      },
      // 监听自定义事件,需与服务端emit事件名一致
      joined(room, id) {
        console.log('joined',room, id)
        this.connectdisabled = true;
        this.leavedisabled = false;
        this.senddisabled = false;
        this.inputdisabled = false;
      },

//发送加入信令
this.$socket.client.emit('join', this.room)

Spring Cloud Gateway

依赖
<!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
配制
spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: false # true 之前的http://localhost:8081/service-consumer/user/info这样的请求地址也能正常访问,因为这时为每个服务创建了2个router。
          lower-case-service-id: true #转换服务id为小写
      routes:
        - id: service_nacos
          uri: lb://nacos #(注册中心中服务的名称)即service-consumer服务的负载均衡地址,并用StripPrefix的filter 在转发之前将/consumer去掉。
          predicates:
            - Path= /nacos/** #将以/consumer/**开头的请求都会转发到uri为lb://service-consumer的地址上
          filters:
            - StripPrefix=1

Gateway 过滤器

Spring Cloud Gateway的filter生命周期不像Zuul那么丰富,它只有两个:“pre”和“post”:

pre:这种过滤器在请求被路由之前调用。可以利用这个过滤器实现身份验证、在集群中选择请求的微服务、记录调试的信息。

post:这种过滤器在路由到服务器之后执行。这种过滤器可用来为响应添加HTTP Header、统计信息和指标、响应从微服务发送给客户端等。

Spring Cloud gateway的filter分为两种:GatewayFilter和Globalfilter。GlobalFilter会应用到所有的路由上,而Gatewayfilter将应用到单个路由或者一个分组的路由上。

利用Gatewayfilter可以修改请求的http的请求或者是响应,或者根据请求或者响应做一些特殊的限制。更多时候可以利用Gatewayfilter做一些具体的路由配置。

Gateway请求匹配

Gateway网关可以根据不同的方式进行匹配进而把请求分发到不同的后端服务上。

Gateway熔断

Spring Cloud Gateway也可以利用Hystrix的熔断特性,在流量过大时进行服务降级,同时项目中必须加上Hystrix的依赖。

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

Gateway重试路由器

Retry GatewayFilter通过四个参数来控制重试机制,参数说明如下:

retries:重试次数,默认值是 3 次。

statuses:HTTP 的状态返回码,取值请参考:org.springframework.http.HttpStatus。

methods:指定哪些方法的请求需要进行重试逻辑,默认值是 GET 方法,取值参考:org.springframework.http.HttpMethod。

series:一些列的状态码配置,取值参考:org.springframework.http.HttpStatus.Series。符合的某段状态码才会进行重试逻辑,默认值是 SERVER_ERROR,值是 5,也就是 5XX(5 开头的状态码),共有5个值。

使用上述配置进行测试,当后台服务不可用时,会在控制台看到请求三次的日志,证明此配置有效。

Gateway 限流操作

Spring Cloud Gateway本身集成了限流操作,Gateway限流需要使用Redis,pom文件中添加Redis依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    </dependency>
配置了Redis的信息,并配置了RequestRateLimiter的限流过滤器,该过滤器需要配置三个参数:
    BurstCapacity:令牌桶的总容量。
    replenishRate:令牌通每秒填充平均速率。
    Key-resolver:用于限流的解析器的Bean对象的名字。它使用SpEL表达式#{@beanName}从Spring容器中获取bean对象。
    注意:filter下的name必须是RequestRateLimiter。
Key-resolver参数后面的bean需要自己实现,然后注入到Spring容器中。KeyResolver需要实现resolve方法,比如根据ip进行限流,则需要用hostAddress去判断。

自定义Gatewayfilter

Spring Cloud Gateway自定义过滤器,过滤器需要实现GatewayFilter和Ordered这两个接口。
再将该过滤器注册到router中

    private static final Log log = LogFactory.getLog(GatewayFilter.class);
    private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
        return chain.filter(exchange).then(
                Mono.fromRunnable(() -> {
                    Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
                    if (startTime != null) {
                        log.info("请求路径:"+exchange.getRequest().getURI().getRawPath() + "消耗时间: " + (System.currentTimeMillis() - startTime) + "ms");
                    }
                })
        );
    }
    @Override
    public int getOrder() {
        return 0;
    }
}
注册
    @Bean
        public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {
            return builder.routes()
                    .route(r -> r.path("/user/**")
                            .filters(f -> f.filter(new RequestTimeFilter())
                                    .addResponseHeader("X-Response-Default-Foo", "Default-Bar"))
                            .uri("http://localhost:8504/user/info")
                            .order(0)
                            .id("customer_filter_router")
                    )
                    .build();
        }
除了上述代码的方式配置我们自定义的过滤器的方式之外,也可以在application.yml文件中直接配置

自定义GlobalFilter

Spring Cloud Gateway根据作用范围分为GatewayFilter和GlobalFilter,二者区别如下:

GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上。
GlobalFilter:全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。
public class TokenFilter implements GlobalFilter, Ordered {
    Logger logger= LoggerFactory.getLogger( TokenFilter.class );
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (token == null || token.isEmpty()) {
            logger.info( "token 为空,无法进行访问." );
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

rancher 负载均衡时 default backend – 404

Nacos

官方网址:http://nacos.io
官网教程

docker

https://github.com/nacos-group/nacos-docker.git
https://hub.docker.com/r/nacos/nacos-server/tags?page=1&ordering=last_updated
docker pull nacos/nacos-server:2.0.0
docker pull nacos/nacos-server:latest

单机内存
docker run --name nacos-standalone -e MODE=standalone -p 8848:8848 -d --restart=always nacos/nacos-server:2.0.0
单机Mysql
docker run -d \
--name nacos-server \
-e PREFER_HOST_MODE=hostname \
-e MODE=standalone \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_MASTER_SERVICE_HOST=172.16.0.17 \
-e MYSQL_MASTER_SERVICE_PORT=3306 \
-e MYSQL_MASTER_SERVICE_USER=root \
-e MYSQL_MASTER_SERVICE_PASSWORD=root \
-e MYSQL_MASTER_SERVICE_DB_NAME=nacos \
-e MYSQL_SLAVE_SERVICE_HOST=192.168.1.3 \
-e MYSQL_SLAVE_SERVICE_PORT=3306 \
-p 8848:8848 \
--restart=always \
nacos/nacos-server:2.0.0

mkdir logs
mkdir properties
vi custom.properties

server.contextPath=/nacos
server.servlet.contextPath=/nacos
server.port=8848

spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://172.16.0.17:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=PW

nacos.cmdb.dumpTaskInterval=3600
nacos.cmdb.eventTaskInterval=10
nacos.cmdb.labelTaskInterval=300
nacos.cmdb.loadDataAtStart=false

management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false

server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i

nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health/**,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**,/v1/console/server/**
nacos.naming.distro.taskDispatchThreadCount=1
nacos.naming.distro.taskDispatchPeriod=200
nacos.naming.distro.batchSyncKeyCount=1000
nacos.naming.distro.initDataRatio=0.9
nacos.naming.distro.syncRetryDelay=5000
nacos.naming.data.warmup=true
nacos.naming.expireInstance=true

docker  run \
--name nacos -d \
-p 8848:8848 \
--privileged=true \
--restart=always \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
-e MODE=standalone \
-e PREFER_HOST_MODE=hostname \
-v ~/nacos/logs:/home/nacos/logs \
-v ~/nacos/custom.properties:/home/nacos/init.d/custom.properties \
nacos/nacos-server:2.0.0

2.下载源码或者安装包

你可以通过源码和发行包两种方式来获取 Nacos。
从 Github 上下载源码方式
git clone https://github.com/alibaba/nacos.git
cd nacos/
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
ls -al distribution/target/
// change the $version to your actual path
cd distribution/target/nacos-server-$version/nacos/bin
下载编译后压缩包方式
您可以从 最新稳定版本 下载 nacos-server-$version.zip 包。
unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz
cd nacos/bin
3.启动服务器
Linux/Unix/Mac
启动命令(standalone代表着单机模式运行,非集群模式):
sh startup.sh -m standalone
如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

bash startup.sh -m standalone
Windows
启动命令:
cmd startup.cmd
或者双击startup.cmd运行文件。
4.服务注册&发现和配置管理
服务注册
curl -X POST ‘http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080’
服务发现
curl -X GET ‘http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName’
发布配置
curl -X POST “http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld”
获取配置
curl -X GET “http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test”
5.关闭服务器
Linux/Unix/Mac
sh shutdown.sh
Windows
cmd shutdown.cmd
或者双击shutdown.cmd运行文件。

DOCKER uick Start

Run the following command:

Clone project

git clone --depth 1 https://github.com/nacos-group/nacos-docker.git
cd nacos-docker

Standalone Derby

docker-compose -f example/standalone-derby.yaml up

Standalone Mysql

docker-compose -f example/standalone-mysql.yaml up

Cluster

docker-compose -f example/cluster-hostname.yaml up 

Service registration

curl -X PUT 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'

Service discovery

  curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instances?serviceName=nacos.naming.serviceName'

Publish config

curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=helloWorld"

Get config

  curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

Open the Nacos console in your browser

link:http://127.0.0.1:8848/nacos/ 默认账号密码都是nacos

Common property configuration

name description option
MODE cluster/standalone cluster/standalone default cluster
NACOS_SERVERS nacos cluster address eg. ip1:port1 ip2:port2 ip3:port3
PREFER_HOST_MODE Whether hostname are supported hostname/ip default ip
NACOS_SERVER_PORT nacos server port default 8848
NACOS_SERVER_IP custom nacos server ip when network was mutil-network
SPRING_DATASOURCE_PLATFORM standalone support mysql mysql / empty default empty
MYSQL_SERVICE_HOST mysql host
MYSQL_SERVICE_PORT mysql database port default : 3306
MYSQL_SERVICE_DB_NAME mysql database name
MYSQL_SERVICE_USER username of database
MYSQL_SERVICE_PASSWORD password of database
MYSQL_MASTER_SERVICE_HOST The latest version of the image removes this attribute, using MYSQL_SERVICE_HOST
MYSQL_MASTER_SERVICE_PORT The latest version of the image removes this attribute, using MYSQL_SERVICE_PORT default : 3306
MYSQL_MASTER_SERVICE_DB_NAME The latest version of the image removes this attribute, using MYSQL_SERVICE_DB_NAME
MYSQL_MASTER_SERVICE_USER The latest version of the image removes this attribute, using MYSQL_SERVICE_USER
MYSQL_MASTER_SERVICE_PASSWORD The latest version of the image removes this attribute, using MYSQL_SERVICE_PASSWORD
MYSQL_SLAVE_SERVICE_HOST The latest version of the image removes this attribute
MYSQL_SLAVE_SERVICE_PORT The latest version of the image removes this attribute default :3306
MYSQL_DATABASE_NUM It indicates the number of database default :1
JVM_XMS -Xms default :2g
JVM_XMX -Xmx default :2g
JVM_XMN -Xmn default :1g
JVM_MS -XX:MetaspaceSize default :128m
JVM_MMS -XX:MaxMetaspaceSize default :320m
NACOS_DEBUG enable remote debug y/n default :n
TOMCAT_ACCESSLOG_ENABLED server.tomcat.accesslog.enabled default :false
NACOS_AUTH_SYSTEM_TYPE The auth system to use, currently only ‘nacos’ is supported default :nacos
NACOS_AUTH_ENABLE If turn on auth system default :false
NACOS_AUTH_TOKEN_EXPIRE_SECONDS The token expiration in seconds default :18000
NACOS_AUTH_TOKEN The default token default :SecretKey012345678901234567890123456789012345678901234567890123456789
NACOS_AUTH_CACHE_ENABLE Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay. default : false

集成

<!--阿里依赖管理-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <!--<version>${latest.version}</version>-->
        </dependency>

spring.application.name=nacos
spring.cloud.nacos.discovery.server-addr=102.168.88.127:8848

在 Nacos Spring Cloud 中,dataId 的完整格式如下:
${prefix}-${spring.profile.active}.${file-extension}

    prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
    spring.profile.active 即为当前环境对应的 profile,详情可以参考 Spring Boot文档。 注意:当 spring.profile.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
    file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.88.127:8848
      config:
        server-addr: 192.168.88.127:8848
        #namespace: example.properties # Data Id
        file-extension: yml # yml or properties

Nexus Maven库

# 赋予权限,不然启动会报错,无操作权限
chmod 777 nexus-data
docker run -d -p 8081:8081 --name nexus -v /srv/nexus-data:/nexus-data --restart=always sonatype/nexus3
# 进入镜像
docker exec -it nexus bash
# 查看密码,路径在登录框会提示,然后复制即可,登陆成功后会让你修改密码
cat /nexus-data/admin-password

二、Nexus仓库
1、仓库类型
Nexus有四种仓库和四种仓库类型
a、仓库
仓库名 描述
maven-central maven中央库,默认从https://repo1.maven.org/maven2/拉取jar
maven-releases 私库发行版jar
maven-snapshots 私库快照(调试版本)jar
maven-public 仓库分组,把上面三个仓库组合在一起对外提供服务,在本地maven基础配置settings.xml中使用
b、类型
类型 描述
group(仓库组类型) 用于方便开发人员自己设定的仓库
hosted(宿主类型) 内部项目的发布仓库(内部开发人员,发布上去存放的仓库)
proxy(代理类型) 从远程中央仓库中寻找数据的仓库(可以点击对应的仓库的Configuration页签下Remote Storage Location属性的值即被代理的远程仓库的路径)
virtual(虚拟类型) 虚拟仓库(这个基本用不到,重点关注上面三个仓库的使用)

2、拉取jar包流程
Maven可直接从宿主仓库下载构件,也可以从代理仓库下载构件,而代理仓库间接的从远程仓库下载并缓存构件,为了方便,Maven可以从仓库组下载构件,而仓库组并没有实际的内容(下图中用虚线表示,它会转向包含的宿主仓库或者代理仓库获得实际构件的内容)

3、创建仓库
进过上面的讲解,我们对仓库已经有了了解,接下来我们进行创建仓库,分为是代理仓库(proxy)、宿主仓库(hosted)、仓库组(group),点击主页上面的小螺丝然后在选择Repositories进入仓库管理列表,然后就可以开始创建我们的仓库啦,选择仓库类型的时候一定要选择maven2

第一种是在项目的pom.xml中进行更改,让单个项目使用nexus仓库;

代理中央仓库
只要在PMO文件中配置私服的地址即可,配置如下:
<repositories>
        <repository>
            <id>maven-central</id>
            <name>maven-central</name>
            <url>http://maven:8081/repository/maven-public/</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
    </repositories>
maven配置setting文件
Snapshot包的管理
1)修改Maven的settings.xml文件,加入认证机制
<servers>
    <server>
      <id>nexus</id><!--对应项目pom文件中设置的-->
      <username>admin</username>
      <password>admin123</password>
    </server>
</servers>
修改工程的Pom文件 要配置snapshot仓库
    <distributionManagement>
        <repository>
            <!--ID可以随便写,但是要与maven的setting文件中一致-->
            <id>releases</id>
             <name>Nexus Repository</name>
            <!--指向仓库类型为hosted(宿主仓库)的储存类型为Release的仓库---->
            <url>http://你nexus仓库的IP:8081/repository/me-release/</url>
        </repository>
        <snapshotRepository>
            <id>nexus</id>
            <name>Nexus Snapshot</name>
            <url>http://192.168.1.14:8081/repository/maven-snapshots/</url>
        </snapshotRepository>
        <site>
            <id>nexus</id>
            <name>Nexus Sites</name>
            <url>dav:http://192.168.1.14:8081/repository/maven-snapshots/</url>
        </site>
    </distributionManagement>

一种是通过修改maven的配置文件settings.xml进行更改,让所有项目都使用nexus仓库。

Maven 的配置文件名称为:setting.xml。它被存放在两个地方:
1)/usr/local/maven/conf/settings.xml #安装的目录;
2)~/.m2/settings.xml #用户的家目录;
如果两者都存在,他们的内容将被合并,并且用户范围的settings.xml优先。
关于settings.xml文件常用的的配置修改如下:
1)修改本地仓库存储路径,默认值是~/.m2/repository 可在settings.xml中的localrepository修改成自己需要的目录;
2)如果构建服务器因为网络故障或者安全问题不能与远程仓库相连,需要离线模式下,设置offline属性,设置为true,默认为false;
3)修改中央仓库服务器,修改配置文件中便签,添加或修改镜像地址;
4)设置代理地址,修改配置文件中proxy标签,定义代理服务器,实现maven的代理。

拉取jar的私服仓库地址只要写我们的仓库组就ok,因为在创建这个组的时候,里面已经包含了其它三个仓库
settings.xml文件
在maven的settings文件中找到mirrors,加上我们组仓库的mirror,url填写我们创建的组地址即可,id、name可以随便填写

 <!-- 配置Maven服务器的账号信息,上传需要用到 -->
    <server>
        <id>maven-releases</id>
        <username>developer</username>
        <password>developer</password>
    </server>
    <server>
        <id>maven-snapshots</id>
        <username>developer</username>
        <password>developer</password>
    </server>
    <server>
        <id>maven-public</id>
        <username>developer</username>
        <password>developer</password>
    </server>
 <!-- 使用Mirror配置节可以强制所有包请求都会被转向内网Nexus服务器的地址 -->
<mirrors>
    <mirror>
        <id>maven-public</id>
        <name>myself nexus repository</name>
        <url>http://maven:8081/repository/maven-public/</url>
        <!--里是要替代的仓库的id。代理原有仓库,如果填写*表示替换所有仓库-->
        <mirrorOf>central</mirrorOf>
    </mirror>
     <mirror>
      <id>maven-releases</id>
      <name>myself nexus maven-releases</name>
      <url>http://maven:8081/repository/maven-releases/</url>
      <!--里是要替代的仓库的id。代理原有仓库,如果填写*表示替换所有仓库-->
      <mirrorOf>central</mirrorOf>
    </mirror>
    <mirror>
      <id>maven-snapshots</id>
      <name>myself nexus maven-snapshots</name>
      <url>http://maven:8081/repository/maven-snapshots/</url>
      <!--里是要替代的仓库的id。代理原有仓库,如果填写*表示替换所有仓库-->
      <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>
   <!-- 这个配置决定了我们的Maven服务器开启snapshot配置,否则不能下载SNAPSHOTS的相关资源 -->
</profiles>
 <profile>
       <id>myconf</id>
      <repositories>
         <repository>
           <id>nexus</id>
           <url>http://maven:8081/repository/maven-public/</url>
           <releases>
             <enable>true</enable>
           </releases>
           <snapshots>
             <enable>true</enable>
             <updatePolicy>always</updatePolicy>
           </snapshots>
        </repository>
       </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>nexus</id>
          <url>http://maven:8081/repository/maven-public/</url>
           <releases>
            <enable>true</enable>
          </releases>
          <snapshots>
             <enable>true</enable>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
     </profile>
  </profiles>       需在该标签以上进行添加!
  <activeProfiles>
    <activeProfile>myconf</activeProfile>    这里的值一定要和上面profile的ID对应,才可以激活
  </activeProfiles>
</settings>          将 <activeProfiles>字段写在settings字段上面
需要发布jar资源到团队内部镜像服务器的项目的pom.xml配置<distributionManagement>增加snapshot的支持,
 <distributionManagement>
        <repository>
            <id>maven-releases</id>
            <name>Nexus Release Repository</name>
            <url>http://maven:8081/repository/maven-releases/</url>
        </repository>
        <snapshotRepository>
            <id>maven-snapshots</id>
            <name>Nexus Snapshot Repository</name>
            <url>http://maven:8081/repository/maven-snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

Nexus 启用上传功能
  团队有了私有的镜像服务器以后,团队内部代码的依赖也就不再需要源码依赖了,大家可以通过发布不同版本的jar到nexus镜像上来供调用者直接通过Maven下载使用,这样不同研发人员直接的依赖也就没有那么强了,大家可以基于已经发布的版本进行各自的开发。
  那么如何发布个人的jar资源到团队内部镜像上呢?
  1. 在Nexus 中创建一个developer的角色,拥有的权利为【nx-repository-view-maven2--edit】和【nx-repository-view-maven2--add】权利,如果该角色将来可能还有nuget,npm相关上传权利,则将其权利改为【nx-repository-view--edit】和【nx-repository-view--add】权利。
  2. 创建用户,用户拥有的角色为【nx-anonymous】和刚创建的【developer】角色。其中nx-anonymous角色是nexus默认自带的角色。

上传到私仓库 mvn clean deploy -U

异常处理

*UNKNOWN com.sonatype.nexus.plugins.outreach.internal.outreach.SonatypeOutreach – Could not download page bundle
org.apache.http.conn.HttpHostConnectException: Connect to sonatype-download.global.ssl.fastly.net:443 [sonatype-download.global.ssl.fastly.net/69.171.245.49] failed: 连接超时
打开【System】–》【Capabilities】,将【Outreach:Management】禁用即可。
mvn deploy

Pinpoint 链路监控

链路监控 Pinpoint

https://github.com/naver/pinpoint
安装服务
https://github.com/naver/pinpoint-docker

https://github.com/naver/pinpoint/releases
下载 pinpoint-agent-2.0.2.tar.gz
修改配制文件ponpoint.config
profiler.collector.iP=XX.XX.XXX.XXX #服务器地址
profiler.sampling.rate = 1 采样率1/N,1为100%全部采,20=5%
profiler.applicationservertype=TOMCAT 改SPRING_BOOT 采样服务器类型
查找修改SPRING_BOOT配制中的
profiler.sprintboot.bootstrap.main,增加要监控的main()函数类名
com.xx.xx

配制应用启动参数,指明使用代理
running the application:

-javaagent:$AGENT_PATH/pinpoint-bootstrap-$VERSION.jar
Additionally, Pinpoint Agent requires 2 command-line arguments in order to identify itself in the distributed system:
-Dpinpoint.agentId – uniquely identifies the application instance in which the agent is running on
-Dpinpoint.applicationName – groups a number of identical application instances as a single service

与日志相结合,利用 Transation 与ELK关联

docker-elk

github源码
Bringing up the stack
Clone this repository onto the Docker host that will run the stack, then start services locally using Docker Compose:
$ docker-compose up

5000: Logstash TCP input
9200: Elasticsearch HTTP user:elastic password:changeme
9300: Elasticsearch TCP transport 集群通信保持心跳
5601: Kibana      user:elastic password:changeme

LogStash 离散的日志收集,处理,过滤,格式转换
ElasticSearch 搜索引擎,进行索引,方便检索
Kibana 展示数据

springboot集成logbacku将日志输出到logstash

<!-- https://mvnrepository.com/artifact/net.logstash.logback/logstash-logback-encoder -->
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>6.3</version>
</dependency>

grok表达式

logstash.config
filter{
    grok{
        match => {
            "message" => "%{TIMESTAPM_ISO8601:logTime} %{GREEDYDATA:logThread} %{LOGLEVEL:logLevel} %{GREEDYDATA:loggerClass} - %{GREEDYDATA:logContent}"
        }
    }
}

在ELK前使用消息队列提高可用性,可分享性,如Kafka
配制LogStash从kafka接收
配制springboot项目发送到kafka

<!-- https://mvnrepository.com/artifact/com.github.danielwegener/logback-kafka-appender -->
<dependency>
    <groupId>com.github.danielwegener</groupId>
    <artifactId>logback-kafka-appender</artifactId>
    <version>0.2.0-RC2</version>
</dependency>
建立日志配制文件logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>

    <!--将日志发送到LOGSTASH-->
   <!-- <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashAccessTcpSocketAppender">
        <destination>localhost:5000</destination>-->
        <!--整个日志信息转为一个JSON发送-->
       <!-- <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/>-->
        <!--自定义一个发送格式-->
       <!-- <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>-->

    <!--将日志发送到kafka-->
    <appender name="KAFKA" class="com.github.danielwegener.logback.kafka.KafkaAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <topic>test</topic>
        <keyingStrategy class="com.github.danielwegener.logback.kafka.keying.NoKeyKeyingStrategy"/>
        <deliveryStrategy class="com.github.danielwegener.logback.kafka.delivery.AsynchronousDeliveryStrategy"/>
        <producerConfig>bootstrap.servers=192.168.88.108:9092</producerConfig>
        <appender-ref ref="CONSOLE"/>
    </appender>

    <include resource="org/springframework/boot/logging/logback/base.xml"/>

    <root level="INFO">
        <!--<appender-ref ref="LOGSTASH"/>-->
        <appender-ref ref="KAFKA"/>
        <appender-ref ref="CONSOLE"/>
    </root>

</configuration>

Prometheus

官网 https://prometheus.io/
github源码:https://github.com/prometheus/prometheus
docker镜像:https://hub.docker.com/r/prom/prometheus

适用范围:
Prometheus使用定时采样,常常用于在服务集群中采集实时监控数据进行图表分析

不适范围:
不能保证100%的数据完整,不适用于高精度要求的统计分析。

四种指标模型
Counter:只增不减的计数器,非常适合请求的个数,任务计数器, 出现的错误个数,产品的统计数等
Gauge:可增可减的仪表盘,可用于即时测量值指标
Histogram:自带buckets区间分布统计图,还提供了所有观测值的和
Summary:客户端定义的数据分布统计图,计算滑动时间窗口上的可配置分位数

Prometheus使用PromQL查询表达式进行数据查询
rate(is_request_counter{service=”/datav/ks”,method=”GET”}[1m])
单位时间内的计数

Prometheus可自定义告警规则进行告警。告警的触发条件是一个查询表达式。告警规则可配置在Prometheus服务端的配置文件中。

Prometheus 采取拉取数据进行数据采集.
其中pushgateway中间数据处理接收数据供server拉取
自带简单的webUI,有更高级图表Grafana,也可自写API调取数据

推送->Alertmanager->pagerduty/mail/etc

Docker方式安装
docker run -d –name prometheus -p 9090:9090 -v ~/prometheus/:/etc/prometheus/ prom/prometheus:V2.4.3

docker run -d –name grafana -p 3000:3000 -v ~/grafana/config/grafana.ini:/etc/grafana/grafana.ini -v ~/grafana/provisioning/:/etc/grafana/provisioning/ -env_file ~/grafana/config.monitoring grafana/grafana:5.2.4

default admin user is admin/admin.
提供数据

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <!--<version>2.1.6.RELEASE</version>-->
        </dependency>
         <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>

management:
  endpoint:
    prometheus: #启用prometheus
      enabled: true
  endpoints:
    web:
      exposure:
        include: #只对外显示以下信息
          - prometheus
          - info
          - health

放行不用认证
@Configuration
public class ActuatorSecurityConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 所有的端点状态信息不需要身份认证
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                // 其它的都需要认证访问
                .anyRequest().authenticated();
    }
}

Zookeeper

官网

https://zookeeper.apache.org/
下载包安装先修改配制文件
cp -f zoo_sample.cfg zoo.cfg
./zkServer.sh start/stop
./zkCli.sh 客户端工具,默认连接本机2181端口

建议docker pull zookeeper
https://hub.docker.com/_/zookeeper

docker run --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 -p 8080:8080 --restart always -d zookeeper