精华内容
下载资源
问答
  • STL主要包含容器、算法和迭代器三部分。容器实现了大多数数据结构;迭代器类似指针,通过它的有序移动将容器中的元素与算法关联起来,实现STL的基础。常用的STL包含头文件如下: 容器(contain) 容纳,...

    1、STL基本头文件
    STL主要包含容器、算法和迭代器三个部分。容器实现了大多数数据结构;迭代器类似指针,通过它的有序移动将容器中的元素与算法关联起来,是实现STL的基础。常用的STL包含头文件如下:
    在这里插入图片描述

    容器(contain)

    是容纳,包含一组元素的对象。
    而容器又包含以下几种:
    在这里插入图片描述
    这七种容器可以分为两种基本类型:
    顺序容器:一组具有相同类型的元素以严格的线性形式组织起来。向量,双端队列,列表容器属于这一种
    在这里插入图片描述
    关于三者的优缺点主要是:
    A:vector矢量容器:可以随机访问容器的内容,在序列末尾添加或删除对象,但是因为是从尾部删除,过程非常慢,因为必须移动插入或删除点后面的所有对象。
    在这里插入图片描述
    关联容器:具有根据一组索性来快速提取元素的能力,集合和映射属于这一类
    关联容器支持高效的关键字查找和访问。主要的关联容器类型是map和set,其中map中的元素是一些关键字-值(key-value)对:关键字起到索引的作用,值则表示索引相关联的数据;set中每个元素只包括一个关键字,set支持高效的关键字查询操作-检查一个给定关键字是否在set中。关联容器类型如下:

    在这里插入图片描述

    迭代器(iterator)

    C++的标准模板库(STL)中有容器、算法和迭代器,其中迭代器是非常重要的;
    容器又分为顺序容器和关联容器,每一种容器都有自己的迭代器,但是所有的迭代器的接口都是一样的,即所有的迭代器的操作方法都是一样的;
    迭代器实际上是一个指针

    begin操作返回一个迭代器,且该迭代器指向容器的第一个数据;
    end是指向最后一个的下一个;
    之所以这样设计end是为了很多情况下代码更容易写;
    在这里插入图片描述
    特定容器有特定的迭代器,故将迭代器作为内部类更适合应用。每个容器均有对应的迭代器,容器通过迭代器共享某一具体算法,而算法不具体依赖某一具体容器。由此可见,STL的编程思想是:1.形成容器元素;2.取出所需的迭代指针;3.调用通用算法。STL迭代器共分五大类型:
    输入迭代器istream_iterator,按其顺序只能读取一次。构造函数可参阅STL库;
    输出迭代器ostream_iterator,按顺序只写一次。构造函数可参阅STL库;
    前向迭代器,这种迭代器包含了输入输出迭代器两者所有可能,可以对一个值多次读写。前向迭代器只能向前移动;
    双向迭代器,具有前向迭代器的全部功能,它也可以向后移动操作;
    随机访问迭代器,具有双向迭代器的全部功能,再加上一个指针的所有功能。

    *iter      返回迭代器iter所指元素的引用
    iter->men  解引用iter并获得该元素的名为men的成员,相当于(*iter).men
    ++iter      令iter指示容器的下一个元素
     --iter      令iter指示容器的上一个元素
    iter1==iter2  如果两个迭代器指示的是同一个元素或者它指向同一个容器的尾后迭代器,则相等.
    

    下面给出一个使用迭代器运算符修改容器元素的代码示例:

    #include<iostream>
    using namespace std;
    #include<vector>
    int main()
    {
        vector <int> v(10, 1);
        int i=1;
        cout << "未修改前:";
        for (auto v_quote : v)
        {
            cout << v_quote << " " ;   //未修改前
        }
        cout << endl;
        for (auto v_quote = v.begin(); v_quote != v.end(); ++v_quote)
        {
            *v_quote += i;
            ++i;
        }
        cout << "修改后:";
        for (auto v_quote : v)
        {
            cout << v_quote << " ";
        }
        cout << endl;
        return 0;
    }
    

    那些拥有迭代器的标准库类型都是使用:iterator和const_iterator来表示迭代器的类型:

     vector <int> ::iterator it;        //it能读写vector<int>的元素
        vector <int>::const_iterator it;   //it只能读vector<int>的元素,不可以修改vector<int>中的元素
    
        string::iterator s;                //s可以读写string对象中的元素
        string::const_iterator s;          //s只可以读string对象中的元素,不可以修改string对象中的元素
    

    迭代器的运算

    iter+n           //迭代器加上一个整数值仍得到一个迭代器,迭代器指示的新位置向前移动了,指示可能是容器的一个元素或者是尾部的下一个位置
    iter-n          //相反,迭代器指示的位置向后移动了,指示可能是容器的一个元素或者是尾部的下一个位置
    iter1+=n        //等价于iter1+n
    iter1-=n        //等价于iter2-n
    iter1-iter2     //两个迭代器的距离,
    

    函数对象(function object)

    函数对象时一个行为类似函数的对象,对他可以像调用函数一样调用。任何普通的函数和重载了“()”运算符的类的对象作为函数使用,寒素对象是泛化的函数

    标准C++库根据operator()参数个数为0,1,2划分,有如下几种函数对象:

    a. 发生器:没有参数且返回任意类型值的函数对象,如随机函数发生器;

    b. 一元函数:只有一个任意类型的参数,返回一个可能不同类型的函数对象;

    c. 二元函数:两个任意类型参数,且返回一个任意类型的函数对象;

    d. 一元判定函数:返回bool类型的一元函数;

    e. 二元判定函数:返回bool类型的二元函数;

    //函数对象
    #include<iostream>
    #include<vector>
    #include<functional>
    #include<algorithm>
    #include<numeric> 
    using namespace std;
    int sumSquares(int total,int value){
    	return total+value*value;
    }
    template <class T>
    void PrintInterval(T first,T last){
    	for(;first!=last;++first){
    		cout<<*first<<",";
    	}
    	cout<<endl;
    }
    template <class T>
    class SumPowers{
    	private:
    		int power;
    	public:
    		SumPowers(int p):power(p){
    		}
    		const T operator() (const T & total,const T & value){
    			//计算value 的power 次方,加到total上
    			T v=value;
    			for(int i=0;i<power-1;++i)
    				v=v*value; 
    			return total+v;	
    		}	
    		
    };
    int main(void){
    	const int SIZE=10;
    	int a1[]={1,2,3,4,5,6,7,8,9,10};
    	vector<int> v(a1,a1+SIZE);
    	cout<<"1)";PrintInterval(v.begin(),v.end());
    	int result=accumulate(v.begin(),v.end(),0,sumSquares);
    	cout<<"2)平方和 "<<result<<endl;
    	result=accumulate(v.begin(),v.end(),0,SumPowers<int>(3));
    	cout<<"3)立方和"<<result<<endl;
    	result=accumulate(v.begin(),v.end(),0,SumPowers<int>(4));
    	cout<<"4)4次方和"<<result; 
    	return 0;
    } 
    
    

    算法(algorithm)

    函数库对数据类型的选择对其可重用性起着至关重要的作用。举例来说,一个求方根的函数,在使用浮点数作为其参数类型的情况下的可重用性肯定比使用整型作为它的参数类性要高。而C++通过模板的机制允许推迟对某些类型的选择,直到真正想使用模板或者说对模板进行特化的时候,STL就利用了这一点提供了相当多的有用算法。它是在一个有效的框架中完成这些算法的——你可以将所有的类型划分为少数的几类,然后就可以在模版的参数中使用一种类型替换掉同一种类中的其他类型。
    STL提供了大约100个实现算法的模版函数,比如算法for_each将为指定序列中的每一个元素调用指定的函数,stable_sort以你所指定的规则对序列进行稳定性排序等等。只要我们熟悉了STL之后,许多代码可以被大大的化简,只需要通过调用一两个算法模板,就可以完成所需要的功能并大大地提升效率。
    算法部分主要由头文件,和组成。
    是所有STL头文件中最大的一个(尽管它很好理解),它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。
    体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。
    中则定义了一些模板类,用以声明函数对象。
    STL中算法大致分为四类:
    1)非可变序列算法:指不直接修改其所操作的容器内容的算法。
    2)可变序列算法:指可以修改它们所操作的容器内容的算法。
    3)排序算法:对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作。
    4)数值算法:对容器内容进行数值计算。
    以下对所有算法进行细致分类并标明功能:
    <一>查找算法(13个):判断容器中是否包含某个值

    adjacent_find: 在iterator对标识元素范围内,查找一对相邻重复元素,找到则返回指向这对元素的第一个元素的ForwardIterator。否则返回last。重载版本使用输入的二元操作符代替相等的判断。
    binary_search: 在有序序列中查找value,找到返回true。重载的版本实用指定的比较函数对象或函数指针来判断相等。
    count: 利用等于操作符,把标志范围内的元素与输入值比较,返回相等元素个数。
    count_if: 利用输入的操作符,对标志范围内的元素进行操作,返回结果为true的个数。
    equal_range: 功能类似equal,返回一对iterator,第一个表示lower_bound,第二个表示upper_bound。
    find: 利用底层元素的等于操作符,对指定范围内的元素与输入值进行比较。当匹配时,结束搜索,返回该元素的一个InputIterator。
    find_end: 在指定范围内查找"由输入的另外一对iterator标志的第二个序列"的最后一次出现。找到则返回最后一对的第一个ForwardIterator,否则返回输入的"另外一对"的第一个ForwardIterator。重载版本使用用户输入的操作符代替等于操作。
    find_first_of: 在指定范围内查找"由输入的另外一对iterator标志的第二个序列"中任意一个元素的第一次出现。重载版本中使用了用户自定义操作符。
    find_if: 使用输入的函数代替等于操作符执行find。
    lower_bound: 返回一个ForwardIterator,指向在有序序列范围内的可以插入指定值而不破坏容器顺序的第一个位置。重载函数使用自定义比较操作。
    upper_bound: 返回一个ForwardIterator,指向在有序序列范围内插入value而不破坏容器顺序的最后一个位置,该位置标志一个大于value的值。重载函数使用自定义比较操作。
    search: 给出两个范围,返回一个ForwardIterator,查找成功指向第一个范围内第一次出现子序列(第二个范围)的位置,查找失败指向last1。重载版本使用自定义的比较操作。
    search_n: 在指定范围内查找val出现n次的子序列。重载版本使用自定义的比较操作。
    

    <二>排序和通用算法(14个):提供元素排序策略
    i

    nplace_merge: 合并两个有序序列,结果序列覆盖两端范围。重载版本使用输入的操作进行排序。
    merge: 合并两个有序序列,存放到另一个序列。重载版本使用自定义的比较。
    nth_element: 将范围内的序列重新排序,使所有小于第n个元素的元素都出现在它前面,而大于它的都出现在后面。重载版本使用自定义的比较操作。
    partial_sort: 对序列做部分排序,被排序元素个数正好可以被放到范围内。重载版本使用自定义的比较操作。
    partial_sort_copy: 与partial_sort类似,不过将经过排序的序列复制到另一个容器。
    partition: 对指定范围内元素重新排序,使用输入的函数,把结果为true的元素放在结果为false的元素之前。
    random_shuffle: 对指定范围内的元素随机调整次序。重载版本输入一个随机数产生操作。
    reverse: 将指定范围内元素重新反序排序。
    reverse_copy: 与reverse类似,不过将结果写入另一个容器。
    rotate: 将指定范围内元素移到容器末尾,由middle指向的元素成为容器第一个元素。
    rotate_copy: 与rotate类似,不过将结果写入另一个容器。
    sort: 以升序重新排列指定范围内的元素。重载版本使用自定义的比较操作。
    stable_sort: 与sort类似,不过保留相等元素之间的顺序关系。
    stable_partition: 与partition类似,不过不保证保留容器中的相对顺序。
    

    <三>删除和替换算法(15个)

    copy: 复制序列
    copy_backward: 与copy相同,不过元素是以相反顺序被拷贝。
    iter_swap: 交换两个ForwardIterator的值。
    remove: 删除指定范围内所有等于指定元素的元素。注意,该函数不是真正删除函数。内置函数不适合使用remove和remove_if函数。
    remove_copy: 将所有不匹配元素复制到一个制定容器,返回OutputIterator指向被拷贝的末元素的下一个位置。
    remove_if: 删除指定范围内输入操作结果为true的所有元素。
    remove_copy_if: 将所有不匹配元素拷贝到一个指定容器。
    replace: 将指定范围内所有等于vold的元素都用vnew代替。
    replace_copy: 与replace类似,不过将结果写入另一个容器。
    replace_if: 将指定范围内所有操作结果为true的元素用新值代替。
    replace_copy_if: 与replace_if,不过将结果写入另一个容器。
    swap: 交换存储在两个对象中的值。
    swap_range: 将指定范围内的元素与另一个序列元素值进行交换。
    unique: 清除序列中重复元素,和remove类似,它也不能真正删除元素。重载版本使用自定义比较操作。
    unique_copy: 与unique类似,不过把结果输出到另一个容器。
    

    <四>排列组合算法(2个):提供计算给定集合按一定顺序的所有可能排列组合

    next_permutation: 取出当前范围内的排列,并重新排序为下一个排列。重载版本使用自定义的比较操作。
    prev_permutation: 取出指定范围内的序列并将它重新排序为上一个序列。如果不存在上一个序列则返回false。重载版本使用自定义的比较操作。
    

    <五>算术算法(4个)

    accumulate: iterator对标识的序列段元素之和,加到一个由val指定的初始值上。重载版本不再做加法,而是传进来的二元操作符被应用到元素上。
    partial_sum: 创建一个新序列,其中每个元素值代表指定范围内该位置前所有元素之和。重载版本使用自定义操作代替加法。
    inner_product: 对两个序列做内积(对应元素相乘,再求和)并将内积加到一个输入的初始值上。重载版本使用用户定义的操作。
    adjacent_difference: 创建一个新序列,新序列中每个新值代表当前元素与上一个元素的差。重载版本用指定二元操作计算相邻元素的差。
    

    <六>生成和异变算法(6个)

    fill: 将输入值赋给标志范围内的所有元素。
    fill_n: 将输入值赋给first到first+n范围内的所有元素。
    for_each: 用指定函数依次对指定范围内所有元素进行迭代访问,返回所指定的函数类型。该函数不得修改序列中的元素。
    generate: 连续调用输入的函数来填充指定的范围。
    generate_n: 与generate函数类似,填充从指定iterator开始的n个元素。
    transform: 将输入的操作作用与指定范围内的每个元素,并产生一个新的序列。重载版本将操作作用在一对元素上,另外一个元素来自输入的另外一个序列。结果输出到指定容器。
    

    <七>关系算法(8个)

    equal: 如果两个序列在标志范围内元素都相等,返回true。重载版本使用输入的操作符代替默认的等于操作符。
    includes: 判断第一个指定范围内的所有元素是否都被第二个范围包含,使用底层元素的<操作符,成功返回true。重载版本使用用户输入的函数。
    lexicographical_compare: 比较两个序列。重载版本使用用户自定义比较操作。
    max: 返回两个元素中较大一个。重载版本使用自定义比较操作。
    max_element: 返回一个ForwardIterator,指出序列中最大的元素。重载版本使用自定义比较操作。
    min: 返回两个元素中较小一个。重载版本使用自定义比较操作。
    min_element: 返回一个ForwardIterator,指出序列中最小的元素。重载版本使用自定义比较操作。
    mismatch: 并行比较两个序列,指出第一个不匹配的位置,返回一对iterator,标志第一个不匹配元素位置。如果都匹配,返回每个容器的last。重载版本使用自定义的比较操作
    


    <八>集合算法(4个)

    set_union: 构造一个有序序列,包含两个序列中所有的不重复元素。重载版本使用自定义的比较操作。
    set_intersection: 构造一个有序序列,其中元素在两个序列中都存在。重载版本使用自定义的比较操作。
    set_difference: 构造一个有序序列,该序列仅保留第一个序列中存在的而第二个中不存在的元素。重载版本使用自定义的比较操作。
    set_symmetric_difference: 构造一个有序序列,该序列取两个序列的对称差集(并集-交集)。
    

    <九>堆算法(4个)

    make_heap: 把指定范围内的元素生成一个堆。重载版本使用自定义比较操作。
    pop_heap: 并不真正把最大元素从堆中弹出,而是重新排序堆。它把first和last-1交换,然后重新生成一个堆。可使用容器的back来访问被"弹出"的元素或者使用pop_back进行真正的删除。重载版本使用自定义的比较操作。
    push_heap: 假设first到last-1是一个有效堆,要被加入到堆的元素存放在位置last-1,重新生成堆。在指向该函数前,必须先把元素插入容器后。重载版本使用指定的比较操作。
    sort_heap: 对指定范围内的序列重新排序,它假设该序列是个有序堆。重载版本使用自定义比较操作。
    
    展开全文
  • UPnP 体系架构和基本原理 —— UPnP 网络组件 UPnP 网络组件 ...例如:一个播放器设备可以包含歌曲播放服务和时钟服务,而一个多媒体设备可以包含播放器设备和资源搜索服务。该设备可以物理上...

    UPnP 体系架构和基本原理 —— UPnP 网络组件

    UPnP 网络组件

    UPnP 网络组件通常由设备(Device)、服务(Service)和控制点(Control Point)这三个基础组件组成。

    UPnP 网络组件

    设备

    UPnP最基本的概念模型就是设备模型,设备是服务和嵌入式设备的容器。例如:一个播放器设备可以包含歌曲播放服务和时钟服务,而一个多媒体设备可以包含播放器设备和资源搜索服务。该设备可以是物理上的设备,如电视机;也可以是逻辑上的设备,如笔记本电脑内的一个播放器所模拟的电视机。因此,UPnP设备并非传统意义上的硬件设备,还应当包括其中的服务功能。

    由于不同种类的UPnP设备需要关联不同的服务和嵌入式设备,因此它们的服务和嵌入式设备都应该有所不同,用以区分。一个UPnP设备可以由多个嵌入式设备嵌入组成,但根设备和嵌入式设备之间有所差别。根设备中存在自身的服务描述信息,因此根设备中的嵌入式设备需要独立自身的描述文档以便与根设备的服务描述信息区别开。

    服务

    服务是UPnP网络中最基础的控制单元。每个服务描述设备所提供的若干动作和相关的状态。如一个播放器,服务有媒体服务、时钟服务等,媒体服务包含播放进度、播放总时长、音量等状态和播放、暂停、音量调节等动作,而时钟服务包含时钟设置和时钟显示等动作。
    UPnP设备的设备信息和其拥有的服务相关描述信息都保存在一个XML描述文件中,当设备了建立联系和使用时,XML文件可以与其进行关联。从图可知,一个设备服务由一个状态变量表(State Table)、一个控制服务器(Control Server)和一个事件服务器(Event Server)组成。

    1. 状态变量表:状态变量表中使用状态变量用于描述服务的状态,当服务状态发生变化时,需要更新状态变量表中的相关状态变量。
    2. 控制服务器:控制服务器用于接收并执行网络内其它设备对该设备的服务的动作请求,更新状态变量表中相关状态变量,返回响应结果。
    3. 事件服务器:事件服务器接受事件订阅者对设备事件的订阅请求,当服务的状态发生变化时,会向订阅该事件的订阅者发生事件通知。

    控制点

    在UPnP网络中,控制点是对网络中的设备和服务进行控制操作的控制者,可以发现并控制其它设备的控制设备。控制点的主要任务有:

    1. 搜索网络内的设备描述和服务描述。
    2. 向服务发送动作请求。
    3. 获取服务的状态变化情况。
    4. 接受服务的事件通知信息。

    上面所述的动作请求信息、状态信息、事件通知信息等各种信息,根据不同信息采用的格式保存在XML文件中,以区分出信息的种类,保证可以各取所需,不会混淆。

    展开全文
  •   HelmKubernetes的一个包管理工具,用来简化Kubernetes应用的部署和管理。可以把Helm比作CentOS的yum工具.  Helm有如下几个基本概念: Chart: Helm管理的安装包,里面包含需要部署的安装包资源。可以把...

    Helm的使用

    1. Helm简介:

    1. Helm的概念

      Helm是Kubernetes的一个包管理工具,用来简化Kubernetes应用的部署和管理。可以把Helm比作CentOS的yum工具.
      Helm有如下几个基本概念:

    • Chart: 是Helm管理的安装包,里面包含需要部署的安装包资源。可以把Chart比作CentOS yum使用的rpm文件。每个Chart包含下面两部分:

      1. 包的基本描述文件Chart.yaml
      2. 放在templates目录中的一个或多个Kubernetes manifest文件模板
    • Release:是chart的部署实例,一个chart在一个Kubernetes集群上可以有多个release,即这个chart可以被安装多次

    • Repository:chart的仓库,用于发布和存储chart

      使用Helm可以完成以下事情:

    • 管理Kubernetes manifest files
    • 管理Helm安装包charts
    • 基于chart的Kubernetes应用分发

    2. Helm的组成

      Helm由两部分组成,客户端helm和服务端tiller。

    • tiller运行在Kubernetes集群上,管理chart安装的release
    • helm是一个命令行工具,可在本地运行,一般运行在CI/CD Server上。

    3. Helm的安装

      下载Helm二进制文件:https://github.com/helm/helm/releases/tag/v2.13.1

    [root@test111 software]# tar xzvf helm-v2.13.1-linux-amd64.tar.gz
    [root@test111 software]# cd linux-amd64/
    [root@test111 linux-amd64]# cp -r helm /usr/local/bin/
    [root@test111 linux-amd64]# helm version
    Client: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}
    Error: Get http://localhost:8080/api/v1/namespaces/kube-system/pods?labelSelector=app%3Dhelm%2Cname%3Dtiller: dial tcp [::1]:8080: connect: connection refused
    [root@test111 linux-amd64]#

      此时运行helm version可以打印出客户端helm的版本,同时会提示无法连接到服务端Tiller。
      为了安装服务端tiller,还需要在这台机器上配置好kubectl工具和kubeconfig文件,确保kubectl工具可以在这台机器上访问apiserver且正常使用。
      从kubemaster的服务器上面拷贝两个文件到安装Helm客户端的机器,分别拷贝kubectl命令和/root/.kube/config文件

    [root@kubemaster ~]# which kubectl
    /usr/bin/kubectl
    [root@kubemaster ~]# scp -r /usr/bin/kubectl root@test111:/usr/bin/
    kubectl                                                                                                                                                      100%   37MB  12.5MB/s   00:03
    [root@kubemaster ~]# scp -r /root/.kube/config root@test111:/root/.kube/
    config                                                                                                                                                       100% 5448   328.6KB/s   00:00
    [root@kubemaster ~]#

      然后在安装Helm客户端的任何一台机器上面,输入命令检查是否可以连接集群

    [root@test111 linux-amd64]# kubectl get cs
    NAME                 STATUS    MESSAGE              ERROR
    scheduler            Healthy   ok
    controller-manager   Healthy   ok
    etcd-0               Healthy   {"health": "true"}

      接下来是安装服务端Tiller

    # 配置 service account tiller 和 ClusterRoleBinding tiller
    vim sa.yaml
    
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: tiller
      namespace: kube-system
    
    vim ClusterRoleBinding.yaml
    
      apiVersion: rbac.authorization.k8s.io/v1beta1
      kind: ClusterRoleBinding
      metadata:
        name: tiller
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: ClusterRole
        name: cluster-admin
      subjects:
        - kind: ServiceAccount
          name: tiller
          namespace: kube-system
    kubectl apply -f  sa.yaml
    kubectl apply -f  ClusterRoleBinding.yaml
    

      初始化tiller服务端

    helm init --service-account tiller --upgrade --tiller-image=registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.13.1
    #注意这里的tiller服务器镜像版本,一定要和helm client的版本一致。这里的版本都为最新的版本  v2.13.1
    [root@test111 ~]# helm version
    Client: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}
    Server: &version.Version{SemVer:"v2.13.1", GitCommit:"a80231648a1473929271764b920a8e346f6de844", GitTreeState:"clean"}
    

      设置charts仓库为微软azure仓库,这个仓库同步的是最新的helm包,阿里云仓库的helm包好久不更新了

    [root@test111 ~]# cat /root/.helm/repository/repositories.yaml
    apiVersion: v1
    generated: 2018-11-10T20:32:27.187074383+08:00
    repositories:
    - caFile: ""
      cache: /root/.helm/repository/cache/stable-index.yaml
      certFile: ""
      keyFile: ""
      name: stable
      password: "password"
      url: http://mirror.azure.cn/kubernetes/charts/
      username: "username"
    - caFile: ""
      cache: /root/.helm/repository/cache/local-index.yaml
      certFile: ""
      keyFile: ""
      name: local
      password: ""
      url: http://127.0.0.1:8879/charts
      username: ""
    [root@test111 ~]#
    
    #更新chart repo:
    helm repo update
    
    Hang tight while we grab the latest from your chart repositories...
    ...Skip local chart repository
    ...Successfully got an update from the "stable" chart repository
    Update Complete. ⎈ Happy Helming!⎈
    

    4. 管理chart仓库

    [root@test111 software]# helm repo list
    NAME    URL
    stable  https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
    local   http://127.0.0.1:8879/charts
    [root@test111 software]#
    #查看目前的chart仓库
    
    [root@test111 software]# helm repo remove stable
    "stable" has been removed from your repositories
    #删除目前的仓库
    
    [root@test111 software]# helm repo add stable https://cnych.github.io/kube-charts-mirror/
    "stable" has been added to your repositories
    #添加新的远程仓库
    
    [root@test111 software]# helm repo list
    NAME    URL
    local   http://127.0.0.1:8879/charts
    stable  https://cnych.github.io/kube-charts-mirror/
    #查看目前的chart仓库
    
    [root@test111 software]# helm repo update
    Hang tight while we grab the latest from your chart repositories...
    ...Skip local chart repository
    ...Successfully got an update from the "stable" chart repository
    Update Complete. ⎈ Happy Helming!⎈
    [root@test111 software]#
    #更新repo

    5. Helm安装hello-svc应用

      使用helm create chart名称 安装一个应用。同时会下载hello-svc项目的目录文件到本地

    helm create hello-svc
    [root@test111 ~]# tree hello-svc/
    hello-svc/
    ├── charts
    ├── Chart.yaml
    ├── templates
    │   ├── deployment.yaml
    │   ├── _helpers.tpl
    │   ├── ingress.yaml
    │   ├── NOTES.txt
    │   ├── service.yaml
    │   └── tests
    │       └── test-connection.yaml
    └── values.yaml

      我们来熟悉一下hello-svc这个chart中目录和文件内容:

    • charts目录中是本chart依赖的chart,当前是空的
    • Chart.yaml这个yaml文件用于描述Chart的基本信息,如名称版本等
    • templates目录是Kubernetes manifest文件模板目录,模板使用chart配置的值生成Kubernetes manifest文件。模板文件使用的Go语言模板语法
    • templates/NOTES.txt 纯文本文件,可在其中填写chart的使用说明
    • value.yaml 是chart配置的默认值
    • 通过查看deployment.yaml和value.yaml,大概知道这个chart默认安装就是在Kubernetes部署一个nginx服务。
    cd /root/hello-svc
    helm install --dry-run --debug ./  #对chart的模板和配置进行测试
    helm install ./  #在Kubernetes上安装chart
    helm list    #查看release
    [root@test111 hello-svc]# helm list
    NAME                REVISION    UPDATED                     STATUS      CHART               APP VERSION NAMESPACE
    silly-gecko         1           Wed Mar 27 11:25:11 2019    DEPLOYED    hello-svc-0.1.0     1.0         default
    stultified-prawn    1           Mon Mar  4 15:21:21 2019    DEPLOYED    nginx-ingress-0.9.5 0.10.2      default
    [root@test111 hello-svc]#
    

    6. 使用Helm安装Redis-HA应用

      在我以前的博文中介绍过在传统虚拟机上面实现Redis的安装步骤。本文重点介绍在kubernetes容器集群中如何部署Redis应用。在部署之前首先介绍一下Redis集群的两种常用方案:

    1. redis-HA方案:

      Redis-HA方案应该叫做主从复制方案,不能称为集群方案。主从复制方案的主要原理是,如果主节点宕机,从节点作为主节点的备份会随时顶替主节点工作,也可以将读请求分配到从节点,类似于Mysql的读写分离案节例一样。但是如果主节宕机,从节升级为主节点,但是应用程序连接的redis服务器IP仍然为主节点IP,这个时候还需要人工
    干预应用程序的连结Redis服务器的IP,所以需要把这个IP配置成VIP地址,实现自动切换。
      
    Redis Sentinel是一个分布式架构,包含若干个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当发现节点不可达时,会对节点做下线标识。
    如果被标识的是主节点,他还会选择和其他Sentinel节点进行“协商”,当大多数的Sentinel节点都认为主节点不可达时,他们会选举出一个Sentinel节点来完成自动故障转移工作,同时将这个变化通知给Redis应用方。

      每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒且没有回复,则判定不可达。当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作 。

    2. redis-Cluster方案:

      Redis官方在3.0版本之后才开始支持集群方案。Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation)。Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
    Redis集群提供了两个好处,第一是将数据自动切分(split)到多个节点,第二是当集群中有一部分节点失效或者无法进行通讯时,仍然可以继续处理命令请求;
      Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现。 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和。
    集群中的每个节点负责处理一部分哈希槽。 举个例子, 一个集群可以有三个哈希槽, 其中:

    • 节点 A 负责处理 0 号至 5500 号哈希槽
    • 节点 B 负责处理 5501 号至 11000 号哈希槽
    • 节点 C 负责处理 11001 号至 16384 号哈希槽。

      这种将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。 比如说:

    • 如果用户将新节点 D 添加到集群中, 那么集群只需要将节点 A 、B 、 C 中的某些槽移动到节点 D 就可以了。
    • 与此类似, 如果用户要从集群中移除节点 A , 那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C , 然后再移除空白(不包含任何哈希槽)的节点 A 就可以了。

      为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下, 仍然可以正常运作, Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其余的 N-1 个复制品为从节点(slave)。

      在之前列举的节点 A 、B 、C 的例子中, 如果节点 B 下线了, 那么集群将无法正常运行, 因为集群找不到节点来处理 5501 号至 11000号的哈希槽。
    另一方面, 假如在创建集群的时候(或者至少在节点 B 下线之前), 我们为主节点 B 添加了从节点 B1 , 那么当主节点 B 下线的时候, 集群就会将 B1 设置为新的主节点, 并让它代替下线的主节点 B , 继续处理 5501 号至 11000 号的哈希槽, 这样集群就不会因为主节点 B 的下线而无法正常运作了。

      对于Redis集群方案,国内的豌豆荚公司开发的一个分布式的基于代理的高性能Redis 集群解决方案,名字叫做Codis.(国内还有类似于Twemproxy的软件也能实现同样的功能)用Go语言开发的。对于上层的应用来说,连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别 (不支持的命令列表),Codis 底层会处理请求的转发,不停机的数据迁移等工作。所有后边的一切事情,对于前面的客户端来说是透明的,可以简单的认为后边连接的是一个内存无限大的 Redis 服务。具体的方案可以参考https://github.com/CodisLabs/codis

      Codis 由四部分组成:

    • Codis Proxy (codis-proxy),处理客户端请求,支持Redis协议,因此客户端访问Codis Proxy跟访问原生Redis没有什么区别;

    • Codis Dashboard (codis-config),Codis 的管理工具,支持添加/删除 Redis 节点、添加/删除 Proxy 节点,发起数据迁移等操作。codis-config 本身还自带了一个 http server,会启动一个 dashboard,用户可以直接在浏览器上观察 Codis 集群的运行状态;
    • Codis Redis (codis-server),Codis 项目维护的一个 Redis 分支,基于 2.8.21 开发,加入了 slot 的支持和原子的数据迁移指令;

    • ZooKeeper/Etcd,Codis 依赖 ZooKeeper 来存放数据路由表和 codis-proxy 节点的元信息,codis-config 发起的命令都会通过 ZooKeeper 同步到各个存活的 codis-proxy
    • helm的使用和redis、mq等公共组件的容器化实践

    3. 使用Helm安装redis-sentinel主从:

      所有的官方Helm包都可以在https://github.com/helm/charts/tree/master/stable/ 网址下载。包括我本次实验的Redis-HA,Mysql、RabbitMQ、Jenkins等。

      配置好helm仓库之后,最好微软的那个helm仓库,是同步更新github。然后可以使用命令:

    [root@master-01 helm_jenkins]#  helm repo list
    NAME        URL
    local       http://127.0.0.1:8879/charts
    stable      http://mirror.azure.cn/kubernetes/charts/
    kiwigrid    https://kiwigrid.github.io
    [root@master-01 helm_jenkins]# helm search redis
    NAME                                CHART VERSION   APP VERSION DESCRIPTION
    stable/prometheus-redis-exporter    1.0.2           0.28.0      Prometheus exporter for Redis metrics
    stable/redis                        7.0.0           4.0.14      Open source, advanced key-value store. It is often referr...
    stable/redis-ha                     3.4.0           5.0.3       Highly available Kubernetes implementation of Redis
    stable/sensu                        0.2.3           0.28        Sensu monitoring framework backed by the Redis transport
    [root@master-01 helm_jenkins]#

      然后下载redis-ha的helm包到本地.先创建一个本地的目录,然后直接把helm包下载到本地的目录

    [root@master-01 tmp]# mkdir -p redis-ha
    [root@master-01 tmp]# helm fetch stable/redis-ha --untar --untardir ./redis-ha/

      第二步就是修改value.yaml文件。这个文件的修改方法一般是参考官方的helm说明。https://github.com/helm/charts/tree/master/stable/redis-ha 这个文件的修改方法一般是参考官方的helm说明。官网一般都会详细描述每一个key的用途,value值的默认参数等。

    ## Configure resource requests and limits
    ## ref: http://kubernetes.io/docs/user-guide/compute-resources/
    ##
    image:
      repository: k8s.harbor.test.site/system/redis
      tag: 5.0.3-alpine
      pullPolicy: IfNotPresent
    ## replicas number for each component
    replicas: 3
    
    ## Custom labels for the redis pod
    labels: {}
    
    ## Pods Service Account
    ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
    serviceAccount:
      ## Specifies whether a ServiceAccount should be created
      ##
      create: true
      ## The name of the ServiceAccount to use.
      ## If not set and create is true, a name is generated using the redis-ha.fullname template
      # name:
    
    ## Role Based Access
    ## Ref: https://kubernetes.io/docs/admin/authorization/rbac/
    ##
    
    rbac:
      create: true
    
    sysctlImage:
      enabled: false
      command: []
      registry: docker.io
      repository: k8s.harbor.test.site/system/minideb:latest
      tag: latest
      pullPolicy: Always
      mountHostSys: false
    
    ## Redis specific configuration options
    redis:
      port: 6379
      masterGroupName: mymaster
      config:
        ## Additional redis conf options can be added below
        ## For all available options see http://download.redis.io/redis-stable/redis.conf
        min-slaves-to-write: 1
        min-slaves-max-lag: 5   # Value in seconds
        maxmemory: "0"       # Max memory to use for each redis instance. Default is unlimited.
        maxmemory-policy: "volatile-lru"  # Max memory policy to use for each redis instance. Default is volatile-lru.
        # Determines if scheduled RDB backups are created. Default is false.
        # Please note that local (on-disk) RDBs will still be created when re-syncing with a new slave. The only way to prevent this is to enable diskless replication.
        save: "900 1"
        # When enabled, directly sends the RDB over the wire to slaves, without using the disk as intermediate storage. Default is false.
        repl-diskless-sync: "yes"
        rdbcompression: "yes"
        rdbchecksum: "yes"
    
      ## Custom redis.conf files used to override default settings. If this file is
      ## specified then the redis.config above will be ignored.
      # customConfig: |-
          # Define configuration here
    
      resources: {}
      #  requests:
      #    memory: 200Mi
      #    cpu: 100m
      #  limits:
      #    memory: 700Mi
    
    ## Sentinel specific configuration options
    sentinel:
      port: 26379
      quorum: 2
      config:
        ## Additional sentinel conf options can be added below. Only options that
        ## are expressed in the format simialar to 'sentinel xxx mymaster xxx' will
        ## be properly templated.
        ## For available options see http://download.redis.io/redis-stable/sentinel.conf
        down-after-milliseconds: 10000
        ## Failover timeout value in milliseconds
        failover-timeout: 180000
        parallel-syncs: 5
    
      ## Custom sentinel.conf files used to override default settings. If this file is
      ## specified then the sentinel.config above will be ignored.
      # customConfig: |-
          # Define configuration here
    
      resources: {}
      #  requests:
      #    memory: 200Mi
      #    cpu: 100m
      #  limits:
      #    memory: 200Mi
    
    securityContext:
      runAsUser: 1000
      fsGroup: 1000
      runAsNonRoot: true
    
    ## Node labels, affinity, and tolerations for pod assignment
    ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
    ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature
    ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
    affinity: |
      podAntiAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                app: {{ template "redis-ha.name" . }}
                release: {{ .Release.Name }}
            topologyKey: kubernetes.io/hostname
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app:  {{ template "redis-ha.name" . }}
                  release: {{ .Release.Name }}
              topologyKey: failure-domain.beta.kubernetes.io/zone
    
    # Prometheus exporter specific configuration options
    exporter:
      enabled: true
      image: k8s.harbor.test.site/system/redis_exporter
      tag: v0.31.0
      pullPolicy: IfNotPresent
    
      # prometheus port & scrape path
      port: 9121
      scrapePath: /metrics
    
      # cpu/memory resource limits/requests
      resources: {}
    
      # Additional args for redis exporter
      extraArgs: {}
    
    podDisruptionBudget: {}
      # maxUnavailable: 1
      # minAvailable: 1
    
    ## Configures redis with AUTH (requirepass & masterauth conf params)
    auth: true
    redisPassword: aaaaaa
    
    ## Use existing secret containing "auth" key (ignores redisPassword)
    # existingSecret:
    
    persistentVolume:
      enabled: true
      ## redis-ha data Persistent Volume Storage Class
      ## If defined, storageClassName: <storageClass>
      ## If set to "-", storageClassName: "", which disables dynamic provisioning
      ## If undefined (the default) or set to null, no storageClassName spec is
      ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
      ##   GKE, AWS & OpenStack)
      ##
      storageClass: "dynamic"
      accessModes:
        - ReadWriteOnce
      size: 10Gi
      annotations: {}
    init:
      resources: {}
    
    # To use a hostPath for data, set persistentVolume.enabled to false
    # and define hostPath.path.
    # Warning: this might overwrite existing folders on the host system!
    hostPath:
      ## path is evaluated as template so placeholders are replaced
      # path: "/data/{{ .Release.Name }}"
    
      # if chown is true, an init-container with root permissions is launched to
      # change the owner of the hostPath folder to the user defined in the
      # security context
      chown: true
    

       在修改value.yaml之前,建议先看一下官方的说明。并且使用helm安装redis-ha等由状态应用之前,需要熟悉redis-ha有状态应用的原理,
    并且最好是自己搭建过环境,理解里面的配置。

       我一般的个人习惯是,先把value.yaml里面用到的镜像下载到本地然后上传到公司的harbor私有仓库,然后把value.yaml里面的镜像地址都换成
    公司私有仓库的镜像地址,这样部署起来会比较快。因为redis-ha应用需要用到持久化存储,这个reids-ha应用主要是kubernetes里面的statefulset资源类型,
    也就是每一个Pod重启之后都需要有固定的名称,一般为pod名称+无头服务的名称+namespace+svc.cluster.local. 并且每一个pod重新启动之后需要找到原来的
    pvc.

       所以我们还要存储这块的配置,增加我们以前配置的storageClassName的名字为dynamic。这个是我们这个环境的ceph RBD存储的sc的名字。这个heml包里面还自带安装了redis-exporter。专门用于将redis的metrics监控数据上传到prometheus的用途;

       配置文件中这一段配置podAntiAffinity,主要的用途是调度反亲和性,属于运行时调度策略.podAntiAffinity主要解决POD不能和哪些POD部署在同一个拓扑域中的问题。它们处理的是Kubernetes集群内部POD和POD之间的关系。目的就是让redis Master不要和redis Slave两个pod不要启动在一个物理节点上面;

       同时还定义了redis的配置文件,sentinel的配置文件。指定了redis的副本数为3,指定了连接redis的密码。

       关于测试redis-ha配置是否正常,可以通过命令helm status redis-ha来查看

    [root@master-01 redis-ha]# helm status my-redis
    LAST DEPLOYED: Tue Apr 23 15:57:27 2019
    NAMESPACE: kube-system
    STATUS: DEPLOYED
    
    RESOURCES:
    ==> v1/ServiceAccount
    NAME               SECRETS  AGE
    my-redis-redis-ha  1        8d
    
    ==> v1/Role
    NAME               AGE
    my-redis-redis-ha  8d
    
    ==> v1/RoleBinding
    NAME               AGE
    my-redis-redis-ha  8d
    
    ==> v1/Service
    NAME                          TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)                      AGE
    my-redis-redis-ha-announce-2  ClusterIP  10.200.111.254  <none>       6379/TCP,26379/TCP           8d
    my-redis-redis-ha-announce-0  ClusterIP  10.200.192.130  <none>       6379/TCP,26379/TCP           8d
    my-redis-redis-ha-announce-1  ClusterIP  10.200.55.75    <none>       6379/TCP,26379/TCP           8d
    my-redis-redis-ha             ClusterIP  None            <none>       6379/TCP,26379/TCP,9121/TCP  8d
    
    ==> v1/StatefulSet
    NAME                      DESIRED  CURRENT  AGE
    my-redis-redis-ha-server  3        3        8d
    
    ==> v1/Pod(related)
    NAME                        READY  STATUS   RESTARTS  AGE
    my-redis-redis-ha-server-0  3/3    Running  3         8d
    my-redis-redis-ha-server-1  3/3    Running  4         5d18h
    my-redis-redis-ha-server-2  3/3    Running  0         2d19h
    
    ==> v1/Secret
    NAME               TYPE    DATA  AGE
    my-redis-redis-ha  Opaque  1     8d
    
    ==> v1/ConfigMap
    NAME                         DATA  AGE
    my-redis-redis-ha-configmap  3     8d
    my-redis-redis-ha-probes     2     8d
    
    NOTES:
    Redis can be accessed via port 6379 and Sentinel can be accessed via port 26379 on the following DNS name from within your cluster:
    my-redis-redis-ha.kube-system.svc.cluster.local
    
    To connect to your Redis server:
    1. To retrieve the redis password:
       echo $(kubectl get secret my-redis-redis-ha -o "jsonpath={.data['auth']}" | base64 --decode)
    
    2. Connect to the Redis master pod that you can use as a client. By default the my-redis-redis-ha-server-0 pod is configured as the master:
    
       kubectl exec -it my-redis-redis-ha-server-0 sh -n kube-system
    
    3. Connect using the Redis CLI (inside container):
    
       redis-cli -a <REDIS-PASS-FROM-SECRET>
    

      如果其他的应用需要连接这个redis-ha,就需要使用命令 redis-cli -h my-redis-redis-ha -p 6379 -a aaaaaa 使用这个命令只有在k8s集群内部的应用可以。如果是外部的应用,就需要把redis-ha的端口通过NodePort的类型暴露出去才可以;

    4. 使用Helm安装RabbitMQ集群:

      前面的博文中我也已经介绍过如何在虚拟机里面安装RabbitMQ集群。通过练习大家应该知道了RabbitMQ集群的一些基础概念和配置。包括生产者、消费者、Exchange、Queue、BinDings、Connection、Channel、交换机的类型单播和广播、消息的持久化定义等。

      最简单的RabbitMQ集群需要有3个节点,两个内存节点,一个磁盘节点。顾名思义内存节点就是将所有数据放在内存,磁盘节点将数据放在磁盘。不过,如果在投递消息时,打开了消息的持久化,那么即使是内存节点,数据还是安全的放在磁盘。

      由于RabbitMQ是用erlang开发的,RabbitMQ完全依赖Erlang的Cluster,因为erlang天生就是一门分布式语言,集群非常方便,但其本身并不支持负载均衡。Erlang的集群中各节点是经由过程一个magic cookie来实现的,这个cookie存放在 $home/.erlang.cookie 中(像我的root用户安装的就是放在我的root/.erlang.cookie中),文件是400的权限。所以必须包管各节点cookie对峙一致,不然节点之间就无法通信。

      Rabbitmq集群大概分为二种方式:

    • 普通模式:默认的集群模式。

    • 镜像模式:把需要的队列做成镜像队列。(我们一般都采用此模式)
      rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'

        这行命令创建了一个策略,策略名称为ha-all,策略模式为 all 即复制到所有节点,包含新增节点,策略正则表达式为 “^” 表示所有匹配所有队列名称。

      良好的设计架构可以如下:在一个集群里,有3台以上机器,其中1台使用磁盘模式,其它使用内存模式。其它几台为内存模式的节点,无疑速度更快,因此客户端(consumer、producer)连接访问它们。而磁盘模式的节点,由于磁盘IO相对较慢,因此仅作数据备份使用。

      和前面的redis-ha的helm安装一样,先是找到官方网站 https://github.com/helm/charts/tree/master/stable/rabbitmq-ha 仔细阅读以下官方的说明,官方文档里面有针对配置value.yaml的详细说明,并且指导你可以安装chart,卸载chart等;显示搜索rabbitmq,然后下载rabbitmq.这里就不在介绍了。主要有个问题说明以下,rabbitmq有几个版本的chart,有个rabbitmq的chart,我始终都没有研究成功。每次配置好之只要已启动就会报错

    NAME                                CHART VERSION   APP VERSION DESCRIPTION
    stable/prometheus-rabbitmq-exporter 0.4.0           v0.29.0     Rabbitmq metrics exporter for prometheus
    stable/rabbitmq                     5.5.0           3.7.14      Open source message broker software that implements the A...
    stable/rabbitmq-ha                  1.25.0          3.7.12      Highly available RabbitMQ cluster, the open source messag...
    [root@master-01 redis-ha]#
    

      我刚开始的时候一直使用的是stable/rabbitmq这个chart,然后研究了很久都不成功,安装helm包之后启动应用总是报错.

    kubectl logs -f -n kube-system my-rabbitmq-0 rabbitmq
    Error from server (BadRequest): a container name must be specified for pod my-rabbitmq-0, choose one of: [rabbitmq metrics]

      后面找了很久也没有找到问题原因,网上都是说因为找不到正确的节点名字,所以集群无法创建成功。因为在k8s的rabbitmq方案中,rabbitmq有一个专门的k8s插件,这个插件可以实现通过k8s集群的api接口通过pod名字自动发现和创建集群。最终采用了另外一个chart stable/rabbitmq-ha就好了。如果有时间我还要再深究一下两个之间的区别。我的value.yaml文件配置如下:

    ## RabbitMQ application credentials
    ## Ref: http://rabbitmq.com/access-control.html
    ##
    rabbitmqUsername: guest
    rabbitmqPassword: guest123
    
    ## RabbitMQ Management user used for health checks
    managementUsername: management
    managementPassword: 123456
    
    ## Place any additional key/value configuration to add to rabbitmq.conf
    ## Ref: https://www.rabbitmq.com/configure.html#config-items
    extraConfig: |
    #  queue_master_locator = min-masters
    
    ## Place advanced.config file in /etc/rabbitmq/advanced.config
    ## Ref: https://www.rabbitmq.com/configure.html#advanced-config-file
    advancedConfig: |
    
    ## Definitions specification within the secret, will always be mounted
    ## at /etc/definitions/defintions.json
    definitionsSource: definitions.json
    
    ## Place any additional plugins to enable in /etc/rabbitmq/enabled_plugins
    ## Ref: https://www.rabbitmq.com/plugins.html
    extraPlugins: |
      rabbitmq_shovel,
      rabbitmq_shovel_management,
      rabbitmq_federation,
      rabbitmq_federation_management,
    
    definitions:
      users: |-
       {
         "name": "test_producer01",
         "password": "111111",
         "tags": "administrator"
       }
      vhosts: |-
       {
         "name": "/rabbit"
       }
      parameters: |-
       {
         "value": {
           "src-uri": "amqp://localhost",
           "src-queue": "source",
           "dest-uri": "amqp://localhost",
           "dest-queue": "destination",
           "add-forward-headers": false,
           "ack-mode": "on-confirm",
           "delete-after": "never"
         },
         "vhost": "/",
         "component": "shovel",
         "name": "test"
       }
      permissions: |-
       {
         "user": "test_producer01",
         "vhost": "/rabbit",
         "configure": ".*",
         "write": ".*",
         "read": ".*"
       }
      queues: |-
        {
           "name":"myName",
           "vhost":"/rabbit",
           "durable":true,
           "auto_delete":false,
           "arguments":{}
        }
      exchanges: |-
        {
           "name":"myName",
           "vhost":"/rabbit",
           "type":"direct",
           "durable":true,
           "auto_delete":false,
           "internal":false,
           "arguments":{}
        }
      bindings: |-
        {
           "source":"myName",
           "vhost":"/rabbit",
           "destination":"myName",
           "destination_type":"queue",
           "routing_key":"myKey",
           "arguments":{}
        }
    ## Sets the policies in definitions.json. This can be used to control the high
    ## availability of queues by mirroring them to multiple nodes.
    ## Ref: https://www.rabbitmq.com/ha.html
      policies: |-
        {
          "name": "ha-all",
          "pattern": ".*",
          "vhost": "/",
          "definition": {
            "ha-mode": "all",
            "ha-sync-mode": "automatic",
            "ha-sync-batch-size": 1
          }
        }
    
    ## RabbitMQ default VirtualHost
    ## Ref: https://www.rabbitmq.com/vhosts.html
    ##
    rabbitmqVhost: "/"
    
    ## Erlang cookie to determine whether different nodes are allowed to communicate with each other
    ## Ref: https://www.rabbitmq.com/clustering.html
    ##
    # rabbitmqErlangCookie:
    
    ## RabbitMQ Memory high watermark
    ## Ref: http://www.rabbitmq.com/memory.html
    ##
    rabbitmqMemoryHighWatermark: 256MB
    rabbitmqMemoryHighWatermarkType: absolute
    
    ## EPMD port for peer discovery service used by RabbitMQ nodes and CLI tools
    ## Ref: https://www.rabbitmq.com/clustering.html
    ##
    rabbitmqEpmdPort: 4369
    
    ## Node port
    rabbitmqNodePort: 5672
    
    ## Manager port
    rabbitmqManagerPort: 15672
    
    ## Set to true to precompile parts of RabbitMQ with HiPE, a just-in-time
    ## compiler for Erlang. This will increase server throughput at the cost of
    ## increased startup time. You might see 20-50% better performance at the cost
    ## of a few minutes delay at startup.
    rabbitmqHipeCompile: false
    
    ## SSL certificates
    ## Red: http://www.rabbitmq.com/ssl.html
    rabbitmqCert:
      enabled: false
    
      # Specifies an existing secret to be used for SSL Certs
      existingSecret: ""
    
      ## Create a new secret using these values
      cacertfile: |
      certfile: |
      keyfile: |
    
    ## Extra volumes for statefulset
    extraVolumes: []
    
    ## Extra volume mounts for statefulset
    extraVolumeMounts: []
    
    ## Authentication mechanism
    ## Ref: http://www.rabbitmq.com/authentication.html
    rabbitmqAuth:
      enabled: false
    
      config: |
        # auth_mechanisms.1 = PLAIN
        # auth_mechanisms.2 = AMQPLAIN
        # auth_mechanisms.3 = EXTERNAL
    
    ## Automatic Partition Handling Strategy (split brain handling)
    ## Ref: https://www.rabbitmq.com/partitions.html#automatic-handling
    ## Note: pause-if-all-down is not supported without using a custom configmap since it requires extra
    ## configuration.
    
    rabbitmqClusterPartitionHandling: autoheal
    
    ## Authentication backend
    ## Ref: https://github.com/rabbitmq/rabbitmq-auth-backend-http
    rabbitmqAuthHTTP:
      enabled: false
    
      config: |
        # auth_backends.1 = http
        # auth_http.user_path     = http://some-server/auth/user
        # auth_http.vhost_path    = http://some-server/auth/vhost
        # auth_http.resource_path = http://some-server/auth/resource
        # auth_http.topic_path    = http://some-server/auth/topic
    
    ## LDAP Plugin
    ## Ref: http://www.rabbitmq.com/ldap.html
    rabbitmqLDAPPlugin:
      enabled: false
    
      ## LDAP configuration:
      config: |
        # auth_backends.1 = ldap
        # auth_ldap.servers.1  = my-ldap-server
        # auth_ldap.user_dn_pattern = cn=${username},ou=People,dc=example,dc=com
        # auth_ldap.use_ssl    = false
        # auth_ldap.port       = 389
        # auth_ldap.log        = false
    
    ## MQTT Plugin
    ## Ref: http://www.rabbitmq.com/mqtt.html
    rabbitmqMQTTPlugin:
      enabled: false
    
      ## MQTT configuration:
      config: |
        # mqtt.default_user     = guest
        # mqtt.default_pass     = guest
        # mqtt.allow_anonymous  = true
    
    ## Web MQTT Plugin
    ## Ref: http://www.rabbitmq.com/web-mqtt.html
    rabbitmqWebMQTTPlugin:
      enabled: false
    
      ## Web MQTT configuration:
      config: |
        # web_mqtt.ssl.port       = 12345
        # web_mqtt.ssl.backlog    = 1024
        # web_mqtt.ssl.certfile   = /etc/cert/cacert.pem
        # web_mqtt.ssl.keyfile    = /etc/cert/cert.pem
        # web_mqtt.ssl.cacertfile = /etc/cert/key.pem
        # web_mqtt.ssl.password   = changeme
    
    ## STOMP Plugin
    ## Ref: http://www.rabbitmq.com/stomp.html
    rabbitmqSTOMPPlugin:
      enabled: false
    
      ## STOMP configuration:
      config: |
        # stomp.default_user = guest
        # stomp.default_pass = guest
    
    ## Web STOMP Plugin
    ## Ref: http://www.rabbitmq.com/web-stomp.html
    rabbitmqWebSTOMPPlugin:
      enabled: false
    
      ## Web STOMP configuration:
      config: |
        # web_stomp.ws_frame = binary
        # web_stomp.cowboy_opts.max_keepalive = 10
    
    ## AMQPS support
    ## Ref: http://www.rabbitmq.com/ssl.html
    rabbitmqAmqpsSupport:
      enabled: false
    
      # NodePort
      amqpsNodePort: 5671
    
      # SSL configuration
      config: |
        # listeners.ssl.default             = 5671
        # ssl_options.cacertfile            = /etc/cert/cacert.pem
        # ssl_options.certfile              = /etc/cert/cert.pem
        # ssl_options.keyfile               = /etc/cert/key.pem
        # ssl_options.verify                = verify_peer
        # ssl_options.fail_if_no_peer_cert  = false
    
    ## Number of replicas
    replicaCount: 3
    
    image:
      repository: k8s.harbor.test.site/system/rabbitmq
      tag: 3.7.12-alpine
      pullPolicy: IfNotPresent
      ## Optionally specify an array of imagePullSecrets.
      ## Secrets must be manually created in the namespace.
      ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
      ##
      # pullSecrets:
      #   - myRegistrKeySecretName
    
    busyboxImage:
      repository: k8s.harbor.test.site/system/busybox
      tag: latest
      pullPolicy: Always
    
    ## Duration in seconds the pod needs to terminate gracefully
    terminationGracePeriodSeconds: 10
    
    service:
      annotations: {}
      clusterIP: None
    
      ## List of IP addresses at which the service is available
      ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips
      ##
      externalIPs: []
    
      loadBalancerIP: ""
      loadBalancerSourceRanges: []
      type: ClusterIP
    
      ## Customize nodePort number when the service type is NodePort
      ### Ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
      ###
      epmdNodePort: null
      amqpNodePort: null
      managerNodePort: null
    
    podManagementPolicy: OrderedReady
    
    ## Statefulsets rolling update update strategy
    ## Ref: https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#rolling-update
    ##
    updateStrategy: OnDelete
    
    ## Statefulsets Pod Priority
    ## Ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass
    ## priorityClassName: ""
    
    ## We usually recommend not to specify default resources and to leave this as
    ## a conscious choice for the user. This also increases chances charts run on
    ## environments with little resources, such as Minikube. If you do want to
    ## specify resources, uncomment the following lines, adjust them as necessary,
    ## and remove the curly braces after 'resources:'.
    ## If you decide to set the memory limit, make sure to also change the
    ## rabbitmqMemoryHighWatermark following the formula:
    ##   rabbitmqMemoryHighWatermark = 0.4 * resources.limits.memory
    ##
    resources: {}
      # limits:
      #   cpu: 100m
      #   memory: 1Gi
      # requests:
      #   cpu: 100m
      #   memory: 1Gi
    initContainer:
      resources: {}
      #   limits:
      #     cpu: 100m
      #     memory: 128Mi
      #   requests:
      #     cpu: 100m
      #     memory: 128Mi
    
    ## Use an alternate scheduler, e.g. "stork".
    ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/
    ##
    # schedulerName:
    
    ## Data Persistency
    persistentVolume:
      enabled: true
      ## If defined, storageClassName: <storageClass>
      ## If set to "-", storageClassName: "", which disables dynamic provisioning
      ## If undefined (the default) or set to null, no storageClassName spec is
      ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
      ##   GKE, AWS & OpenStack)
      ##
      storageClass: "dynamic"
      name: data
      accessModes:
        - ReadWriteOnce
      size: 8Gi
      annotations: {}
    
    ## Node labels for pod assignment
    ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
    ##
    nodeSelector: {}
    
    ## Node tolerations for pod assignment
    ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature
    ##
    tolerations: []
    
    ## Extra Annotations to be added to pod
    podAnnotations: {}
    
    ## Pod affinity
    ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
    podAntiAffinity: soft
    
    ## Create default configMap
    ##
    existingConfigMap: false
    
    ## Add additional labels to all resources
    ##
    extraLabels: {}
    
    ## Role Based Access
    ## Ref: https://kubernetes.io/docs/admin/authorization/rbac/
    ##
    rbac:
      create: true
    
    ## Service Account
    ## Ref: https://kubernetes.io/docs/admin/service-accounts-admin/
    ##
    serviceAccount:
      create: true
    
      ## The name of the ServiceAccount to use.
      ## If not set and create is true, a name is generated using the fullname template
      # name:
    
    ingress:
      ## Set to true to enable ingress record generation
      enabled: true
    
      path: /
    
      ## The list of hostnames to be covered with this ingress record.
      ## Most likely this will be just one host, but in the event more hosts are needed, this is an array
      hostName: k8s.rabbitmq.test.site
    
      ## Set this to true in order to enable TLS on the ingress record
      tls: false
    
      ## If TLS is set to true, you must declare what secret will store the key/certificate for TLS
      tlsSecret: myTlsSecret
    
      ## Ingress annotations done as key:value pairs
      annotations:
        kubernetes.io/ingress.class: traefik
    
    livenessProbe:
      initialDelaySeconds: 120
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 6
    
    readinessProbe:
      failureThreshold: 6
      initialDelaySeconds: 20
      timeoutSeconds: 3
      periodSeconds: 5
    
    # Specifies an existing secret to be used for RMQ password and Erlang Cookie
    existingSecret: ""
    
    ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
    ##
    securityContext:
      fsGroup: 101
      runAsGroup: 101
      runAsNonRoot: true
      runAsUser: 100
    
    prometheus:
      ## Configures Prometheus Exporter to expose and scrape stats.
      exporter:
        enabled: true
        env: {}
        image:
          repository: kbudde/rabbitmq-exporter
          tag: v0.29.0
          pullPolicy: IfNotPresent
    
        ## Port Prometheus scrapes for metrics
        port: 9090
        ## Comma-separated list of extended scraping capabilities supported by the target RabbitMQ server
        capabilities: "bert,no_sort"
    
        ## Allow overriding of container resources
        resources: {}
         # limits:
         #   cpu: 200m
         #   memory: 1Gi
         # requests:
         #   cpu: 100m
         #   memory: 100Mi
    
      ## Prometheus is using Operator.  Setting to true will create Operator specific resources like ServiceMonitors and Alerts
      operator:
        ## Are you using Prometheus Operator? [Blog Post](https://coreos.com/blog/the-prometheus-operator.html)
        enabled: true
    
        ## Configures Alerts, which will be setup via Prometheus Operator / ConfigMaps.
        alerts:
          ## Prometheus exporter must be enabled as well
          enabled: true
    
          ## Selector must be configured to match Prometheus Install, defaulting to whats done by Prometheus Operator
          ## See [CoreOS Prometheus Chart](https://github.com/coreos/prometheus-operator/tree/master/helm)
          selector:
            role: alert-rules
          labels: {}
    
        serviceMonitor:
          ## Interval at which Prometheus scrapes RabbitMQ Exporter
          interval: 10s
    
          # Namespace Prometheus is installed in
          namespace: kube-system
    
          ## Defaults to whats used if you follow CoreOS [Prometheus Install Instructions](https://github.com/coreos/prometheus-operator/tree/master/helm#tldr)
          ## [Prometheus Selector Label](https://github.com/coreos/prometheus-operator/blob/master/helm/prometheus/templates/prometheus.yaml#L65)
          ## [Kube Prometheus Selector Label](https://github.com/coreos/prometheus-operator/blob/master/helm/kube-prometheus/values.yaml#L298)
          selector:
            prometheus: kube-prometheus
    
    ## Kubernetes Cluster Domain
    clusterDomain: cluster.local
    
    ## Pod Disruption Budget
    podDisruptionBudget: {}
      # maxUnavailable: 1
      # minAvailable: 1
    

      根据官方文档的参考,我主要修改了如下的配置

    • rabbitmq的一些初始账户和密码信息;
    • 默认安装了一些pulgins,主要是队列消息同步的组件;
    • 定义了一个初始化的vhost、生产者用户、用户权限、队列名、Exchange、Bindings、同步策略等;
    • 定义了集群的参数,包括ErlangCookie、集群同步的端口、web管理端口15672、服务端口5672;
    • 定义Pods的副本数为3,也就是创建一个3节点的mq集群;定义镜像全部为私有仓库镜像,镜像包括mq镜像,用于初始化的busybox镜像,用于prometheus监控的rabbitmq-exporter镜像
    • 还定义了Pod的启动策略 OrderedReady,因为mq集群也是有状态应用,启动和停止都需要有顺序;
    • 定义了持久化存储,使用ceph sc;
    • 定义了一个ingress,主要是用于访问web管理页面;

      使用helm status my-rabbitmq-ha 来查看如何访问rabbitmq

    [root@master-01 rabbitmq-ha]# helm status my-rabbitmq-ha
    LAST DEPLOYED: Thu Apr 25 19:43:02 2019
    NAMESPACE: kube-system
    STATUS: DEPLOYED
    
    RESOURCES:
    ==> v1/Secret
    NAME            TYPE    DATA  AGE
    my-rabbitmq-ha  Opaque  4     6d16h
    
    ==> v1beta1/Role
    NAME            AGE
    my-rabbitmq-ha  6d16h
    
    ==> v1beta1/Ingress
    NAME            HOSTS                       ADDRESS  PORTS  AGE
    my-rabbitmq-ha  k8s.rabbitmq.maimaiti.site  80       6d16h
    
    ==> v1/PrometheusRule
    NAME                            AGE
    my-rabbitmq-ha-rabbitmq-alerts  6d16h
    
    ==> v1/ConfigMap
    NAME            DATA  AGE
    my-rabbitmq-ha  2     6d16h
    
    ==> v1/ServiceAccount
    NAME            SECRETS  AGE
    my-rabbitmq-ha  1        6d16h
    
    ==> v1beta1/RoleBinding
    NAME            AGE
    my-rabbitmq-ha  6d16h
    
    ==> v1/Service
    NAME                      TYPE       CLUSTER-IP  EXTERNAL-IP  PORT(S)                               AGE
    my-rabbitmq-ha-discovery  ClusterIP  None        <none>       15672/TCP,5672/TCP,4369/TCP           6d16h
    my-rabbitmq-ha            ClusterIP  None        <none>       15672/TCP,5672/TCP,4369/TCP,9090/TCP  6d16h
    
    ==> v1beta1/StatefulSet
    NAME            DESIRED  CURRENT  AGE
    my-rabbitmq-ha  3        3        6d16h
    
    ==> v1/ServiceMonitor
    NAME            AGE
    my-rabbitmq-ha  6d16h
    
    ==> v1/Pod(related)
    NAME              READY  STATUS   RESTARTS  AGE
    my-rabbitmq-ha-0  2/2    Running  2         5d20h
    my-rabbitmq-ha-1  2/2    Running  2         6d15h
    my-rabbitmq-ha-2  2/2    Running  0         2d20h
    
    NOTES:
    ** Please be patient while the chart is being deployed **
    
      Credentials:
    
        Username      : guest
        Password      : $(kubectl get secret --namespace kube-system my-rabbitmq-ha -o jsonpath="{.data.rabbitmq-password}" | base64 --decode)
        ErLang Cookie : $(kubectl get secret --namespace kube-system my-rabbitmq-ha -o jsonpath="{.data.rabbitmq-erlang-cookie}" | base64 --decode)
    
      RabbitMQ can be accessed within the cluster on port 5672 at my-rabbitmq-ha.kube-system.svc.cluster.local
    
      To access the cluster externally execute the following commands:
    
        export POD_NAME=$(kubectl get pods --namespace kube-system -l "app=rabbitmq-ha" -o jsonpath="{.items[0].metadata.name}")
        kubectl port-forward $POD_NAME --namespace kube-system 5672:5672 15672:15672
        kubectl port-forward $POD_NAME --namespace kube-system 9090:9090
    
      To Access the RabbitMQ AMQP port:
    
        amqp://127.0.0.1:5672/
      To Access the RabbitMQ Exporter metrics port:
    
        http://127.0.0.1:9090/ 
    
      To Access the RabbitMQ Management interface:
    
        URL : http://127.0.0.1:15672
    
    [root@master-01 rabbitmq-ha]# 
    

    好的,今天的博文就写到这里。由于51放假这几天的大多时间都用来陪伴家人了,趁着今天值班就把这几天的k8s实验总结一下。最近这几个月一直都在忙k8s的项目,后续还会补充一些helm安装mysql、helm安装jenkins,重点还会介绍一下k8s容器里面的CI/CD是如何实现的。希望大家持续关注一下我的技术博客和公众号。

    推荐关注我的个人微信公众号 “云时代IT运维”,周期性更新最新的应用运维类技术文档。关注虚拟化和容器技术、CI/CD、自动化运维等最新前沿运维技术和趋势;

    helm的使用和redis、mq等公共组件的容器化实践

    转载于:https://blog.51cto.com/zgui2000/2388287

    展开全文
  • Bit.dev的基础组件设计系统 用于构建的。 成分 此前端代码库中的所有组件都作为组可独立使用的组件。...我们使用包含和公开任何代码库中的组件,作为中的组API,API可以集成到不同的页面和应用程序中。
  • PB扩展组件

    2006-03-16 00:00:00
    TStringList TStrings的扩充,可以给每一个串命名。 TVisualManager 可视化对象的管理对象,可以管理一组Fir组件或PB的可视化组件。 TComponent 基本组件对象,该对象有基本的排列方式属性 TPanel TComponent...
  • 下面最简单的列表组件,它包含一个列表项组件 Item 以及一个列表项容器组件 List。 Item: { xml: "<li id='item'>" }, List: { xml: "<ul id='list'>" } 此列表组件尽管简单,但所构建的框架为我们的继续扩展...
  • 拼图是一个完整而强大的Web组件集。 当前版本包含42个组件,6个容器,5个服务和5个指令,基本上涵盖了Web应用程序的各个方面。 简而言之,拼图具有几乎所有其他组件集的功能,而拼图则功能更强大且性能更好。 因此...
  • 【单选题】java.awt和javax.swing包提供了基本的java程序的GUI设计工具,包含控件、容器和() (5.0分)【单选题】线程控制方法中,yield()的作用()【其它】使用Swing组件编写一个Application,JFrame框架(frame)中包含...

    【填空题】表达式 1/4+2.75 的值是 。

    【单选题】java.awt和javax.swing包提供了基本的java程序的GUI设计工具,包含控件、容器和() (5.0分)

    【单选题】线程控制方法中,yield()的作用是()

    【其它】使用Swing组件编写一个Application,JFrame框架(frame)中包含一个标签(lbl),一个OK按钮(btnok),一个Cancel按钮(btncancel)。布局方式采用FlowLayout布局方式,初始状态如图1所示,当用户单击按钮时,标签显示相应的信息,运行结果如下图2,图3所示。 (15.0分)

    【单选题】不是字节流的是( )

    【填空题】若a是int型变量,则执行表达式"a=25/3%3"后,a的值为 。

    【填空题】在组件中显示时所使用的字体可以用____________方法来设置。 (5.0分)

    【单选题】以下哪一项不是面向对象程序设计的核心特征?

    【单选题】语句“int m,n,k;m=(n=4)+(k=10-7);”执行后,变量m的值为:

    【单选题】事件处理机制能够让图形界面响应用户的操作,主要包括 (5.0分)

    【单选题】在Java语言中,负责代码并发执行的机制是( )

    【单选题】关于java线程,下面说法错误的是()

    【填空题】每个java应用程序可以包括许多方法,但必须有且只能有一个_____方法。

    【单选题】下列关于线程的描述,错误的是( )

    【单选题】下列描述中错误的是( )

    【填空题】java 中的非字符输出流都是________抽象类的子类。

    【简答题】create some statements according to the dialogue on page 115

    【单选题】表达式k=(12<10)? 4: 1 ? 2 : 3的值为:

    【单选题】线程调用了sleep()方法后,该线程将进入( )状态。

    【单选题】File类获取一个不包含路径的文件名的方法为

    【填空题】Swing的事件处理机制包括_____、事件和事件处理者。 (5.0分)

    【填空题】若s是int型变量,且s=6,则表达式“s%2+(s+1)%2”的值为 。

    【单选题】所谓膜的去极化表现为

    【填空题】java 中的字符输出流都是抽象类________的子类.

    【填空题】______________布局管理器包括五个明显的区域:东、南、西、北、中。 (5.0分)

    【填空题】容器里的组件的位置和大小是由_____________安排的 。 (5.0分)

    【填空题】文件类的类名是_______它是java.io中的一个重要的非流类,里面封装了对文件系统进行操作的功能.

    【简答题】你想对世界人民说什么?

    【填空题】有如下程序段,其输出结果是: ( ) int a=3; float b=15.6,f=1.5; printf(“%d”,a+(int)b/2+(int)f%3);

    【单选题】( )布局管理器使容器中各个构件呈网格布局,平均占据容器空间。 (5.0分)

    【单选题】设有以下定义 int a=0; double b=1.25; char c=’A’; #define d 2 则下面语句中错误的是:

    【单选题】框架(JFrame)的缺省布局管理器就是 (5.0分)

    【单选题】是否查询关于Einthoven的资料

    【单选题】观看《心电图之歌》视频,哪些信息没有出现在歌词中。

    【其它】图形用户界面如图所示,在文本框中输入两个数字,点击“加”按钮,在标签中显示相加结果。 (10.0分)

    【其它】使用Swing组件编写一个Application程序,JFrame框架(frame)包含三个标签(lblname,lblhobby,lblmsg)、两个文本框(txtname,txthobby)和两个按钮(btnOk,btnCancel),布局方式采用FlowLayout布局方式,框架有标题“字符串连接”,框架大小为(200,200),标签lblmsg中信息为空,初始状态如图1所示。当用户单击“确定”按钮时,把两个文本框中的内容连接后显示到标签lblmsg中,运行结果如下图2所示。单击“取消”按钮,文本框及lblmsg标签中的信息清空,如图1。 (10.0分)

    【填空题】有以下程序运行后的输出结果是: main() { char a='A',b; print("%c,",++a); printf("%c\n",b=a++); }

    【填空题】可以使用setLocation(),setSize()或____________中的任何一中方法设定组件的大小或位置。 (5.0分)

    【单选题】抽象窗口工具包( )是java提供的建立图形用户界面GUI的开发包. (5.0分)

    【填空题】面向对象程序设计的三大特性是: 、 和 。

    【单选题】Java 中的布局管理器,下列说法错误的是 。 (5.0分)

    【单选题】在 Java 核心包中,默认导入的包是:

    【填空题】_____________布局管理器是容器中各个构件呈网格布局,平均占据容器空间 (5.0分)

    【填空题】JAVA 系统运行时,通过_____机制周期性的释放无用对象所使用的内存,完成对象的清除。

    【填空题】若定义:char c=‘\010’;则变量c中包含的字符个数是 。

    【单选题】已知字母A的ASCII码为十进制数65,且c2为字符型,则执行语句 char c2 = 'A' + '6' - '3'; 后c2中的值为

    【填空题】a=12,n=5, 表达式a/=(n%=2)值是 。

    【单选题】下列不属于FileInputStream输入流的read()成员函数的是

    【填空题】框架的缺省布局管理器是_________。 (5.0分)

    【填空题】已知字符A的ACSII码值为65,以下语句的输出结果是 。 char ch=’B’; printf( “%c,%d\n”,ch,ch);

    展开全文
  • 该模块包含一个基本的内存容器,该容器可以嵌入服务或应用程序内部,也可以单独运行。 第二种容器类型可以作为系统级进程运行,并且可以通过命令行参数进行配置。 也可以用来创建docker容器容器可以从JSON或...
  • Tomcat基本知识(

    2019-09-24 03:58:39
    Tomcat中最顶层的容器是Server,代表着整个服务器,从上图中可以看出,一个Server可以包含至少一个Service,用于具体提供服务。 Service主要包含两个部分:Connector和Container。从上图中可以看出Tomcat的心脏就是...
  • C4Sharp( C4S )用于构建一个NET库。 它就像的超集一样,开发人员可以通过它创建,共享和使用作为代码(C#),例如上下文图,容器图,组件图和部署图。 入门 安装方式 该程序包可通过Nuget程序包获得: ://...
  • React-Redux示例 此仓库包含两个使用React和Redux的示例应用程序,它们是使用Babel和Webpack构建的,并使用Jest进行了测试: (基本,无异步操作) ... 它是一个模块捆绑器。 本质上,它是用来将项目构建为可交付组件
  • 视图容器,倘若进行分开理解,视图就是希望用户所看到的,而容器可以包容其他的功能组件,从整个页面的角度理解为占位符,而从所包含的功能组件的角度理解为框架。个人理解,此为所有组件中最重要的一个。 ...
  • 例如,一个包含 Nginx 应用程序的镜像,其内部包含一个基本的操作系统环境以及 Nginx 应用程序 。 镜像创建 Docker 容器的基础,通过版本管理和增量文件系统, Docker 提供了一套机制来创建或更新现有的镜像,我们...
  • PodKubernetes最基本的部署调度单元可以包含Container逻辑上表示某种应用的一个实例比如一个web站点应用由前端后端及数据库构建而成这三个组件将运行在各自的容器中那么我们可以创建包含三个Container的Pod ...
  • API接口,但Binding Registry是一个write-only对象,所有只有Create操作可以使用, 否则会引起错误。3.1.7. Scheduler Scheduler收集和分析当前Kubernetes集群中所有Minion节点的资源(内存、CPU)负载情况,然后依此...
  • tomcat基本使用

    千次阅读 2015-12-08 10:28:09
    一、Tomcat的架构: Tomcat 6支持Servlet 2.5和JSP 2.1的规范,它由一组嵌套的层次和组件组成,一般可分为以下四类: 顶级组件:位于配置层次的...被嵌套的组件:位于一个容器当中,但不能包含其它组件
  • EXTJS的基本概念

    2019-10-03 03:26:32
    容器组件:能够包含其它容器或者元件组件的类,其进行单元化组件开发的基础 元件组件:能图形化形式表现一个片面功能的组件,其不仅在实现了原有传统WEB程序的现有组件,而且还扩展了许多实用的组件,如刻度器、...
  • Docker 基本概念

    2020-04-06 10:18:15
    Docker 基本概念 Docker 包括三个基本概念 ...Docker 引擎是一个包含以下主要组件的客户端服务器应用程序。 一种服务器,它是一种称为守护进程并且长时间运行的程序。 REST API用于指定程序可以用来与守护进程通...
  • Spring主要包含哪些模块?

    千次阅读 2018-11-05 19:22:23
    Spring是一个分层架构,由7个定义良好的模块组成。Spring模块构建在核心容器之上,核心容器定义了创建、配置和管理bean的方式。 组成Spring框架的每个模块(或组件可以单独存在,或者与其他一个或多个模块联合...
  • 用Java编写一个最简单的桌面程序

    万次阅读 多人点赞 2018-03-03 13:42:30
    使用这可以编写简单的Java桌面应用程序.Java的javax.swing包提供了许多用来设计GUI的组件类,在学习GUI编程时,需要掌握两概念:容器类(Container)和组件类(Component),以下GUI编程中经常提到的基本知识点.&...
  • 包含并管理应用对象的配置和生命周期,这意义上是一容器。 将简单组件配置组合成为复杂的内容,这意义上是一种框架。 框架就是制定一套规范或者规则,大家在该规范或者规则(思想)下工作。
  • react全局状态管理基本概念下面开始小例子参考阮一峰的网络日志 先来看一下Redux的流程图 基本概念 Store: 保存数据的地方,可以看成...Action: 是一个对象。其中的type属性是必须的,表示Action的名称(下面会有...
  • tomcat基本使用(二)

    2015-12-07 17:43:38
    一、Tomcat的架构:Tomcat 6支持Servlet 2.5和JSP 2.1的规范,它由一组嵌套的层次和组件组成,一般可分为以下四类:顶级组件:...被嵌套的组件:位于一个容器当中,但不能包含其它组件;各常见组件:1、服务器(se...
  • 调查发现 Antd 将所有组件都写入一个项目中,这样方便组件统一管理,开发时不需要在多个仓库之间切换,而且预览效果只需运行跟项目,而不是为每个组件开启一个端口进行预览。其依赖的 ...
  • WorkItem是一个运行时容器,该容器包含完成一个用例所需要了各种各样的组件组件可以是可视化的也可以是非可视化的,比如:SmartPart,Service,Commonds等等。 WorkItem中定义了如下的属性: Services ...
  • 一个模块一个项目,模块下划分业务组件,属于模块上对业务的细分,一个模块可以包含多个组件。一般建议把项目按照模块划分,把业务按照业务组件进行划分,这样做的好处以后运行的时候下载的代码比较少,只下载需要...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 268
精华内容 107
关键字:

容器是一个可以包含基本组件