0%

Cordova环境搭建

混合开发环境,Cordova提供了js和原生API的调用接口,通过插件,我们可以实现例如拍照,扫码等操作; 并且提供了静态文件转换成APP的功能。

步骤:

  1. 安装nodejs

  2. 安装cordova执行npm install -g cordova

  3. 在工作空间目录执行cordova create MyApp创建一个Cordova项目

  4. 切换进入刚刚创建的项目跟目录cd MyApp

  5. cordova platform查看该项目可用的平台和已安装的平台

    1
    2
    3
    4
    5
    6
    7
    8
    Installed platforms:
    android 7.0.0
    Available platforms:
    browser ~5.0.1
    ios ~4.5.4
    osx ~4.0.1
    windows ~5.0.0
    www ^3.12.0
  6. 如果没有安装,添加一个平台cordova platform add android

  7. 添加Android sdk系统环境变量三个

    1
    2
    3
    JAVA_HOME:C:\Program Files\Java\jdk1.8.0_131
    ANDROID_HOME:F:\xuan\sdk
    PATH:%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;
  8. 然后执行cordova requirements检查相关环境,如果失败,环境变量配置有问题,这里需要注意,环境变量配置了要重启终端,才会生效

    1
    2
    3
    4
    5
    6
    7
    Android Studio project detected

    Requirements check results for android:
    Java JDK: installed 1.8.0
    Android SDK: installed true
    Android target: installed android-27,android-26,android-25,android-24,android-23,android-22
    Gradle: installed C:\Program Files\Android\Android Studio\gradle\gradle-4.1\bin\gradle
  9. 然后执行cordova build android编译项目

  10. 然后执行cordova run android运行项目,需要连接Android设备,如果是模拟器执行cordova emulate android

  11. chrome浏览器调试chrome://inspect/#devices

Cordova 实例

调用相机demo

  1. 顺序执行下面的命令

    1
    2
    3
    4
    cordova create cameraDemo #创建cameraDemo相机demo
    cd cameraDemo #进入工程目录
    cordova platform add android #添加android
    cordova plugin add cordova-plugin-camera #添加相机组件
  2. 在上面步骤生成应用的目录,修改www目录下的index.html

    1
    2
    3
    4
      <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript" src="js/index.js"></script>
    <button id = "camera">调用相机</button>
    <button id = "wxlogin">微信</button>
  3. 修改www\js目录下的index.js

    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
    var app = {
    initialize: function() {
    document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
    document.getElementById("camera").addEventListener("click", this.wxloginEvent);
    },
    wxloginEvent: function(){
    // alert('触发了');
    navigator.camera.getPicture(onSuccess,onFail,{
    quality: 50,
    destinationType: Camera.DestinationType.DATA_URL
    });

    function onSuccess(imageData) {
    var image = document.getElementById('myImage');
    image.src = "data:image/jpeg;base64," + imageData;
    }
    function onFail(message) {
    alert('Failed because: ' + message);
    }
    },
    onDeviceReady: function() {
    this.receivedEvent('deviceready');
    },
    receivedEvent: function(id) {
    var parentElement = document.getElementById(id);
    var listeningElement = parentElement.querySelector('.listening');
    var receivedElement = parentElement.querySelector('.received');

    listeningElement.setAttribute('style', 'display:none;');
    receivedElement.setAttribute('style', 'display:block;');
    console.log('Received Event: ' + id);
    }
    };
    window.onload=function(){ //注意添加此方法包裹,不然会还没加载就调用方法而报错
    app.initialize();
    }
  4. 执行cordova run android运行项目,需要连接Android设备

Cordova 加载远程HTML(修改了html,一定要清除app的缓存)

上面已经成功创建了一个相机demo,但是他是读取的本地网页,下面记录访问远程html

先分析下生成的目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|cordovaDemo  //跟目录
├─hooks
├─node_modules //模块
│ ├─cordova-android //Android设备
│ ├─cordova-plugin-barcodescanner
│ ├─cordova-plugin-compat
│ └─cordova-plugin-whitelist
├─platforms //设备目录
│ └─android //Android源码
│ ├─assets
│ │ └─www //html资源目录,要在远程运行需要把此目录放到远程目录,改相应的配置文件
│ ├─CordovaLib //Cordova 依赖
│ ├─res
│ ├─xml─config.xml //修改里面的<content src="url地址" /> 默认是index.html
│ └─src //Android java源文件
├─plugins //插件目录
│ ├─cordova-plugin-barcodescanner
│ ├─cordova-plugin-compat
│ └─cordova-plugin-whitelist
├─res
└─www //网页源文件,修改之后,build(run)会改变android-assets
  1. 在上面相机demo运行完项目后,用as打开生成的Android的项目(.\platforms\android)

  2. 复制.\platforms\android\assets目录下的源码到服务器上运行,注意idea复制包名有可能丢失

  3. 修改Android项目下的res\xml\config.xml配置文件

    1
    2
    <!--<content src="index.html" />-->
    <content src="http://112." /> //服务器地址
  4. 如果要制作个android外壳,还需要解决webview跳出到浏览器的问题,修改CordovaLib\java\...\engine\SystemWebViewClient下的

    1
    2
    3
    4
    5
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
    // return parentEngine.client.onNavigationAttempt(url); //注释这句
    return false; //添加这句,具体可以详查webview的使用
    }
  5. 直接在as里面运行Android项目,如果用run android运行会覆盖修改掉的东西

config.xml文件详解

在新建的cordova项目跟目录下的config.xml将被复制到各个平台配置文件下,不会被更改,Android的是app/platforms/android/res/xml/config.xml

下面个详细介绍下里面的配置

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
<?xml version='1.0' encoding='utf-8'?>
<widget id="通用包名" android-packageName="Android包名" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<!--插件-->
<feature name="Whitelist">
<param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
<param name="onload" value="true" />
</feature>
<!--应用名称-->
<name>e想行空</name>
<!--应用图标,更改后卸载重装生效-->
<icon src="res/icon/logo.png" />
<!--应用描述-->
<description>
e想天开,天马行空!
</description>
<!--作者email,网站-->
<author email="exxk.lx@gmail.com" href="http://www.blog.iexxk.com">
e想行空
</author>
<!--加载h5的资源,默认index.html是本地资源-->
<content src="http://www.blog.iexxk.com" />
<!--允许哪些域可以和组件通信-->
<access origin="http://www.blog.iexxk.com/*" />
<!--允许哪些域通过webview打开-->
<allow-navigation href="http://www.blog.iexxk.com/*" />
<!--允许哪些域可以被打开-->
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<allow-intent href="market:*" />
<preference name="loglevel" value="DEBUG" />
</widget>

app签名

  1. 在项目跟目录新建一个build.json

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    {
    "android": {
    "debug": {
    "keystore": "./android.keystore",
    "storePassword": "android",
    "alias": "mykey1",
    "password" : "password",
    "keystoreType": ""
    },
    "release": {
    "keystore": "./android.keystore",
    "storePassword": "",
    "alias": "mykey2",
    "password" : "password",
    "keystoreType": ""
    }
    }
    }
  2. 复制android.keystore到项目跟目录

  3. 执行cordova build --release android然后生成platforms\android\app\build\outputs\apk\release\app-release.apk

文档资源

官网cordova

cordova plugins

常见问题

  1. 浏览器打开提示www/cordova.js net::ERR_FILE_NOT_FOUND此错误,但是打包Android不会出现

  2. 安装插件:

    1
    2
    3
    Plugin doesn't support this project's cordova-android version. cordova-android: 7.0.0, failed version requirement:
    <6.3.0
    Skipping 'cordova-plugin-compat' for android

    解决执行cordova platform rm androidcordova platform remove android然后安装cordova platform add android@6.2.0

方式一docker-zipkin+zipkin+sleuth

请求原理图

graph LR
请求-->微服务客户端-->sleuth采集请求-->zipkin发送请求的信息-->docker-zipkin接受并展示
sleuth 采样+++zipkin 发送分析展示采样数据
  1. 安装penzipkin/docker-zipkin 服务端,听说官方不建议编译,直接提供jar包了,因此采用docker方式进行部署

  2. 添加依赖在需要监控的服务

    1
    2
    compile('org.springframework.cloud:spring-cloud-starter-sleuth')
    compile('org.springframework.cloud:spring-cloud-starter-zipkin')
  3. 添加配置,在application.yml添加zipkin服务端地址,和采样比例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    spring:
    zipkin:
    base-url: http://10.14.0.7:14009/
    sleuth:
    web:
    client:
    enabled: true
    sampler:
    probability: 1.0 #采样比例0~1之间,1全部采样
  4. 访问http://10.14.0.7:14009/进行测试

测试结果
  1. 在eureka服务注册端添加没监控到请求
  2. 启动两个一样的服务提供者,端口不一致,以一个服务展示,但是能看到两个客户端
  3. 请求之后才能监控到

方式二docker-zipkin+rabbitMQ+sleuth(暂时未成功)

graph LR
请求-->微服务客户端-->sleuth采集请求-->mq发送请求的信息-->docker-zipkin接受并展示
  1. 修改docker-compose部署添加环境变量(目测该镜像还不支持改环境变量)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    version: '3'

    services:
    zipkin:
    restart: always
    image: openzipkin/zipkin
    environment:
    RABBIT_ADDRESSES: mq的地址
    RABBIT_PASSWORD: mq的密码
    RABBIT_USER: mq的用户名
    ports:
    - "14009:9411"
    deploy:
    replicas: 1
    restart_policy:
    condition: on-failure
    placement:
    constraints: [node.hostname == worker]
  2. 修改客户端依赖

    1
    2
    3
    compile('org.springframework.cloud:spring-cloud-starter-sleuth')
    //compile('org.springframework.cloud:spring-cloud-starter-zipkin') //注释这句
    compile('org.springframework.boot:spring-boot-starter-amqp')
  3. 修改配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #  zipkin:
    # base-url: http://10.14.0.7:14009/
    sleuth:
    web:
    client:
    enabled: true
    sampler:
    probability: 1.0 #采样比例0~1之间,1全部采样
    rabbitmq:
    port: 14002
    host: 10.14.0.1
    username: root
    password: adminroot
  4. 测试失败,读不到服务,通过看docker-zipkin似乎是这里的mq没启动起

数据持久化zipkin+mysql

待更新。。。

参考:Baeldung-SpingCloud-Sleuth

史上最简单的 SpringCloud 教程 | 终章

Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin【Finchley 版】

SpringCloud Bus是将分布式的节点用轻量的消息代理连接起来。用于服务间广播、通信、监控等。

该篇实现:通过bus实现配置修改后通知服务更改

步骤

  1. 在configclient的基础上添加依赖

    1
    compile('org.springframework.cloud:spring-cloud-starter-bus-amqp')
  2. Hicontroller类添加注解@RefreshScope

  3. 在配置文件添加mq的服务器地址,和开启刷新

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    spring:  
    rabbitmq:
    host: 112.74.51.136
    port: 14002
    username: root
    password: adminroot
    management:
    endpoints:
    web:
    exposure:
    include: ["health","info","bus-refresh"]
  4. 测试,依次运行注册中心、配置中心、该服务,然后访问接口,然后修改git config下的配置信息,然后访问接口,还是没变,需要调用127.0.0.1:8097/actuator/bus-refresh?destination=config-client:8097其中的config-client:8097是指定更新那台服务,也可以不指定参数,默认就是更新所有,然后在访问测试接口,发现已经配置已经改变了。

架构优化

可以在config-server添加config-client的配置,这样就可以调配置刷新127.0.0.1:8096/actuator/bus-refresh/接口,刷新所有配置客户端的配置了,注意依赖要加上 compile('org.springframework.cloud:spring-cloud-starter-config')config-client的配置依赖,因为config-client的依赖和config-serverbus-refresh接口不一样

image-20200811155609870

Docker之基础系统Alpine Linux

Alpine是一个linux迷你系统,体积小、安全,docker中ubuntu的替代系统

  • 小巧: 官方镜像docker pull alpine只有4.15M
  • 安全: 面向安全的轻量发行版
  • 简单: 提供apk包管理工具从仓库管理安装
  • 容器的基础镜像

gliderlabs/docker-alpine

文档Alpine

基本使用

Alpine仓库搜索你要安装的组件(package)然后执行apk add --no-cache <Package name>

docker 中alpine使用

1
2
3
4
5
6
7
8
9
10
11
docker run alpine echo '123' #输出123,运行完镜像即摧毁
docker run -it --name myalpine alpine #运行一个容器并进入
### alpine常用命令,apk --help
apk info #查看安装的apk
apk update #更新镜像列表
cat /etc/apk/repositories #查看源
#http://dl-cdn.alpinelinux.org/alpine/v3.7/main
#http://dl-cdn.alpinelinux.org/alpine/v3.7/community
echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories #添加测试源,记得apk update
cat /etc/apk/arch #查看系统版本Architecture,修改之后,之后的安装包都以该修改后的为准
apk upgrade #升级系统软件,解决编译版本过低等问题

利用docker 构建mysql镜像

1
2
3
FROM alpine:3.5
RUN apk add --no-cache mysql-client
ENTRYPOINT ["mysql"]

构建opencv镜像

1
2
3
FROM alpine:3.5
RUN apk add --no-cache opencv
ENTRYPOINT ["opencv"]

参考

Alpine Linux 使用简介

1
2
3
4
5
6
7
8
9
10
#采用国内阿里云的源,文件内容为:
cat > /etc/apk/repositories <<EOF
https://mirrors.aliyun.com/alpine/v3.7/main/
https://mirrors.aliyun.com/alpine/v3.7/community/
https://mirrors.aliyun.com/alpine/edge/testing/
EOF
# 如果采用中国科技大学的源,文件内容为:
https://mirrors.ustc.edu.cn/alpine/v3.6/main/
https://mirrors.ustc.edu.cn/alpine/v3.6/community/
https://mirrors.ustc.edu.cn/alpine/edge/testing/

mac开发环境

  1. 环境准备

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 安装开发基本组件(一般都安装了)可以跳过
    xcode-select --install
    # 安装ant,这里是使用Homebrew进行安装,为了方便管理
    brew install ant
    # 编辑配置文件(其实就vim编辑配置文件)
    brew edit opencv
    >修改为 -DBUILD_opencv_java=ON
    # 最后安装opencv,依赖于python2,可以提前建好,也可以通过依赖的方式自动安装
    brew install --build-from-source opencv
  2. 安装成功后jar包位于/usr/local/Cellar/opencv/3.x.x/share/OpenCV/java/

  3. idea设置vm启动参数-Djava.library.path=/usr/local/Cellar/opencv/3.4.3/share/OpenCV/java/

问题
  1. Permission denied @ dir_s_mkdir

    解决:重建目录

    1
    2
    3
    4
    sudo mkdir /usr/local/Frameworks
    sudo chown $(whoami):admin /usr/local/Frameworks
    # 测试
    brew link python

idea+springboot+opencv3.4.1+alpine

安装

由于alpine apk add opencv 运行报错,等待opencv出正式版

等待升级中。。。。。。。

opencv_java341.dll

Docker 安装 Oracle

镜像:sath89/oracle-12c

挂载需要修改权限

chown -R 1001:1001 /data/oracle

docker run -d –name oracle -p 8080:8080 -p 1521:1521 -e TZ=Asia/Shanghai sath89/oracle-12c

类别 host container 备注
port 1521 1521
port 8080 8080
volume /dockerdata/manager/oracledata/initdb /docker-entrypoint-initdb.d 初始化导入数据库用(非必需)
volume /dockerdata/manager/oracledata/data /u01/app/oracle
env IMPORT_FROM_VOLUME true 触发首次运行自动初始化数据(非必需)

oracle初始用户

1
2
3
4
5
6
7
8
port: 1521
sid: xe
service name: xe
username: system
password: oracle
user: sys
password: oracle
connect as sysdba: true

运行完成后,注意这里第一次运行要初始化,注意看日志,等待它完成

到处dmp文件:exp manager/manager buffer=64000 file=/test.dmp full=y

配置

修改数据库服务名xepdborcl

参考:Oracle 更改服务名方法

  1. 进入容器内执行命令,连接Oracle,执行sqlplus sys/oracle as sysdba 进入oracle,其中sys为用户名,oracle为密码,sysdba作为系统dba登入

    1
    2
    show parameter service_name #显示服务名
    alter system set service_names='pdborcl' scope=both; #更改服务名为pdborcl
  2. 添加表空间MANAGERDATASPACE

    1
    2
    3
    4
    5
    6
    7
    CREATE TABLESPACE MANAGERDATASPACE
    LOGGING
    DATAFILE '/u01/app/oracle/oradata/xe/MANAGERDATASPACE.DBF'
    SIZE 32M
    AUTOEXTEND ON
    NEXT 32M MAXSIZE UNLIMITED
    EXTENT MANAGEMENT LOCAL;
  3. 服务端更改完成,客户端的连接也要更改listener.ora文件,这里不记录

新建用户并导入dmp文件初始数据库

  1. 通过plsql添加用户manage

    user右键new 新建用户,设置 default tablespace=users,temp tablespace=temp

    role选项卡添加connect、dba、resource

  2. ftp上传文件dmp备份文件到挂在目录/dockerdata/manager/oracleinitdb/initdb

  3. 进入容器执行切换到/docker-entrypoint-initdb.d目录imp manager/manager file=manager20180413am1052.dmp log=imp_sysdb.log grants=no full=y导入恢复数据

数据库前的准备工作/创建数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--创建表空间
create tablespace SY_DB logging datafile '/u01/app/oracle/oradata/SY_DB.DBF' size 50m autoextend on next 50m maxsize 20480m extent management local;
--创建用户
create user SY_DB identified by "SY_DB@2018" default tablespace SY_DB temporary tablespace TEMP profile DEFAULT password expire;
-- Grant/Revoke role privileges
grant dba to SY_DB;
--给用户分配权限
grant create any table to SY_DB;
grant create any view to SY_DB;
grant create user to SY_DB;
grant drop tablespace to SY_DB;
grant unlimited tablespace to SY_DB;
--查询用户密码有效期
select * from dba_profiles where profile='DEFAULT' and resource_name='PASSWORD_LIFE_TIME';
--查询用户和密码
select username,password from dba_users;
--修改用户密码(密码里面最好不要有@符号,不然执行导入命令时一直无权限)
alter user SY_DB identified by mimaoracle;
--去除用户密码有效期
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;
--创建虚拟目录存储导出文件
create directory db_bak as '/docker-entrypoint-initdb.d';

数据库导入导出(容器bash执行)

1
2
3
4
--数据泵导入文件
impdp SY_DB/mimaoracle DIRECTORY=db_bak DUMPFILE=SY_DB20190829.DMP SCHEMAS=SY_DB
--数据泵导出文件
expdp SY_DB/"""SY_DB@2018"""@orcl DIRECTORY=db_bak DUMPFILE=SY_DB20190829.DMP SCHEMAS=SY_DB;

修改字符集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 进入sql命令行
sqlplus sys/oracle as sysdba
--若此时数据库服务器已启动,则先执行 SHUTDOWN IMMEDIATE 命令关闭数据库服务器,
然后执行以下命令:
SQL>shutdown immediate
SQL>STARTUP MOUNT
SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
SQL>ALTER DATABASE OPEN;
SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
SQL>ALTER DATABASE CHARACTER SET INTERNAL_USE ZHS16GBK;
--执行错误,未解决该错误
--ERROR at line 1:
--ORA-12712: new character set must be a superset of old character set
SQL>SHUTDOWN IMMEDIATE
SQL>STARTUP

问题

  1. 导入表空间报错

    解决将manager20180413am1052.dmp文件内容中的 MANAGERDATASPACE替换USERS

    待优化处理:???

hyper-v设置静态ip

创建NAT网络

用管理员权限运行powershell,下面命令会创建一个NAT内部网络,网段为192.168.204.0/24,可以在网络适配器可以找到新建的NAT-Docker网络适配器

1
2
3
4
5
6
7
8
#创建新的虚拟交换机NAT-Docker
New-VMSwitch –SwitchName "NAT-Docker" –SwitchType Internal –Verbose
#查看所有网路适配器,找到对应ifIndex 值
Get-NetAdapter
#新建一个NAT网关192.168.204.181,注意替换InterfaceIndex为ifIndex值
New-NetIPAddress –IPAddress 192.168.204.1 -PrefixLength 24 -InterfaceIndex 37 –Verbose
#创建一个nat网络
New-NetNat –Name NATNetwork –InternalIPInterfaceAddressPrefix 192.168.204.0/24 –Verbose

配置NAT网络

在新建的网络适配器NAT-Docker设置固定ip为192.168.204.1,dns记得也要设置202.96.128.86根据自己实际情况设置dns

在hyper-v虚拟机里切换centos使用该网络

centos配置静态ip

在centos修改网络配置文件vim /etc/sysconfig/network-scripts/ifcfg-eth0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
#BOOTPROTO="dhcp"
BOOTPROTO="static"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="eth0"
UUID="d49f62d7-9c2a-4f6f-8077-605d0dd65eea"
DEVICE="eth0"
ONBOOT="yes"
#---以下新加
NM_CONTROLLED="no"
IPADDR="192.168.204.181"
NETMASK="255.255.255.0"
GATEWAY="192.168.204.1"
BROADCAST="192.168.204.255"
DNS1="8.8.8.8"

执行service network restart重启网络

端口映射(需管理员权限)

1531476067353

1
2
3
4
5
6
7
8
9
10
#查询端口映射情况
netsh interface portproxy show v4tov4
#添加端口映射
netsh interface portproxy add v4tov4 listenport=外网端口 listenaddress=主IP connectaddress=私网IP connectport=私网IP端口
#eg
netsh interface portproxy add v4tov4 listenport=14014 listenaddress=192.168.1.158 connectaddress=192.168.204.182 connectport=14014
#删除一个端口映射
netsh interface portproxy delete v4tov4 listenaddress=主IP listenport=外网端口
#eg
netsh interface portproxy delete v4tov4 listenaddress=192.168.1.158 listenport=14014

1531475386029

参考Hyper-V 共享式网络链接 端口映射

双网卡

设置/etc/sysconfig/network,决定走那个网关和网卡

1
2
GATEWAY=10.2.2.1
GATEWAYDEV=em3

在网卡配置文件里面只有一个网卡设置网关,内网的不要设置

问题

  1. 端口偶发性映射失效,重启失效

    解决:目前删除重新添加,也可以添加个脚本,待寻找更好的方法

    参考:

    netsh interface portproxy 偶发性失效

    netsh portproxy not working after reboot

  2. 网络配置实现,使用ip a s查看可以一个网卡下有两个ip

    原因:存在相同名字的网卡配置文件,但后缀不一样,主要是由于备份原来文件导致的,例如.back等,

    解决:千万不要在当前目录进行备份,且不要用后缀模式

  3. 设置静态网络时,出现双ip问题

    原因:未知

    解决:在网络配置文件添加NM_CONTROLLED=no然后重启

  4. 网段如何计算,网段计算原理,ip后面的16和24是什么意思,在线计算子网掩码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #------概念-------
    192.168.0.0(ip)/16(掩码位)
    掩码:255.255.0.0 二进制:11111111.11111111.00000000.00000000总共就16位
    第一个(192.168.0.0网络)和最后一个(192.168.255.255广播)是固定网络地址也被称为CIRD
    #------------举例16位--------
    192.168.0.0/16
    转换为8位二进制就是
    二进 11000000.10101000.00000000.00000000
    掩码 11111111.11111111.00000000.00000000
    16就代表前面16位不动,所有就有192.168.0-256.0-256共65536个可用ip
    减去192.168.0.0和192.168.255.255,剩下可用ip位65534个
    #------------举例24位--------
    192.168.0.0/24
    转换为8位二进制就是
    二进 11000000.10101000.00000000.00000000
    掩码 11111111.11111111.11111111.00000000
    16就代表前面16位不动,所有就有192.168.0.0-256共256个可用ip
    减去192.168.0.0和192.168.0.255,剩下可用ip位254个

配置(config)中心

作用多服务统一配置管理,主要分配置中心服务端,和配置中心客户端(主要存储配置)

image-20200811155609870

Config Server

  1. 新建一个springboot项目,取名configserver,勾选

    • Cloud discovery-> eureka server 注释掉了,引用了不注册报错,如果要用,就注册就行,这里是测试config所以先不注册
    • Cloud config->config server
  2. application启动类添加@EnableConfigServer

  3. 新建一个git配置文件仓库,这里就在当前工程创建,因为这个反正都要上传git,在项目目录新建一个config目录,然后在目录里新建一个配置仓库testrepo,再在仓库添加配置文件config-client-dev.properties内容如下

    1
    2
    config-client.testsmsg = hello config me
    test = haa
  4. 然后git commit push推送到远程分支

  5. 在配置文件application.yml添加如下内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    server:
    port: 8096
    spring:
    application:
    name: config-server
    cloud:
    config:
    label: master #配置仓库分支
    server:
    git:
    uri: https://github.com/xuanfong1/SpringCloud/ #配置仓库git地址
    search-paths: config/testrepo #配置仓库路径
    username: #访问git仓库的用户名,这里因为是开放项目所以不需要设置
    password: #访问git仓库的密码
  6. 访问http://127.0.0.1:8096/config-client/dev/master这个地址读取配置文件

    下面介绍http请求地址与资源文件映射问题

    Url : /{application}/{profile}[/{label}]

    资源文件格式可以为

    • /{application}-{profile}.yml

    • /{label}/{application}-{profile}.yml

    • /{application}-{profile}.properties

    • /{label}/{application}-{profile}.properties

      举例:master分支有配置文件config-client-dev.properties访问的url为ip:port/config-client/dev/master

config client

  1. 新建一个springboot项目,取名configserver,勾选

    • web->web
    • Cloud config->config client
  2. 修改配置文件application.properties一定要修改为**bootstrap.yml**并添加如下内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    server:
    port: 8097
    spring:
    application:
    name: config-client
    cloud:
    config:
    label: master #指明远程仓库的分支
    profile: dev #dev(开放)、test(测试)、pro(正式)
    uri: http://127.0.0.1:8096/ #配置中心地址
  3. 添加一个api接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @RestController
    public class HiController {
    @Value("${test}") //调用配置中心的配置
    String test;

    @RequestMapping(value = "/hi")
    public String hi(){
    return test;
    }
    }
  4. 访问http://127.0.0.1:8097/hi进行测试

配置中心高可用

config server
  1. 添加依赖compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')

  2. Application启动类添加注解@EnableEurekaClient

  3. Application.yml配置文件增加

    1
    2
    3
    4
    eureka:
    client:
    service-url:
    defaultZone: http://127.0.0.1:8091/eureka/ #注意要加eureka,不然找不到
config client
  1. 添加依赖compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')

  2. Application启动类添加注解@EnableEurekaClient

  3. bootstrap.yml配置文件修改如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    server:
    port: 8097
    spring:
    application:
    name: config-client
    cloud:
    config:
    label: master #指明远程仓库的分支
    profile: dev #dev(开放)、test(测试)、pro(正式)
    # uri: http://127.0.0.1:8096/ #配置中心地址 ,用eureka就不是ip地址了
    discovery:
    enabled: true
    service-id: config-server #这里用服务名

    eureka:
    client:
    service-url:
    defaultZone: http://127.0.0.1:8091/eureka/ #注意要加eureka,不然找不到

    所以多个config-server运行,通过负载均衡就可以达到高可用

    测试

    依次运行服务注册中心、配置中心服务、读配置中心的客户端服务

    访问http://127.0.0.1:8097/hi进行测试

    图示

       graph LR
    A[git仓库] -->B(config server)
    A[git仓库] -->B1(config server)
    A[git仓库] -->B2(config server)
    B --> C{负载均衡}
    B1 --> C{负载均衡}
    B2 --> C{负载均衡}
    C --> D[service A]
    C --> E[service B]
    F[eureka service]

使用本地文件作为配置中心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server:
port: 8096
spring:
application:
name: config-server
profiles:
active: native #这里进行仓库预选,可设置native和git,分别对应spring.cloud.config.server下面的值
cloud:
config:
label: master #配置仓库分支
server:
git:
uri: https://github.com/xuanfong1/SpringCloud/ #配置仓库git地址
search-paths: config/testrepo #配置仓库路径
# username: #访问git仓库的用户名,这里因为是开放项目所以不需要设置
# password: #访问git仓库的密码
native: #本地配置文件仓库的绝对路径
search-locations: /Users/xuanleung/workspace/SpringCloud/config/testrepo
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8091/eureka/ #注意要加eureka,不然找不到

公共配置文件

1
2
3
4
5
6
application.properties #公共配置文件,所有服务都会加载这个默认配置文件,适合放公共的数据库配置等
application-dev.properties #公共带环境的配置文件,dev环境会默认加载这个公共配置文件
config-client-dev.properties #config-client服务的私有配置
test-dev.properties #部分项目的公共配置,如一些项目引用mysql,一些不引用
#使用指定配置,需要在项目中设置下面这个选项
spring.cloud.config.name = config-client,test #指定配置文件,如果不需要指定,注释该行

额外

如果要使用vm启动参数,需要在config client设置如下三个参数

1
2
3
4
#使用vm启动参数,去掉下面的注释
spring.cloud.config.allowOverride=true
spring.cloud.config.overrideNone=false
spring.cloud.config.overrideSystemProperties=false

疑问:vm设置-Dserver.port等参数时,又不需要上面的设置
解释:vm参数如果不设置上面的会被配置文件里面的覆盖,如果配置文件里面没有设置,那就是用的vm的了

加载顺序

举例server.port

  1. client 里面的resources/bootstrap.yml

  2. vm里面-Dserver.port

  3. config里面config-client-dev.properties

三个都设置,使用3,只设置1,2使用2,只设置1,使用1

可推测优先级3>2>1

开发加载自己配置优化

利用默认分支功能,全局修改所有微服务为自己的配置

  1. 新建个自己的配置分支
  2. 复写spring config server启动参数spring.cloud.config.server.git.default-label=my-baranch为自己的分支号
  3. 注意不要在spring config client指定分支spring.cloud.config.label=master

SpringCloud 路由网关(Zuul)

Zuul的主要功能是路由转发和过滤器。例如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。

zuul功能点(下面只简单介绍勾选的)
  • Authentication 认证
  • Insights 洞察?
  • Stress Testing 压力测试
  • Canary Testing 金丝雀测试
  • Dynamic Routing 动态路由
  • Service Migration 服务迁移
  • Load Shedding 加载脱落
  • Security 安全
  • Static Response handling 静态响应处理
  • Active/Active traffic management 活动/活动流量管理

步骤

  1. 新建springboot项目勾选如下

    • web->web
    • Cloud discovery-> eureka server
    • Cloud routing->zuul
  2. EurekazuulApplication启动类添加注解@EnableZuulProxy开启zuul功能@EnableEurekaClient也需要注册到服务中心

  3. application.yml添加如下配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    server:
    port: 8095
    spring:
    application:
    name: zuul-client
    eureka:
    client:
    service-url:
    defaultZone: http://127.0.0.1:8091/eureka/ #注意要加eureka,不然找不到
    zuul:
    routes:
    api-a:
    path: /api-a/** #以/api-a/ 开头的请求都转发给ribbon-client服务
    serviceId: ribbon-client
    api-b:
    path: /api-b/** #以/api-b/ 开头的请求都转发给feign-client服务
    serviceId: feign-client
  4. 依次启动注册中心、ribbon服务端、feign服务端、zuul服务端

    http://127.0.0.1:8095/api-b/sayhi?name=32访问的就是feign服务端

    注意:api-b不需要在control里面添加路径,只需要添加sayhi就行

    http://127.0.0.1:8095/api-a/resthi?name=32访问的就是ribbon服务端

  5. 到此就实现了路由功能

服务过滤

服务过滤安全校验功能等,新建一个MyFilter类注意加注解@Component,然后继承ZuulFilter

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
@Component
public class MyFilter extends ZuulFilter {

@Override
public String filterType() {
return "pre"; //pre:路由之前,routing:路由之时,post:路由之后,error:发送错误调用
}

@Override
public int filterOrder() {
return 0; //filterOrder:过滤的顺序
}

@Override
public boolean shouldFilter() {
return true; //shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
}

@Override
public Object run() throws ZuulException {
//run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
RequestContext ctx=RequestContext.getCurrentContext();
HttpServletRequest request=ctx.getRequest();
System.out.print("method:"+request.getMethod()+",url:"+request.getRequestURL().toString());
Object token=request.getParameter("token");
if (token==null){
System.out.print("token is null");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
try {
ctx.getResponse().getWriter().write("token is null");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
System.out.print("ok");
return null;
}
}

在ribbon+restTemplate方式使用熔断器hystrix

阻止服务故障的“雪崩”效应(我简称保险)

  1. ribbonrest项目上添加compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix')该依赖(这里用的gradle,maven做相应格式修改),或者直接新建一个项目勾选如下

    • web->web
    • Cloud discovery-> eureka server
    • Cloud routing->ribbon
    • Cloud Circuit Breaker->Hystrix
  2. application启动类添加一个注解@EnableHystrix拉上保险开关

  3. 修改服务调用类HelloService

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Service
    public class HelloService {
    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hiError") //调用发生错误就调用hiError方法
    public String hiService(String name){
    //eureka-client为服务提供者的spring.application.name=eureka-client
    return restTemplate.getForObject("http://eureka-client/hi?name="+name,String.class);
    }
    //发生错误调用的方法
    public String hiError(String name) {
    return "hi,"+name+",sorry,error!";
    }
    }
  4. 启动该服务(8093),然后访问http://127.0.0.1:8093/resthi?name=32,然后再停止两台服务提供者的其中一台,然后刷新一台提示错误,一台正常访问

    启动顺序 访问结果 再启动 结果
    注册中心-服务提供者(1和2)-服务消费者 2台交替访问
    注册中心-服务提供者(1)-服务消费者-服务提供者(2) 1能访问
    注册中心-服务提供者(1和2)-服务消费者-停止1 1抛异常,2正常访问 再启动1 恢复时间慢
    注册中心-服务提供者(1和2)-服务消费者(开启了熔断器)-停止1 1返回熔断器自定义的错误信息,2正常访问 再启动1 马上可以交替访问

在feign模式使用熔断器

Feign是自带断路器的

  1. 新建SchedualServiceHiHystric实现服务调用的接口

    1
    2
    3
    4
    5
    6
    7
    @Component
    public class SchedualServiceHiHystric implements FeignSchedualService{
    @Override
    public String sayHiFromEurekaClient(String name) {
    return "sorry "+name;
    }
    }
  2. 在服务调用接口的@FeignClient添加fallback指向刚刚实现这个接口的类

    1
    2
    3
    4
    5
    @FeignClient(value = "eureka-client",fallback = SchedualServiceHiHystric.class) //指定调用那个服务(服务名spring.application.name)
    public interface FeignSchedualService {
    @RequestMapping(value = "/hi",method = RequestMethod.GET) //指定调用eureka-client服务的那个接口
    String sayHiFromEurekaClient(@RequestParam(value = "name") String name);
    }
  3. application配置文件添加该配置启用熔断器

    1
    2
    3
    feign:
    hystrix:
    enabled: true
  4. 依次启动注册中心,该服务(8094),然后访问http://127.0.0.1:8094/sayhi?name=32,启动测试见上面的第四步骤

    区别:服务提供者挂了一个不会交替返回正确错误信息,只要还有一个服务正常就返回正确信息,直到所有服务提供者挂了才返回错误信息。

参考

用 Feign Hystrix 进行服务集成

forezp/SpringCloudLearning